From 290999932cc5621fc8de42d4b3557db3584d5e80 Mon Sep 17 00:00:00 2001 From: Sascha Tandel <514405+sastan@users.noreply.github.com> Date: Wed, 14 Dec 2022 22:19:24 +0100 Subject: [PATCH] add radix ui preset (#419) --- .changeset/beige-crabs-call.md | 5 + .changeset/breezy-beans-promise.md | 5 + .changeset/cold-zoos-nail.md | 7 + .changeset/pink-rivers-leave.md | 5 + .codesandbox/ci.json | 1 + .github/actions/publish-prerelease/action.yml | 13 + .github/workflows/ci.yml | 2 +- .stackblitz/codeflow.json | 1 + CHANGELOG.md | 1 + documentation/preset-line-clamp.md | 2 +- documentation/preset-radix-ui.md | 208 ++++ documentation/preset-tailwind.md | 31 + packages/preset-radix-ui/README.md | 31 + packages/preset-radix-ui/colors.d.ts | 3 + packages/preset-radix-ui/darkColor.d.ts | 3 + packages/preset-radix-ui/defaultTheme.d.ts | 3 + packages/preset-radix-ui/index.d.ts | 8 + packages/preset-radix-ui/package.json | 74 ++ .../scripts/generate-colors.js | 54 ++ packages/preset-radix-ui/src/colors.ts | 846 +++++++++++++++++ packages/preset-radix-ui/src/darkColor.ts | 9 + packages/preset-radix-ui/src/defaultTheme.ts | 3 + packages/preset-radix-ui/src/index.ts | 8 + packages/preset-radix-ui/tsconfig.json | 7 + packages/preset-tailwind/base.d.ts | 4 + packages/preset-tailwind/baseTheme.d.ts | 4 + packages/preset-tailwind/index.d.ts | 2 + packages/preset-tailwind/package.json | 17 + packages/preset-tailwind/src/base.ts | 53 ++ packages/preset-tailwind/src/baseTheme.ts | 897 ++++++++++++++++++ packages/preset-tailwind/src/colors.ts | 6 - packages/preset-tailwind/src/defaultTheme.ts | 893 +---------------- packages/preset-tailwind/src/index.ts | 22 +- packages/preset-tailwind/src/preflight.ts | 8 +- packages/preset-typography/src/index.ts | 2 +- pnpm-lock.yaml | 20 +- sites/cdn.twind.style/src/index.ts | 1 + sites/twind.run/package.json | 2 +- .../lib/templates/preset-radix-ui/config.tpl | 67 ++ .../lib/templates/preset-radix-ui/html.tpl | 29 + .../lib/templates/preset-radix-ui/index.ts | 12 + .../lib/templates/preset-radix-ui/script.tpl | 15 + sites/twind.run/src/lib/transpile.api.ts | 58 +- .../src/routes/[[key]]/+page.server.ts | 6 +- .../twind.run/src/routes/[[key]]/+page.svelte | 105 +- .../src/routes/[[key]]/discover.svelte | 2 +- .../twind.run/src/routes/[[key]]/info.svelte | 17 +- sites/twind.run/src/twind.config.ts | 83 +- sites/twind.style/package.json | 2 +- .../src/lib/markdown/remark-code.ts | 2 +- sites/twind.style/src/twind.config.ts | 81 +- 51 files changed, 2619 insertions(+), 1121 deletions(-) create mode 100644 .changeset/beige-crabs-call.md create mode 100644 .changeset/breezy-beans-promise.md create mode 100644 .changeset/cold-zoos-nail.md create mode 100644 .changeset/pink-rivers-leave.md create mode 100644 documentation/preset-radix-ui.md create mode 100644 packages/preset-radix-ui/README.md create mode 100644 packages/preset-radix-ui/colors.d.ts create mode 100644 packages/preset-radix-ui/darkColor.d.ts create mode 100644 packages/preset-radix-ui/defaultTheme.d.ts create mode 100644 packages/preset-radix-ui/index.d.ts create mode 100644 packages/preset-radix-ui/package.json create mode 100644 packages/preset-radix-ui/scripts/generate-colors.js create mode 100644 packages/preset-radix-ui/src/colors.ts create mode 100644 packages/preset-radix-ui/src/darkColor.ts create mode 100644 packages/preset-radix-ui/src/defaultTheme.ts create mode 100644 packages/preset-radix-ui/src/index.ts create mode 100644 packages/preset-radix-ui/tsconfig.json create mode 100644 packages/preset-tailwind/base.d.ts create mode 100644 packages/preset-tailwind/baseTheme.d.ts create mode 100644 packages/preset-tailwind/src/base.ts create mode 100644 packages/preset-tailwind/src/baseTheme.ts create mode 100644 sites/twind.run/src/lib/templates/preset-radix-ui/config.tpl create mode 100644 sites/twind.run/src/lib/templates/preset-radix-ui/html.tpl create mode 100644 sites/twind.run/src/lib/templates/preset-radix-ui/index.ts create mode 100644 sites/twind.run/src/lib/templates/preset-radix-ui/script.tpl diff --git a/.changeset/beige-crabs-call.md b/.changeset/beige-crabs-call.md new file mode 100644 index 000000000..2ab4d64d5 --- /dev/null +++ b/.changeset/beige-crabs-call.md @@ -0,0 +1,5 @@ +--- +'@twind/preset-typography': patch +--- + +use flattend color name to lookup dark shade for a color diff --git a/.changeset/breezy-beans-promise.md b/.changeset/breezy-beans-promise.md new file mode 100644 index 000000000..a0b76ad3d --- /dev/null +++ b/.changeset/breezy-beans-promise.md @@ -0,0 +1,5 @@ +--- +'@twind/preset-tailwind': minor +--- + +allow to omit the default color palette diff --git a/.changeset/cold-zoos-nail.md b/.changeset/cold-zoos-nail.md new file mode 100644 index 000000000..c048908c4 --- /dev/null +++ b/.changeset/cold-zoos-nail.md @@ -0,0 +1,7 @@ +--- +'@twind/preset-radix-ui': patch +'@sites/twind.run': patch +'@sites/twind.style': patch +--- + +add radix-ui example to twind.run diff --git a/.changeset/pink-rivers-leave.md b/.changeset/pink-rivers-leave.md new file mode 100644 index 000000000..a412134b9 --- /dev/null +++ b/.changeset/pink-rivers-leave.md @@ -0,0 +1,5 @@ +--- +'@twind/preset-radix-ui': patch +--- + +add radix ui preset diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index eff0960fa..22de310db 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -19,6 +19,7 @@ "@twind/preset-container-queries": "packages/preset-container-queries/dist", "@twind/preset-ext": "packages/preset-ext/dist", "@twind/preset-line-clamp": "packages/preset-line-clamp/dist", + "@twind/preset-radix-ui": "packages/preset-radix-ui/dist", "@twind/preset-tailwind": "packages/preset-tailwind/dist", "@twind/preset-tailwind-forms": "packages/preset-tailwind-forms/dist", "@twind/preset-typography": "packages/preset-typography/dist", diff --git a/.github/actions/publish-prerelease/action.yml b/.github/actions/publish-prerelease/action.yml index 665679971..e7c210efc 100644 --- a/.github/actions/publish-prerelease/action.yml +++ b/.github/actions/publish-prerelease/action.yml @@ -40,6 +40,19 @@ runs: shell: bash run: pnpm changeset --empty + - name: πŸ“ Ensure sites versions are bumped + uses: fertrig/create-file-action@1.0.2 + with: + path: '.changesets' + file: 'sites-versions-bump.md' + content: | + --- + '@sites/twind.run': patch + '@sites/twind.style': patch + --- + + bump version + - name: πŸ“¦ Update packages shell: bash run: pnpm changeset version --no-git-tag --snapshot ${{ inputs.tag }} --snapshot-prerelease-template "${{ inputs.template }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03da2ec40..6ff0da200 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -172,7 +172,7 @@ jobs: uses: thollander/actions-comment-pull-request@v2 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - comment_includes: '## Deployed site previews with [![Cloudflare Pages]' + comment_tag: '## Deployed site previews with [![Cloudflare Pages]' message: | > **Latest commit**: ${{ github.sha }} diff --git a/.stackblitz/codeflow.json b/.stackblitz/codeflow.json index 632b7dbc9..873767cf7 100644 --- a/.stackblitz/codeflow.json +++ b/.stackblitz/codeflow.json @@ -8,6 +8,7 @@ "@twind/preset-container-queries": "./packages/preset-container-queries", "@twind/preset-ext": "./packages/preset-ext", "@twind/preset-line-clamp": "./packages/preset-line-clamp", + "@twind/preset-radix-ui": "./packages/preset-radix-ui", "@twind/preset-tailwind": "./packages/preset-tailwind", "@twind/preset-tailwind-forms": "./packages/preset-tailwind-forms", "@twind/preset-typography": "./packages/preset-typography", diff --git a/CHANGELOG.md b/CHANGELOG.md index 415ecbb89..47b105d20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [@twind/preset-conatiner-queries](./packages/preset-conatiner-queries/CHANGELOG.md) - [@twind/preset-ext](./packages/preset-ext/CHANGELOG.md) - [@twind/preset-line-clamp](./packages/preset-line-clamp/CHANGELOG.md) +- [@twind/preset-radix-ui](./packages/preset-radix-ui/CHANGELOG.md) - [@twind/preset-tailwind](./packages/preset-tailwind/CHANGELOG.md) - [@twind/preset-tailwind-forms](./packages/preset-tailwind-forms/CHANGELOG.md) - [@twind/preset-typography](./packages/preset-typography/CHANGELOG.md) diff --git a/documentation/preset-line-clamp.md b/documentation/preset-line-clamp.md index 34010453c..81ddb9075 100644 --- a/documentation/preset-line-clamp.md +++ b/documentation/preset-line-clamp.md @@ -5,7 +5,7 @@ package: '@twind/preset-line-clamp' playground: true excerpt: | A preset that provides utilities for visually truncating text after a fixed number of lines. -next: ./preset-tailwind.md +next: ./preset-radix-ui.md --- > **Note** diff --git a/documentation/preset-radix-ui.md b/documentation/preset-radix-ui.md new file mode 100644 index 000000000..93c0fa85c --- /dev/null +++ b/documentation/preset-radix-ui.md @@ -0,0 +1,208 @@ +--- +section: Presets +label: Radix UI +package: '@twind/preset-radix-ui' +playground: true +excerpt: | + The [Radix UI](https://www.radix-ui.com/colors) [color scales](https://www.radix-ui.com/docs/colors/palette-composition/the-scales) as a twind preset with automatic dark colors. +next: ./preset-tailwind.md +--- + +## 🀝 Compatibility + +| @twind/preset-tailwind | @radix-ui/colors | +| ---------------------- | ---------------- | +| `>=1.1.0 <1.2.0` | `0.1.8` | + +## πŸ“¦ Installation + +> **Important** +> This preset only includes the [color scales](https://www.radix-ui.com/docs/colors/palette-composition/the-scales) from [Radix UI β€Ί Colors](https://www.radix-ui.com/colors) and a dark color function to enable automatic dark colors. It does not include any rules or variants. Please read the [Usage](#-usage) guide for detailed instructions. + +**with [@twind/core](./installation#local--bundler)** + +Install from npm: + +```sh +npm install @twind/core @twind/preset-radix-ui +``` + +Add the preset to your twind config: + +```js title="twind.config.js" +import { defineConfig } from '@twind/core' +import presetRadixUi from '@twind/preset-radix-ui' + +export default defineConfig({ + presets: [presetRadixUi()], + /* config */ +}) +``` + +
Usage with a script tag + +```html + + + + +``` + +
+ +**with [Twind CDN](./installation#twind-cdn)** + +```html + + + + +``` + +## πŸ™‡ Usage + +This preset does not include any rules or variants but it includes all [colors](https://www.radix-ui.com/docs/colors/palette-composition/the-scales). To reduce the package size it is advised to select only the colors you'll need. Please refer to [Radix UI β€Ί Colors β€Ί Composing a color palette](https://www.radix-ui.com/docs/colors/palette-composition/composing-a-palette) for a guide how to compose a color palette and [Radix UI β€Ί Colors β€Ί Understanding the scale](https://www.radix-ui.com/docs/colors/palette-composition/understanding-the-scale) to learn which scale step is the most appropriate for each use case. + +### With @twind/preset-tailwind + +The following example shows how to use the colors with [@twind/preset-tailwind](./preset-tailwind) using [semantic color names](https://www.radix-ui.com/docs/colors/palette-composition/composing-a-palette#choosing-semantic-scales) with automatic dark colors. + +```js title="twind.config.js" +import { defineConfig } from '@twind/core' +import presetAutoprefix from '@twind/preset-autoprefix' +// Using @twind/preset-tailwind/base to exclude the default tailwind colors +import presetTailwind from '@twind/preset-tailwind/base' + +// Following https://www.radix-ui.com/docs/colors/palette-composition/composing-a-palette +// This color palette is used on this site +import { + sky as brand, + skyDark as brandDark, + plum as accent, + plumDark as accentDark, + slate as neutral, + slateDark as neutralDark, + + // Error: Red/Tomato/Crimson + tomato as error, + tomatoDark as errorDark, + + // Success: Teal/Green/Grass/Mint + green as success, + greenDark as successDark, + + // Warning: Yellow/Amber + amber as warning, + amberDark as warningDark, + + // Info: Blue/Sky/Cyan + cyan as info, + cyanDark as infoDark, +} from '@twind/preset-radix-ui/colors' + +// Optional: enable automatic dark colors +import darkColor from '@twind/preset-radix-ui/darkColor' + +export default defineConfig({ + presets: [ + presetAutoprefix(), + presetTailwind({ + colors: { + brand, + brandDark, + accent, + accentDark, + neutral, + neutralDark, + + // Error: Red/Tomato/Crimson + error, + errorDark, + + // Success: Teal/Green/Grass/Mint + success, + successDark, + + // Warning: Yellow/Amber + warning, + warningDark, + + // Info: Blue/Sky/Cyan + info, + infoDark, + }, + }), + ], + // auto dark colors + darkColor, +}) +``` + +> **Hint** +> Radix UI uses a different [color scale](https://www.radix-ui.com/docs/colors/palette-composition/understanding-the-scale) that tailwindcss. There are 12 steps in each scale. Each step was designed for at least one specific use case. + +```html +
+``` + +### With @twind/preset-typography + +The following example shows how to use the colors with [@twind/preset-typography](./preset-typography). + +```js title="twind.config.js" +import { defineConfig } from '@twind/core' +import presetAutoprefix from '@twind/preset-autoprefix' +import presetTailwind from '@twind/preset-tailwind/base' +import presetTypography from '@twind/preset-typography' + +// Import other colors as needed +import { sky as brand, skyDark as brandDark } from '@twind/preset-radix-ui/colors' + +// Use automatic dark colors +import darkColor from '@twind/preset-radix-ui/darkColor' + +export default defineConfig({ + presets: [ + presetAutoprefix(), + presetTailwind({ colors: { brand, brandDark /* define other colors as needed */ } }), + presetTypography({ + // The color to use when `prose` without a color is used + defaultColor: 'brand', + colors: { + body: '11', + headings: '12', + lead: '11', + links: '12', + bold: '12', + counters: '7', + bullets: '6', + hr: '6', + quotes: '12', + 'quote-borders': '6', + captions: '11', + code: '11', + 'pre-code': '11', + 'pre-bg': '3', + 'th-borders': '7', + 'td-borders': '6', + // invert colors (dark mode) β€” default to auto dark color + dark: null, + }, + }), + ], + darkColor, +}) +``` diff --git a/documentation/preset-tailwind.md b/documentation/preset-tailwind.md index 8f46fc5db..c0e7238f9 100644 --- a/documentation/preset-tailwind.md +++ b/documentation/preset-tailwind.md @@ -70,3 +70,34 @@ All utilities and variants from [Tailwind CSS](https://tailwindcss.com) are avai This preset can be configured with the following options: - `disablePreflight: boolean` β€” allows to disable the [preflight](https://tailwindcss.com/docs/preflight) + +## πŸͺ„ Advanced + +This presets allows to omit the [default color palette](https://tailwindcss.com/docs/customizing-colors) to reduce the file size. + +The following example selectively imports colors from the default palette but different colors can be used as well (see [@twind/preset-radix-ui](./preset-radix-ui#with-twindpreset-tailwind) for an example). + +```js title="twind.config.js" +import { defineConfig } from '@twind/core' +import presetAutoprefix from '@twind/preset-autoprefix' +// Using @twind/preset-tailwind/base to exclude the default tailwind colors +import presetTailwind from '@twind/preset-tailwind/base' + +// Selectively import colors +import { + slate as gray, + red, + amber as yellow, + emerald as green, + indigo as blue, +} from '@twind/preset-tailwind/colors' + +export default defineConfig({ + presets: [ + presetAutoprefix(), + presetTailwind({ + colors: { gray, yellow, green, blue }, + }), + ], +}) +``` diff --git a/packages/preset-radix-ui/README.md b/packages/preset-radix-ui/README.md new file mode 100644 index 000000000..20db74f3d --- /dev/null +++ b/packages/preset-radix-ui/README.md @@ -0,0 +1,31 @@ +# @twind/preset-radix-ui [![MIT License](https://flat.badgen.net/github/license/tw-in-js/twind)](https://github.com/tw-in-js/twind/blob/main/LICENSE) [![Latest Release](https://flat.badgen.net/npm/v/@twind/preset-radix-ui?icon=npm&label&cache=10800&color=blue)](https://www.npmjs.com/package/@twind/preset-radix-ui) [![Github](https://flat.badgen.net/badge/icon/tw-in-js%2Ftwind%23preset-radix-ui?icon=github&label)](https://github.com/tw-in-js/twind/tree/main/packages/preset-radix-ui) + +The [Radix UI](https://www.radix-ui.com/colors) [color scales](https://www.radix-ui.com/docs/colors/palette-composition/the-scales) as a twind preset with automatic dark colors. + +- πŸ“– Study [the documentation](https://twind.style/preset-radix-ui) +- πŸ€– Try [the playground](https://twind.run/preset-radix-ui) +- 🧭 Explore [the examples](https://twind.style/examples) +- πŸ““ Consult [the API reference](https://twind.style/packages/@twind/preset-radix-ui) +- πŸ“œ Read [the changelog](https://github.com/tw-in-js/twind/tree/main/packages/preset-radix-ui/CHANGELOG.md) + +## πŸ“– Documentation + +The full documentation is available at [twind.style/preset-radix-ui](https://twind.style/preset-radix-ui). + +## πŸ’¬ Community + +For help, discussion about best practices, or any other conversation that would benefit from being searchable use [Github Discussions](https://github.com/tw-in-js/twind/discussions). + +To ask questions and discuss with other Twind users in real time use [Discord Chat](https://chat.twind.style). + +## 🧱 Contribute + +See the [Contributing Guide](../../CONTRIBUTING.md) for information on how to contribute to this project. + +## πŸ“œ Changelog + +The Changelog for this package is [available on GitHub](https://github.com/tw-in-js/twind/tree/main/packages/preset-radix-ui/CHANGELOG.md). + +## βš–οΈ License + +The [MIT license](https://github.com/tw-in-js/twind/blob/main/LICENSE) governs your use of Twind. diff --git a/packages/preset-radix-ui/colors.d.ts b/packages/preset-radix-ui/colors.d.ts new file mode 100644 index 000000000..8f03618dc --- /dev/null +++ b/packages/preset-radix-ui/colors.d.ts @@ -0,0 +1,3 @@ +// ONLY FOR TYPESCRIPT TO FIND @twind/preset-radix-ui/colors + +export * from './src/colors' diff --git a/packages/preset-radix-ui/darkColor.d.ts b/packages/preset-radix-ui/darkColor.d.ts new file mode 100644 index 000000000..2fa15d359 --- /dev/null +++ b/packages/preset-radix-ui/darkColor.d.ts @@ -0,0 +1,3 @@ +// ONLY FOR TYPESCRIPT TO FIND @twind/preset-radix-ui/darkColor + +export { default } from './src/darkColor' diff --git a/packages/preset-radix-ui/defaultTheme.d.ts b/packages/preset-radix-ui/defaultTheme.d.ts new file mode 100644 index 000000000..2f46ded49 --- /dev/null +++ b/packages/preset-radix-ui/defaultTheme.d.ts @@ -0,0 +1,3 @@ +// ONLY FOR TYPESCRIPT TO FIND @twind/preset-radix-ui/defaultTheme + +export { default } from './src/defaultTheme' diff --git a/packages/preset-radix-ui/index.d.ts b/packages/preset-radix-ui/index.d.ts new file mode 100644 index 000000000..6c19a9afe --- /dev/null +++ b/packages/preset-radix-ui/index.d.ts @@ -0,0 +1,8 @@ +// ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) + +export { default } from './src/index' +export * from './src/index' + +export * as colors from './src/colors' +export * as darkColor from './src/darkColor' +export * as defaultTheme from './src/defaultTheme' diff --git a/packages/preset-radix-ui/package.json b/packages/preset-radix-ui/package.json new file mode 100644 index 000000000..1dbe1b8a9 --- /dev/null +++ b/packages/preset-radix-ui/package.json @@ -0,0 +1,74 @@ +{ + "name": "@twind/preset-radix-ui", + "version": "1.0.3", + "description": "The Radix UI color scales as a twind preset with automatic dark colors.", + "homepage": "https://twind.style/preset-radix-ui", + "keywords": [ + "twind", + "twind-preset", + "radix-ui", + "tw-in-js", + "tailwind-in-js", + "preset" + ], + "type": "module", + "// The 'module', 'unpkg' and 'types' fields are added by distilt": "", + "main": "src/index.ts", + "// Each entry is expanded into several bundles (types, esnext, module, script, node, and default)": "", + "exports": { + ".": "./src/index.ts", + "./colors": "./src/colors.ts", + "./darkColor": "./src/darkColor.ts", + "./defaultTheme": "./src/defaultTheme.ts", + "./package.json": "./package.json" + }, + "typedoc": { + "entryPoint": "./index.d.ts" + }, + "// These are relative from within the dist/ folder": "", + "sideEffects": false, + "size-limit": [ + { + "name": "@twind/preset-radix-ui", + "path": "dist/preset-radix-ui.esnext.js", + "brotli": true, + "limit": "2.7kb", + "ignore": [ + "twind" + ] + }, + { + "name": "@twind/preset-radix-ui/colors", + "path": "dist/colors.esnext.js", + "brotli": true, + "limit": "2.3kb" + }, + { + "name": "@twind/preset-radix-ui/defaultTheme", + "path": "dist/defaultTheme.esnext.js", + "brotli": true, + "limit": "2.6kb" + } + ], + "peerDependencies": { + "@twind/core": "^1.0.3", + "typescript": "^4.8.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + }, + "devDependencies": { + "@radix-ui/colors": "^0.1.8", + "@twind/core": "^1.0.3", + "typescript": "^4.8.4" + }, + "scripts": { + "build": "distilt" + }, + "publishConfig": { + "access": "public", + "directory": "dist" + } +} diff --git a/packages/preset-radix-ui/scripts/generate-colors.js b/packages/preset-radix-ui/scripts/generate-colors.js new file mode 100644 index 000000000..730469e00 --- /dev/null +++ b/packages/preset-radix-ui/scripts/generate-colors.js @@ -0,0 +1,54 @@ +import { writeFileSync } from 'node:fs' + +import * as RADIX_COLORS from '@radix-ui/colors' + +const targetFile = new URL('../src/colors.ts', import.meta.url) + +const header = ` +// Based on https://github.com/radix-ui/colors +// Generated by ../scripts/generate-colors.js + +/** + * @module @twind/preset-radix-ui/colors + */ +` + +const colors = Object.entries(RADIX_COLORS) + .filter(([name]) => !['default', '__esModule'].includes(name) && !name.endsWith('A')) + .map(([name, scale]) => + [ + `export const ${name} = {`, + ...Object.entries(scale).map( + ([key, value]) => ` ${key.replace(/\D/g, '')}: '${hslToHex(value)}',`, + ), + `} as const`, + ].join('\n'), + ) + +writeFileSync(targetFile, [header.trim(), ...colors].join('\n\n') + '\n') + +console.log(`Written colors to ${targetFile}`) + +// https://stackoverflow.com/a/44134328/968997 +function hslToHex(hsl) { + let { + // eslint-disable-next-line prefer-const + 1: h, + // eslint-disable-next-line prefer-const + 2: s, + 3: l, + } = /(\d+), ([\d.]+)%, ([\d.]+)%/.exec(hsl) + + l /= 100 + const a = (s * Math.min(l, 1 - l)) / 100 + const f = (n) => { + const k = (n + h / 30) % 12 + const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1) + // convert to Hex and prefix "0" if needed + return Math.round(255 * color) + .toString(16) + .padStart(2, '0') + } + + return `#${f(0)}${f(8)}${f(4)}` +} diff --git a/packages/preset-radix-ui/src/colors.ts b/packages/preset-radix-ui/src/colors.ts new file mode 100644 index 000000000..89eefc99a --- /dev/null +++ b/packages/preset-radix-ui/src/colors.ts @@ -0,0 +1,846 @@ +// Based on https://github.com/radix-ui/colors +// Generated by ../scripts/generate-colors.js + +/** + * @module @twind/preset-radix-ui/colors + */ + +export const amber = { + 1: '#fefdfb', + 2: '#fff9ed', + 3: '#fff4d5', + 4: '#ffecbc', + 5: '#ffe3a2', + 6: '#ffd386', + 7: '#f3ba63', + 8: '#ee9d2b', + 9: '#ffb224', + 10: '#ffa01c', + 11: '#ad5700', + 12: '#4e2009', +} as const + +export const amberDark = { + 1: '#1f1300', + 2: '#271700', + 3: '#341c00', + 4: '#3f2200', + 5: '#4a2900', + 6: '#573300', + 7: '#693f05', + 8: '#824e00', + 9: '#ffb224', + 10: '#ffcb47', + 11: '#f1a10d', + 12: '#fef3dd', +} as const + +export const blue = { + 1: '#fbfdff', + 2: '#f5faff', + 3: '#edf6ff', + 4: '#e1f0ff', + 5: '#cee7fe', + 6: '#b7d9f8', + 7: '#96c7f2', + 8: '#5eb0ef', + 9: '#0090ff', + 10: '#0081f1', + 11: '#006adc', + 12: '#00254d', +} as const + +export const blueDark = { + 1: '#0f1720', + 2: '#0f1b2d', + 3: '#10243e', + 4: '#102a4c', + 5: '#0f3058', + 6: '#0d3868', + 7: '#0a4481', + 8: '#0954a5', + 9: '#0090ff', + 10: '#369eff', + 11: '#52a9ff', + 12: '#eaf6ff', +} as const + +export const bronze = { + 1: '#fdfcfc', + 2: '#fdf8f6', + 3: '#f8f1ee', + 4: '#f2e8e4', + 5: '#eaddd7', + 6: '#e0cec7', + 7: '#d2bab0', + 8: '#bfa094', + 9: '#a18072', + 10: '#977669', + 11: '#846358', + 12: '#43302b', +} as const + +export const bronzeDark = { + 1: '#191514', + 2: '#1f1917', + 3: '#2a211f', + 4: '#332824', + 5: '#3b2e29', + 6: '#453530', + 7: '#57433c', + 8: '#74594e', + 9: '#a18072', + 10: '#b08c7d', + 11: '#cba393', + 12: '#f9ede7', +} as const + +export const brown = { + 1: '#fefdfc', + 2: '#fcf9f6', + 3: '#f8f1ea', + 4: '#f4e9dd', + 5: '#efddcc', + 6: '#e8cdb5', + 7: '#ddb896', + 8: '#d09e72', + 9: '#ad7f58', + 10: '#a07653', + 11: '#886349', + 12: '#3f2c22', +} as const + +export const brownDark = { + 1: '#1a1513', + 2: '#221813', + 3: '#2e201a', + 4: '#36261e', + 5: '#3e2d22', + 6: '#493528', + 7: '#5c4332', + 8: '#775940', + 9: '#ad7f58', + 10: '#bd8b60', + 11: '#dba16e', + 12: '#faf0e5', +} as const + +export const crimson = { + 1: '#fffcfd', + 2: '#fff7fb', + 3: '#feeff6', + 4: '#fce5f0', + 5: '#f9d8e7', + 6: '#f4c6db', + 7: '#edadc8', + 8: '#e58fb1', + 9: '#e93d82', + 10: '#e03177', + 11: '#d31e66', + 12: '#3d0d1d', +} as const + +export const crimsonDark = { + 1: '#1d1418', + 2: '#27141c', + 3: '#3c1827', + 4: '#481a2d', + 5: '#541b33', + 6: '#641d3b', + 7: '#801d45', + 8: '#ae1955', + 9: '#e93d82', + 10: '#f04f88', + 11: '#f76190', + 12: '#feecf4', +} as const + +export const cyan = { + 1: '#fafdfe', + 2: '#f2fcfd', + 3: '#e7f9fb', + 4: '#d8f3f6', + 5: '#c4eaef', + 6: '#aadee6', + 7: '#84cdda', + 8: '#3db9cf', + 9: '#05a2c2', + 10: '#0894b3', + 11: '#0c7792', + 12: '#04313c', +} as const + +export const cyanDark = { + 1: '#07191d', + 2: '#061e24', + 3: '#072830', + 4: '#07303b', + 5: '#073844', + 6: '#064150', + 7: '#045063', + 8: '#00647d', + 9: '#05a2c2', + 10: '#00b1cc', + 11: '#00c2d7', + 12: '#e1f8fa', +} as const + +export const gold = { + 1: '#fdfdfc', + 2: '#fbf9f2', + 3: '#f5f2e9', + 4: '#eeeadd', + 5: '#e5dfd0', + 6: '#dad1bd', + 7: '#cbbda4', + 8: '#b8a383', + 9: '#978365', + 10: '#8c795d', + 11: '#776750', + 12: '#3b352b', +} as const + +export const goldDark = { + 1: '#171613', + 2: '#1c1a15', + 3: '#26231c', + 4: '#2e2a21', + 5: '#353026', + 6: '#3e382c', + 7: '#504737', + 8: '#6b5d48', + 9: '#978365', + 10: '#a59071', + 11: '#bfa888', + 12: '#f7f4e7', +} as const + +export const grass = { + 1: '#fbfefb', + 2: '#f3fcf3', + 3: '#ebf9eb', + 4: '#dff3df', + 5: '#ceebcf', + 6: '#b7dfba', + 7: '#97cf9c', + 8: '#65ba75', + 9: '#46a758', + 10: '#3d9a50', + 11: '#297c3b', + 12: '#1b311e', +} as const + +export const grassDark = { + 1: '#0d1912', + 2: '#0f1e13', + 3: '#132819', + 4: '#16301d', + 5: '#193921', + 6: '#1d4427', + 7: '#245530', + 8: '#2f6e3b', + 9: '#46a758', + 10: '#55b467', + 11: '#63c174', + 12: '#e5fbeb', +} as const + +export const gray = { + 1: '#fcfcfc', + 2: '#f8f8f8', + 3: '#f3f3f3', + 4: '#ededed', + 5: '#e8e8e8', + 6: '#e2e2e2', + 7: '#dbdbdb', + 8: '#c7c7c7', + 9: '#8f8f8f', + 10: '#858585', + 11: '#6f6f6f', + 12: '#171717', +} as const + +export const grayDark = { + 1: '#161616', + 2: '#1c1c1c', + 3: '#232323', + 4: '#282828', + 5: '#2e2e2e', + 6: '#343434', + 7: '#3e3e3e', + 8: '#505050', + 9: '#707070', + 10: '#7e7e7e', + 11: '#a0a0a0', + 12: '#ededed', +} as const + +export const green = { + 1: '#fbfefc', + 2: '#f2fcf5', + 3: '#e9f9ee', + 4: '#ddf3e4', + 5: '#ccebd7', + 6: '#b4dfc4', + 7: '#92ceac', + 8: '#5bb98c', + 9: '#30a46c', + 10: '#299764', + 11: '#18794e', + 12: '#153226', +} as const + +export const greenDark = { + 1: '#0d1912', + 2: '#0c1f17', + 3: '#0f291e', + 4: '#113123', + 5: '#133929', + 6: '#164430', + 7: '#1b543a', + 8: '#236e4a', + 9: '#30a46c', + 10: '#3cb179', + 11: '#4cc38a', + 12: '#e5fbeb', +} as const + +export const indigo = { + 1: '#fdfdfe', + 2: '#f8faff', + 3: '#f0f4ff', + 4: '#e6edfe', + 5: '#d9e2fc', + 6: '#c6d4f9', + 7: '#aec0f5', + 8: '#8da4ef', + 9: '#3e63dd', + 10: '#3a5ccc', + 11: '#3451b2', + 12: '#101d46', +} as const + +export const indigoDark = { + 1: '#131620', + 2: '#15192d', + 3: '#192140', + 4: '#1c274f', + 5: '#1f2c5c', + 6: '#22346e', + 7: '#273e89', + 8: '#2f4eb2', + 9: '#3e63dd', + 10: '#5373e7', + 11: '#849dff', + 12: '#eef1fd', +} as const + +export const lime = { + 1: '#fcfdfa', + 2: '#f7fcf0', + 3: '#eefadc', + 4: '#e4f7c7', + 5: '#d7f2b0', + 6: '#c9e894', + 7: '#b1d16a', + 8: '#94ba2c', + 9: '#99d52a', + 10: '#93c926', + 11: '#5d770d', + 12: '#263209', +} as const + +export const limeDark = { + 1: '#141807', + 2: '#181d08', + 3: '#1e260d', + 4: '#252e0f', + 5: '#2b3711', + 6: '#344213', + 7: '#415215', + 8: '#536716', + 9: '#99d52a', + 10: '#c4f042', + 11: '#87be22', + 12: '#effbdd', +} as const + +export const mauve = { + 1: '#fdfcfd', + 2: '#f9f8f9', + 3: '#f4f2f4', + 4: '#eeedef', + 5: '#e9e8ea', + 6: '#e4e2e4', + 7: '#dcdbdd', + 8: '#c8c7cb', + 9: '#908e96', + 10: '#86848d', + 11: '#6f6e77', + 12: '#1a1523', +} as const + +export const mauveDark = { + 1: '#161618', + 2: '#1c1c1f', + 3: '#232326', + 4: '#28282c', + 5: '#2e2e32', + 6: '#34343a', + 7: '#3e3e44', + 8: '#504f57', + 9: '#706f78', + 10: '#7e7d86', + 11: '#a09fa6', + 12: '#ededef', +} as const + +export const mint = { + 1: '#f9fefd', + 2: '#effefa', + 3: '#e1fbf4', + 4: '#d2f7ed', + 5: '#c0efe3', + 6: '#a5e4d4', + 7: '#7dd4c0', + 8: '#40c4aa', + 9: '#70e1c8', + 10: '#69d9c1', + 11: '#147d6f', + 12: '#09342e', +} as const + +export const mintDark = { + 1: '#081917', + 2: '#05201e', + 3: '#052926', + 4: '#04312c', + 5: '#033a34', + 6: '#01453d', + 7: '#00564a', + 8: '#006d5b', + 9: '#70e1c8', + 10: '#95f3d9', + 11: '#25d0ab', + 12: '#e7fcf7', +} as const + +export const olive = { + 1: '#fcfdfc', + 2: '#f8faf8', + 3: '#f2f4f2', + 4: '#ecefec', + 5: '#e6e9e6', + 6: '#e0e4e0', + 7: '#d8dcd8', + 8: '#c3c8c2', + 9: '#8b918a', + 10: '#818780', + 11: '#6b716a', + 12: '#141e12', +} as const + +export const oliveDark = { + 1: '#151715', + 2: '#1a1d19', + 3: '#20241f', + 4: '#262925', + 5: '#2b2f2a', + 6: '#313530', + 7: '#3b3f3a', + 8: '#4c514b', + 9: '#687366', + 10: '#778175', + 11: '#9aa299', + 12: '#eceeec', +} as const + +export const orange = { + 1: '#fefcfb', + 2: '#fef8f4', + 3: '#fff1e7', + 4: '#ffe8d7', + 5: '#ffdcc3', + 6: '#ffcca7', + 7: '#ffb381', + 8: '#fa934e', + 9: '#f76808', + 10: '#ed5f00', + 11: '#bd4b00', + 12: '#451e11', +} as const + +export const orangeDark = { + 1: '#1f1206', + 2: '#2b1400', + 3: '#391a03', + 4: '#441f04', + 5: '#4f2305', + 6: '#5f2a06', + 7: '#763205', + 8: '#943e00', + 9: '#f76808', + 10: '#ff802b', + 11: '#ff8b3e', + 12: '#feeadd', +} as const + +export const pink = { + 1: '#fffcfe', + 2: '#fff7fc', + 3: '#feeef8', + 4: '#fce5f3', + 5: '#f9d8ec', + 6: '#f3c6e2', + 7: '#ecadd4', + 8: '#e38ec3', + 9: '#d6409f', + 10: '#d23197', + 11: '#cd1d8d', + 12: '#3b0a2a', +} as const + +export const pinkDark = { + 1: '#1f121b', + 2: '#271421', + 3: '#3a182f', + 4: '#451a37', + 5: '#501b3f', + 6: '#601d48', + 7: '#7a1d5a', + 8: '#a71873', + 9: '#d6409f', + 10: '#e34ba9', + 11: '#f65cb6', + 12: '#feebf7', +} as const + +export const plum = { + 1: '#fefcff', + 2: '#fff8ff', + 3: '#fceffc', + 4: '#f9e5f9', + 5: '#f3d9f4', + 6: '#ebc8ed', + 7: '#dfafe3', + 8: '#cf91d8', + 9: '#ab4aba', + 10: '#a43cb4', + 11: '#9c2bad', + 12: '#340c3b', +} as const + +export const plumDark = { + 1: '#1d131d', + 2: '#251425', + 3: '#341a34', + 4: '#3e1d40', + 5: '#48214b', + 6: '#542658', + 7: '#692d6f', + 8: '#883894', + 9: '#ab4aba', + 10: '#bd54c6', + 11: '#d864d8', + 12: '#fbecfc', +} as const + +export const purple = { + 1: '#fefcfe', + 2: '#fdfaff', + 3: '#f9f1fe', + 4: '#f3e7fc', + 5: '#eddbf9', + 6: '#e3ccf4', + 7: '#d3b4ed', + 8: '#be93e4', + 9: '#8e4ec6', + 10: '#8445bc', + 11: '#793aaf', + 12: '#2b0e44', +} as const + +export const purpleDark = { + 1: '#1b141d', + 2: '#221527', + 3: '#301a3a', + 4: '#3a1e48', + 5: '#432155', + 6: '#4e2667', + 7: '#5f2d84', + 8: '#7938b2', + 9: '#8e4ec6', + 10: '#9d5bd2', + 11: '#bf7af0', + 12: '#f7ecfc', +} as const + +export const red = { + 1: '#fffcfc', + 2: '#fff8f8', + 3: '#ffefef', + 4: '#ffe5e5', + 5: '#fdd8d8', + 6: '#f9c6c6', + 7: '#f3aeaf', + 8: '#eb9091', + 9: '#e5484d', + 10: '#dc3d43', + 11: '#cd2b31', + 12: '#381316', +} as const + +export const redDark = { + 1: '#1f1315', + 2: '#291415', + 3: '#3c181a', + 4: '#481a1d', + 5: '#541b1f', + 6: '#671e22', + 7: '#822025', + 8: '#aa2429', + 9: '#e5484d', + 10: '#f2555a', + 11: '#ff6369', + 12: '#feecee', +} as const + +export const sage = { + 1: '#fbfdfc', + 2: '#f8faf9', + 3: '#f1f4f3', + 4: '#ecefed', + 5: '#e6e9e8', + 6: '#dfe4e2', + 7: '#d7dcda', + 8: '#c2c9c6', + 9: '#8a918e', + 10: '#808784', + 11: '#6a716e', + 12: '#111c18', +} as const + +export const sageDark = { + 1: '#141716', + 2: '#191d1b', + 3: '#1f2421', + 4: '#252a27', + 5: '#2a2f2c', + 6: '#303633', + 7: '#393f3c', + 8: '#4a524e', + 9: '#66736d', + 10: '#75817b', + 11: '#99a29e', + 12: '#eceeed', +} as const + +export const sand = { + 1: '#fdfdfc', + 2: '#f9f9f8', + 3: '#f3f3f2', + 4: '#eeeeec', + 5: '#e9e9e6', + 6: '#e3e3e0', + 7: '#dbdbd7', + 8: '#c8c7c1', + 9: '#90908c', + 10: '#868682', + 11: '#706f6c', + 12: '#1b1b18', +} as const + +export const sandDark = { + 1: '#161615', + 2: '#1c1c1a', + 3: '#232320', + 4: '#282826', + 5: '#2e2e2b', + 6: '#353431', + 7: '#3e3e3a', + 8: '#51504b', + 9: '#717069', + 10: '#7f7e77', + 11: '#a1a09a', + 12: '#ededec', +} as const + +export const sky = { + 1: '#f9feff', + 2: '#f1fcff', + 3: '#e4f9ff', + 4: '#d5f4fd', + 5: '#c1ecf9', + 6: '#a4dff1', + 7: '#79cfea', + 8: '#2ebde5', + 9: '#68ddfd', + 10: '#5fd4f4', + 11: '#0078a1', + 12: '#003242', +} as const + +export const skyDark = { + 1: '#0c1820', + 2: '#071d2a', + 3: '#082636', + 4: '#082d41', + 5: '#08354c', + 6: '#083e59', + 7: '#064b6b', + 8: '#005d85', + 9: '#68ddfd', + 10: '#8ae8ff', + 11: '#2ec8ee', + 12: '#eaf8ff', +} as const + +export const slate = { + 1: '#fbfcfd', + 2: '#f8f9fa', + 3: '#f1f3f5', + 4: '#eceef0', + 5: '#e6e8eb', + 6: '#dfe3e6', + 7: '#d7dbdf', + 8: '#c1c8cd', + 9: '#889096', + 10: '#7e868c', + 11: '#687076', + 12: '#11181c', +} as const + +export const slateDark = { + 1: '#151718', + 2: '#1a1d1e', + 3: '#202425', + 4: '#26292b', + 5: '#2b2f31', + 6: '#313538', + 7: '#3a3f42', + 8: '#4c5155', + 9: '#697177', + 10: '#787f85', + 11: '#9ba1a6', + 12: '#ecedee', +} as const + +export const teal = { + 1: '#fafefd', + 2: '#f1fcfa', + 3: '#e7f9f5', + 4: '#d9f3ee', + 5: '#c7ebe5', + 6: '#afdfd7', + 7: '#8dcec3', + 8: '#53b9ab', + 9: '#12a594', + 10: '#0e9888', + 11: '#067a6f', + 12: '#10302b', +} as const + +export const tealDark = { + 1: '#091915', + 2: '#04201b', + 3: '#062923', + 4: '#07312b', + 5: '#083932', + 6: '#09443c', + 7: '#0b544a', + 8: '#0c6d62', + 9: '#12a594', + 10: '#10b3a3', + 11: '#0ac5b3', + 12: '#e1faf4', +} as const + +export const tomato = { + 1: '#fffcfc', + 2: '#fff8f7', + 3: '#fff0ee', + 4: '#ffe6e2', + 5: '#fdd8d3', + 6: '#fac7be', + 7: '#f3b0a2', + 8: '#ea9280', + 9: '#e54d2e', + 10: '#db4324', + 11: '#ca3214', + 12: '#341711', +} as const + +export const tomatoDark = { + 1: '#1d1412', + 2: '#2a1410', + 3: '#3b1813', + 4: '#481a14', + 5: '#541c15', + 6: '#652016', + 7: '#7f2315', + 8: '#a42a12', + 9: '#e54d2e', + 10: '#ec5e41', + 11: '#f16a50', + 12: '#feefec', +} as const + +export const violet = { + 1: '#fdfcfe', + 2: '#fbfaff', + 3: '#f5f2ff', + 4: '#ede9fe', + 5: '#e4defc', + 6: '#d7cff9', + 7: '#c4b8f3', + 8: '#aa99ec', + 9: '#6e56cf', + 10: '#644fc1', + 11: '#5746af', + 12: '#20134b', +} as const + +export const violetDark = { + 1: '#17151f', + 2: '#1c172b', + 3: '#251e40', + 4: '#2c2250', + 5: '#32275f', + 6: '#392c72', + 7: '#443592', + 8: '#5842c3', + 9: '#6e56cf', + 10: '#7c66dc', + 11: '#9e8cfc', + 12: '#f1eefe', +} as const + +export const yellow = { + 1: '#fdfdf9', + 2: '#fffce8', + 3: '#fffbd1', + 4: '#fff8bb', + 5: '#fef2a4', + 6: '#f9e68c', + 7: '#efd36c', + 8: '#ebbc00', + 9: '#f5d90a', + 10: '#f7ce00', + 11: '#946800', + 12: '#35290f', +} as const + +export const yellowDark = { + 1: '#1c1500', + 2: '#221a00', + 3: '#2c2100', + 4: '#352800', + 5: '#3e3000', + 6: '#493c00', + 7: '#594a05', + 8: '#705d00', + 9: '#f5d90a', + 10: '#ffef5c', + 11: '#f0c000', + 12: '#fffad1', +} as const diff --git a/packages/preset-radix-ui/src/darkColor.ts b/packages/preset-radix-ui/src/darkColor.ts new file mode 100644 index 000000000..5e3f799c8 --- /dev/null +++ b/packages/preset-radix-ui/src/darkColor.ts @@ -0,0 +1,9 @@ +import type { BaseTheme, ColorValue, Context } from '@twind/core' + +export default function darkColor( + section: string, + key: string, + { theme }: Context, +): ColorValue | undefined { + return theme(section, key.replace(/^([a-z]+)($|[.-])/, '$1Dark$2')) as ColorValue +} diff --git a/packages/preset-radix-ui/src/defaultTheme.ts b/packages/preset-radix-ui/src/defaultTheme.ts new file mode 100644 index 000000000..cb005c2d2 --- /dev/null +++ b/packages/preset-radix-ui/src/defaultTheme.ts @@ -0,0 +1,3 @@ +import * as colors from './colors' + +export default { colors } diff --git a/packages/preset-radix-ui/src/index.ts b/packages/preset-radix-ui/src/index.ts new file mode 100644 index 000000000..78229cac1 --- /dev/null +++ b/packages/preset-radix-ui/src/index.ts @@ -0,0 +1,8 @@ +import type { Preset } from '@twind/core' + +import theme from './defaultTheme' +import darkColor from './darkColor' + +export default function presetRadixUI(): Preset { + return { theme, darkColor } +} diff --git a/packages/preset-radix-ui/tsconfig.json b/packages/preset-radix-ui/tsconfig.json new file mode 100644 index 000000000..e7e695a7a --- /dev/null +++ b/packages/preset-radix-ui/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["./src", "./*.d.ts"], + "compilerOptions": { + "baseUrl": "./" + } +} diff --git a/packages/preset-tailwind/base.d.ts b/packages/preset-tailwind/base.d.ts new file mode 100644 index 000000000..b5bb0b841 --- /dev/null +++ b/packages/preset-tailwind/base.d.ts @@ -0,0 +1,4 @@ +// ONLY FOR TYPESCRIPT TO FIND @twind/preset-tailwind/base + +export { default } from './src/base' +export * from './src/base' diff --git a/packages/preset-tailwind/baseTheme.d.ts b/packages/preset-tailwind/baseTheme.d.ts new file mode 100644 index 000000000..2485864bd --- /dev/null +++ b/packages/preset-tailwind/baseTheme.d.ts @@ -0,0 +1,4 @@ +// ONLY FOR TYPESCRIPT TO FIND @twind/preset-tailwind/baseTheme + +export { default } from './src/baseTheme' +export * from './src/baseTheme' diff --git a/packages/preset-tailwind/index.d.ts b/packages/preset-tailwind/index.d.ts index 89470f927..c7159ea20 100644 --- a/packages/preset-tailwind/index.d.ts +++ b/packages/preset-tailwind/index.d.ts @@ -3,6 +3,8 @@ export { default } from './src/index' export * from './src/index' +export * as base from './src/base' +export * as baseTheme from './src/baseTheme' export * as colors from './src/colors' export * as defaultTheme from './src/defaultTheme' export * as rules from './src/rules' diff --git a/packages/preset-tailwind/package.json b/packages/preset-tailwind/package.json index ae0947704..2b1ba67a4 100644 --- a/packages/preset-tailwind/package.json +++ b/packages/preset-tailwind/package.json @@ -18,6 +18,8 @@ "// Each entry is expanded into several bundles (types, esnext, module, script, node, and default)": "", "exports": { ".": "./src/index.ts", + "./base": "./src/base.ts", + "./baseTheme": "./src/baseTheme.ts", "./colors": "./src/colors.ts", "./defaultTheme": "./src/defaultTheme.ts", "./preflight": "./src/preflight.ts", @@ -51,6 +53,21 @@ "path": "dist/defaultTheme.esnext.js", "brotli": true, "limit": "3.5kb" + }, + { + "name": "@twind/preset-tailwind/base", + "path": "dist/base.esnext.js", + "brotli": true, + "limit": "8.6kb", + "ignore": [ + "twind" + ] + }, + { + "name": "@twind/preset-tailwind/baseTheme", + "path": "dist/baseTheme.esnext.js", + "brotli": true, + "limit": "2.5kb" } ], "peerDependencies": { diff --git a/packages/preset-tailwind/src/base.ts b/packages/preset-tailwind/src/base.ts new file mode 100644 index 000000000..972545f6e --- /dev/null +++ b/packages/preset-tailwind/src/base.ts @@ -0,0 +1,53 @@ +/** + * @module @twind/preset-tailwind/base + */ + +import type { BaseTheme, Preset } from '@twind/core' +import type { TailwindTheme } from './types' + +import theme from './baseTheme' +import preflight from './preflight' +import rules from './rules' +import variants from './variants' + +export * from './types' + +export interface TailwindPresetBaseOptions { + colors?: BaseTheme['colors'] + /** Allows to disable to tailwind preflight (default: `false` eg include the tailwind preflight ) */ + disablePreflight?: boolean | undefined +} + +/** + * @experimental + */ +export default function presetTailwindBase({ + colors, + disablePreflight, +}: TailwindPresetBaseOptions = {}): Preset { + return { + // allow other preflight to run + preflight: disablePreflight ? undefined : preflight, + theme: { + ...theme, + colors: { + inherit: 'inherit', + current: 'currentColor', + transparent: 'transparent', + black: '#000', + white: '#fff', + ...colors, + }, + }, + variants, + rules, + finalize(rule) { + // automatically add `content: ''` to before and after so you don’t have to specify it unless you want a different value + if (rule.r.some((r) => /^&::(before|after)$/.test(r)) && !rule.d?.includes('content:')) { + return { ...rule, d: ['content:var(--tw-content)', rule.d].filter(Boolean).join(';') } + } + + return rule + }, + } +} diff --git a/packages/preset-tailwind/src/baseTheme.ts b/packages/preset-tailwind/src/baseTheme.ts new file mode 100644 index 000000000..7607ac4af --- /dev/null +++ b/packages/preset-tailwind/src/baseTheme.ts @@ -0,0 +1,897 @@ +/** + * @module @twind/preset-tailwind/baseTheme + */ + +import type { ThemeSection, ThemeSectionResolver } from '@twind/core' +import type { TailwindTheme } from './types' + +export type OmitedSections = + | 'aria' + | 'backgroundPosition' + | 'colors' + | 'container' + | 'cursor' + | 'data' + | 'gridColumnEnd' + | 'gridColumnStart' + | 'gridRowEnd' + | 'gridRowStart' + | 'listStyleType' + | 'objectPosition' + | 'supports' + | 'transformOrigin' + +export type StableSections = + | 'screens' + | 'columns' + | 'spacing' + | 'durations' + | 'borderRadius' + | 'borderWidth' + | 'boxShadow' + | 'fontFamily' + | 'fontSize' + +export type BaseTheme = { + [Section in StableSections]: Section extends 'fontSize' + ? { + xs: [size: string, lineHeight: string] + sm: [size: string, lineHeight: string] + base: [size: string, lineHeight: string] + lg: [size: string, lineHeight: string] + xl: [size: string, lineHeight: string] + '2xl': [size: string, lineHeight: string] + '3xl': [size: string, lineHeight: string] + '4xl': [size: string, lineHeight: string] + '5xl': [size: string, lineHeight: string] + '6xl': [size: string, lineHeight: string] + '7xl': [size: string, lineHeight: string] + '8xl': [size: string, lineHeight: string] + '9xl': [size: string, lineHeight: string] + } + : TailwindTheme[Section] +} & { + [Section in Exclude]: ThemeSection< + TailwindTheme[Section], + TailwindTheme + > +} & { + [Section in OmitedSections]?: ThemeSection +} + +/** + * @experimental + */ +const theme: BaseTheme = { + screens: { + sm: '640px', + md: '768px', + lg: '1024px', + xl: '1280px', + '2xl': '1536px', + }, + + columns: { + auto: 'auto', + // Handled by plugin, + // 1: '1', + // 2: '2', + // 3: '3', + // 4: '4', + // 5: '5', + // 6: '6', + // 7: '7', + // 8: '8', + // 9: '9', + // 10: '10', + // 11: '11', + // 12: '12', + '3xs': '16rem', + '2xs': '18rem', + xs: '20rem', + sm: '24rem', + md: '28rem', + lg: '32rem', + xl: '36rem', + '2xl': '42rem', + '3xl': '48rem', + '4xl': '56rem', + '5xl': '64rem', + '6xl': '72rem', + '7xl': '80rem', + }, + + spacing: { + px: '1px', + 0: '0px', + .../* #__PURE__ */ linear(4, 'rem', 4, 0.5, 0.5), + // 0.5: '0.125rem', + // 1: '0.25rem', + // 1.5: '0.375rem', + // 2: '0.5rem', + // 2.5: '0.625rem', + // 3: '0.75rem', + // 3.5: '0.875rem', + // 4: '1rem', + .../* #__PURE__ */ linear(12, 'rem', 4, 5), + // 5: '1.25rem', + // 6: '1.5rem', + // 7: '1.75rem', + // 8: '2rem', + // 9: '2.25rem', + // 10: '2.5rem', + // 11: '2.75rem', + // 12: '3rem', + 14: '3.5rem', + .../* #__PURE__ */ linear(64, 'rem', 4, 16, 4), + // 16: '4rem', + // 20: '5rem', + // 24: '6rem', + // 28: '7rem', + // 32: '8rem', + // 36: '9rem', + // 40: '10rem', + // 44: '11rem', + // 48: '12rem', + // 52: '13rem', + // 56: '14rem', + // 60: '15rem', + // 64: '16rem', + 72: '18rem', + 80: '20rem', + 96: '24rem', + }, + + durations: { + 75: '75ms', + 100: '100ms', + 150: '150ms', + 200: '200ms', + 300: '300ms', + 500: '500ms', + 700: '700ms', + 1000: '1000ms', + }, + + animation: { + none: 'none', + spin: 'spin 1s linear infinite', + ping: 'ping 1s cubic-bezier(0,0,0.2,1) infinite', + pulse: 'pulse 2s cubic-bezier(0.4,0,0.6,1) infinite', + bounce: 'bounce 1s infinite', + }, + + aspectRatio: { + auto: 'auto', + square: '1/1', + video: '16/9', + }, + + backdropBlur: /* #__PURE__ */ alias('blur'), + backdropBrightness: /* #__PURE__ */ alias('brightness'), + backdropContrast: /* #__PURE__ */ alias('contrast'), + backdropGrayscale: /* #__PURE__ */ alias('grayscale'), + backdropHueRotate: /* #__PURE__ */ alias('hueRotate'), + backdropInvert: /* #__PURE__ */ alias('invert'), + backdropOpacity: /* #__PURE__ */ alias('opacity'), + backdropSaturate: /* #__PURE__ */ alias('saturate'), + backdropSepia: /* #__PURE__ */ alias('sepia'), + + backgroundColor: /* #__PURE__ */ alias('colors'), + backgroundImage: { + none: 'none', + // These are built-in + // 'gradient-to-t': 'linear-gradient(to top, var(--tw-gradient-stops))', + // 'gradient-to-tr': 'linear-gradient(to top right, var(--tw-gradient-stops))', + // 'gradient-to-r': 'linear-gradient(to right, var(--tw-gradient-stops))', + // 'gradient-to-br': 'linear-gradient(to bottom right, var(--tw-gradient-stops))', + // 'gradient-to-b': 'linear-gradient(to bottom, var(--tw-gradient-stops))', + // 'gradient-to-bl': 'linear-gradient(to bottom left, var(--tw-gradient-stops))', + // 'gradient-to-l': 'linear-gradient(to left, var(--tw-gradient-stops))', + // 'gradient-to-tl': 'linear-gradient(to top left, var(--tw-gradient-stops))', + }, + backgroundOpacity: /* #__PURE__ */ alias('opacity'), + // backgroundPosition: { + // // The following are already handled by the plugin: + // // center, right, left, bottom, top + // // 'bottom-10px-right-20px' -> bottom 10px right 20px + // }, + backgroundSize: { + auto: 'auto', + cover: 'cover', + contain: 'contain', + }, + blur: { + none: 'none', + 0: '0', + sm: '4px', + DEFAULT: '8px', + md: '12px', + lg: '16px', + xl: '24px', + '2xl': '40px', + '3xl': '64px', + }, + brightness: { + .../* #__PURE__ */ linear(200, '', 100, 0, 50), + // 0: '0', + // 50: '.5', + // 150: '1.5', + // 200: '2', + + .../* #__PURE__ */ linear(110, '', 100, 90, 5), + // 90: '.9', + // 95: '.95', + // 100: '1', + // 105: '1.05', + // 110: '1.1', + 75: '0.75', + 125: '1.25', + }, + borderColor: ({ theme }) => ({ + DEFAULT: theme('colors.gray.200', 'currentColor'), + ...theme('colors'), + }), + borderOpacity: /* #__PURE__ */ alias('opacity'), + borderRadius: { + none: '0px', + sm: '0.125rem', + DEFAULT: '0.25rem', + md: '0.375rem', + lg: '0.5rem', + xl: '0.75rem', + '2xl': '1rem', + '3xl': '1.5rem', + '1/2': '50%', + full: '9999px', + }, + borderSpacing: /* #__PURE__ */ alias('spacing'), + borderWidth: { + DEFAULT: '1px', + .../* #__PURE__ */ exponential(8, 'px'), + // 0: '0px', + // 2: '2px', + // 4: '4px', + // 8: '8px', + }, + boxShadow: { + sm: '0 1px 2px 0 rgba(0,0,0,0.05)', + DEFAULT: '0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px -1px rgba(0,0,0,0.1)', + md: '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)', + lg: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)', + xl: '0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.1)', + '2xl': '0 25px 50px -12px rgba(0,0,0,0.25)', + inner: 'inset 0 2px 4px 0 rgba(0,0,0,0.05)', + none: '0 0 #0000', + }, + boxShadowColor: alias('colors'), + // container: {}, + // cursor: { + // // Default values are handled by plugin + // }, + caretColor: /* #__PURE__ */ alias('colors'), + accentColor: ({ theme }) => ({ + auto: 'auto', + ...theme('colors'), + }), + contrast: { + .../* #__PURE__ */ linear(200, '', 100, 0, 50), + // 0: '0', + // 50: '.5', + // 150: '1.5', + // 200: '2', + 75: '0.75', + 125: '1.25', + }, + content: { + none: 'none', + }, + divideColor: /* #__PURE__ */ alias('borderColor'), + divideOpacity: /* #__PURE__ */ alias('borderOpacity'), + divideWidth: /* #__PURE__ */ alias('borderWidth'), + dropShadow: { + sm: '0 1px 1px rgba(0,0,0,0.05)', + DEFAULT: ['0 1px 2px rgba(0,0,0,0.1)', '0 1px 1px rgba(0,0,0,0.06)'], + md: ['0 4px 3px rgba(0,0,0,0.07)', '0 2px 2px rgba(0,0,0,0.06)'], + lg: ['0 10px 8px rgba(0,0,0,0.04)', '0 4px 3px rgba(0,0,0,0.1)'], + xl: ['0 20px 13px rgba(0,0,0,0.03)', '0 8px 5px rgba(0,0,0,0.08)'], + '2xl': '0 25px 25px rgba(0,0,0,0.15)', + none: '0 0 #0000', + }, + fill: ({ theme }) => ({ + ...theme('colors'), + none: 'none', + }), + grayscale: { + DEFAULT: '100%', + 0: '0', + }, + hueRotate: { + 0: '0deg', + 15: '15deg', + 30: '30deg', + 60: '60deg', + 90: '90deg', + 180: '180deg', + }, + invert: { + DEFAULT: '100%', + 0: '0', + }, + flex: { + 1: '1 1 0%', + auto: '1 1 auto', + initial: '0 1 auto', + none: 'none', + }, + flexBasis: ({ theme }) => ({ + ...theme('spacing'), + ...ratios(2, 6), + // '1/2': '50%', + // '1/3': '33.333333%', + // '2/3': '66.666667%', + // '1/4': '25%', + // '2/4': '50%', + // '3/4': '75%', + // '1/5': '20%', + // '2/5': '40%', + // '3/5': '60%', + // '4/5': '80%', + // '1/6': '16.666667%', + // '2/6': '33.333333%', + // '3/6': '50%', + // '4/6': '66.666667%', + // '5/6': '83.333333%', + + ...ratios(12, 12), + // '1/12': '8.333333%', + // '2/12': '16.666667%', + // '3/12': '25%', + // '4/12': '33.333333%', + // '5/12': '41.666667%', + // '6/12': '50%', + // '7/12': '58.333333%', + // '8/12': '66.666667%', + // '9/12': '75%', + // '10/12': '83.333333%', + // '11/12': '91.666667%', + + auto: 'auto', + full: '100%', + }), + flexGrow: { + DEFAULT: 1, + 0: 0, + }, + flexShrink: { + DEFAULT: 1, + 0: 0, + }, + fontFamily: { + sans: 'ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"'.split( + ',', + ), + serif: 'ui-serif,Georgia,Cambria,"Times New Roman",Times,serif'.split(','), + mono: 'ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace'.split( + ',', + ), + }, + fontSize: { + xs: ['0.75rem', '1rem'], + sm: ['0.875rem', '1.25rem'], + base: ['1rem', '1.5rem'], + lg: ['1.125rem', '1.75rem'], + xl: ['1.25rem', '1.75rem'], + '2xl': ['1.5rem', '2rem'], + '3xl': ['1.875rem', '2.25rem'], + '4xl': ['2.25rem', '2.5rem'], + '5xl': ['3rem', '1'], + '6xl': ['3.75rem', '1'], + '7xl': ['4.5rem', '1'], + '8xl': ['6rem', '1'], + '9xl': ['8rem', '1'], + }, + fontWeight: { + thin: '100', + extralight: '200', + light: '300', + normal: '400', + medium: '500', + semibold: '600', + bold: '700', + extrabold: '800', + black: '900', + }, + gap: /* #__PURE__ */ alias('spacing'), + gradientColorStops: /* #__PURE__ */ alias('colors'), + gridAutoColumns: { + auto: 'auto', + min: 'min-content', + max: 'max-content', + fr: 'minmax(0,1fr)', + }, + gridAutoRows: { + auto: 'auto', + min: 'min-content', + max: 'max-content', + fr: 'minmax(0,1fr)', + }, + gridColumn: { + // span-X is handled by the plugin: span-1 -> span 1 / span 1 + auto: 'auto', + 'span-full': '1 / -1', + }, + // gridColumnEnd: { + // // Defaults handled by plugin + // }, + // gridColumnStart: { + // // Defaults handled by plugin + // }, + gridRow: { + // span-X is handled by the plugin: span-1 -> span 1 / span 1 + auto: 'auto', + 'span-full': '1 / -1', + }, + // gridRowStart: { + // // Defaults handled by plugin + // }, + // gridRowEnd: { + // // Defaults handled by plugin + // }, + gridTemplateColumns: { + // numbers are handled by the plugin: 1 -> repeat(1, minmax(0, 1fr)) + none: 'none', + }, + gridTemplateRows: { + // numbers are handled by the plugin: 1 -> repeat(1, minmax(0, 1fr)) + none: 'none', + }, + height: ({ theme }) => ({ + ...theme('spacing'), + ...ratios(2, 6), + // '1/2': '50%', + // '1/3': '33.333333%', + // '2/3': '66.666667%', + // '1/4': '25%', + // '2/4': '50%', + // '3/4': '75%', + // '1/5': '20%', + // '2/5': '40%', + // '3/5': '60%', + // '4/5': '80%', + // '1/6': '16.666667%', + // '2/6': '33.333333%', + // '3/6': '50%', + // '4/6': '66.666667%', + // '5/6': '83.333333%', + min: 'min-content', + max: 'max-content', + fit: 'fit-content', + auto: 'auto', + full: '100%', + screen: '100vh', + }), + inset: ({ theme }) => ({ + ...theme('spacing'), + ...ratios(2, 4), + // '1/2': '50%', + // '1/3': '33.333333%', + // '2/3': '66.666667%', + // '1/4': '25%', + // '2/4': '50%', + // '3/4': '75%', + auto: 'auto', + full: '100%', + }), + keyframes: { + spin: { + from: { + transform: 'rotate(0deg)', + }, + to: { + transform: 'rotate(360deg)', + }, + }, + ping: { + '0%': { + transform: 'scale(1)', + opacity: '1', + }, + '75%,100%': { + transform: 'scale(2)', + opacity: '0', + }, + }, + pulse: { + '0%,100%': { + opacity: '1', + }, + '50%': { + opacity: '.5', + }, + }, + bounce: { + '0%, 100%': { + transform: 'translateY(-25%)', + animationTimingFunction: 'cubic-bezier(0.8,0,1,1)', + }, + '50%': { + transform: 'none', + animationTimingFunction: 'cubic-bezier(0,0,0.2,1)', + }, + }, + }, + letterSpacing: { + tighter: '-0.05em', + tight: '-0.025em', + normal: '0em', + wide: '0.025em', + wider: '0.05em', + widest: '0.1em', + }, + lineHeight: { + .../* #__PURE__ */ linear(10, 'rem', 4, 3), + // 3: '.75rem', + // 4: '1rem', + // 5: '1.25rem', + // 6: '1.5rem', + // 7: '1.75rem', + // 8: '2rem', + // 9: '2.25rem', + // 10: '2.5rem', + none: '1', + tight: '1.25', + snug: '1.375', + normal: '1.5', + relaxed: '1.625', + loose: '2', + }, + // listStyleType: { + // // Defaults handled by plugin + // }, + margin: ({ theme }) => ({ + auto: 'auto', + ...theme('spacing'), + }), + maxHeight: ({ theme }) => ({ + full: '100%', + min: 'min-content', + max: 'max-content', + fit: 'fit-content', + screen: '100vh', + ...theme('spacing'), + }), + maxWidth: ({ theme, breakpoints }) => ({ + ...breakpoints(theme('screens')), + none: 'none', + 0: '0rem', + xs: '20rem', + sm: '24rem', + md: '28rem', + lg: '32rem', + xl: '36rem', + '2xl': '42rem', + '3xl': '48rem', + '4xl': '56rem', + '5xl': '64rem', + '6xl': '72rem', + '7xl': '80rem', + full: '100%', + min: 'min-content', + max: 'max-content', + fit: 'fit-content', + prose: '65ch', + }), + minHeight: { + 0: '0px', + full: '100%', + min: 'min-content', + max: 'max-content', + fit: 'fit-content', + screen: '100vh', + }, + minWidth: { + 0: '0px', + full: '100%', + min: 'min-content', + max: 'max-content', + fit: 'fit-content', + }, + // objectPosition: { + // // The plugins joins all arguments by default + // }, + opacity: { + .../* #__PURE__ */ linear(100, '', 100, 0, 10), + // 0: '0', + // 10: '0.1', + // 20: '0.2', + // 30: '0.3', + // 40: '0.4', + // 60: '0.6', + // 70: '0.7', + // 80: '0.8', + // 90: '0.9', + // 100: '1', + 5: '0.05', + 25: '0.25', + 75: '0.75', + 95: '0.95', + }, + order: { + // Handled by plugin + // 1: '1', + // 2: '2', + // 3: '3', + // 4: '4', + // 5: '5', + // 6: '6', + // 7: '7', + // 8: '8', + // 9: '9', + // 10: '10', + // 11: '11', + // 12: '12', + first: '-9999', + last: '9999', + none: '0', + }, + padding: /* #__PURE__ */ alias('spacing'), + placeholderColor: /* #__PURE__ */ alias('colors'), + placeholderOpacity: /* #__PURE__ */ alias('opacity'), + outlineColor: /* #__PURE__ */ alias('colors'), + outlineOffset: /* #__PURE__ */ exponential(8, 'px'), + // 0: '0px', + // 1: '1px', + // 2: '2px', + // 4: '4px', + // 8: '8px',, + outlineWidth: /* #__PURE__ */ exponential(8, 'px'), + // 0: '0px', + // 1: '1px', + // 2: '2px', + // 4: '4px', + // 8: '8px',, + ringColor: ({ theme }) => ({ + ...theme('colors'), + DEFAULT: '#3b82f6', + }), + ringOffsetColor: /* #__PURE__ */ alias('colors'), + ringOffsetWidth: /* #__PURE__ */ exponential(8, 'px'), + // 0: '0px', + // 1: '1px', + // 2: '2px', + // 4: '4px', + // 8: '8px',, + ringOpacity: ({ theme }) => ({ + ...theme('opacity'), + DEFAULT: '0.5', + }), + ringWidth: { + DEFAULT: '3px', + .../* #__PURE__ */ exponential(8, 'px'), + // 0: '0px', + // 1: '1px', + // 2: '2px', + // 4: '4px', + // 8: '8px', + }, + rotate: { + .../* #__PURE__ */ exponential(2, 'deg'), + // 0: '0deg', + // 1: '1deg', + // 2: '2deg', + .../* #__PURE__ */ exponential(12, 'deg', 3), + // 3: '3deg', + // 6: '6deg', + // 12: '12deg', + .../* #__PURE__ */ exponential(180, 'deg', 45), + // 45: '45deg', + // 90: '90deg', + // 180: '180deg', + }, + saturate: /* #__PURE__ */ linear(200, '', 100, 0, 50), + // 0: '0', + // 50: '.5', + // 100: '1', + // 150: '1.5', + // 200: '2', + scale: { + .../* #__PURE__ */ linear(150, '', 100, 0, 50), + // 0: '0', + // 50: '.5', + // 150: '1.5', + .../* #__PURE__ */ linear(110, '', 100, 90, 5), + // 90: '.9', + // 95: '.95', + // 100: '1', + // 105: '1.05', + // 110: '1.1', + 75: '0.75', + 125: '1.25', + }, + scrollMargin: /* #__PURE__ */ alias('spacing'), + scrollPadding: /* #__PURE__ */ alias('spacing'), + sepia: { + 0: '0', + DEFAULT: '100%', + }, + skew: { + .../* #__PURE__ */ exponential(2, 'deg'), + // 0: '0deg', + // 1: '1deg', + // 2: '2deg', + .../* #__PURE__ */ exponential(12, 'deg', 3), + // 3: '3deg', + // 6: '6deg', + // 12: '12deg', + }, + space: /* #__PURE__ */ alias('spacing'), + stroke: ({ theme }) => ({ + ...theme('colors'), + none: 'none', + }), + strokeWidth: /* #__PURE__ */ linear(2), + // 0: '0', + // 1: '1', + // 2: '2',, + textColor: /* #__PURE__ */ alias('colors'), + textDecorationColor: /* #__PURE__ */ alias('colors'), + textDecorationThickness: { + 'from-font': 'from-font', + auto: 'auto', + .../* #__PURE__ */ exponential(8, 'px'), + // 0: '0px', + // 1: '1px', + // 2: '2px', + // 4: '4px', + // 8: '8px', + }, + textUnderlineOffset: { + auto: 'auto', + .../* #__PURE__ */ exponential(8, 'px'), + // 0: '0px', + // 1: '1px', + // 2: '2px', + // 4: '4px', + // 8: '8px', + }, + textIndent: /* #__PURE__ */ alias('spacing'), + textOpacity: /* #__PURE__ */ alias('opacity'), + // transformOrigin: { + // // The following are already handled by the plugin: + // // center, right, left, bottom, top + // // 'bottom-10px-right-20px' -> bottom 10px right 20px + // }, + transitionDuration: ({ theme }) => ({ + ...theme('durations'), + DEFAULT: '150ms', + }), + transitionDelay: /* #__PURE__ */ alias('durations'), + transitionProperty: { + none: 'none', + all: 'all', + DEFAULT: + 'color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter', + colors: 'color,background-color,border-color,text-decoration-color,fill,stroke', + opacity: 'opacity', + shadow: 'box-shadow', + transform: 'transform', + }, + transitionTimingFunction: { + DEFAULT: 'cubic-bezier(0.4,0,0.2,1)', + linear: 'linear', + in: 'cubic-bezier(0.4,0,1,1)', + out: 'cubic-bezier(0,0,0.2,1)', + 'in-out': 'cubic-bezier(0.4,0,0.2,1)', + }, + translate: ({ theme }) => ({ + ...theme('spacing'), + ...ratios(2, 4), + // '1/2': '50%', + // '1/3': '33.333333%', + // '2/3': '66.666667%', + // '1/4': '25%', + // '2/4': '50%', + // '3/4': '75%', + full: '100%', + }), + width: ({ theme }) => ({ + min: 'min-content', + max: 'max-content', + fit: 'fit-content', + screen: '100vw', + ...theme('flexBasis'), + }), + willChange: { + scroll: 'scroll-position', + // other options handled by rules + // auto: 'auto', + // contents: 'contents', + // transform: 'transform', + }, + zIndex: { + .../* #__PURE__ */ linear(50, '', 1, 0, 10), + // 0: '0', + // 10: '10', + // 20: '20', + // 30: '30', + // 40: '40', + // 50: '50', + auto: 'auto', + }, +} + +export default theme + +// '1/2': '50%', +// '1/3': '33.333333%', +// '2/3': '66.666667%', +// '1/4': '25%', +// '2/4': '50%', +// '3/4': '75%', +// '1/5': '20%', +// '2/5': '40%', +// '3/5': '60%', +// '4/5': '80%', +// '1/6': '16.666667%', +// '2/6': '33.333333%', +// '3/6': '50%', +// '4/6': '66.666667%', +// '5/6': '83.333333%', +function ratios(start: number, end: number): Record { + const result: Record = {} + + do { + // XXX: using var to avoid strange bug when generating cjs where `= 1` is removed + // eslint-disable-next-line no-var + for (var dividend = 1; dividend < start; dividend++) { + result[`${dividend}/${start}`] = Number(((dividend / start) * 100).toFixed(6)) + '%' + } + } while (++start <= end) + + return result +} + +// 0: '0px', +// 2: '2px', +// 4: '4px', +// 8: '8px', +function exponential(stop: number, unit: string, start = 0): Record { + const result: Record = {} + + for (; start <= stop; start = start * 2 || 1) { + result[start] = start + unit + } + + return result +} + +// 3: '.75rem', +// 4: '1rem', +// 5: '1.25rem', +// 6: '1.5rem', +// 7: '1.75rem', +// 8: '2rem', +// 9: '2.25rem', +// 10: '2.5rem', +function linear( + stop: number, + unit = '', + divideBy = 1, + start = 0, + step = 1, + result: Record = {}, + // eslint-disable-next-line max-params +): Record { + for (; start <= stop; start += step) { + result[start] = start / divideBy + unit + } + + return result +} + +function alias
( + section: Section, +): ThemeSectionResolver { + return ({ theme }) => theme(section) +} diff --git a/packages/preset-tailwind/src/colors.ts b/packages/preset-tailwind/src/colors.ts index 9eceb3bde..506c6aa90 100644 --- a/packages/preset-tailwind/src/colors.ts +++ b/packages/preset-tailwind/src/colors.ts @@ -4,12 +4,6 @@ * @module @twind/preset-tailwind/colors */ -export const inherit = 'inherit' -export const current = 'currentColor' -export const transparent = 'transparent' -export const black = '#000' -export const white = '#fff' - export const slate = { 50: '#f8fafc', 100: '#f1f5f9', diff --git a/packages/preset-tailwind/src/defaultTheme.ts b/packages/preset-tailwind/src/defaultTheme.ts index fd705fdac..1d8d4b448 100644 --- a/packages/preset-tailwind/src/defaultTheme.ts +++ b/packages/preset-tailwind/src/defaultTheme.ts @@ -2,899 +2,14 @@ * @module @twind/preset-tailwind/defaultTheme */ -import type { ThemeSection, ThemeSectionResolver } from '@twind/core' -import type { TailwindTheme } from './types' +import type { BaseTheme } from './baseTheme' import * as colors from './colors' -export type OmitedSections = - | 'aria' - | 'backgroundPosition' - | 'container' - | 'cursor' - | 'data' - | 'gridColumnEnd' - | 'gridColumnStart' - | 'gridRowEnd' - | 'gridRowStart' - | 'listStyleType' - | 'objectPosition' - | 'supports' - | 'transformOrigin' +import baseTheme from './baseTheme' -export type StableSections = - | 'screens' - | 'columns' - | 'spacing' - | 'durations' - | 'borderRadius' - | 'borderWidth' - | 'boxShadow' - | 'fontFamily' - | 'fontSize' +export type DefaultTheme = { colors: typeof colors } & BaseTheme -export type DefaultTheme = { - colors: typeof colors -} & { - [Section in StableSections]: Section extends 'fontSize' - ? { - xs: [size: string, lineHeight: string] - sm: [size: string, lineHeight: string] - base: [size: string, lineHeight: string] - lg: [size: string, lineHeight: string] - xl: [size: string, lineHeight: string] - '2xl': [size: string, lineHeight: string] - '3xl': [size: string, lineHeight: string] - '4xl': [size: string, lineHeight: string] - '5xl': [size: string, lineHeight: string] - '6xl': [size: string, lineHeight: string] - '7xl': [size: string, lineHeight: string] - '8xl': [size: string, lineHeight: string] - '9xl': [size: string, lineHeight: string] - } - : TailwindTheme[Section] -} & { - [Section in Exclude< - keyof TailwindTheme, - 'colors' | StableSections | OmitedSections - >]: ThemeSection -} & { - [Section in OmitedSections]?: ThemeSection -} - -// TODO use named exports -const theme: DefaultTheme = { - screens: { - sm: '640px', - md: '768px', - lg: '1024px', - xl: '1280px', - '2xl': '1536px', - }, - - colors, - - columns: { - auto: 'auto', - // Handled by plugin, - // 1: '1', - // 2: '2', - // 3: '3', - // 4: '4', - // 5: '5', - // 6: '6', - // 7: '7', - // 8: '8', - // 9: '9', - // 10: '10', - // 11: '11', - // 12: '12', - '3xs': '16rem', - '2xs': '18rem', - xs: '20rem', - sm: '24rem', - md: '28rem', - lg: '32rem', - xl: '36rem', - '2xl': '42rem', - '3xl': '48rem', - '4xl': '56rem', - '5xl': '64rem', - '6xl': '72rem', - '7xl': '80rem', - }, - - spacing: { - px: '1px', - 0: '0px', - .../* #__PURE__ */ linear(4, 'rem', 4, 0.5, 0.5), - // 0.5: '0.125rem', - // 1: '0.25rem', - // 1.5: '0.375rem', - // 2: '0.5rem', - // 2.5: '0.625rem', - // 3: '0.75rem', - // 3.5: '0.875rem', - // 4: '1rem', - .../* #__PURE__ */ linear(12, 'rem', 4, 5), - // 5: '1.25rem', - // 6: '1.5rem', - // 7: '1.75rem', - // 8: '2rem', - // 9: '2.25rem', - // 10: '2.5rem', - // 11: '2.75rem', - // 12: '3rem', - 14: '3.5rem', - .../* #__PURE__ */ linear(64, 'rem', 4, 16, 4), - // 16: '4rem', - // 20: '5rem', - // 24: '6rem', - // 28: '7rem', - // 32: '8rem', - // 36: '9rem', - // 40: '10rem', - // 44: '11rem', - // 48: '12rem', - // 52: '13rem', - // 56: '14rem', - // 60: '15rem', - // 64: '16rem', - 72: '18rem', - 80: '20rem', - 96: '24rem', - }, - - durations: { - 75: '75ms', - 100: '100ms', - 150: '150ms', - 200: '200ms', - 300: '300ms', - 500: '500ms', - 700: '700ms', - 1000: '1000ms', - }, - - animation: { - none: 'none', - spin: 'spin 1s linear infinite', - ping: 'ping 1s cubic-bezier(0,0,0.2,1) infinite', - pulse: 'pulse 2s cubic-bezier(0.4,0,0.6,1) infinite', - bounce: 'bounce 1s infinite', - }, - - aspectRatio: { - auto: 'auto', - square: '1/1', - video: '16/9', - }, - - backdropBlur: /* #__PURE__ */ alias('blur'), - backdropBrightness: /* #__PURE__ */ alias('brightness'), - backdropContrast: /* #__PURE__ */ alias('contrast'), - backdropGrayscale: /* #__PURE__ */ alias('grayscale'), - backdropHueRotate: /* #__PURE__ */ alias('hueRotate'), - backdropInvert: /* #__PURE__ */ alias('invert'), - backdropOpacity: /* #__PURE__ */ alias('opacity'), - backdropSaturate: /* #__PURE__ */ alias('saturate'), - backdropSepia: /* #__PURE__ */ alias('sepia'), - - backgroundColor: /* #__PURE__ */ alias('colors'), - backgroundImage: { - none: 'none', - // These are built-in - // 'gradient-to-t': 'linear-gradient(to top, var(--tw-gradient-stops))', - // 'gradient-to-tr': 'linear-gradient(to top right, var(--tw-gradient-stops))', - // 'gradient-to-r': 'linear-gradient(to right, var(--tw-gradient-stops))', - // 'gradient-to-br': 'linear-gradient(to bottom right, var(--tw-gradient-stops))', - // 'gradient-to-b': 'linear-gradient(to bottom, var(--tw-gradient-stops))', - // 'gradient-to-bl': 'linear-gradient(to bottom left, var(--tw-gradient-stops))', - // 'gradient-to-l': 'linear-gradient(to left, var(--tw-gradient-stops))', - // 'gradient-to-tl': 'linear-gradient(to top left, var(--tw-gradient-stops))', - }, - backgroundOpacity: /* #__PURE__ */ alias('opacity'), - // backgroundPosition: { - // // The following are already handled by the plugin: - // // center, right, left, bottom, top - // // 'bottom-10px-right-20px' -> bottom 10px right 20px - // }, - backgroundSize: { - auto: 'auto', - cover: 'cover', - contain: 'contain', - }, - blur: { - none: 'none', - 0: '0', - sm: '4px', - DEFAULT: '8px', - md: '12px', - lg: '16px', - xl: '24px', - '2xl': '40px', - '3xl': '64px', - }, - brightness: { - .../* #__PURE__ */ linear(200, '', 100, 0, 50), - // 0: '0', - // 50: '.5', - // 150: '1.5', - // 200: '2', - - .../* #__PURE__ */ linear(110, '', 100, 90, 5), - // 90: '.9', - // 95: '.95', - // 100: '1', - // 105: '1.05', - // 110: '1.1', - 75: '0.75', - 125: '1.25', - }, - borderColor: ({ theme }) => ({ - DEFAULT: theme('colors.gray.200', 'currentColor'), - ...theme('colors'), - }), - borderOpacity: /* #__PURE__ */ alias('opacity'), - borderRadius: { - none: '0px', - sm: '0.125rem', - DEFAULT: '0.25rem', - md: '0.375rem', - lg: '0.5rem', - xl: '0.75rem', - '2xl': '1rem', - '3xl': '1.5rem', - '1/2': '50%', - full: '9999px', - }, - borderSpacing: /* #__PURE__ */ alias('spacing'), - borderWidth: { - DEFAULT: '1px', - .../* #__PURE__ */ exponential(8, 'px'), - // 0: '0px', - // 2: '2px', - // 4: '4px', - // 8: '8px', - }, - boxShadow: { - sm: '0 1px 2px 0 rgba(0,0,0,0.05)', - DEFAULT: '0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px -1px rgba(0,0,0,0.1)', - md: '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)', - lg: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)', - xl: '0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.1)', - '2xl': '0 25px 50px -12px rgba(0,0,0,0.25)', - inner: 'inset 0 2px 4px 0 rgba(0,0,0,0.05)', - none: '0 0 #0000', - }, - boxShadowColor: alias('colors'), - // container: {}, - // cursor: { - // // Default values are handled by plugin - // }, - caretColor: /* #__PURE__ */ alias('colors'), - accentColor: ({ theme }) => ({ - auto: 'auto', - ...theme('colors'), - }), - contrast: { - .../* #__PURE__ */ linear(200, '', 100, 0, 50), - // 0: '0', - // 50: '.5', - // 150: '1.5', - // 200: '2', - 75: '0.75', - 125: '1.25', - }, - content: { - none: 'none', - }, - divideColor: /* #__PURE__ */ alias('borderColor'), - divideOpacity: /* #__PURE__ */ alias('borderOpacity'), - divideWidth: /* #__PURE__ */ alias('borderWidth'), - dropShadow: { - sm: '0 1px 1px rgba(0,0,0,0.05)', - DEFAULT: ['0 1px 2px rgba(0,0,0,0.1)', '0 1px 1px rgba(0,0,0,0.06)'], - md: ['0 4px 3px rgba(0,0,0,0.07)', '0 2px 2px rgba(0,0,0,0.06)'], - lg: ['0 10px 8px rgba(0,0,0,0.04)', '0 4px 3px rgba(0,0,0,0.1)'], - xl: ['0 20px 13px rgba(0,0,0,0.03)', '0 8px 5px rgba(0,0,0,0.08)'], - '2xl': '0 25px 25px rgba(0,0,0,0.15)', - none: '0 0 #0000', - }, - fill: ({ theme }) => ({ - ...theme('colors'), - none: 'none', - }), - grayscale: { - DEFAULT: '100%', - 0: '0', - }, - hueRotate: { - 0: '0deg', - 15: '15deg', - 30: '30deg', - 60: '60deg', - 90: '90deg', - 180: '180deg', - }, - invert: { - DEFAULT: '100%', - 0: '0', - }, - flex: { - 1: '1 1 0%', - auto: '1 1 auto', - initial: '0 1 auto', - none: 'none', - }, - flexBasis: ({ theme }) => ({ - ...theme('spacing'), - ...ratios(2, 6), - // '1/2': '50%', - // '1/3': '33.333333%', - // '2/3': '66.666667%', - // '1/4': '25%', - // '2/4': '50%', - // '3/4': '75%', - // '1/5': '20%', - // '2/5': '40%', - // '3/5': '60%', - // '4/5': '80%', - // '1/6': '16.666667%', - // '2/6': '33.333333%', - // '3/6': '50%', - // '4/6': '66.666667%', - // '5/6': '83.333333%', - - ...ratios(12, 12), - // '1/12': '8.333333%', - // '2/12': '16.666667%', - // '3/12': '25%', - // '4/12': '33.333333%', - // '5/12': '41.666667%', - // '6/12': '50%', - // '7/12': '58.333333%', - // '8/12': '66.666667%', - // '9/12': '75%', - // '10/12': '83.333333%', - // '11/12': '91.666667%', - - auto: 'auto', - full: '100%', - }), - flexGrow: { - DEFAULT: 1, - 0: 0, - }, - flexShrink: { - DEFAULT: 1, - 0: 0, - }, - fontFamily: { - sans: 'ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"'.split( - ',', - ), - serif: 'ui-serif,Georgia,Cambria,"Times New Roman",Times,serif'.split(','), - mono: 'ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace'.split( - ',', - ), - }, - fontSize: { - xs: ['0.75rem', '1rem'], - sm: ['0.875rem', '1.25rem'], - base: ['1rem', '1.5rem'], - lg: ['1.125rem', '1.75rem'], - xl: ['1.25rem', '1.75rem'], - '2xl': ['1.5rem', '2rem'], - '3xl': ['1.875rem', '2.25rem'], - '4xl': ['2.25rem', '2.5rem'], - '5xl': ['3rem', '1'], - '6xl': ['3.75rem', '1'], - '7xl': ['4.5rem', '1'], - '8xl': ['6rem', '1'], - '9xl': ['8rem', '1'], - }, - fontWeight: { - thin: '100', - extralight: '200', - light: '300', - normal: '400', - medium: '500', - semibold: '600', - bold: '700', - extrabold: '800', - black: '900', - }, - gap: /* #__PURE__ */ alias('spacing'), - gradientColorStops: /* #__PURE__ */ alias('colors'), - gridAutoColumns: { - auto: 'auto', - min: 'min-content', - max: 'max-content', - fr: 'minmax(0,1fr)', - }, - gridAutoRows: { - auto: 'auto', - min: 'min-content', - max: 'max-content', - fr: 'minmax(0,1fr)', - }, - gridColumn: { - // span-X is handled by the plugin: span-1 -> span 1 / span 1 - auto: 'auto', - 'span-full': '1 / -1', - }, - // gridColumnEnd: { - // // Defaults handled by plugin - // }, - // gridColumnStart: { - // // Defaults handled by plugin - // }, - gridRow: { - // span-X is handled by the plugin: span-1 -> span 1 / span 1 - auto: 'auto', - 'span-full': '1 / -1', - }, - // gridRowStart: { - // // Defaults handled by plugin - // }, - // gridRowEnd: { - // // Defaults handled by plugin - // }, - gridTemplateColumns: { - // numbers are handled by the plugin: 1 -> repeat(1, minmax(0, 1fr)) - none: 'none', - }, - gridTemplateRows: { - // numbers are handled by the plugin: 1 -> repeat(1, minmax(0, 1fr)) - none: 'none', - }, - height: ({ theme }) => ({ - ...theme('spacing'), - ...ratios(2, 6), - // '1/2': '50%', - // '1/3': '33.333333%', - // '2/3': '66.666667%', - // '1/4': '25%', - // '2/4': '50%', - // '3/4': '75%', - // '1/5': '20%', - // '2/5': '40%', - // '3/5': '60%', - // '4/5': '80%', - // '1/6': '16.666667%', - // '2/6': '33.333333%', - // '3/6': '50%', - // '4/6': '66.666667%', - // '5/6': '83.333333%', - min: 'min-content', - max: 'max-content', - fit: 'fit-content', - auto: 'auto', - full: '100%', - screen: '100vh', - }), - inset: ({ theme }) => ({ - ...theme('spacing'), - ...ratios(2, 4), - // '1/2': '50%', - // '1/3': '33.333333%', - // '2/3': '66.666667%', - // '1/4': '25%', - // '2/4': '50%', - // '3/4': '75%', - auto: 'auto', - full: '100%', - }), - keyframes: { - spin: { - from: { - transform: 'rotate(0deg)', - }, - to: { - transform: 'rotate(360deg)', - }, - }, - ping: { - '0%': { - transform: 'scale(1)', - opacity: '1', - }, - '75%,100%': { - transform: 'scale(2)', - opacity: '0', - }, - }, - pulse: { - '0%,100%': { - opacity: '1', - }, - '50%': { - opacity: '.5', - }, - }, - bounce: { - '0%, 100%': { - transform: 'translateY(-25%)', - animationTimingFunction: 'cubic-bezier(0.8,0,1,1)', - }, - '50%': { - transform: 'none', - animationTimingFunction: 'cubic-bezier(0,0,0.2,1)', - }, - }, - }, - letterSpacing: { - tighter: '-0.05em', - tight: '-0.025em', - normal: '0em', - wide: '0.025em', - wider: '0.05em', - widest: '0.1em', - }, - lineHeight: { - .../* #__PURE__ */ linear(10, 'rem', 4, 3), - // 3: '.75rem', - // 4: '1rem', - // 5: '1.25rem', - // 6: '1.5rem', - // 7: '1.75rem', - // 8: '2rem', - // 9: '2.25rem', - // 10: '2.5rem', - none: '1', - tight: '1.25', - snug: '1.375', - normal: '1.5', - relaxed: '1.625', - loose: '2', - }, - // listStyleType: { - // // Defaults handled by plugin - // }, - margin: ({ theme }) => ({ - auto: 'auto', - ...theme('spacing'), - }), - maxHeight: ({ theme }) => ({ - full: '100%', - min: 'min-content', - max: 'max-content', - fit: 'fit-content', - screen: '100vh', - ...theme('spacing'), - }), - maxWidth: ({ theme, breakpoints }) => ({ - ...breakpoints(theme('screens')), - none: 'none', - 0: '0rem', - xs: '20rem', - sm: '24rem', - md: '28rem', - lg: '32rem', - xl: '36rem', - '2xl': '42rem', - '3xl': '48rem', - '4xl': '56rem', - '5xl': '64rem', - '6xl': '72rem', - '7xl': '80rem', - full: '100%', - min: 'min-content', - max: 'max-content', - fit: 'fit-content', - prose: '65ch', - }), - minHeight: { - 0: '0px', - full: '100%', - min: 'min-content', - max: 'max-content', - fit: 'fit-content', - screen: '100vh', - }, - minWidth: { - 0: '0px', - full: '100%', - min: 'min-content', - max: 'max-content', - fit: 'fit-content', - }, - // objectPosition: { - // // The plugins joins all arguments by default - // }, - opacity: { - .../* #__PURE__ */ linear(100, '', 100, 0, 10), - // 0: '0', - // 10: '0.1', - // 20: '0.2', - // 30: '0.3', - // 40: '0.4', - // 60: '0.6', - // 70: '0.7', - // 80: '0.8', - // 90: '0.9', - // 100: '1', - 5: '0.05', - 25: '0.25', - 75: '0.75', - 95: '0.95', - }, - order: { - // Handled by plugin - // 1: '1', - // 2: '2', - // 3: '3', - // 4: '4', - // 5: '5', - // 6: '6', - // 7: '7', - // 8: '8', - // 9: '9', - // 10: '10', - // 11: '11', - // 12: '12', - first: '-9999', - last: '9999', - none: '0', - }, - padding: /* #__PURE__ */ alias('spacing'), - placeholderColor: /* #__PURE__ */ alias('colors'), - placeholderOpacity: /* #__PURE__ */ alias('opacity'), - outlineColor: /* #__PURE__ */ alias('colors'), - outlineOffset: /* #__PURE__ */ exponential(8, 'px'), - // 0: '0px', - // 1: '1px', - // 2: '2px', - // 4: '4px', - // 8: '8px',, - outlineWidth: /* #__PURE__ */ exponential(8, 'px'), - // 0: '0px', - // 1: '1px', - // 2: '2px', - // 4: '4px', - // 8: '8px',, - ringColor: ({ theme }) => ({ - ...theme('colors'), - DEFAULT: '#3b82f6', - }), - ringOffsetColor: /* #__PURE__ */ alias('colors'), - ringOffsetWidth: /* #__PURE__ */ exponential(8, 'px'), - // 0: '0px', - // 1: '1px', - // 2: '2px', - // 4: '4px', - // 8: '8px',, - ringOpacity: ({ theme }) => ({ - ...theme('opacity'), - DEFAULT: '0.5', - }), - ringWidth: { - DEFAULT: '3px', - .../* #__PURE__ */ exponential(8, 'px'), - // 0: '0px', - // 1: '1px', - // 2: '2px', - // 4: '4px', - // 8: '8px', - }, - rotate: { - .../* #__PURE__ */ exponential(2, 'deg'), - // 0: '0deg', - // 1: '1deg', - // 2: '2deg', - .../* #__PURE__ */ exponential(12, 'deg', 3), - // 3: '3deg', - // 6: '6deg', - // 12: '12deg', - .../* #__PURE__ */ exponential(180, 'deg', 45), - // 45: '45deg', - // 90: '90deg', - // 180: '180deg', - }, - saturate: /* #__PURE__ */ linear(200, '', 100, 0, 50), - // 0: '0', - // 50: '.5', - // 100: '1', - // 150: '1.5', - // 200: '2', - scale: { - .../* #__PURE__ */ linear(150, '', 100, 0, 50), - // 0: '0', - // 50: '.5', - // 150: '1.5', - .../* #__PURE__ */ linear(110, '', 100, 90, 5), - // 90: '.9', - // 95: '.95', - // 100: '1', - // 105: '1.05', - // 110: '1.1', - 75: '0.75', - 125: '1.25', - }, - scrollMargin: /* #__PURE__ */ alias('spacing'), - scrollPadding: /* #__PURE__ */ alias('spacing'), - sepia: { - 0: '0', - DEFAULT: '100%', - }, - skew: { - .../* #__PURE__ */ exponential(2, 'deg'), - // 0: '0deg', - // 1: '1deg', - // 2: '2deg', - .../* #__PURE__ */ exponential(12, 'deg', 3), - // 3: '3deg', - // 6: '6deg', - // 12: '12deg', - }, - space: /* #__PURE__ */ alias('spacing'), - stroke: ({ theme }) => ({ - ...theme('colors'), - none: 'none', - }), - strokeWidth: /* #__PURE__ */ linear(2), - // 0: '0', - // 1: '1', - // 2: '2',, - textColor: /* #__PURE__ */ alias('colors'), - textDecorationColor: /* #__PURE__ */ alias('colors'), - textDecorationThickness: { - 'from-font': 'from-font', - auto: 'auto', - .../* #__PURE__ */ exponential(8, 'px'), - // 0: '0px', - // 1: '1px', - // 2: '2px', - // 4: '4px', - // 8: '8px', - }, - textUnderlineOffset: { - auto: 'auto', - .../* #__PURE__ */ exponential(8, 'px'), - // 0: '0px', - // 1: '1px', - // 2: '2px', - // 4: '4px', - // 8: '8px', - }, - textIndent: /* #__PURE__ */ alias('spacing'), - textOpacity: /* #__PURE__ */ alias('opacity'), - // transformOrigin: { - // // The following are already handled by the plugin: - // // center, right, left, bottom, top - // // 'bottom-10px-right-20px' -> bottom 10px right 20px - // }, - transitionDuration: ({ theme }) => ({ - ...theme('durations'), - DEFAULT: '150ms', - }), - transitionDelay: /* #__PURE__ */ alias('durations'), - transitionProperty: { - none: 'none', - all: 'all', - DEFAULT: - 'color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter', - colors: 'color,background-color,border-color,text-decoration-color,fill,stroke', - opacity: 'opacity', - shadow: 'box-shadow', - transform: 'transform', - }, - transitionTimingFunction: { - DEFAULT: 'cubic-bezier(0.4,0,0.2,1)', - linear: 'linear', - in: 'cubic-bezier(0.4,0,1,1)', - out: 'cubic-bezier(0,0,0.2,1)', - 'in-out': 'cubic-bezier(0.4,0,0.2,1)', - }, - translate: ({ theme }) => ({ - ...theme('spacing'), - ...ratios(2, 4), - // '1/2': '50%', - // '1/3': '33.333333%', - // '2/3': '66.666667%', - // '1/4': '25%', - // '2/4': '50%', - // '3/4': '75%', - full: '100%', - }), - width: ({ theme }) => ({ - min: 'min-content', - max: 'max-content', - fit: 'fit-content', - screen: '100vw', - ...theme('flexBasis'), - }), - willChange: { - scroll: 'scroll-position', - // other options handled by rules - // auto: 'auto', - // contents: 'contents', - // transform: 'transform', - }, - zIndex: { - .../* #__PURE__ */ linear(50, '', 1, 0, 10), - // 0: '0', - // 10: '10', - // 20: '20', - // 30: '30', - // 40: '40', - // 50: '50', - auto: 'auto', - }, -} +const theme: DefaultTheme = { ...baseTheme, colors } export default theme - -// '1/2': '50%', -// '1/3': '33.333333%', -// '2/3': '66.666667%', -// '1/4': '25%', -// '2/4': '50%', -// '3/4': '75%', -// '1/5': '20%', -// '2/5': '40%', -// '3/5': '60%', -// '4/5': '80%', -// '1/6': '16.666667%', -// '2/6': '33.333333%', -// '3/6': '50%', -// '4/6': '66.666667%', -// '5/6': '83.333333%', -function ratios(start: number, end: number): Record { - const result: Record = {} - - do { - // XXX: using var to avoid strange bug when generating cjs where `= 1` is removed - // eslint-disable-next-line no-var - for (var dividend = 1; dividend < start; dividend++) { - result[`${dividend}/${start}`] = Number(((dividend / start) * 100).toFixed(6)) + '%' - } - } while (++start <= end) - - return result -} - -// 0: '0px', -// 2: '2px', -// 4: '4px', -// 8: '8px', -function exponential(stop: number, unit: string, start = 0): Record { - const result: Record = {} - - for (; start <= stop; start = start * 2 || 1) { - result[start] = start + unit - } - - return result -} - -// 3: '.75rem', -// 4: '1rem', -// 5: '1.25rem', -// 6: '1.5rem', -// 7: '1.75rem', -// 8: '2rem', -// 9: '2.25rem', -// 10: '2.5rem', -function linear( - stop: number, - unit = '', - divideBy = 1, - start = 0, - step = 1, - result: Record = {}, - // eslint-disable-next-line max-params -): Record { - for (; start <= stop; start += step) { - result[start] = start / divideBy + unit - } - - return result -} - -function alias
( - section: Section, -): ThemeSectionResolver { - return ({ theme }) => theme(section) -} diff --git a/packages/preset-tailwind/src/index.ts b/packages/preset-tailwind/src/index.ts index 723a1662d..9209ce4f7 100644 --- a/packages/preset-tailwind/src/index.ts +++ b/packages/preset-tailwind/src/index.ts @@ -1,10 +1,8 @@ import type { Preset } from '@twind/core' import type { TailwindTheme } from './types' -import theme from './defaultTheme' -import preflight from './preflight' -import rules from './rules' -import variants from './variants' +import presetTailwindBase from './base' +import * as colors from './colors' export * from './types' @@ -16,19 +14,5 @@ export interface TailwindPresetOptions { export default function presetTailwind({ disablePreflight, }: TailwindPresetOptions = {}): Preset { - return { - // allow other preflight to run - preflight: disablePreflight ? undefined : preflight, - theme, - variants, - rules, - finalize(rule) { - // automatically add `content: ''` to before and after so you don’t have to specify it unless you want a different value - if (rule.r.some((r) => /^&::(before|after)$/.test(r)) && !rule.d?.includes('content:')) { - return { ...rule, d: ['content:var(--tw-content)', rule.d].filter(Boolean).join(';') } - } - - return rule - }, - } + return presetTailwindBase({ colors, disablePreflight }) } diff --git a/packages/preset-tailwind/src/preflight.ts b/packages/preset-tailwind/src/preflight.ts index 735dd62b6..5abe00a72 100644 --- a/packages/preset-tailwind/src/preflight.ts +++ b/packages/preset-tailwind/src/preflight.ts @@ -4,7 +4,7 @@ import type { Preflight } from '@twind/core' -import defaultTheme from './defaultTheme' +import baseTheme from './baseTheme' const preflight: Preflight = { /* @@ -33,7 +33,7 @@ const preflight: Preflight = { MozTabSize: '4' /* 3 */, tabSize: 4 /* 3 */, fontFamily: `theme(fontFamily.sans, ${ - (defaultTheme.fontFamily as Record).sans + (baseTheme.fontFamily as Record).sans })` /* 4 */, fontFeatureSettings: 'theme(fontFamily.sans[1].fontFeatureSettings, normal)' /* 5 */, }, @@ -77,9 +77,7 @@ const preflight: Preflight = { 3. Correct the odd `em` font sizing in all browsers. */ 'code,kbd,samp,pre': { - fontFamily: `theme(fontFamily.mono, ${ - (defaultTheme.fontFamily as Record).mono - })`, + fontFamily: `theme(fontFamily.mono, ${(baseTheme.fontFamily as Record).mono})`, fontFeatureSettings: 'theme(fontFamily.mono[1].fontFeatureSettings, normal)', fontSize: '1em', }, diff --git a/packages/preset-typography/src/index.ts b/packages/preset-typography/src/index.ts index 050d1d6fa..7464103e3 100644 --- a/packages/preset-typography/src/index.ts +++ b/packages/preset-typography/src/index.ts @@ -692,7 +692,7 @@ export default function presetTypography({ // support auto dark colors const darkColor = - target != darkProperties && context.d('colors', `${colorName}.${shade}`, color) + target != darkProperties && context.d('colors', `${colorName}-${shade}`, color) if (darkColor) { darkProperties[('--tw-prose-' + key) as keyof CustomProperties] = toColorValue(darkColor) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7bd84bb30..1fddb8b68 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -352,6 +352,17 @@ importers: typescript: 4.8.4 publishDirectory: dist + packages/preset-radix-ui: + specifiers: + '@radix-ui/colors': ^0.1.8 + '@twind/core': ^1.0.3 + typescript: ^4.8.4 + devDependencies: + '@radix-ui/colors': 0.1.8 + '@twind/core': link:../core + typescript: 4.8.4 + publishDirectory: dist + packages/preset-tailwind: specifiers: '@twind/core': ^1.0.3 @@ -492,7 +503,6 @@ importers: '@jsenv/importmap': ^1.2.1 '@jsenv/logger': 4.1.1 '@jspm/generator': 1.0.0-beta.38 - '@radix-ui/colors': ^0.1.8 '@rollup/browser': ^3.3.0 '@rollup/plugin-commonjs': ^23.0.2 '@rollup/pluginutils': ^5.0.2 @@ -502,6 +512,7 @@ importers: '@twind/core': ^1.0.3 '@twind/intellisense': ^1.0.4 '@twind/preset-autoprefix': ^1.0.3 + '@twind/preset-radix-ui': ^1.0.3 '@twind/preset-tailwind': ^1.0.3 '@twind/preset-typography': ^1.0.3 '@twind/with-sveltekit': ^1.0.3 @@ -540,7 +551,6 @@ importers: '@jsenv/importmap': 1.2.1_x4kvtnlfhhtsajb4py2iyzfui4 '@jsenv/logger': 4.1.1_livkr6tcf7bvqgbmqomvfiozau '@jspm/generator': 1.0.0-beta.38_xd5gsfploetblhb7b2jkkvxw6u_nxk3t66zrxuafd3dzooks6vs24 - '@radix-ui/colors': 0.1.8 '@rollup/browser': 3.3.0 '@rollup/plugin-commonjs': 23.0.2_rollup@2.79.1 '@rollup/pluginutils': 5.0.2_rollup@2.79.1 @@ -550,6 +560,7 @@ importers: '@twind/core': link:../../packages/core '@twind/intellisense': link:../../packages/intellisense '@twind/preset-autoprefix': link:../../packages/preset-autoprefix + '@twind/preset-radix-ui': link:../../packages/preset-radix-ui '@twind/preset-tailwind': link:../../packages/preset-tailwind '@twind/preset-typography': link:../../packages/preset-typography '@twind/with-sveltekit': link:../../packages/with-sveltekit @@ -586,13 +597,13 @@ importers: sites/twind.style: specifiers: '@cloudflare/workers-types': ^3.18.0 - '@radix-ui/colors': ^0.1.8 '@sastan/svelte-headlessui': ^1.0.2 '@sveltejs/adapter-static': 1.0.0-next.48 '@sveltejs/kit': 1.0.0-next.547 '@twind/core': ^1.0.3 '@twind/preset-autoprefix': ^1.0.3 '@twind/preset-ext': ^1.0.3 + '@twind/preset-radix-ui': ^1.0.3 '@twind/preset-tailwind': ^1.0.3 '@twind/preset-typography': ^1.0.3 '@twind/with-sveltekit': ^1.0.3 @@ -645,13 +656,13 @@ importers: wrangler: ^2.2.1 dependencies: '@cloudflare/workers-types': 3.18.0 - '@radix-ui/colors': 0.1.8 '@sastan/svelte-headlessui': 1.0.2_svelte@3.53.1 '@sveltejs/adapter-static': 1.0.0-next.48 '@sveltejs/kit': 1.0.0-next.547_svelte@3.53.1+vite@3.2.3 '@twind/core': link:../../packages/core '@twind/preset-autoprefix': link:../../packages/preset-autoprefix '@twind/preset-ext': link:../../packages/preset-ext + '@twind/preset-radix-ui': link:../../packages/preset-radix-ui '@twind/preset-tailwind': link:../../packages/preset-tailwind '@twind/preset-typography': link:../../packages/preset-typography '@twind/with-sveltekit': link:../../packages/with-sveltekit @@ -3804,6 +3815,7 @@ packages: /@radix-ui/colors/0.1.8: resolution: {integrity: sha512-jwRMXYwC0hUo0mv6wGpuw254Pd9p/R6Td5xsRpOmaWkUHlooNWqVcadgyzlRumMq3xfOTXwJReU0Jv+EIy4Jbw==} + dev: true /@remix-run/dev/1.7.5_eeahpycm5e6orraz2s54jlxxca: resolution: {integrity: sha512-z/HEMi6e2eO6DvCrH+rNbqNohD5m1QMzVfXoIG976jw6Pn72PTaiGFNtDc5vNB2IjVuRAu1j0X9TbWLmU/+fOw==} diff --git a/sites/cdn.twind.style/src/index.ts b/sites/cdn.twind.style/src/index.ts index bdb98722f..369939767 100644 --- a/sites/cdn.twind.style/src/index.ts +++ b/sites/cdn.twind.style/src/index.ts @@ -32,6 +32,7 @@ const WELL_KNOWN_PRESETS: Record = { ext: '@twind/preset-ext', 'container-queries': '@twind/preset-container-queries', 'line-clamp': '@twind/preset-line-clamp', + 'radix-ui': '@twind/preset-radix-ui', 'tailwind-forms': '@twind/preset-tailwind-forms', // compat for Tailwind CSS Play CDN forms: '@twind/preset-tailwind-forms', diff --git a/sites/twind.run/package.json b/sites/twind.run/package.json index 543244d20..02426821d 100644 --- a/sites/twind.run/package.json +++ b/sites/twind.run/package.json @@ -35,7 +35,6 @@ "@jsenv/importmap": "^1.2.1", "@jsenv/logger": "4.1.1", "@jspm/generator": "1.0.0-beta.38", - "@radix-ui/colors": "^0.1.8", "@rollup/browser": "^3.3.0", "@rollup/plugin-commonjs": "^23.0.2", "@rollup/pluginutils": "^5.0.2", @@ -45,6 +44,7 @@ "@twind/core": "^1.0.3", "@twind/intellisense": "^1.0.4", "@twind/preset-autoprefix": "^1.0.3", + "@twind/preset-radix-ui": "^1.0.3", "@twind/preset-tailwind": "^1.0.3", "@twind/preset-typography": "^1.0.3", "@twind/with-sveltekit": "^1.0.3", diff --git a/sites/twind.run/src/lib/templates/preset-radix-ui/config.tpl b/sites/twind.run/src/lib/templates/preset-radix-ui/config.tpl new file mode 100644 index 000000000..7c08712d7 --- /dev/null +++ b/sites/twind.run/src/lib/templates/preset-radix-ui/config.tpl @@ -0,0 +1,67 @@ +import { defineConfig } from "@twind/core" +import presetAutoprefix from "@twind/preset-autoprefix" +// Using @twind/preset-tailwind/base to exclude the default tailwind colors +import presetTailwind from "@twind/preset-tailwind/base" + +// Following https://www.radix-ui.com/docs/colors/palette-composition/composing-a-palette +import { + mint as brand, + mintDark as brandDark, + violet as accent, + violetDark as accentDark, + mauve as neutral, + mauveDark as neutralDark, + + // Error: Red/Tomato/Crimson + tomato as error, + tomatoDark as errorDark, + + // Success: Teal/Green/Grass/Mint + teal as success, + tealDark as successDark, + + // Warning: Yellow/Amber + amber as warning, + amberDark as warningDark, + + // Info: Blue/Sky/Cyan + cyan as info, + cyanDark as infoDark, +} from "@twind/preset-radix-ui/colors" + +// Optional: enable automatic dark colors +import darkColor from "@twind/preset-radix-ui/darkColor" + +export default defineConfig({ + presets: [ + presetAutoprefix(), + presetTailwind({ + colors: { + brand, + brandDark, + accent, + accentDark, + neutral, + neutralDark, + + // Error: Red/Tomato/Crimson + error, + errorDark, + + // Success: Teal/Green/Grass/Mint + success, + successDark, + + // Warning: Yellow/Amber + warning, + warningDark, + + // Info: Blue/Sky/Cyan + info, + infoDark, + }, + }), + ], + // auto dark colors + darkColor, +}) diff --git a/sites/twind.run/src/lib/templates/preset-radix-ui/html.tpl b/sites/twind.run/src/lib/templates/preset-radix-ui/html.tpl new file mode 100644 index 000000000..939e220d5 --- /dev/null +++ b/sites/twind.run/src/lib/templates/preset-radix-ui/html.tpl @@ -0,0 +1,29 @@ +
+ Twind Logo + +

+ twind.style +

+

+ The smallest, fastest, most feature complete tailwind-in-js solution in + existence. +

+ + +
diff --git a/sites/twind.run/src/lib/templates/preset-radix-ui/index.ts b/sites/twind.run/src/lib/templates/preset-radix-ui/index.ts new file mode 100644 index 000000000..151caff22 --- /dev/null +++ b/sites/twind.run/src/lib/templates/preset-radix-ui/index.ts @@ -0,0 +1,12 @@ +import type { Workspace } from "$lib/types" + +import config from "./config.tpl?raw" +import html from "./html.tpl?raw" +import script from "./script.tpl?raw" + +export const workspace: Workspace = { + version: "*", + html: { path: "index.html", value: html }, + script: { path: "index.ts", value: script }, + config: { path: "twind.config.ts", value: config }, +} diff --git a/sites/twind.run/src/lib/templates/preset-radix-ui/script.tpl b/sites/twind.run/src/lib/templates/preset-radix-ui/script.tpl new file mode 100644 index 000000000..a14c7f343 --- /dev/null +++ b/sites/twind.run/src/lib/templates/preset-radix-ui/script.tpl @@ -0,0 +1,15 @@ +import { tw, cx, tx, css, style } from "@twind/core" + +// imported and executed once after the tw instance has been created but before new document.body is set + +export async function beforeUpdate() { + // runs every time before a new document.body is set +} + +export async function afterUpdate() { + // runs every time after a new document.body is set +} + +export async function dispose() { + // runs before a new script is activated +} diff --git a/sites/twind.run/src/lib/transpile.api.ts b/sites/twind.run/src/lib/transpile.api.ts index 1e6195b07..2767e43be 100644 --- a/sites/twind.run/src/lib/transpile.api.ts +++ b/sites/twind.run/src/lib/transpile.api.ts @@ -92,16 +92,7 @@ const api: Transpile = { (!input.version || SemverRange.match(input.version, output.version)) ) { source = output.id + output.path - } - } - - for (const [key, value] of Object.entries(manifest.imports || {})) { - // add all sub-path imports - if ( - key === source || - (key.startsWith(source + '/') && key !== source + '/package.json') - ) { - ;(inputMap.imports ||= {})[key] = value + ;(inputMap.imports ||= {})[source] = resolved } } @@ -121,10 +112,11 @@ const api: Transpile = { ], }) + // console.debug({ manifest, dependencies, inputMap }) + const generator = new Generator({ baseUrl: 'memory://', inputMap, - defaultProvider: 'jspm.system', env: [ 'development', 'modern', @@ -135,9 +127,49 @@ const api: Transpile = { 'import', 'default', ], + defaultProvider: 'jspm.system', + providers: { + '@twind': 'local', + }, + customProviders: { + local: { + pkgToUrl(pkg) { + if (manifest.packages[pkg.name] === pkg.version) { + return new URL(`./immutable/cdn/${pkg.name}@${pkg.version}/`, manifest.url) + .href as 'x/' + } + + return `https://ga.system.jspm.io/${pkg.registry}:${pkg.name}@${pkg.version}/` + }, + parseUrlPkg(url) { + const base = new URL(`./immutable/cdn/`, manifest.url).href + if (url.startsWith(base)) { + const [, name, version] = + url + .slice(base.length) + .match(/^((?:@[^/\\%@]+\/)?[^./\\%@][^/\\%@]*)@([^\/]+)(\/.*)?$/) || [] + + return { registry: 'npm', name, version } + } + }, + async resolveLatestTarget(target, layer, parentUrl) { + const version = manifest.packages[target.name] + + if (version) { + return { registry: target.registry, name: target.name, version } + } + + return null + }, + }, + }, }) - // TODO: trace generator.logStream + // ;(async () => { + // for await (const { type, message } of generator.logStream()) { + // console.log(`${type}: ${message}`); + // } + // })(); const [{ dynamicDeps = [], staticDeps = [] } = {}, { output }] = await Promise.all([ generator.install([...dependencies]), @@ -194,7 +226,7 @@ const api: Transpile = { prefetch: dynamicDeps.map(scopeToManifest), } - console.debug('importMap', importMap) + // console.debug('importMap', importMap) return { ...Object.fromEntries( output diff --git a/sites/twind.run/src/routes/[[key]]/+page.server.ts b/sites/twind.run/src/routes/[[key]]/+page.server.ts index 2398c9d5d..99b675b0b 100644 --- a/sites/twind.run/src/routes/[[key]]/+page.server.ts +++ b/sites/twind.run/src/routes/[[key]]/+page.server.ts @@ -200,11 +200,11 @@ export async function load({ const alias = version === '*' ? 'latest' : version.toLowerCase().replace(/[^a-z\d]/g, '-') const origin = - version === SITE_VERSION + !(dev && version === SITE_VERSION) || alias.includes('-dev-') ? new URL(request.url).origin : alias === 'latest' ? `https://${HOSTNAME}` - : `https://${/^\d\.\d\.\d/.test(alias) ? 'v' + alias : alias}.${HOSTNAME}` + : `https://${/\d/.test(alias) ? 'v' + alias : alias}.${HOSTNAME}` const url = origin + MANIFEST_PATH @@ -220,7 +220,7 @@ export async function load({ response = await fetch(url) if (!(response.ok && response.status === 200)) { - throw new Error(`[${response.status}] ${response.statusText || 'request failed'}`) + throw new Error(`[${response.status}] ${response.statusText || 'request failed'}: ${url}`) } cache?.put(url, response.clone()) diff --git a/sites/twind.run/src/routes/[[key]]/+page.svelte b/sites/twind.run/src/routes/[[key]]/+page.svelte index b9df1b296..87761b35c 100644 --- a/sites/twind.run/src/routes/[[key]]/+page.svelte +++ b/sites/twind.run/src/routes/[[key]]/+page.svelte @@ -8,7 +8,6 @@ import copy from 'clipboard-copy' import { Pane, Splitpanes } from 'svelte-splitpanes' import { - Transition, Listbox, ListboxLabel, ListboxButton, @@ -34,7 +33,6 @@ CheckSolid, ChevronUpDownMini, EllipsisHorizontalMini, - Link16, LoadingSpin, ShareAndroid24, Stars, @@ -422,7 +420,6 @@ class="relative group max-w-([6rem] lg:[12rem] xl:fit)" value={$workspace.version} on:change={(event) => ($workspace.version = event.detail)} - let:open > Change selected version @@ -440,64 +437,56 @@ - - - {#each data.manifests as manifest (manifest.version)} - - cx( - 'cursor-default select-none p-2 text-sm', - active - ? 'text-brand-12 bg-brand-4' - : selected - ? 'text-accent-11 bg-brand-3' - : 'text-brand-11 bg-brand-3', - )} - let:active - let:selected - > -
-
-

- v{manifest.version} -

- {#if selected} - - {/if} -
-

- {#if manifest.pr} - - PR #{manifest.pr} - β€” still in development - {:else if manifest['dist-tag'] === 'latest'} - stable version β€” for most users - {:else if manifest['dist-tag'] === 'next'} - next version β€” for early adopters - {:else} - canary version β€” still in development - {/if} + {#each data.manifests as manifest (manifest.version)} + + cx( + 'cursor-default select-none p-2 text-sm', + active + ? 'text-brand-12 bg-brand-4' + : selected + ? 'text-accent-11 bg-brand-3' + : 'text-brand-11 bg-brand-3', + )} + let:active + let:selected + > +

+
+

+ v{manifest.version}

+ {#if selected} + + {/if}
- - {/each} - - +

+ {#if manifest.pr} + + PR #{manifest.pr} + β€” still in development + {:else if manifest['dist-tag'] === 'latest'} + stable version β€” for most users + {:else if manifest['dist-tag'] === 'next'} + next version β€” for early adopters + {:else} + canary version β€” still in development + {/if} +

+
+ + {/each} +