@twind/core
Advanced tools
Comparing version 1.0.0-next.14 to 1.0.1-next-20221118224314
803
CHANGELOG.md
# @twind/core | ||
## 1.0.0-next.14 | ||
## 1.0.1-next-20221118224314 | ||
### Patch Changes | ||
- be less strict about interpolations values ([#245](https://github.com/tw-in-js/twind/pull/245)) | ||
- introduce new @twind/core package to prevent issue with existing code that imports from CDNs without a version ([`97805f45`](https://github.com/tw-in-js/twind/commit/97805f4584ef70a527beacc1ca6c622e0f17885b)) | ||
* golf: refactor sheets — always use a dedicated style element ([#245](https://github.com/tw-in-js/twind/pull/245)) | ||
- prevent name mangling of toplevel variables when creating a iife script ([`5949d61a`](https://github.com/tw-in-js/twind/commit/5949d61adeb3008c7b76f5ddb9453c000849fcb9)) | ||
- support any target for stringify ([#245](https://github.com/tw-in-js/twind/pull/245)) | ||
## 1.0.0 | ||
* add `stringify` helper to convert as `sheet.target` to a string; this makes `extract` isomorphic ([#245](https://github.com/tw-in-js/twind/pull/245)) | ||
### Patch Changes | ||
- use `data-twind` to locate SSR style element ([#245](https://github.com/tw-in-js/twind/pull/245)) | ||
- helpful error message during dev when no active twind instance is found ([`fe891f9c`](https://github.com/tw-in-js/twind/commit/fe891f9c7990a041e0eccaff9a4f58d0834d46d2)) | ||
## 1.0.0-next.13 | ||
- big documentation update ([`a63ca2cb`](https://github.com/tw-in-js/twind/commit/a63ca2cbf450d8a6f72f4d60f5856cee88d16911)) | ||
- allow for `cssom` and `dom` to accept a selector string to find the server rendered stylesheet ([`e2c17a2e`](https://github.com/tw-in-js/twind/commit/e2c17a2e8087875f1725e3b07bc32218d2f0c2c0)) | ||
- BREAKING: use `install` instead of `setup` for cdn configuration to align with other integrations ([`d481948b`](https://github.com/tw-in-js/twind/commit/d481948b0513a59cc3495d5e31f0437c9690d59b)) | ||
- handle hex encoded ampersand ([`a61e0d1d`](https://github.com/tw-in-js/twind/commit/a61e0d1d4a31be6f398b57ceefffdb04b6bceccf)) | ||
- warn about invalid classes and invalid css during development ([`e6acbea2`](https://github.com/tw-in-js/twind/commit/e6acbea2f48e3c6441e0cf71cd069f48500ca493)) | ||
When run in development mode, which is determined by the [export condition](https://nodejs.org/api/packages.html#packages_conditional_exports) `development`, twind notifies about invalid classes and invalid css. | ||
> Further reading: | ||
> | ||
> - [Conditional exports](https://nodejs.org/api/packages.html#packages_conditional_exports) | ||
> - [Vite](https://vitejs.dev/config/shared-options.html#resolve-conditions) | ||
> - [esbuild](https://esbuild.github.io/api/#conditions) | ||
In the the browser a `warning` event is emitted on the `window` object and, in case there is no event listener or the event listener did not call `event.preventDefault()`, a warning is logged to the console. | ||
```js | ||
addEventListener('warning', (event) => { | ||
// prevent default console.warn(`[<code>] <message>: <detail>`) logging | ||
event.preventDefault() | ||
const warning = event.detail | ||
// { message: '...', code: 'TWIND_INVALID_CLASS', detail: '<className>'} | ||
// { message: '...', code: 'TWIND_INVALID_CSS', detail: '<css>'} | ||
console.warn(warning) | ||
}) | ||
``` | ||
In Node.js a warning is emitted using [`process.emitWarning`](https://nodejs.org/api/process.html#processemitwarningwarning-options). | ||
If there is no `warning` event listener, the warning is printed to `stderr`. | ||
``` | ||
(node:56338) [TWIND_INVALID_CLASS] Warning: ... | ||
``` | ||
Alternatively, you can use the [`process.on('warning', ...)`](https://nodejs.org/api/process.html#event-warning) to handle warnings. | ||
```js | ||
import process from 'node:process' | ||
process.on('warning', (warning) => { | ||
console.warn(warning.message) // Print the warning message | ||
console.warn(warning.code) // 'TWIND_INVALID_CLASS' | 'TWIND_INVALID_CSS' | ||
console.warn(warning.detail) // '<className>' | '<css>' | ||
}) | ||
``` | ||
- initial intellisense support ([`2ac8e695`](https://github.com/tw-in-js/twind/commit/2ac8e6950ad37bac0eb88116448bee8738388f59)) | ||
- stringify in user config always wins ([`0705e419`](https://github.com/tw-in-js/twind/commit/0705e41946e191974da76c2b27019755520d9c0a)) | ||
## 1.0.0 | ||
### Patch Changes | ||
- BREAKING(preset authors): removed `preset()` helper to simplify config merging — What needs to change? instead calling preset, return your preset ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
- helpful error message during dev when no active twind instance is found (fe891f9c) | ||
* remove auto string conversion for style selector; this wouldn't have worked with `css()` anyway ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
- allow for `cssom` and `dom` to accept a selector string to find the server rendered stylesheet (e2c17a2e) | ||
- add `comsume(html, tw)` to process static HTML ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
- BREAKING: use `install` instead of `setup` for cdn configuration to align with other integrations (d481948b) | ||
* BREAKING: rename `config.tag` to `config.hash` as it better reflects what it does ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
- warn about invalid classes and invalid css during development (e6acbea2) | ||
- feat: support array property value which act as fallbacks for browser taht do not support a specific syntax or value ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
When run in development mode, which is determined by the [export condition](https://nodejs.org/api/packages.html#packages_conditional_exports) `development`, twind notifies about invalid classes and invalid css. | ||
* only update class attributes if the class names within are different (ignore order) ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
> Further reading: | ||
> | ||
> - [Conditional exports](https://nodejs.org/api/packages.html#packages_conditional_exports) | ||
> - [Vite](https://vitejs.dev/config/shared-options.html#resolve-conditions) | ||
> - [esbuild](https://esbuild.github.io/api/#conditions) | ||
- fix: ensure nullish values are not converted to array with one nullish element ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
In the the browser a `warning` event is emitted on the `window` object and, in case there is no event listener or the event listener did not call `event.preventDefault()`, a warning is logged to the console. | ||
* feat: `@layer ...` values can be arrays; this allows the same selector several times ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
```js | ||
addEventListener('warning', (event) => { | ||
// prevent default console.warn(`[<code>] <message>: <detail>`) logging | ||
event.preventDefault() | ||
- add `extract(html, tw)` to simplify SSR use case ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
const warning = event.detail | ||
* fix: for unnamed rules apply the condition in normal order; otherwise `&..` is applied before there is a selector ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
// { message: '...', code: 'TWIND_INVALID_CLASS', detail: '<className>'} | ||
// { message: '...', code: 'TWIND_INVALID_CSS', detail: '<css>'} | ||
console.warn(warning) | ||
}) | ||
``` | ||
## 1.0.0-next.12 | ||
In Node.js a warning is emitted using [`process.emitWarning`](https://nodejs.org/api/process.html#processemitwarningwarning-options). | ||
If there is no `warning` event listener, the warning is printed to `stderr`. | ||
``` | ||
(node:56338) [TWIND_INVALID_CLASS] Warning: ... | ||
``` | ||
Alternatively, you can use the [`process.on('warning', ...)`](https://nodejs.org/api/process.html#event-warning) to handle warnings. | ||
```js | ||
import process from 'node:process' | ||
process.on('warning', (warning) => { | ||
console.warn(warning.message) // Print the warning message | ||
console.warn(warning.code) // 'TWIND_INVALID_CLASS' | 'TWIND_INVALID_CSS' | ||
console.warn(warning.detail) // '<className>' | '<css>' | ||
}) | ||
``` | ||
- initial intellisense support (2ac8e695) | ||
- stringify in user config always wins (0705e419) | ||
## 1.0.0-next.39 | ||
### Patch Changes | ||
- introduce `twind/cdn`: a bore bones Tailwind CSS replacement — no additional exports like (`cx`, `style` or `css`) ([`9bc26949`](https://github.com/tw-in-js/twind/commit/9bc26949dd729b7002bc27032bb2f999e766546d)) | ||
- configurable Dark Mode ClassName ([`774e2bb4`](https://github.com/tw-in-js/twind/commit/774e2bb4c7a019d76e55296e9af75fedc77bd054)) | ||
## 1.0.0-next.11 | ||
* Arbitrary variants ([`a3b1bcba`](https://github.com/tw-in-js/twind/commit/a3b1bcba6269bc4a51b63041689baf58f6222b7f)) | ||
- prevent orphaned style tag when calling setup multiple times (closes #321) ([`0e2aa5c4`](https://github.com/tw-in-js/twind/commit/0e2aa5c4f07e5bca3bea37f864773f665935a263)) | ||
* `injectGlobal` support for `@media print (#333, #334) 🙏 @javascriptjedi! ([`9b5e3297`](https://github.com/tw-in-js/twind/commit/9b5e3297470f9d2bdbd4f540d819ee0f42e63595)) | ||
- Add `<alpha-value>` placeholder support for custom colors (closes #349) ([`0a63948e`](https://github.com/tw-in-js/twind/commit/0a63948e9f6c5f1bb8088ae6e21dc4bf215ee9e8)) | ||
* feat: support rgb and hsl colors opacity conversion ([#336](https://github.com/tw-in-js/twind/pull/336)) 🙏🏽 [@javascriptjedi](https://github.com/javascriptjedi)! | ||
- support alpha values for `theme()` function ([`bdc0a7a1`](https://github.com/tw-in-js/twind/commit/bdc0a7a1c353990d0ef009af181f79c1134bfcec)) | ||
* fix missing spaces around arithmetic operators ([`f74163ba`](https://github.com/tw-in-js/twind/commit/f74163ba7310ece8d2de4a80586d19df419bfa86)) | ||
## 1.0.0-next.38 | ||
### Patch Changes | ||
- adjust rule ordering to fix `m-5 mr-3 mx-1` (previously generated `mx-1 m-5 mr-3`) ([#241](https://github.com/tw-in-js/twind/pull/241)) | ||
- fix: replace escaped quotes within class names during SSR ([`b212b52f`](https://github.com/tw-in-js/twind/commit/b212b52fbd53e9ecb38d97589ca2f717445ed185)) | ||
* BREAKING: the match object passed to rules and variants is now a RegExpExecArray with one additional property ([`dc778be0`](https://github.com/tw-in-js/twind/commit/dc778be038180c8f0409adc044305d565d35493f)) | ||
* Rewrites HTML entity & when self-referenced groups are used with (p)react ([`782f93df`](https://github.com/tw-in-js/twind/commit/782f93df6abb1ebd24ef6c45dc08de602e198107)) 🙏🏽 [@rschristian](https://github.com/rschristian)! | ||
- golf: short names within `context`; should not affect most users ([#241](https://github.com/tw-in-js/twind/pull/241)) | ||
- feat: preserve classes created by explicit `tw` calls during SSR ([`fe88051d`](https://github.com/tw-in-js/twind/commit/fe88051deb3176d014ba527471b1345c47bfb28e)) | ||
* fix: ensure proper pseudo-class ordering ([#241](https://github.com/tw-in-js/twind/pull/241)) | ||
Previously `inline` and `extract` cleared the `tw` instance before parsing the html assuming that all classes are available via `class` attributes. That led to missing styles from `injectGlobal` or explicit `tw` calls. | ||
- ensure base and overrides (css) layers are kept in the order the rules are declared ([#241](https://github.com/tw-in-js/twind/pull/241)) | ||
This change introduces a `snaphot` method on `tw` and sheet instances which allows to preserve the classes that are created by explicit `tw` calls. | ||
## 1.0.0-next.10 | ||
**Default Mode** _(nothing changed here)_ | ||
```js | ||
import { inline } from '@twind/core' | ||
function render() { | ||
return inline(renderApp()) | ||
} | ||
``` | ||
**Library Mode** | ||
```js | ||
import { tw, stringify } from '@twind/core' | ||
function render() { | ||
// remember global classes | ||
const restore = tw.snapshot() | ||
// generated html | ||
const html = renderApp() | ||
// create CSS | ||
const css = stringify(tw.target) | ||
// restore global classes | ||
restore() | ||
// inject as last element into the head | ||
return html.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
} | ||
``` | ||
* fix: gradients with arbitrary color stop positions (#296) ([`77954405`](https://github.com/tw-in-js/twind/commit/7795440566fc95a424a7f6210998dd1d16ef216f)) | ||
## 1.0.0-next.37 | ||
### Patch Changes | ||
- support inline named shortcuts (`PrimaryButton~(bg-red-500 text-white ...)` -> `PrimaryButton#asdadf`) ([#240](https://github.com/tw-in-js/twind/pull/240)) | ||
- fix: workaround for replaced `'` and `" when using react renderToString` ([`08c66ee8`](https://github.com/tw-in-js/twind/commit/08c66ee8f7f80a6c998a380acc4f44280aef3280)) | ||
* BREAKING: renamed `apply` to `shortcut` as it better reflect what it does ([#240](https://github.com/tw-in-js/twind/pull/240)) | ||
## 1.0.0-next.36 | ||
- simplify creation of named shortcuts: `shortcut.PrimaryButton\`bg-red-500 text-white\``or`shortcut.PrimaryButton('...', [...], {...})` ([#240](https://github.com/tw-in-js/twind/pull/240)) | ||
### Patch Changes | ||
* golf: shave of some bytes by using short property names within `TwindRule` ([#240](https://github.com/tw-in-js/twind/pull/240)) | ||
- relax some typings where the actual generic type does not matter ([`28cbaef5`](https://github.com/tw-in-js/twind/commit/28cbaef54f226e7542e9197b0dab69e55f588806)) | ||
- fix: style inherits styles from parent ([#240](https://github.com/tw-in-js/twind/pull/240)) | ||
* fix: ensure colors DEFAULT values override nested objects ([`43d61076`](https://github.com/tw-in-js/twind/commit/43d610769152aef2943383b3a2574b9be01acc49)) | ||
## 1.0.0-next.9 | ||
- refactor: include full precendence in resume data ([`80ce410a`](https://github.com/tw-in-js/twind/commit/80ce410a60892ba70fa8805a37aa89f0dbc13c7d)) | ||
* fix: move styles generated by `animation()` into `components` layer — this allows to override animation properties using utilities ([`39b45125`](https://github.com/tw-in-js/twind/commit/39b451256c10bd6f82f45015effbefb41aee8a76)) | ||
- feat: auto dark colors ([`2f8f69d2`](https://github.com/tw-in-js/twind/commit/2f8f69d27531fad4346af57f0fef3f473d2c6ee3)) | ||
If enabled, automatic dark colors are generated for each light color (eg no `dark:` variant is present). This feature is opt-in and twind provides a builtin function that works with [tailwind color palettes](https://tailwindcss.com/docs/customizing-colors) (`50`, `100`, `200`, ..., `800`, `900`). | ||
```ts | ||
import { autoDarkColor } from '@twind/core' | ||
defineConfig({ | ||
// for tailwind color palettes: 50 -> 900, 100 -> 800, ..., 800 -> 100, 900 -> 50 | ||
darkColor: autoDarkColor, | ||
// other possible implementations | ||
darkColor: (section, key, { theme }) => theme(`${section}.${key}-dark`) as ColorValue, | ||
darkColor: (section, key, { theme }) => theme(`dark.${section}.${key}`) as ColorValue, | ||
darkColor: (section, key, { theme }) => theme(`${section}.dark.${key}`) as ColorValue, | ||
darkColor: (section, key, context, lightColor) => generateDarkColor(lightColor), | ||
}) | ||
``` | ||
Example css for `text-gray-900`: | ||
```css | ||
.text-gray-900 { | ||
--tw-text-opacity: 1; | ||
color: rgba(15, 23, 42, var(--tw-text-opacity)); | ||
} | ||
@media (prefers-color-scheme: dark) { | ||
.text-gray-900 { | ||
--tw-text-opacity: 1; | ||
color: rgba(248, 250, 252, var(--tw-text-opacity)); | ||
} | ||
} | ||
``` | ||
The auto-generated dark color can be overridden by the usual `dark:...` variant: `text-gray-900 dark:text-gray-100`. | ||
```css | ||
.text-gray-900 { | ||
--tw-text-opacity: 1; | ||
color: rgba(15, 23, 42, var(--tw-text-opacity)); | ||
} | ||
@media (prefers-color-scheme: dark) { | ||
.text-gray-900 { | ||
--tw-text-opacity: 1; | ||
color: rgba(248, 250, 252, var(--tw-text-opacity)); | ||
} | ||
} | ||
@media (prefers-color-scheme: dark) { | ||
.dark\\:text-gray-100 { | ||
--tw-text-opacity: 1; | ||
color: rgba(241, 245, 249, var(--tw-text-opacity)); | ||
} | ||
} | ||
``` | ||
* fix: handle color function in replacement for `theme(...)` ([`9fc5baec`](https://github.com/tw-in-js/twind/commit/9fc5baeca6031d27ac81402b0e614d01c3cd20e7)) | ||
- fix: always use rgba color ([`aaad7e44`](https://github.com/tw-in-js/twind/commit/aaad7e4426068a55b00e23df2e084cfc8a46b2ca)) | ||
* refactor: move hashing of vars (`--tw-<...>`) from preset-tailwind into core — this allows var hashing without the tailwind preset ([`ae979d12`](https://github.com/tw-in-js/twind/commit/ae979d12fe01cfed32c44eea23ef8a9f2d983eae)) | ||
- fix: prevent double class name hashing ([`fc9b0c27`](https://github.com/tw-in-js/twind/commit/fc9b0c277f26e0fc1aad693bd13a80d50b27c71c)) | ||
* fix: use `text-decoration-line` ([`346efc4e`](https://github.com/tw-in-js/twind/commit/346efc4e84042d043e17bac8d829f0408279448e)) | ||
- fix: ensure theme returns all sections ([`8bbc2a42`](https://github.com/tw-in-js/twind/commit/8bbc2a426054cedc705392eb51aebf0029547d67)) | ||
* fix: use same color section detection ([`8dfd105b`](https://github.com/tw-in-js/twind/commit/8dfd105bf0b10d82e3d024b6a318a4b7e6064d90)) | ||
## 1.0.0-next.35 | ||
### Patch Changes | ||
- BREAKING: a twind instance is now callable `tw('...')` instead of `tw.inject('...')` ([#239](https://github.com/tw-in-js/twind/pull/239)) | ||
- chore: cleanup eslint rules ([`009594c6`](https://github.com/tw-in-js/twind/commit/009594c65fb7d0f1da0203c6b6c26bd258ee46d0)) | ||
* if `config.tag` is `true` or a custom `tag` function is provided the generated class names are tagged ([#239](https://github.com/tw-in-js/twind/pull/239)) | ||
## 1.0.0-next.34 | ||
- setup github actions for auto release ([#239](https://github.com/tw-in-js/twind/pull/239)) | ||
### Patch Changes | ||
* align `tw` with `cx` and `apply`; it now accepts any number of arguments ans can be used as tagged template literal ([`37164d82`](https://github.com/tw-in-js/twind/commit/37164d822506a9d201f9d463f5c867368fddc89e)) | ||
- add animation helper ([`b56b7282`](https://github.com/tw-in-js/twind/commit/b56b7282cb92cbadd70c8d9dd80be54d665093fe)) | ||
- golf: short properties in ConvertedRule ([#239](https://github.com/tw-in-js/twind/pull/239)) | ||
```js | ||
import { animation, keyframes } from '@twind/core' | ||
## 1.0.0-next.8 | ||
const fadeIn = animation( | ||
'1s ease-out', | ||
keyframes` | ||
0% { | ||
opacity: 0; | ||
} | ||
100% { | ||
opacity: 1; | ||
} | ||
`, | ||
) | ||
``` | ||
* BREAKING: removed support for single line comments (`//`) — CSS comments (`/* ... */`) are supported ([`a3191b5f`](https://github.com/tw-in-js/twind/commit/a3191b5ff0bd2b415fe8589f6a369501f239f7c1)) | ||
- adjust typings for `injectGlobal`, `keyframes`, and `tx` to handle `.call` and `.apply` correctly ([`b9da668c`](https://github.com/tw-in-js/twind/commit/b9da668c12aa80daedf3240f4b721d25b41fc0c4)) | ||
* support arrays for @font-face, @import, and @apply in object notation ([`a3191b5f`](https://github.com/tw-in-js/twind/commit/a3191b5ff0bd2b415fe8589f6a369501f239f7c1)) | ||
## 1.0.0-next.33 | ||
### Patch Changes | ||
- server side generated styles are resumed in the browser ([`b223e5bb`](https://github.com/tw-in-js/twind/commit/b223e5bb9f701db03c30e14d3f7b84b705d43ef0)) | ||
Server side generated styles now include resume data that allows twind in the browser to know which styles are already included in the stylesheet. This change significantly reduces the time to interactive, supports hashed classes, and prevents missing classes that have been generated by `css` or `style` and are not yet registered. | ||
Resuming styles is enabled by default for `setup` (_Shim Mode_). | ||
```js | ||
import { setup } from '@twind/core' | ||
import config from './twind.config' | ||
// styles are resumed! | ||
setup(config) | ||
``` | ||
If you want to used the `dom` sheet during development or if you currently pass a sheet as the second argument, please switch to the new `getSheet(useDOMSheet?: boolean, disableResume?: boolean)` function. This function returns a `Sheet` for the current environment — `virtual` on server, either `dom` or `cssom` in browsers. | ||
```js | ||
import { setup, getSheet } from '@twind/core' | ||
import config from './twind.config' | ||
setup(config, getSheet(process.env.NODE_ENV != 'production')) | ||
``` | ||
If you want to use resuming styles with _Library Mode_ you need to adjust your code to use `getSheet`: | ||
```js | ||
import { twind, getSheet } from '@twind/core' | ||
import config from './twind.config' | ||
export const tw = twind(config, getSheet(process.env.NODE_ENV != 'production')) | ||
``` | ||
To generate server side styles use either `inline` or `extract`: | ||
```js | ||
import { inline, extract } from '@twind/core' | ||
// 1. using inline | ||
const html = inline(renderApp()) | ||
// 2. using extract | ||
const { html, css } = extract(renderApp()) | ||
// add the css to the head using <style data-twind>{css}</style> | ||
``` | ||
The signature of `virtual(includeResumeData?: boolean)` has changed as well. This is technically a breaking change, but I doubt anybody has used the previous possible `virtual([])`. | ||
* expose the used config via `tw.config` ([`92037344`](https://github.com/tw-in-js/twind/commit/92037344787e28454ffa688b969244f261d28306)) | ||
## 1.0.0-next.32 | ||
### Patch Changes | ||
- fixing the strange bug now ([`916e7fb9`](https://github.com/tw-in-js/twind/commit/916e7fb928e3e90703126792d704ad561bc1d01a)) | ||
## 1.0.0-next.31 | ||
### Patch Changes | ||
- bump all packages ([`57405812`](https://github.com/tw-in-js/twind/commit/57405812281dd1bf32b1250c459db9a48466786c)) | ||
## 1.0.0-next.30 | ||
### Patch Changes | ||
- mark the twind style sheet ([`39001d2a`](https://github.com/tw-in-js/twind/commit/39001d2a2b6718a92080ae47cb6157d1077405b3)) | ||
```html | ||
<!-- the SSR stylesheet --> | ||
<style data-twind="ssr"></style> | ||
<!-- the client stylesheet --> | ||
<style data-twind></style> | ||
``` | ||
## 1.0.0-next.29 | ||
### Patch Changes | ||
- ensure dark class condition is always applied last ([`a15d2655`](https://github.com/tw-in-js/twind/commit/a15d26559f3b04144552e3123c04672c4260b23b)) | ||
* fix: native methods such as `bind` not working properly when used on twind's apply helper ([#269](https://github.com/tw-in-js/twind/pull/269)) 🙏🏽 Thanks [@IgnusG](https://github.com/IgnusG)! | ||
- keyframes can be use within arbitrary values `` `animate-[1s_${fadeIn}_ease-out]` `` ([`e1d3433a`](https://github.com/tw-in-js/twind/commit/e1d3433a985a906454d53b289554db026dbd527d)) | ||
* merge multiple group and peer classes ([`2c823293`](https://github.com/tw-in-js/twind/commit/2c82329376ef3f743bc25f355468f4a45c36a3e6)) | ||
`peer-disabled:peer-first-child:group-hover:group-focus:focus:hover:space-x-4` | ||
↓ ↓ ↓ ↓ ↓ ↓ | ||
```css | ||
.peer:first-child:disabled | ||
~ .group:focus:hover | ||
.peer-disabled\\:peer-first-child\\:group-hover\\:group-focus\\:focus\\:hover\\:space-x-4:focus:hover | ||
> :not([hidden]) | ||
~ :not([hidden]) { | ||
--tw-space-x-reverse: 0; | ||
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); | ||
margin-right: calc(1rem * var(--tw-space-x-reverse)); | ||
} | ||
``` | ||
- Fix: keyframes Proxy now passthrough Function's own properties ([#270](https://github.com/tw-in-js/twind/pull/270)) 🙏🏽 Thanks [@danielweck](https://github.com/danielweck)! | ||
## 1.0.0-next.28 | ||
### Patch Changes | ||
- BREAKING: changed the definition of shortcuts within config.rules ([`24b095af`](https://github.com/tw-in-js/twind/commit/24b095af51195a43fe32229e5560aed088b97c0a)) | ||
The new format should be more readable and clear about what is happening. | ||
```js | ||
// defineConfig is optional but helps with type inference | ||
defineConfig({ | ||
rules: [ | ||
/* Some aliases */ | ||
// shortcut: styles are generated as defined by twind — same as if they where used alone | ||
// shortcut to multiple utilities | ||
['card', 'py-2 px-4 font-semibold rounded-lg shadow-md'], | ||
// dynamic shortcut — `$` is everything after the match eg `btn-red` -> `red` | ||
['card-', ({ $ }) => `bg-${$}-400 text-${$}-100 py-2 px-4 rounded-lg`], | ||
// single utility alias — need to use `~(...)` as it would be otherwise recognized as a CSS property | ||
['red', '~(text-red-100)'], | ||
// apply: styles are generated in order they are declared | ||
// apply to multiple utilities | ||
['btn-green', '@(bg-green-500 hover:bg-green-700 text-white)'], | ||
// dynamic apply | ||
['btn-', ({ $ }) => `@(bg-${$}-400 text-${$}-100 py-2 px-4 rounded-lg)`], | ||
/* Some rules */ | ||
['hidden', { display: 'none' }], | ||
// Table Layout | ||
// .table-auto { table-layout: auto } | ||
// .table-fixed { table-layout: fixed } | ||
['table-(auto|fixed)', 'tableLayout'], | ||
// dynamic | ||
['table-', (match, context) => /* ... */], | ||
], | ||
}) | ||
``` | ||
* allow `css()`, `cx()`, and `style()` to be used for rule definition ([`b7280003`](https://github.com/tw-in-js/twind/commit/b728000391cffea29eb4215b79a1b23d75751fe8)) | ||
```js | ||
defineConfig({ | ||
rules: [ | ||
// Using css | ||
[ | ||
'target-new-tab', | ||
css` | ||
target-name: new; | ||
target-new: tab; | ||
`, | ||
], | ||
// dynamic | ||
[ | ||
'target-new-(tab|window)', | ||
({ 1: $1 }) => css` | ||
target-name: new; | ||
target-new: ${$1}; | ||
`, | ||
], | ||
// Using cx | ||
['highlight(-rounded)?', ({ 1: rounded }) => cx({ 'bg-yellow-200': true, rounded })], | ||
// Using style | ||
// `box?color=coral` -> `.box\\?color\\=coral{background-color:coral}` | ||
// `box?rounded` -> `.box\\?rounded{border-radius:0.25rem}` | ||
// `box?color=coral&rounded` -> `.box\\?color\\=coral\\&rounded{background-color:coral;border-radius:0.25rem}` | ||
// `box?color=purple&rounded=md` -> `.box\\?color\\=purple\\&rounded\\=md{background-color:purple;border-radius:0.375rem}` | ||
[ | ||
'box\\?(.+)', | ||
style({ | ||
props: { | ||
color: { | ||
coral: css({ | ||
backgroundColor: 'coral', | ||
}), | ||
purple: css` | ||
background-color: purple; | ||
`, | ||
}, | ||
rounded: { | ||
'': 'rounded', | ||
md: 'rounded-md', | ||
}, | ||
}, | ||
}), | ||
], | ||
], | ||
}) | ||
``` | ||
## 1.0.0-next.27 | ||
### Patch Changes | ||
- fix: ensure sources are included in sourcemap ([`bbbbd88e`](https://github.com/tw-in-js/twind/commit/bbbbd88efc7cb8c0c1b73ade9249389958e1d7cf)) | ||
* add ssr marker to server render twind style ([`e8eaae8b`](https://github.com/tw-in-js/twind/commit/e8eaae8b6034b3117bf781ec374c1cd7e05a2d26)) | ||
- perf: remove unnecessary conditions compare ([`b526c888`](https://github.com/tw-in-js/twind/commit/b526c88843424ef8a6caf93c3236947b59414edd)) | ||
## 1.0.0-next.26 | ||
### Patch Changes | ||
- keyframes: access global tw on usage eg lazily ([`bb288434`](https://github.com/tw-in-js/twind/commit/bb2884347354f3edb2fc888ad1a27d953639b91b)) | ||
* rewritten token parser to better supported nested brackets ([`063b002b`](https://github.com/tw-in-js/twind/commit/063b002bafd4782e7d75cd7bf008d237ab4d5649)) | ||
- filter rules can be used alone and modify defaults selector to include `::before` and `::after` ([`966fcb93`](https://github.com/tw-in-js/twind/commit/966fcb93448ea7fe9e69cd5e67df84163a83617c)) | ||
* ensure tw returned by observe is callable ([`f1fe9a81`](https://github.com/tw-in-js/twind/commit/f1fe9a8180f828da1985b166d4abb0e0e30bc1e0)) | ||
- enhance typings for config.theme ([`2b91cf29`](https://github.com/tw-in-js/twind/commit/2b91cf29967d9fa26d95d792650cfbf3b4ead9c3)) | ||
* cssom: the ownerNode might have already been removed ([`49002cac`](https://github.com/tw-in-js/twind/commit/49002cac273d4e6502e98d985174a27a2b87b7d2)) | ||
## 1.0.0-next.25 | ||
### Patch Changes | ||
- update package badges ([`4527aa91`](https://github.com/tw-in-js/twind/commit/4527aa919f853d613c89df9dde2587173cb91a3a)) | ||
## 1.0.0-next.24 | ||
### Patch Changes | ||
- ensure dark variant is handled correctly within nested groups ([`18f0caff`](https://github.com/tw-in-js/twind/commit/18f0caffb903f0de7f5e7d2f1b8f816e5d0d9fad)) | ||
* add `keyframes` function that lazily injects the keyframes into the sheet and return a unique name ([`a415d389`](https://github.com/tw-in-js/twind/commit/a415d3896ec1981cf1d9a2f884a07be9c8a86bcc)) | ||
- add `injectGlobal` which allows to add CSS to the base layer ([`1800dec7`](https://github.com/tw-in-js/twind/commit/1800dec790a3487280d3342f6a00c32c7221f207)) | ||
* ensure each varaiant occurs only onces eg is unique ([`90da3bbc`](https://github.com/tw-in-js/twind/commit/90da3bbc7d47a26453adf5414012d0f5a2892f5a)) | ||
## 1.0.0-next.23 | ||
### Patch Changes | ||
- allow CSS to be used in preflight and rules ([#252](https://github.com/tw-in-js/twind/pull/252)) | ||
```js | ||
setup({ | ||
preflight: css` | ||
body { | ||
background: theme(colors.gray.100); | ||
} | ||
`, | ||
rules: [ | ||
[ | ||
// bg-red, bg-#ccc, bg-transparent | ||
'bg-', | ||
({ $ }) => | ||
css` | ||
background-color: ${$}; | ||
`, | ||
], | ||
], | ||
}) | ||
``` | ||
* refactor: handling of nested (shortcuts atm) groups ([#252](https://github.com/tw-in-js/twind/pull/252)) | ||
- add `apply` and `@(...)` that uses the given order ([#252](https://github.com/tw-in-js/twind/pull/252)) | ||
* inline: pass html to minify function — allows to only include above-the-fold CSS ([#252](https://github.com/tw-in-js/twind/pull/252)) | ||
## 1.0.0-next.22 | ||
### Patch Changes | ||
- add `tx` as convenient helper for `tw(cx(...))` ([`877152d1`](https://github.com/tw-in-js/twind/commit/877152d1401287aaeaa3f5405ce3d4c9673f7bf0)) | ||
* BREAKING: `tw` accepts only a single string argument (use `cx` for more feature) this reduces the bundle size for the shim mode by 0.25kb ([#251](https://github.com/tw-in-js/twind/pull/251)) | ||
- ensure that `dark` variant is always applied first ([#251](https://github.com/tw-in-js/twind/pull/251)) | ||
* BREAKING: move `darkMode` into twind core ([#251](https://github.com/tw-in-js/twind/pull/251)) | ||
- `inline` can accept an options object with a `minify` to minify the resulting CSS before injecting it ([#251](https://github.com/tw-in-js/twind/pull/251)) | ||
## 1.0.0-next.21 | ||
### Patch Changes | ||
- a custom hash function receives the default hash ([`0a2daf0f`](https://github.com/tw-in-js/twind/commit/0a2daf0f3daf7ebfde103407b5c0e914625c17c9)) | ||
* BREAKING: rename `inject` to `inline` ([`762c5153`](https://github.com/tw-in-js/twind/commit/762c515362f09e13e93ea8c10aa84109b65f13b3)) | ||
## 1.0.0-next.20 | ||
### Patch Changes | ||
- revert: remove dom sheet ([`6d50cf5f`](https://github.com/tw-in-js/twind/commit/6d50cf5f7bd8fb79caf02a81c30060c8abf2382e)) | ||
## 1.0.0-next.19 | ||
### Patch Changes | ||
- fix variant cache condition ([`1f578c9e`](https://github.com/tw-in-js/twind/commit/1f578c9ede1882ee714db249a6bed48c0e1e3059)) | ||
## 1.0.0-next.18 | ||
### Patch Changes | ||
- add inject(html) helper to simplify extracting CSS and injecting it into the head element ([#247](https://github.com/tw-in-js/twind/pull/247)) | ||
## 1.0.0-next.17 | ||
### Patch Changes | ||
- bump to same version ([`ca157601`](https://github.com/tw-in-js/twind/commit/ca1576017f172bfb0ba61e936f0f44d36102016c)) | ||
## 1.0.0-next.16 | ||
### Patch Changes | ||
- BREAKING(@twind/runtime): renamed `init` to `setup` to better align with other APIs ([#245](https://github.com/tw-in-js/twind/pull/245)) | ||
* use `data-twind` to locate SSR style element ([#245](https://github.com/tw-in-js/twind/pull/245)) | ||
* Updated dependencies [[`ae9c1201`](https://github.com/tw-in-js/twind/commit/ae9c1201918ea316e14d452818663847886507fa), [`ed21b253`](https://github.com/tw-in-js/twind/commit/ed21b253ea1403ebfee0f38060b5fa8670bcaebb), [`5d40cc5b`](https://github.com/tw-in-js/twind/commit/5d40cc5bbf2f0f8b2f1769ca95630b7d83d6ef8f), [`6bdf326f`](https://github.com/tw-in-js/twind/commit/6bdf326f8aa41bfdc89d77a47f24433536f3c9a5), [`f0715269`](https://github.com/tw-in-js/twind/commit/f0715269afe91c7cbaaf97ee7e21bb99080f37b0), [`13b806cd`](https://github.com/tw-in-js/twind/commit/13b806cd3f74550bdc43cdc995026ee6d65b894f), [`82de0d53`](https://github.com/tw-in-js/twind/commit/82de0d53755f35c72fe41200f9091bdc2c960f83)]: | ||
- @twind/runtime@1.0.0-next.14 | ||
- @twind/core@1.0.0-next.14 | ||
- @twind/preset-autoprefix@1.0.0-next.14 | ||
- @twind/preset-tailwind@1.0.0-next.15 | ||
## 1.0.0-next.15 | ||
### Patch Changes | ||
- ensure globale `twind_core` variable points to bundled `@twind/core` which allows presets to uses it ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
* all bundles should use the same globalName `twind` ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
- BREAKING(preset authors): removed `preset()` helper to simplify config merging — What needs to change? instead calling preset, return your preset ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
* add `comsume(html, tw)` to process static HTML ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
- only update class attributes if the class names within are different (ignore order) ([#244](https://github.com/tw-in-js/twind/pull/244)) | ||
- Updated dependencies [[`61509050`](https://github.com/tw-in-js/twind/commit/61509050a539a0e2e28ec961f7e7bc8ffa15a9e0), [`d45cdfd9`](https://github.com/tw-in-js/twind/commit/d45cdfd98ebccabc3c9376660a077b29f295765b), [`6178fdc8`](https://github.com/tw-in-js/twind/commit/6178fdc8363e9d04133fe14818b522cd07f9d9d1), [`01ac6b62`](https://github.com/tw-in-js/twind/commit/01ac6b62dabf1c2217342ce4ec23ffef272ab780), [`599b903a`](https://github.com/tw-in-js/twind/commit/599b903ab3e9d59cdea47948d46abffe64e8cbe2), [`30b374f6`](https://github.com/tw-in-js/twind/commit/30b374f61bab1780a654b0475c12e993d4b57524), [`d9123489`](https://github.com/tw-in-js/twind/commit/d912348915675a1928df91965b701d7b6eefebf8), [`115a5b07`](https://github.com/tw-in-js/twind/commit/115a5b079972fefe468f9c9ed51ef8feea403690), [`a8a0bf49`](https://github.com/tw-in-js/twind/commit/a8a0bf49cec96285ae79ff6ada9c718784c11d6e), [`0614955f`](https://github.com/tw-in-js/twind/commit/0614955f56aca56c9937e80b3eb5d6ec1b55ec0b), [`67f39048`](https://github.com/tw-in-js/twind/commit/67f39048127c777388b549b6630ea1100d757d35), [`2093be98`](https://github.com/tw-in-js/twind/commit/2093be98bb58c393e29bef93c0e8d425cb97bc1d)]: | ||
- @twind/runtime@1.0.0-next.13 | ||
- @twind/core@1.0.0-next.13 | ||
- @twind/preset-autoprefix@1.0.0-next.13 | ||
- @twind/preset-tailwind@1.0.0-next.14 | ||
## 1.0.0-next.14 | ||
### Patch Changes | ||
- Updated dependencies [[`eb875119`](https://github.com/tw-in-js/twind/commit/eb8751194b21ec0941483e9a72d61a36d90e73da)]: | ||
- @twind/preset-tailwind@1.0.0-next.13 | ||
## 1.0.0-next.13 | ||
### Patch Changes | ||
- introduce `twind/cdn`: a bore bones Tailwind CSS replacement — no additional exports like (`cx`, `style` or `css`) ([`9bc26949`](https://github.com/tw-in-js/twind/commit/9bc26949dd729b7002bc27032bb2f999e766546d)) | ||
- Updated dependencies [[`9bc26949`](https://github.com/tw-in-js/twind/commit/9bc26949dd729b7002bc27032bb2f999e766546d)]: | ||
- @twind/core@1.0.0-next.12 | ||
- @twind/preset-autoprefix@1.0.0-next.12 | ||
- @twind/preset-tailwind@1.0.0-next.12 | ||
- @twind/runtime@1.0.0-next.12 | ||
## 1.0.0-next.12 | ||
### Patch Changes | ||
- Updated dependencies [[`c595b348`](https://github.com/tw-in-js/twind/commit/c595b348dc06ce3061322bcc8235463d2f27d488), [`dc778be0`](https://github.com/tw-in-js/twind/commit/dc778be038180c8f0409adc044305d565d35493f), [`2ba630a3`](https://github.com/tw-in-js/twind/commit/2ba630a36237bdeb428976ab959268e8faee2128), [`5848d13f`](https://github.com/tw-in-js/twind/commit/5848d13f70037c237364b08195a71fe8f8049e1f), [`f41e367f`](https://github.com/tw-in-js/twind/commit/f41e367fa03bb335c2d1226d954d68b725707740), [`bea09c04`](https://github.com/tw-in-js/twind/commit/bea09c040bbe3a6cd4df3530d6090441a1e40535), [`123fb7f8`](https://github.com/tw-in-js/twind/commit/123fb7f897cc2d7999c446c896c622cb4df4712c)]: | ||
- @twind/core@1.0.0-next.11 | ||
- @twind/preset-ext@1.0.0-next.11 | ||
- @twind/preset-tailwind@1.0.0-next.11 | ||
- @twind/preset-autoprefix@1.0.0-next.11 | ||
- @twind/runtime@1.0.0-next.11 | ||
## 1.0.0-next.11 | ||
### Patch Changes | ||
- rename `@twind/preset-mini` to `@twind/preset-ext` ([`d9e8c3a1`](https://github.com/tw-in-js/twind/commit/d9e8c3a12fddb85de4b7f5b0a02a9a9ddcd9c6f8)) | ||
- Updated dependencies [[`8d846cf2`](https://github.com/tw-in-js/twind/commit/8d846cf2b8c5e4d8042c41ab1079109230c92612), [`b2c7f824`](https://github.com/tw-in-js/twind/commit/b2c7f8249a15acc434601c55b0b0b0af2bc5dfa9), [`3e76ea1b`](https://github.com/tw-in-js/twind/commit/3e76ea1ba46b076920ae4029272d64c3a3b21e6b), [`9ac89873`](https://github.com/tw-in-js/twind/commit/9ac89873517e03960f7af8784efe441172b3cbb1), [`a5f112fa`](https://github.com/tw-in-js/twind/commit/a5f112fa4c3dd2ce63334d5111ba04468750911b)]: | ||
- @twind/core@1.0.0-next.10 | ||
- @twind/preset-tailwind@1.0.0-next.10 | ||
- @twind/preset-autoprefix@1.0.0-next.10 | ||
- @twind/preset-ext@1.0.0-next.10 | ||
- @twind/runtime@1.0.0-next.10 | ||
## 1.0.0-next.10 | ||
### Patch Changes | ||
- BREAKING: a twind instance is now callable `tw('...')` instead of `tw.inject('...')` ([#239](https://github.com/tw-in-js/twind/pull/239)) | ||
* setup github actions for auto release ([#239](https://github.com/tw-in-js/twind/pull/239)) | ||
* Updated dependencies [[`56b9adef`](https://github.com/tw-in-js/twind/commit/56b9adef3f8779ad649d89fc69db321a9b8ee71e), [`f618afd7`](https://github.com/tw-in-js/twind/commit/f618afd7c82e372dd64da03eda8ee6f86d70d174), [`bec4218d`](https://github.com/tw-in-js/twind/commit/bec4218d9fe6f8c214aea5100379454c6b11583f), [`37164d82`](https://github.com/tw-in-js/twind/commit/37164d822506a9d201f9d463f5c867368fddc89e), [`e284b0f4`](https://github.com/tw-in-js/twind/commit/e284b0f43c97d53a81fee15ac15406c8db0e694e)]: | ||
- @twind/core@1.0.0-next.9 | ||
- @twind/preset-mini@1.0.0-next.9 | ||
- @twind/preset-tailwind@1.0.0-next.9 | ||
- @twind/runtime@1.0.0-next.9 | ||
- @twind/preset-autoprefix@1.0.0-next.9 | ||
## 1.0.0-next.9 | ||
### Patch Changes | ||
- adding stitches like style helper ([`7360f15a`](https://github.com/tw-in-js/twind/commit/7360f15a828ccd136a0eb40bbe6ccd629b145361)) | ||
* reduce exported types, rename `@label` to `label`, rename some layers ([`be5def30`](https://github.com/tw-in-js/twind/commit/be5def30416835d8100f6c0c3e88b38ab8171487)) | ||
- Updated dependencies [[`cc3c4fee`](https://github.com/tw-in-js/twind/commit/cc3c4fee9d5b572faf46838a0287d30b9eb0045f), [`7360f15a`](https://github.com/tw-in-js/twind/commit/7360f15a828ccd136a0eb40bbe6ccd629b145361), [`be5def30`](https://github.com/tw-in-js/twind/commit/be5def30416835d8100f6c0c3e88b38ab8171487)]: | ||
- @twind/preset-mini@1.0.0-next.8 | ||
- @twind/preset-tailwind@1.0.0-next.8 | ||
- @twind/core@1.0.0-next.8 | ||
- @twind/preset-autoprefix@1.0.0-next.8 | ||
- @twind/runtime@1.0.0-next.8 | ||
## 1.0.0-next.7 | ||
## 1.0.0-next.8 | ||
@@ -105,2 +763,24 @@ ### Patch Changes | ||
* Updated dependencies [[`2a9f1685`](https://github.com/tw-in-js/twind/commit/2a9f1685843b50b741dbe0338f4cf068603411c8), [`a7b25242`](https://github.com/tw-in-js/twind/commit/a7b252425e3f38ce2b5d2097e63d23cca5c6c4f2)]: | ||
- @twind/core@1.0.0-next.7 | ||
- @twind/runtime@1.0.0-next.7 | ||
- @twind/preset-autoprefix@1.0.0-next.7 | ||
- @twind/preset-mini@1.0.0-next.7 | ||
- @twind/preset-tailwind@1.0.0-next.7 | ||
## 1.0.0-next.7 | ||
### Patch Changes | ||
- allow twind and @twind/runime package to be used outside of a DOM environment ([`d8705f9d`](https://github.com/tw-in-js/twind/commit/d8705f9d3b812f2aa71c6d19efdbc743f90cffcb)) | ||
* extract runtime into own package with re-worked autoinit using MutationObserver ([`aa96aef4`](https://github.com/tw-in-js/twind/commit/aa96aef4037d773c1880bfed0c07a7952a668412)) | ||
* Updated dependencies [[`184d96ff`](https://github.com/tw-in-js/twind/commit/184d96ffb934e621bb07f8ccbf809a6a14675298), [`a3d09cf4`](https://github.com/tw-in-js/twind/commit/a3d09cf40db55fb980441500121bf1820ea2a3ae), [`d8705f9d`](https://github.com/tw-in-js/twind/commit/d8705f9d3b812f2aa71c6d19efdbc743f90cffcb), [`aa96aef4`](https://github.com/tw-in-js/twind/commit/aa96aef4037d773c1880bfed0c07a7952a668412), [`881e1e16`](https://github.com/tw-in-js/twind/commit/881e1e16005cecd1930cdb988f6983c2b1aff516)]: | ||
- @twind/core@1.0.0-next.6 | ||
- @twind/preset-mini@1.0.0-next.6 | ||
- @twind/preset-tailwind@1.0.0-next.6 | ||
- @twind/runtime@1.0.0-next.6 | ||
- @twind/preset-autoprefix@1.0.0-next.6 | ||
## 1.0.0-next.6 | ||
@@ -110,6 +790,8 @@ | ||
- observe document.body instead of document.documentElement (fixes [#172](https://github.com/tw-in-js/twind/issues/172)) ([`184d96ff`](https://github.com/tw-in-js/twind/commit/184d96ffb934e621bb07f8ccbf809a6a14675298)) | ||
- Updated dependencies [[`d68ce341`](https://github.com/tw-in-js/twind/commit/d68ce3413ae29b6ea7cd88d3c094e59876d7e5d5), [`2c5792f9`](https://github.com/tw-in-js/twind/commit/2c5792f9c2c1295a7d0aac094e9aa760999f5cc0)]: | ||
- @twind/core@1.0.0-next.5 | ||
- @twind/preset-tailwind@1.0.0-next.5 | ||
- @twind/preset-autoprefix@1.0.0-next.5 | ||
- @twind/preset-mini@1.0.0-next.5 | ||
* fix selector generation ([`a3d09cf4`](https://github.com/tw-in-js/twind/commit/a3d09cf40db55fb980441500121bf1820ea2a3ae)) | ||
## 1.0.0-next.5 | ||
@@ -119,5 +801,9 @@ | ||
- observe: remove hidden attribute from body alongside html (fixes [#172](https://github.com/tw-in-js/twind/issues/172)) ([`d68ce341`](https://github.com/tw-in-js/twind/commit/d68ce3413ae29b6ea7cd88d3c094e59876d7e5d5)) | ||
- add `apply` as known from twind v0.16 ([`230a57ba`](https://github.com/tw-in-js/twind/commit/230a57ba6c6d77ae73ffc6b6a426b9c28ba8c908)) | ||
* support negative order ([`2c5792f9`](https://github.com/tw-in-js/twind/commit/2c5792f9c2c1295a7d0aac094e9aa760999f5cc0)) | ||
- Updated dependencies [[`af822490`](https://github.com/tw-in-js/twind/commit/af822490d0a02a2fc227b8bc19471141a5586de2), [`bda8c19c`](https://github.com/tw-in-js/twind/commit/bda8c19c9abb80678225b5c947db87e1a4f07aa6), [`3382dd0b`](https://github.com/tw-in-js/twind/commit/3382dd0be26fcedba466d1ac011f76403ece278d), [`230a57ba`](https://github.com/tw-in-js/twind/commit/230a57ba6c6d77ae73ffc6b6a426b9c28ba8c908)]: | ||
- @twind/core@1.0.0-next.4 | ||
- @twind/preset-tailwind@1.0.0-next.4 | ||
- @twind/preset-mini@1.0.0-next.4 | ||
- @twind/preset-autoprefix@1.0.0-next.4 | ||
@@ -128,8 +814,10 @@ ## 1.0.0-next.4 | ||
- `cx` expands groups ([`af822490`](https://github.com/tw-in-js/twind/commit/af822490d0a02a2fc227b8bc19471141a5586de2)) | ||
- ensure there is config object when called from setTimeout | ||
* revert to parenthesis grouping syntax ([`bda8c19c`](https://github.com/tw-in-js/twind/commit/bda8c19c9abb80678225b5c947db87e1a4f07aa6)) | ||
- Updated dependencies []: | ||
- @twind/core@1.0.0-next.3 | ||
- @twind/preset-autoprefix@1.0.0-next.3 | ||
- @twind/preset-mini@1.0.0-next.3 | ||
- @twind/preset-tailwind@1.0.0-next.3 | ||
- add `apply` as known from twind v0.16 ([`230a57ba`](https://github.com/tw-in-js/twind/commit/230a57ba6c6d77ae73ffc6b6a426b9c28ba8c908)) | ||
## 1.0.0-next.3 | ||
@@ -139,10 +827,14 @@ | ||
- fix invalid offset calculation for cssom sheet if rules failed to insert | ||
- expose `tw` and `apply` for twind v0.16 compatibility ([`79c63ef9`](https://github.com/tw-in-js/twind/commit/79c63ef9ed3dda9f3bfafde977016b3b75db7c4c)) | ||
## 1.0.0-next.2 | ||
* expose setup function to configure twind ([`79c63ef9`](https://github.com/tw-in-js/twind/commit/79c63ef9ed3dda9f3bfafde977016b3b75db7c4c)) | ||
### Patch Changes | ||
- BREAKING: renamed umd bundles to global (`twind.global.js`) and there are plain IIFEs ([`79c63ef9`](https://github.com/tw-in-js/twind/commit/79c63ef9ed3dda9f3bfafde977016b3b75db7c4c)) | ||
- Updated dependencies [[`79c63ef9`](https://github.com/tw-in-js/twind/commit/79c63ef9ed3dda9f3bfafde977016b3b75db7c4c)]: | ||
- @twind/core@1.0.0-next.2 | ||
- @twind/preset-autoprefix@1.0.0-next.2 | ||
- @twind/preset-mini@1.0.0-next.2 | ||
- @twind/preset-tailwind@1.0.0-next.2 | ||
## 1.0.0-next.1 | ||
@@ -153,1 +845,6 @@ | ||
- Initial publish of twind v1 preview ([`179b9653`](https://github.com/tw-in-js/twind/commit/179b9653de661a62a661c80d5506ae68f7964aba)) | ||
- Updated dependencies [[`179b9653`](https://github.com/tw-in-js/twind/commit/179b9653de661a62a661c80d5506ae68f7964aba)]: | ||
- @twind/core@1.0.0-next.1 | ||
- @twind/preset-autoprefix@1.0.0-next.1 | ||
- @twind/preset-tailwind@1.0.0-next.1 |
854
core.d.ts
@@ -12,15 +12,19 @@ import * as CSS$1 from 'csstype'; | ||
'@import'?: MaybeArray<string | Falsey>; | ||
'@font-face'?: CSSFontFace; | ||
'@font-face'?: MaybeArray<CSSFontFace>; | ||
} | ||
interface CustomProperties { | ||
label?: string; | ||
'@apply'?: string | Falsey; | ||
'@apply'?: MaybeArray<string> | Falsey; | ||
} | ||
declare type CSSProperties = CSS$1.PropertiesFallback<string | Falsey, string | Falsey> & CSS$1.PropertiesHyphenFallback<string | Falsey, string | Falsey> & Partial<CustomProperties>; | ||
declare type CSSFontFace = CSS$1.AtRule.FontFaceFallback & CSS$1.AtRule.FontFaceHyphenFallback; | ||
interface CSSNested extends Record<string, CSSProperties | CSSObject | string | Falsey> { | ||
interface CSSNested extends Record<string, CSSProperties | MaybeArray<CSSObject | string> | Falsey> { | ||
} | ||
declare type CSSBase = BaseProperties & CSSNested; | ||
declare type CSSObject = CSSProperties & CSSBase; | ||
declare type Preflight = CSSBase; | ||
declare type CSSValue = string | number | bigint | Falsey | StringLike; | ||
declare type StringLike = { | ||
toString(): string; | ||
} & string; | ||
declare type Preflight = CSSBase | string; | ||
interface TwindRule { | ||
@@ -39,6 +43,9 @@ /** The calculated precedence taking all variants into account. */ | ||
} | ||
declare type RestoreSnapshot = () => void; | ||
interface Twind<Theme extends BaseTheme = BaseTheme, Target = unknown> { | ||
(strings: TemplateStringsArray | Class, ...interpolations: Class[]): string; | ||
(tokens: StringLike): string; | ||
readonly target: Target; | ||
theme: ThemeFunction<Theme>; | ||
readonly theme: ThemeFunction<ExtractUserTheme<Theme>>; | ||
readonly config: TwindConfig<Theme>; | ||
snapshot(): RestoreSnapshot; | ||
/** Clears all CSS rules from the sheet. */ | ||
@@ -56,2 +63,8 @@ clear(): void; | ||
/** | ||
* returns the dark color | ||
* | ||
* @private | ||
*/ | ||
d(section: string, key: string, color: ColorValue): ColorValue | Falsey; | ||
/** | ||
* resolves a variant | ||
@@ -61,3 +74,3 @@ * | ||
*/ | ||
v(value: string): string; | ||
v: (value: string) => MaybeArray<string>; | ||
/** | ||
@@ -68,3 +81,3 @@ * resolves a rule | ||
*/ | ||
r(value: string): RuleResult; | ||
r: (value: string, isDark?: boolean) => RuleResult; | ||
/** | ||
@@ -75,3 +88,3 @@ * stringifies a CSS property and value to a declaration | ||
*/ | ||
s(property: string, value: string): string; | ||
s: (property: string, value: string) => string; | ||
} | ||
@@ -89,18 +102,15 @@ declare type ThemeValue<T> = T extends Record<string, infer V> ? Exclude<V, Record<string, V>> : T; | ||
<Section extends keyof Theme & string>(key: `${Section}.${string}`, defaultValue: ThemeValue<Theme[Section]>): ThemeValue<Theme[Section]>; | ||
(section: string): unknown | undefined; | ||
(section: string, key: string): unknown | string | undefined; | ||
<T>(section: string, key: string, defaultValue: T): T | string; | ||
<T>(key: string, defaultValue: T): T | string; | ||
} | ||
declare type RuleResult = string | CSSObject | Falsey | Partial<TwindRule>[]; | ||
declare type RuleResolver<Theme extends BaseTheme = BaseTheme> = (match: MatchResult, context: Context<Theme>) => RuleResult; | ||
declare type ShortcutResolver<Theme extends BaseTheme = BaseTheme> = (match: MatchResult, context: Context<Theme>) => string | Falsey; | ||
declare type Shortcuts<Theme extends BaseTheme = BaseTheme> = { | ||
[classname: string]: string | ShortcutResolver<Theme>; | ||
}; | ||
declare type Rule<Theme extends BaseTheme = BaseTheme> = string | RegExp | Shortcuts<Theme> | [ | ||
condition: MaybeArray<string | RegExp>, | ||
resolve: keyof CSSProperties | string | CSSObject | RuleResolver<Theme> | ||
] | [ | ||
condition: MaybeArray<string | RegExp>, | ||
declare type RuleResolver<Theme extends BaseTheme = BaseTheme, Match extends MatchResult = MatchResult> = (match: Match, context: Context<Theme>) => RuleResult; | ||
declare type Rule<Theme extends BaseTheme = BaseTheme> = string | RegExp | [pattern: MaybeArray<string | RegExp>, alias: string & {}] | [pattern: MaybeArray<string | RegExp>, css: CSSObject] | [pattern: MaybeArray<string | RegExp>, resolve: RuleResolver<Theme>] | [pattern: MaybeArray<string | RegExp>, property: keyof CSSProperties] | [ | ||
pattern: MaybeArray<string | RegExp>, | ||
property: keyof CSSProperties, | ||
convert: MatchConverter<Theme> | ||
]; | ||
declare type VariantResult = string | Falsey; | ||
declare type VariantResult = MaybeArray<string> | Falsey; | ||
declare type VariantResolver<Theme extends BaseTheme = BaseTheme> = (match: MatchResult, context: Context<Theme>) => VariantResult; | ||
@@ -114,14 +124,58 @@ declare type Variant<Theme extends BaseTheme = BaseTheme> = [ | ||
$$: string; | ||
/** Can be used to propagate a value like a theme value */ | ||
dark?: boolean; | ||
}; | ||
interface SheetRule { | ||
/** The calculated precedence taking all variants into account. */ | ||
p: number; | ||
o: number; | ||
/** The name to use for `&` expansion in selectors. Maybe empty for at-rules like `@import`, `@font-face`, `@media`, ... */ | ||
n?: string | null; | ||
} | ||
interface Sheet<Target = unknown> { | ||
readonly target: Target; | ||
insert(css: string, index: number, rule: TwindRule): void; | ||
insert(cssText: string, index: number, rule: SheetRule): void; | ||
snapshot(): RestoreSnapshot; | ||
/** Clears all CSS rules from the sheet. */ | ||
clear(): void; | ||
destroy(): void; | ||
resume(addClassName: (className: string) => void, insert: (cssText: string, rule: SheetRule) => void): void; | ||
} | ||
declare type StringifyDeclaration<Theme extends BaseTheme = BaseTheme> = (property: string, value: string, context: Context<Theme>) => string; | ||
declare type PreflightThunk<Theme extends BaseTheme = BaseTheme> = (context: Context<Theme>) => Preflight | Falsey; | ||
declare type HashFunction = (value: string) => string; | ||
declare type HashFunction = (value: string, defaultHash: (value: string) => string) => string; | ||
declare type DarkModeConfig = 'media' | 'class' | (string & {}) | boolean | undefined | [mode: 'class', selector: string]; | ||
/** | ||
* Allows to return a dark color for the given light color. | ||
* | ||
* ```js | ||
* { | ||
* // 50 -> 900, 100 -> 800, ..., 800 -> 100, 900 -> 50 | ||
* darkColor: autoDarkColor | ||
* // custom resolvers | ||
* darkColor: (section, key, { theme }) => theme(`${section}.${key}-dark`) as ColorValue | ||
* darkColor: (section, key, { theme }) => theme(`dark.${section}.${key}`) as ColorValue | ||
* darkColor: (section, key, { theme }) => theme(`${section}.dark.${key}`) as ColorValue | ||
* darkColor: (section, key, context, lightColor) => generateDarkColor(lightColor), | ||
* } | ||
* ``` | ||
* | ||
* Or use the light color to generate a dark color | ||
* | ||
* ```js | ||
* { | ||
* darkColor: (section, key, context, color) => generateDark(color) | ||
* } | ||
* ``` | ||
* @param section the theme section | ||
* @param key the theme key within section — maybe an arbitrary value `[...]` | ||
* @param context the context | ||
* @param color the current color | ||
* @returns the dark color to use | ||
*/ | ||
declare type DarkColor<Theme extends BaseTheme> = (section: string, key: string, context: Context<Theme>, color: ColorValue) => ColorValue | Falsey; | ||
interface TwindConfig<Theme extends BaseTheme = BaseTheme> { | ||
/** Allows to change how the `dark` variant is used (default: `"media"`) */ | ||
darkMode?: DarkModeConfig; | ||
darkColor?: DarkColor<Theme>; | ||
theme: ThemeConfig<Theme>; | ||
@@ -137,7 +191,14 @@ preflight: false | MaybeThunk<Preflight | Falsey, Theme>[]; | ||
declare type ExtractTheme<T> = T extends Preset<infer Theme> ? Theme : T; | ||
declare type ExtractUserTheme<T> = { | ||
[key in keyof T]: key extends 'extend' ? never : T[key] extends ThemeSectionResolver<infer Value, T & BaseTheme> ? Value : T[key]; | ||
} & BaseTheme; | ||
/** @experimental */ | ||
declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; | ||
declare type ExtractThemes<Theme, Presets extends Preset<any>[]> = UnionToIntersection<ExtractTheme<Omit<Theme, 'extend'> | BaseTheme | ArrayType<Presets>>>; | ||
declare type ExtractThemes<Theme, Presets extends Preset<any>[]> = UnionToIntersection<ExtractTheme<ExtractUserTheme<Theme> | BaseTheme | ArrayType<Presets>>>; | ||
interface TwindPresetConfig<Theme = BaseTheme> { | ||
/** Allows to change how the `dark` variant is used (default: `"media"`) */ | ||
darkMode?: DarkModeConfig; | ||
darkColor?: DarkColor<Theme & BaseTheme>; | ||
theme?: ThemeConfig<Theme & BaseTheme>; | ||
preflight?: false | Preflight | PreflightThunk<Theme & BaseTheme>; | ||
preflight?: false | MaybeArray<Preflight | PreflightThunk<Theme & BaseTheme>>; | ||
variants?: Variant<Theme & BaseTheme>[]; | ||
@@ -147,10 +208,30 @@ rules?: Rule<Theme & BaseTheme>[]; | ||
stringify?: StringifyDeclaration<Theme & BaseTheme>; | ||
ignorelist?: (string | RegExp)[]; | ||
ignorelist?: MaybeArray<string | RegExp>; | ||
} | ||
interface TwindUserConfig<Theme = BaseTheme, Presets extends Preset<any>[] = Preset[]> { | ||
presets?: Presets; | ||
theme?: Theme & ThemeConfig<BaseTheme & ExtractThemes<Theme, Presets>>; | ||
preflight?: false | Preflight | PreflightThunk<BaseTheme & ExtractThemes<Theme, Presets>>; | ||
/** Allows to change how the `dark` variant is used (default: `"media"`) */ | ||
darkMode?: DarkModeConfig; | ||
darkColor?: DarkColor<BaseTheme & ExtractThemes<Theme, Presets>>; | ||
theme?: Theme | ThemeConfig<BaseTheme & ExtractThemes<Theme, Presets>>; | ||
preflight?: false | MaybeArray<Preflight | PreflightThunk<BaseTheme & ExtractThemes<Theme, Presets>>>; | ||
variants?: Variant<BaseTheme & ExtractThemes<Theme, Presets>>[]; | ||
rules?: Rule<BaseTheme & ExtractThemes<Theme, Presets>>[]; | ||
/** | ||
* Enables hashing of all classes (default: `false`). | ||
* | ||
* If a function is given it can be used to hash only certain classes: | ||
* | ||
* ```js | ||
* { | ||
* hash(className, defaultHash) { | ||
* if (/^[~@]\(/.test(className)) { | ||
* // a shortcut like `~(...)` or apply like `@(...)` | ||
* return defaultHash(className) | ||
* } | ||
* return className | ||
* } | ||
* } | ||
*``` | ||
*/ | ||
hash?: boolean | undefined | HashFunction; | ||
@@ -201,3 +282,3 @@ stringify?: StringifyDeclaration<BaseTheme & ExtractThemes<Theme, Presets>>; | ||
}; | ||
declare type MatchConverter<Theme extends BaseTheme = BaseTheme> = (match: MatchResult, context: Context<Theme>) => string; | ||
declare type MatchConverter<Theme extends BaseTheme = BaseTheme, Match extends MatchResult = MatchResult> = (match: Match, context: Context<Theme>) => string; | ||
interface PresetThunk<Theme = BaseTheme> { | ||
@@ -211,89 +292,211 @@ (config: TwindConfig<Theme & BaseTheme>): TwindPresetConfig<Theme>; | ||
declare type Class = string | number | boolean | Falsey | ClassObject | Class[]; | ||
declare type NestedFunction = (strings: TemplateStringsArray | Class, ...interpolations: Class[]) => string; | ||
declare type Nested = NestedFunction & { | ||
[label: string]: NestedFunction; | ||
}; | ||
declare function toColorValue(color: ColorValue, options?: ColorFunctionOptions): string; | ||
/** | ||
* @group Class Name Generators | ||
*/ | ||
declare const apply: Nested; | ||
/** | ||
* @group Class Name Generators | ||
*/ | ||
declare const shortcut: Nested; | ||
interface AnimationFunction { | ||
(animation: string | CSSProperties, waypoints: StringLike): StringLike; | ||
} | ||
declare type Animation = AnimationFunction & { | ||
[label: string]: AnimationFunction; | ||
}; | ||
/** | ||
* Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
* @group Class Name Generators | ||
*/ | ||
declare const animation: Animation; | ||
declare type AutocompleteItem = { | ||
prefix?: string; | ||
suffix: string; | ||
theme?: { | ||
section: string; | ||
key: string; | ||
}; | ||
modifiers?: AutocompleteModifier[] | false | null | undefined; | ||
color?: string | false | null | undefined; | ||
label?: string; | ||
}; | ||
declare type AutocompleteModifier = { | ||
modifier: string; | ||
theme?: { | ||
section: string; | ||
key: string; | ||
}; | ||
color?: string | false | null | undefined; | ||
label?: string; | ||
}; | ||
interface AutocompleteContext<Theme extends BaseTheme = BaseTheme> { | ||
/** Allows to resolve theme values. */ | ||
readonly theme: ThemeFunction<Theme>; | ||
readonly variants: Record<string, string>; | ||
} | ||
declare type AutocompleteProvider<Theme extends BaseTheme = BaseTheme> = (match: MatchResult, context: AutocompleteContext<Theme>) => (string | AutocompleteItem)[]; | ||
/** | ||
* @experimental | ||
* @group Configuration | ||
* @param resolver | ||
* @param autocomplete | ||
*/ | ||
declare function withAutocomplete<Theme extends BaseTheme = BaseTheme>(resolver: RuleResolver<Theme>, autocomplete: AutocompleteProvider<Theme> | false | null | undefined): RuleResolver<Theme>; | ||
declare function withAutocomplete<Theme extends BaseTheme = BaseTheme>(resolver: VariantResolver<Theme>, autocomplete: AutocompleteProvider<Theme> | false | null | undefined): VariantResolver<Theme>; | ||
declare function withAutocomplete<Theme extends BaseTheme = BaseTheme>(rule: Rule<Theme>, autocomplete: AutocompleteProvider<Theme> | false | null | undefined): Rule<Theme>; | ||
/** | ||
* @internal | ||
* @param resolver | ||
* @returns | ||
*/ | ||
declare function getAutocompleteProvider<Theme extends BaseTheme = BaseTheme>(resolver: RuleResolver<Theme> | VariantResolver<Theme>): AutocompleteProvider<Theme> | undefined; | ||
/** | ||
* @internal | ||
* @param color | ||
* @param options | ||
* @returns | ||
*/ | ||
declare function toColorValue(color: ColorValue, options?: ColorFunctionOptions): string; | ||
/** | ||
* Looks for a matching dark color within a [tailwind color palette](https://tailwindcss.com/docs/customizing-colors) (`50`, `100`, `200`, ..., `800`, `900`). | ||
* | ||
* 1. parse the markup and process element classes with the provided Twind instance | ||
* 2. update the class attributes _if_ necessary | ||
* 3. return the HTML string with the final element classes | ||
* | ||
* ```js | ||
* import { twind, virtual, consume, stringify } from '@twind/core' | ||
* defineConfig({ | ||
* darkColor: autoDarkColor, | ||
* }) | ||
* ``` | ||
* | ||
* // can be re-used | ||
* const tw = twind(config, virtual()} | ||
* **Note**: Does not work for arbitrary values like `[theme(colors.gray.500)]` or `[theme(colors.gray.500, #ccc)]`. | ||
* | ||
* function render() { | ||
* const html = renderApp() | ||
* @group Configuration | ||
* @param section within theme to use | ||
* @param key of the light color or an arbitrary value | ||
* @param context to use | ||
* @returns the dark color if found | ||
*/ | ||
declare function autoDarkColor(section: string, key: string, { theme }: Context<any>): ColorValue | Falsey; | ||
/** | ||
* @group Class Name Generators | ||
* @param strings | ||
* @param interpolations | ||
*/ | ||
declare function css(strings: TemplateStringsArray, ...interpolations: readonly CSSValue[]): string; | ||
declare function css(style: CSSObject | string): string; | ||
/** | ||
* Constructs `class` strings conditionally. | ||
* | ||
* // clear all styles | ||
* tw.clear() | ||
* Twinds version of popular libraries like [classnames](https://github.com/JedWatson/classnames) or [clsx](https://github.com/lukeed/clsx). | ||
* The key advantage of `cx` is that it supports twinds enhanced class name syntax like grouping and aliases. | ||
* | ||
* // generated markup | ||
* const markup = consume(html, tw) | ||
* @group Class Name Generators | ||
* @param strings | ||
* @param interpolations | ||
* @returns | ||
*/ | ||
declare function cx(strings: TemplateStringsArray, ...interpolations: Class[]): string; | ||
/** | ||
* Constructs `class` strings conditionally. | ||
* | ||
* // create CSS | ||
* const css = stringify(tw.target) | ||
* Twinds version of popular libraries like [classnames](https://github.com/JedWatson/classnames) or [clsx](https://github.com/lukeed/clsx). | ||
* The key advantage of `cx` is that it supports twinds enhanced class name syntax like grouping and aliases. | ||
* | ||
* // inject as last element into the head | ||
* return markup.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* @param markup HTML to process | ||
* @param tw a {@link Twind} instance | ||
* @returns possibly modified HTML | ||
* @group Class Name Generators | ||
* @param input | ||
*/ | ||
declare function consume(markup: string, tw: (className: string) => string): string; | ||
declare function cx(...input: Class[]): string; | ||
declare type CSSValue = string | number | bigint | Falsey; | ||
declare function css(strings: TemplateStringsArray, ...interpolations: readonly CSSValue[]): string; | ||
declare function css(style: CSSObject | string): string; | ||
declare function cx(strings: TemplateStringsArray | Class, ...interpolations: Class[]): string; | ||
/** | ||
* @group Configuration | ||
* @param param0 | ||
* @returns | ||
*/ | ||
declare function defineConfig<Theme = BaseTheme, Presets extends Preset<any>[] = Preset[]>({ presets, ...userConfig }: TwindUserConfig<Theme, Presets>): TwindConfig<BaseTheme & ExtractThemes<Theme, Presets>>; | ||
interface InjectGlobalFunction { | ||
(style: CSSBase | string): void; | ||
(strings: TemplateStringsArray, ...interpolations: readonly CSSValue[]): void; | ||
bind(thisArg?: ((tokens: string) => string) | undefined | void): InjectGlobalFunction; | ||
call(thisArg: ((tokens: string) => string) | undefined | void, style: CSSBase | string): void; | ||
apply(thisArg: ((tokens: string) => string) | undefined | void, args: [CSSBase | string]): void; | ||
} | ||
/** | ||
* Result of {@link extract} | ||
* Injects styles into the global scope and is useful for applications such as gloabl styles, CSS resets or font faces. | ||
* | ||
* It **does not** return a class name, but adds the styles within the base layer to the stylesheet directly. | ||
* | ||
* @group Style Injectors | ||
*/ | ||
interface ExtractResult { | ||
/** The possibly modified HTML */ | ||
html: string; | ||
/** The generated CSS */ | ||
css: string; | ||
declare const injectGlobal: InjectGlobalFunction; | ||
/** | ||
* @group Runtime | ||
* @param config | ||
* @param isProduction | ||
*/ | ||
declare function install<Theme extends BaseTheme = BaseTheme>(config: TwindConfig<Theme>, isProduction?: boolean): Twind<Theme & BaseTheme>; | ||
declare function install<Theme = BaseTheme, Presets extends Preset<any>[] = Preset[]>(config: TwindUserConfig<Theme, Presets>, isProduction?: boolean): Twind<BaseTheme & ExtractThemes<Theme, Presets>>; | ||
interface KeyframesFunction { | ||
(style: CSSObject | string): StringLike; | ||
(strings: TemplateStringsArray, ...interpolations: readonly CSSValue[]): StringLike; | ||
bind(thisArg?: ((tokens: string) => string) | undefined | void): Keyframes & { | ||
[label: string]: KeyframesFunction; | ||
}; | ||
call(thisArg: ((tokens: string) => string) | undefined | void, style: CSSObject | string): StringLike; | ||
call(thisArg: ((tokens: string) => string) | undefined | void, strings: TemplateStringsArray, ...interpolations: readonly CSSValue[]): StringLike; | ||
apply(thisArg: ((tokens: string) => string) | undefined | void, args: [CSSObject | string]): StringLike; | ||
apply(thisArg: ((tokens: string) => string) | undefined | void, args: [CSSObject | string] | [strings: TemplateStringsArray, ...interpolations: readonly CSSValue[]]): StringLike; | ||
} | ||
declare type Keyframes = KeyframesFunction & { | ||
[label: string]: KeyframesFunction; | ||
}; | ||
/** | ||
* Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
* **Note**: The styles will be injected on first use. | ||
* | ||
* **Note**: This {@link Twind.clear clears} the Twind instance before processing the HTML. | ||
* | ||
* 1. parse the markup and process element classes with the provided Twind instance | ||
* 2. update the class attributes _if_ necessary | ||
* 3. return the HTML string with the final element classes | ||
* | ||
* ```js | ||
* import { twind, virtual, extract } from '@twind/core' | ||
* | ||
* // can be re-used | ||
* const tw = twind(config, virtual()} | ||
* | ||
* function render() { | ||
* const { html, css } = extract(renderApp(), tw) | ||
* | ||
* // inject as last element into the head | ||
* return html.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* @param markup HTML to process | ||
* @param tw a {@link Twind} instance | ||
* @returns the possibly modified html and css | ||
* @group Style Injectors | ||
*/ | ||
declare function extract(html: string, tw: Twind): ExtractResult; | ||
declare const keyframes: Keyframes; | ||
declare function observe<Theme extends BaseTheme = BaseTheme, Target = unknown>(tw: Twind<Theme, Target>, target?: false | HTMLElement): Twind<Theme, Target>; | ||
/** | ||
* @group Runtime | ||
* @param tw | ||
* @param target | ||
* @returns | ||
*/ | ||
declare function observe<Theme extends BaseTheme = BaseTheme, Target = unknown>(tw?: Twind<Theme, Target>, target?: false | HTMLElement): Twind<Theme, Target>; | ||
interface ParsedRule { | ||
/** | ||
* The utility name including `-` if set, but without `!` and variants | ||
*/ | ||
readonly n: string; | ||
/** | ||
* All variants without trailing colon: `hover`, `after:`, `[...]` | ||
*/ | ||
readonly v: string[]; | ||
/** | ||
* Something like `!underline` or `!bg-red-500` or `!red-500` | ||
*/ | ||
readonly i?: boolean; | ||
} | ||
interface ParsedDevRule extends ParsedRule { | ||
readonly a: string[]; | ||
readonly l: [start: number, end: number]; | ||
} | ||
/** | ||
* @internal | ||
* @param token | ||
* @returns | ||
*/ | ||
declare function parse(token: string): ParsedRule[]; | ||
declare type ThemeMatchResult<Value> = MatchResult & { | ||
@@ -303,4 +506,74 @@ /** The found theme value */ | ||
}; | ||
declare type ThemeRuleResolver<Value, Theme extends BaseTheme = BaseTheme> = (match: ThemeMatchResult<Value>, context: Context<Theme>) => RuleResult; | ||
declare type ThemeMatchConverter<Value, Theme extends BaseTheme = BaseTheme> = (match: ThemeMatchResult<Value>, context: Context<Theme>) => string; | ||
declare type ThemeRuleResolver<Value, Theme extends BaseTheme = BaseTheme> = RuleResolver<Theme, ThemeMatchResult<Value>>; | ||
declare type ThemeMatchConverter<Value, Theme extends BaseTheme = BaseTheme> = MatchConverter<Theme, ThemeMatchResult<Value>>; | ||
/** | ||
* @group Configuration | ||
* @param pattern | ||
*/ | ||
declare function match<Theme extends BaseTheme = BaseTheme>(pattern: MaybeArray<string | RegExp>): Rule<Theme>; | ||
/** | ||
* @group Configuration | ||
* @param pattern | ||
* @param resolver | ||
*/ | ||
declare function match<Theme extends BaseTheme = BaseTheme>(pattern: MaybeArray<string | RegExp>, resolver: RuleResolver<Theme>): Rule<Theme>; | ||
/** | ||
* @group Configuration | ||
* @param pattern | ||
* @param resolve | ||
*/ | ||
declare function match<Theme extends BaseTheme = BaseTheme>(pattern: MaybeArray<string | RegExp>, resolve: (string & {}) | CSSObject): Rule<Theme>; | ||
/** | ||
* @group Configuration | ||
* @param pattern | ||
* @param resolve | ||
* @param convert | ||
*/ | ||
declare function match<Theme extends BaseTheme = BaseTheme>(pattern: MaybeArray<string | RegExp>, resolve: keyof CSSProperties, convert?: MatchConverter<Theme>): Rule<Theme>; | ||
/** | ||
* @group Configuration | ||
* @internal | ||
* @deprecated Use {@link match} instead. | ||
*/ | ||
declare function fromMatch<Theme extends BaseTheme = BaseTheme>(): RuleResolver<Theme>; | ||
/** | ||
* @group Configuration | ||
* @internal | ||
* @deprecated Use {@link match} instead. | ||
*/ | ||
declare function fromMatch<Theme extends BaseTheme = BaseTheme>(resolver: RuleResolver<Theme>): RuleResolver<Theme>; | ||
/** | ||
* @group Configuration | ||
* @internal | ||
* @deprecated Use {@link match} instead. | ||
*/ | ||
declare function fromMatch<Theme extends BaseTheme = BaseTheme>(resolve: keyof CSSProperties, convert?: MatchConverter<Theme>): RuleResolver<Theme>; | ||
/** | ||
* @group Configuration | ||
* @internal | ||
* @deprecated Use {@link match} instead. | ||
*/ | ||
declare function fromMatch<Theme extends BaseTheme = BaseTheme>(resolve: string | CSSObject): RuleResolver<Theme>; | ||
/** | ||
* @group Configuration | ||
* @param pattern | ||
* @param section | ||
* @param resolve | ||
* @param convert | ||
* @returns | ||
*/ | ||
declare function matchTheme<Theme extends BaseTheme = BaseTheme, Section extends keyof Theme & string = keyof Theme & string>(pattern: MaybeArray<string | RegExp>, | ||
/** Theme section to use (default: `$1` — The first matched group) */ | ||
section?: '' | Section | KebabCase<Section>, | ||
/** The css property (default: value of {@link section}) */ | ||
resolve?: keyof CSSProperties | ThemeRuleResolver<ThemeValue<Theme[Section]>, Theme>, convert?: ThemeMatchConverter<ThemeValue<Theme[Section]>, Theme>): Rule<Theme>; | ||
/** | ||
* @group Configuration | ||
* @internal | ||
* @deprecated Use {@link matchTheme} instead. | ||
* @param section | ||
* @param resolve | ||
* @param convert | ||
* @returns | ||
*/ | ||
declare function fromTheme<Theme extends BaseTheme = BaseTheme, Section extends keyof Theme & string = keyof Theme & string>( | ||
@@ -317,2 +590,4 @@ /** Theme section to use (default: `$1` — The first matched group) */ | ||
color: ColorFunction; | ||
opacityVariable: string | undefined; | ||
opacityValue: string | undefined; | ||
} | ||
@@ -330,11 +605,280 @@ interface ColorFromThemeOptions<Theme extends BaseTheme = BaseTheme, Section extends keyof FilterByThemeValue<Theme, ColorValue> = keyof FilterByThemeValue<Theme, ColorValue>, OpacitySection extends keyof FilterByThemeValue<Theme, string> = keyof FilterByThemeValue<Theme, string>> { | ||
} | ||
/** | ||
* @group Configuration | ||
* @param pattern | ||
* @param options | ||
* @param resolve | ||
* @returns | ||
*/ | ||
declare function matchColor<Theme extends BaseTheme = BaseTheme, Section extends keyof FilterByThemeValue<Theme, ColorValue> = keyof FilterByThemeValue<Theme, ColorValue>, OpacitySection extends keyof FilterByThemeValue<Theme, string> = keyof FilterByThemeValue<Theme, string>>(pattern: MaybeArray<string | RegExp>, options?: ColorFromThemeOptions<Theme, Section, OpacitySection>, resolve?: ThemeRuleResolver<ColorFromThemeValue, Theme>): Rule<Theme>; | ||
/** | ||
* @group Configuration | ||
* @internal | ||
* @deprecated Use {@link matchColor} instead. | ||
* @param options | ||
* @param resolve | ||
* @returns | ||
*/ | ||
declare function colorFromTheme<Theme extends BaseTheme = BaseTheme, Section extends keyof FilterByThemeValue<Theme, ColorValue> = keyof FilterByThemeValue<Theme, ColorValue>, OpacitySection extends keyof FilterByThemeValue<Theme, string> = keyof FilterByThemeValue<Theme, string>>(options?: ColorFromThemeOptions<Theme, Section, OpacitySection>, resolve?: ThemeRuleResolver<ColorFromThemeValue, Theme>): RuleResolver<Theme>; | ||
/** | ||
* @internal | ||
* @param property | ||
* @param value | ||
* @returns | ||
*/ | ||
declare function toCSS(property: string, value: string | ColorFromThemeValue): CSSObject; | ||
/** | ||
* @internal | ||
* @param value | ||
* @param section | ||
* @param context | ||
* @returns | ||
*/ | ||
declare function arbitrary<Theme extends BaseTheme = BaseTheme>(value: string, section: string, context: Context<Theme>): string | undefined; | ||
/** | ||
* @internal | ||
* @param value | ||
* @returns | ||
*/ | ||
declare function normalize(value: string): string; | ||
declare type ShortcutFunction = (strings: TemplateStringsArray | Class, ...interpolations: Class[]) => string; | ||
declare type Shortcut = ShortcutFunction & { | ||
[label: string]: ShortcutFunction; | ||
}; | ||
declare const shortcut: Shortcut; | ||
/** | ||
* @group Runtime | ||
* @param install | ||
* @returns | ||
*/ | ||
declare function auto(install: () => void): () => void; | ||
/** | ||
* A proxy to the currently active Twind instance. | ||
* @group Style Injectors | ||
*/ | ||
declare const tw: Twind<any, any>; | ||
declare type SheetFactory<SheetTarget = unknown> = () => Sheet<SheetTarget>; | ||
/** | ||
* Manages a single Twind instance — works in browser, Node.js, Deno, workers... | ||
* | ||
* @group Runtime | ||
* @param config | ||
* @param sheet | ||
* @param target | ||
* @returns | ||
*/ | ||
declare function setup<Theme extends BaseTheme = BaseTheme, SheetTarget = unknown>(config?: TwindConfig<Theme>, sheet?: Sheet<SheetTarget> | SheetFactory<SheetTarget>, target?: HTMLElement): Twind<Theme, SheetTarget>; | ||
declare function setup<Theme = BaseTheme, Presets extends Preset<any>[] = Preset[], SheetTarget = unknown>(config?: TwindUserConfig<Theme, Presets>, sheet?: Sheet<SheetTarget> | SheetFactory<SheetTarget>, target?: HTMLElement): Twind<BaseTheme & ExtractThemes<Theme, Presets>, SheetTarget>; | ||
/** | ||
* @group Sheets | ||
* @param element | ||
* @returns | ||
*/ | ||
declare function cssom(element?: CSSStyleSheet | HTMLStyleElement | string | null | false): Sheet<CSSStyleSheet>; | ||
/** | ||
* @group Sheets | ||
* @param element | ||
* @returns | ||
*/ | ||
declare function dom(element?: HTMLStyleElement | string | null | false): Sheet<HTMLStyleElement>; | ||
/** | ||
* @group Sheets | ||
* @param includeResumeData | ||
* @returns | ||
*/ | ||
declare function virtual(includeResumeData?: boolean): Sheet<string[]>; | ||
/** | ||
* Returns a sheet useable in the current environment. | ||
* | ||
* @group Sheets | ||
* @param useDOMSheet usually something like `process.env.NODE_ENV != 'production'` or `import.meta.env.DEV` (default: browser={@link cssom}, server={@link virtual}) | ||
* @param disableResume to not include or use resume data | ||
* @returns a sheet to use | ||
*/ | ||
declare function getSheet(useDOMSheet?: boolean, disableResume?: boolean): Sheet<string[] | HTMLStyleElement | CSSStyleSheet>; | ||
/** | ||
* @group Sheets | ||
* @param target | ||
* @returns | ||
*/ | ||
declare function stringify(target: unknown): string; | ||
/** | ||
* Options for {@link inline} | ||
*/ | ||
interface InlineOptions { | ||
/** | ||
* {@link Twind} instance to use (default: {@link @twind/core.tw}) | ||
*/ | ||
tw?: Twind<any, any>; | ||
/** | ||
* Allows to minify the resulting CSS. | ||
*/ | ||
minify?: InlineMinify; | ||
} | ||
interface InlineMinify { | ||
/** | ||
* Called to minify the CSS. | ||
* | ||
* @param css the CSS to minify | ||
* @param html the HTML that will be used — allows to only include above-the-fold CSS | ||
* @return the resulting CSS | ||
*/ | ||
(css: string, html: string): string; | ||
} | ||
/** | ||
* Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
* | ||
* 1. parse the markup and process element classes with the provided Twind instance | ||
* 2. update the class attributes _if_ necessary | ||
* 3. inject a style element with the CSS as last element into the head | ||
* 4. return the HTML string with the final element classes | ||
* | ||
* ```js | ||
* import { inline } from '@twind/core' | ||
* | ||
* function render() { | ||
* return inline(renderApp()) | ||
* } | ||
* ``` | ||
* | ||
* Minify CSS with [@parcel/css](https://www.npmjs.com/package/@parcel/css): | ||
* | ||
* ```js | ||
* import { inline } from '@twind/core' | ||
* import { transform } from '@parcel/css' | ||
* | ||
* function render() { | ||
* return inline(renderApp(), { minify: (css) => transform({ filename: 'twind.css', code: Buffer.from(css), minify: true }) }) | ||
* } | ||
* ``` | ||
* | ||
* You can provide your own Twind instance: | ||
* | ||
* ```js | ||
* import { inline } from '@twind/core' | ||
* import { tw } from './custom/twind/instance' | ||
* | ||
* function render() { | ||
* return inline(renderApp(), { tw }) | ||
* } | ||
* ``` | ||
* | ||
* @group Static Extraction | ||
* @param markup HTML to process | ||
* @param options to customize the processing | ||
* @returns the resulting HTML | ||
*/ | ||
declare function inline(markup: string, options?: InlineOptions['tw'] | InlineOptions): string; | ||
/** | ||
* Result of {@link extract} | ||
*/ | ||
interface ExtractResult { | ||
/** The possibly modified HTML */ | ||
html: string; | ||
/** The generated CSS */ | ||
css: string; | ||
} | ||
/** | ||
* Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
* | ||
* **Note**: Consider using {@link inline} instead. | ||
* | ||
* 1. parse the markup and process element classes with the provided Twind instance | ||
* 2. update the class attributes _if_ necessary | ||
* 3. return the HTML string with the final element classes | ||
* | ||
* ```js | ||
* import { extract } from '@twind/core' | ||
* | ||
* function render() { | ||
* const { html, css } = extract(renderApp()) | ||
* | ||
* // inject as last element into the head | ||
* return html.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* You can provide your own Twind instance: | ||
* | ||
* ```js | ||
* import { extract } from '@twind/core' | ||
* import { tw } from './custom/twind/instance' | ||
* | ||
* function render() { | ||
* const { html, css } = extract(renderApp(), tw) | ||
* | ||
* // inject as last element into the head | ||
* return html.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* @group Static Extraction | ||
* @param markup HTML to process | ||
* @param tw a {@link Twind} instance (default: twind managed tw) | ||
* @returns the possibly modified html and css | ||
*/ | ||
declare function extract(html: string, tw?: Twind<any, any>): ExtractResult; | ||
/** | ||
* Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
* | ||
* **Note**: Consider using {@link inline} or {@link extract} instead. | ||
* | ||
* 1. parse the markup and process element classes with the provided Twind instance | ||
* 2. update the class attributes _if_ necessary | ||
* 3. return the HTML string with the final element classes | ||
* | ||
* ```js | ||
* import { consume, stringify, tw } from '@twind/core' | ||
* | ||
* function render() { | ||
* const html = renderApp() | ||
* | ||
* // remember global classes | ||
* const restore = tw.snapshot() | ||
* | ||
* // generated markup | ||
* const markup = consume(html) | ||
* | ||
* // create CSS | ||
* const css = stringify(tw.target) | ||
* | ||
* // restore global classes | ||
* restore() | ||
* | ||
* // inject as last element into the head | ||
* return markup.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* You can provide your own Twind instance: | ||
* | ||
* ```js | ||
* import { consume, stringify } from '@twind/core' | ||
* import { tw } from './custom/twind/instance' | ||
* | ||
* function render() { | ||
* const html = renderApp() | ||
* | ||
* // remember global classes | ||
* const restore = snapshot(tw.target) | ||
* | ||
* // generated markup | ||
* const markup = consume(html) | ||
* | ||
* // restore global classes | ||
* restore() | ||
* | ||
* // create CSS | ||
* const css = stringify(tw.target) | ||
* | ||
* // inject as last element into the head | ||
* return markup.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* @group Static Extraction | ||
* @param markup HTML to process | ||
* @param tw a {@link Twind} instance | ||
* @returns possibly modified HTML | ||
*/ | ||
declare function consume(markup: string, tw?: (className: string) => string): string; | ||
declare type StrictMorphVariant<T> = T extends number ? `${T}` | T : T extends 'true' ? true | T : T extends 'false' ? false | T : T; | ||
@@ -350,3 +894,3 @@ declare type MorphVariant<T> = T extends number ? `${T}` | T : T extends 'true' ? boolean | T : T extends 'false' ? boolean | T : T extends `${number}` ? number | T : T; | ||
* import { HTMLAttributes } from "react"; | ||
* import { style, PropsOf } from "twind"; | ||
* import { style, PropsOf } from "@twind/core"; | ||
* const button = style({ ... }) | ||
@@ -410,2 +954,21 @@ * type ButtonProps = PropsOf<typeof button> | ||
(props?: StyleProps<Variants>): string; | ||
/** | ||
* To be used as resolve within config.rules: | ||
* | ||
* ```js | ||
* { | ||
* rules: [ | ||
* // label?prop=value&other=propValue | ||
* // if the style has base eg no prop is required | ||
* ['label(\\?.+)?', style( /* ... *\/ )], | ||
* | ||
* // if the style requires at least one prop | ||
* ['label\\?(.+)', style( /* ... *\/ )], | ||
* ] | ||
* } | ||
* ``` | ||
* | ||
* The first group is used to extract the props using {@link !URLSearchParams | URLSearchParams}. | ||
*/ | ||
(match: MatchResult): string; | ||
readonly defaults: StyleProps<Variants>; | ||
@@ -447,23 +1010,96 @@ /** | ||
} | ||
/** | ||
* @group Class Name Generators | ||
*/ | ||
declare const style: StyleFunction; | ||
/** | ||
* @group Runtime | ||
* @param config | ||
* @param sheet | ||
*/ | ||
declare function twind<Theme extends BaseTheme = BaseTheme, Target = unknown>(config: TwindConfig<Theme>, sheet: Sheet<Target>): Twind<Theme, Target>; | ||
declare function twind<Theme = BaseTheme, Presets extends Preset<any>[] = Preset[], Target = unknown>(config: TwindUserConfig<Theme, Presets>, sheet: Sheet<Target>): Twind<BaseTheme & ExtractThemes<Theme, Presets>, Target>; | ||
declare global { | ||
interface Window { | ||
tw?: HTMLStyleElement; | ||
} | ||
interface TxFunction { | ||
(...classes: Class[]): string; | ||
(strings: TemplateStringsArray, ...interpolations: readonly Class[]): string; | ||
bind(thisArg?: ((tokens: string) => string) | undefined | void): TxFunction; | ||
call(thisArg: ((tokens: string) => string) | undefined | void, ...classes: Class[]): string; | ||
call(thisArg: ((tokens: string) => string) | undefined | void, strings: TemplateStringsArray, ...interpolations: readonly Class[]): string; | ||
apply(thisArg: ((tokens: string) => string) | undefined | void, classes: Class[] | [strings: TemplateStringsArray, ...interpolations: readonly Class[]]): string; | ||
} | ||
declare function cssom(target?: CSSStyleSheet): Sheet<CSSStyleSheet>; | ||
declare function dom(target?: HTMLStyleElement): Sheet<HTMLStyleElement>; | ||
declare function virtual(target?: string[]): Sheet<string[]>; | ||
declare function stringify(target: unknown): string; | ||
/** | ||
* Combines {@link tw} and {@link cx}. | ||
* | ||
* Using the default `tw` instance: | ||
* | ||
* ```js | ||
* import { tw } from '@twind/core' | ||
* tx`underline ${falsy && 'italic'}` | ||
* tx('underline', falsy && 'italic') | ||
* tx({'underline': true, 'italic': false}) | ||
* | ||
* // using a custom twind instance | ||
* import { tw } from './custom/twind' | ||
* import { tw } from './custom/twind' | ||
* tx.bind(tw) | ||
* ``` | ||
* | ||
* Using a custom `tw` instance: | ||
* | ||
* ```js | ||
* import { tx as tx$ } from '@twind/core' | ||
* import { tw } from './custom/twind' | ||
* | ||
* export const tx = tx$.bind(tw) | ||
* | ||
* tx`underline ${falsy && 'italic'}` | ||
* tx('underline', falsy && 'italic') | ||
* tx({'underline': true, 'italic': false}) | ||
* ``` | ||
* | ||
* @group Style Injectors | ||
* @param this {@link Twind} instance to use (default: {@link tw}) | ||
* @param strings | ||
* @param interpolations | ||
* @returns the class name | ||
*/ | ||
declare const tx: TxFunction; | ||
/** | ||
* @internal | ||
*/ | ||
declare const escape: typeof CSS.escape; | ||
/** | ||
* @group Configuration | ||
* @param value | ||
* @returns | ||
*/ | ||
declare function hash(value: string): string; | ||
/** | ||
* @internal | ||
* @param screen | ||
* @param prefix | ||
* @returns | ||
*/ | ||
declare function mql(screen: MaybeArray<ScreenValue>, prefix?: string): string; | ||
/** | ||
* @internal | ||
* @param value | ||
* @returns | ||
*/ | ||
declare function asArray<T>(value?: T): T extends Array<any> ? T : T[]; | ||
/** | ||
* @internal | ||
* @param value | ||
* @returns | ||
*/ | ||
declare function identity<T>(value: T): T; | ||
/** | ||
* @internal | ||
*/ | ||
declare function noop(): void; | ||
export { BaseProperties, BaseTheme, CSSBase, CSSFontFace, CSSNested, CSSObject, CSSProperties, CSSValue, Class, ClassObject, ColorFromThemeOptions, ColorFromThemeValue, ColorFunction, ColorFunctionOptions, ColorRecord, ColorValue, Context, CustomProperties, DefaultVariants, ExtractResult, ExtractThemes, Falsey, FilterByThemeValue, HashFunction, KebabCase, MatchConverter, MatchResult, MaybeArray, MaybeColorValue, MaybeThunk, MorphVariant, PartialTheme, Preflight, PreflightThunk, Preset, PresetThunk, PropsOf, Rule, RuleResolver, RuleResult, ScreenValue, Sheet, Shortcut, ShortcutFunction, ShortcutResolver, Shortcuts, StrictMorphVariant, StringifyDeclaration, Style, StyleConfig, StyleFunction, StyleProps, StyleToken, StyleTokenValue, ThemeConfig, ThemeFunction, ThemeMatchConverter, ThemeMatchResult, ThemeRuleResolver, ThemeSection, ThemeSectionResolver, ThemeSectionResolverContext, ThemeValue, Twind, TwindConfig, TwindPresetConfig, TwindRule, TwindUserConfig, TypedAtRules, Variant, VariantResolver, VariantResult, VariantsProps, When, arbitrary, asArray, colorFromTheme, consume, css, cssom, cx, defineConfig, dom, escape, extract, fromTheme, hash, mql, observe, shortcut, stringify, style, toColorValue, twind, virtual }; | ||
export { Animation, AnimationFunction, ArrayType, AutocompleteContext, AutocompleteItem, AutocompleteModifier, AutocompleteProvider, BaseProperties, BaseTheme, CSSBase, CSSFontFace, CSSNested, CSSObject, CSSProperties, CSSValue, Class, ClassObject, ColorFromThemeOptions, ColorFromThemeValue, ColorFunction, ColorFunctionOptions, ColorRecord, ColorValue, Context, CustomProperties, DarkColor, DarkModeConfig, DefaultVariants, ExtractResult, ExtractTheme, ExtractThemes, ExtractUserTheme, Falsey, FilterByThemeValue, HashFunction, InjectGlobalFunction, InlineMinify, InlineOptions, KebabCase, Keyframes, KeyframesFunction, MatchConverter, MatchResult, MaybeArray, MaybeColorValue, MaybeThunk, MorphVariant, Nested, NestedFunction, ParsedDevRule, ParsedRule, PartialTheme, Preflight, PreflightThunk, Preset, PresetThunk, PropsOf, RestoreSnapshot, Rule, RuleResolver, RuleResult, ScreenValue, Sheet, SheetFactory, SheetRule, StrictMorphVariant, StringLike, StringifyDeclaration, Style, StyleConfig, StyleFunction, StyleProps, StyleToken, StyleTokenValue, ThemeConfig, ThemeFunction, ThemeMatchConverter, ThemeMatchResult, ThemeRuleResolver, ThemeSection, ThemeSectionResolver, ThemeSectionResolverContext, ThemeValue, Twind, TwindConfig, TwindPresetConfig, TwindRule, TwindUserConfig, TxFunction, TypedAtRules, TypedAtRulesKeys, UnionToIntersection, Variant, VariantResolver, VariantResult, VariantsProps, When, animation, apply, arbitrary, asArray, auto, autoDarkColor, colorFromTheme, consume, css, cssom, cx, defineConfig, dom, escape, extract, fromMatch, fromTheme, getAutocompleteProvider, getSheet, hash, identity, injectGlobal, inline, install, keyframes, match, matchColor, matchTheme, mql, noop, normalize, observe, parse, setup, shortcut, stringify, style, toCSS, toColorValue, tw, twind, tx, virtual, withAutocomplete }; | ||
//# sourceMappingURL=core.d.ts.map |
1607
core.esnext.js
@@ -1,1606 +0,1 @@ | ||
function parseColorComponent(chars, factor) { | ||
return Math.round(parseInt(chars, 16) * factor); | ||
} | ||
function toColorValue(color, options = {}) { | ||
if (typeof color == 'function') { | ||
return color(options); | ||
} | ||
const { opacityValue ='1' , opacityVariable } = options; | ||
const opacity = opacityVariable ? `var(${opacityVariable})` : opacityValue; | ||
if (opacity == '1') return color; | ||
if (opacity == '0') return '#0000'; | ||
// rgb hex: #0123 and #001122 | ||
if (color[0] == '#' && (color.length == 4 || color.length == 7)) { | ||
const size = (color.length - 1) / 3; | ||
const factor = [ | ||
17, | ||
1, | ||
0.062272 | ||
][size - 1]; | ||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions | ||
return `rgba(${[ | ||
parseColorComponent(color.substr(1, size), factor), | ||
parseColorComponent(color.substr(1 + size, size), factor), | ||
parseColorComponent(color.substr(1 + 2 * size, size), factor), | ||
opacity, | ||
]})`; | ||
} | ||
return color; | ||
} | ||
/** | ||
* Determines if two class name strings contain the same classes. | ||
* | ||
* @param a first class names | ||
* @param b second class names | ||
* @returns are they different | ||
*/ function changed(a, b) { | ||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands | ||
return a != b && '' + a.split(' ').sort() != '' + b.split(' ').sort(); | ||
} | ||
/** | ||
* Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
* | ||
* 1. parse the markup and process element classes with the provided Twind instance | ||
* 2. update the class attributes _if_ necessary | ||
* 3. return the HTML string with the final element classes | ||
* | ||
* ```js | ||
* import { twind, virtual, consume, stringify } from '@twind/core' | ||
* | ||
* // can be re-used | ||
* const tw = twind(config, virtual()} | ||
* | ||
* function render() { | ||
* const html = renderApp() | ||
* | ||
* // clear all styles | ||
* tw.clear() | ||
* | ||
* // generated markup | ||
* const markup = consume(html, tw) | ||
* | ||
* // create CSS | ||
* const css = stringify(tw.target) | ||
* | ||
* // inject as last element into the head | ||
* return markup.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* @param markup HTML to process | ||
* @param tw a {@link Twind} instance | ||
* @returns possibly modified HTML | ||
*/ function consume(markup, tw) { | ||
let result = ''; | ||
let lastChunkStart = 0; | ||
extract$1(markup, (startIndex, endIndex, quote)=>{ | ||
const value = markup.slice(startIndex, endIndex); | ||
const className = tw(value); | ||
// We only need to shift things around if we need to actually change the markup | ||
if (changed(value, className)) { | ||
// We've hit another mutation boundary | ||
// Add quote if necessary | ||
quote = quote ? '' : '"'; | ||
result += markup.slice(lastChunkStart, startIndex) + quote + className + quote; | ||
lastChunkStart = endIndex; | ||
} | ||
}); | ||
// Combine the current result with the tail-end of the input | ||
return result + markup.slice(lastChunkStart, markup.length); | ||
} | ||
// For now we are using a simple parser adapted from htm (https://github.com/developit/htm/blob/master/src/build.mjs) | ||
// If we find any issues we can switch to something more sophisticated like | ||
// - https://github.com/acrazing/html5parser | ||
// - https://github.com/fb55/htmlparser2 | ||
const MODE_SLASH = 0; | ||
const MODE_TEXT = 1; | ||
const MODE_WHITESPACE = 2; | ||
const MODE_TAGNAME = 3; | ||
const MODE_COMMENT = 4; | ||
const MODE_ATTRIBUTE = 5; | ||
function extract$1(markup, onClass) { | ||
let mode = MODE_TEXT; | ||
let startIndex = 0; | ||
let quote = ''; | ||
let char = ''; | ||
let attributeName = ''; | ||
const commit = (currentIndex)=>{ | ||
if (mode == MODE_ATTRIBUTE && attributeName == 'class') { | ||
onClass(startIndex, currentIndex, quote); | ||
} | ||
}; | ||
for(let position = 0; position < markup.length; position++){ | ||
char = markup[position]; | ||
if (mode == MODE_TEXT) { | ||
if (char == '<') { | ||
mode = markup.substr(position + 1, 3) == '!--' ? MODE_COMMENT : MODE_TAGNAME; | ||
} | ||
} else if (mode == MODE_COMMENT) { | ||
// Ignore everything until the last three characters are '-', '-' and '>' | ||
if (char == '>' && markup.slice(position - 2, position) == '--') { | ||
mode = MODE_TEXT; | ||
} | ||
} else if (quote) { | ||
if (char == quote && markup[position - 1] != '\\') { | ||
commit(position); | ||
mode = MODE_WHITESPACE; | ||
quote = ''; | ||
} | ||
} else if (char == '"' || char == "'") { | ||
quote = char; | ||
startIndex += 1; | ||
} else if (char == '>') { | ||
commit(position); | ||
mode = MODE_TEXT; | ||
} else if (!mode) ; else if (char == '=') { | ||
attributeName = markup.slice(startIndex, position); | ||
mode = MODE_ATTRIBUTE; | ||
startIndex = position + 1; | ||
} else if (char == '/' && (mode < MODE_ATTRIBUTE || markup[position + 1] == '>')) { | ||
commit(position); | ||
mode = MODE_SLASH; | ||
} else if (/\s/.test(char)) { | ||
// <a class=font-bold> | ||
commit(position); | ||
mode = MODE_WHITESPACE; | ||
startIndex = position + 1; | ||
} | ||
} | ||
} | ||
const registry = new Map(); | ||
function register(className, factory) { | ||
registry.set(className, factory); | ||
return className; | ||
} | ||
function resolve(rule, context) { | ||
const factory = registry.get(rule.n); | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument | ||
return factory ? factory(rule, context) : context.r(rule.n); | ||
} | ||
const escape = typeof CSS !== 'undefined' && CSS.escape || // Simplified: escaping only special characters | ||
// Needed for NodeJS and Edge <79 (https://caniuse.com/mdn-api_css_escape) | ||
((className)=>className// Simplifed escape testing only for chars that we know happen to be in tailwind directives | ||
.replace(/[!"'`*+.,;:\\/<=>?@#$%&^|~()[\]{}]/g, '\\$&')// If the character is the first character and is in the range [0-9] (2xl, ...) | ||
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point | ||
.replace(/^\d/, '\\3$& ') | ||
); | ||
// Based on https://stackoverflow.com/a/52171480 | ||
function hash(value) { | ||
// eslint-disable-next-line no-var | ||
for(var h = 9, index = value.length; index--;){ | ||
h = Math.imul(h ^ value.charCodeAt(index), 1597334677); | ||
} | ||
return '#' + ((h ^ h >>> 9) >>> 0).toString(36); | ||
} | ||
function mql(screen1, prefix = '@media ') { | ||
return prefix + asArray(screen1).map((screen)=>{ | ||
if (typeof screen == 'string') { | ||
screen = { | ||
min: screen | ||
}; | ||
} | ||
return screen.raw || Object.keys(screen).map((feature)=>`(${feature}-width:${screen[feature]})` | ||
).join(' and '); | ||
}).join(','); | ||
} | ||
function asArray(value = []) { | ||
return Array.isArray(value) ? value : value == null ? [] : [ | ||
value | ||
]; | ||
} | ||
function toClassName(rule) { | ||
return [ | ||
...rule.v, | ||
(rule.i ? '!' : '') + rule.n | ||
].join(':'); | ||
} | ||
// Based on https://github.com/kripod/otion | ||
// License MIT | ||
// export const enum Shifts { | ||
// darkMode = 30, | ||
// layer = 27, | ||
// screens = 26, | ||
// responsive = 22, | ||
// atRules = 18, | ||
// variants = 0, | ||
// } | ||
const Layer = { | ||
/** | ||
* 1. `default` (public) | ||
*/ d: 0 << 27 /* Shifts.layer */ , | ||
/** | ||
* 2. `base` (public) —for things like reset rules or default styles applied to plain HTML elements. | ||
*/ b: 1 << 27 /* Shifts.layer */ , | ||
/** | ||
* 3. `components` (public, used by `style()`) — is for class-based styles that you want to be able to override with utilities. | ||
*/ c: 2 << 27 /* Shifts.layer */ , | ||
// reserved for style(): | ||
// - props: 0b011 | ||
// - when: 0b100 | ||
/** | ||
* 6. `shortcuts` (public, used by `apply()`) — `~(...)` | ||
*/ s: 5 << 27 /* Shifts.layer */ , | ||
/** | ||
* 6. `utilities` (public) — for small, single-purpose classes | ||
*/ u: 6 << 27 /* Shifts.layer */ , | ||
/** | ||
* 7. `overrides` (public, used by `css()`) | ||
*/ o: 7 << 27 /* Shifts.layer */ | ||
}; | ||
/* | ||
To have a predictable styling the styles must be ordered. | ||
This order is represented by a precedence number. The lower values | ||
are inserted before higher values. Meaning higher precedence styles | ||
overwrite lower precedence styles. | ||
Each rule has some traits that are put into a bit set which form | ||
the precedence: | ||
| bits | trait | | ||
| ---- | ---------------------------------------------------- | | ||
| 1 | dark mode | | ||
| 2 | layer: preflight, global, components, utilities, css | | ||
| 1 | screens: is this a responsive variation of a rule | | ||
| 5 | responsive based on min-width | | ||
| 4 | at-rules | | ||
| 18 | pseudo and group variants | | ||
| 4 | number of declarations (descending) | | ||
| 4 | greatest precedence of properties | | ||
**Dark Mode: 1 bit** | ||
Flag for dark mode rules. | ||
**Layer: 3 bits** | ||
- defaults = 0: The preflight styles and any base styles registered by plugins. | ||
- vase = 1: The global styles registered by plugins. | ||
- components = 2 | ||
- variants = 3 | ||
- compounds = 4 | ||
- shortcuts = 5 | ||
- utilities = 6: Utility classes and any utility classes registered by plugins. | ||
- css = 7: Styles generated by css | ||
**Screens: 1 bit** | ||
Flag for screen variants. They may not always have a `min-width` to be detected by _Responsive_ below. | ||
**Responsive: 4 bits** | ||
Based on extracted `min-width` value: | ||
- 576px -> 3 | ||
- 1536px -> 10 | ||
- 36rem -> 3 | ||
- 96rem -> 9 | ||
**At-Rules: 4 bits** | ||
Based on the count of special chars (`-:,`) within the at-rule. | ||
**Pseudo and group variants: 18 bits** | ||
Ensures predictable order of pseudo classes. | ||
- https://bitsofco.de/when-do-the-hover-focus-and-active-pseudo-classes-apply/#orderofstyleshoverthenfocusthenactive | ||
- https://developer.mozilla.org/docs/Web/CSS/:active#Active_links | ||
- https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js#L718 | ||
**Number of declarations (descending): 4 bits** | ||
Allows single declaration styles to overwrite styles from multi declaration styles. | ||
**Greatest precedence of properties: 4 bits** | ||
Ensure shorthand properties are inserted before longhand properties; eg longhand override shorthand | ||
*/ function moveToLayer(precedence, layer) { | ||
// Set layer (first reset, than set) | ||
return precedence & ~Layer.o | layer; | ||
} | ||
/* | ||
To set a bit: n |= mask; | ||
To clear a bit: n &= ~mask; | ||
To test if a bit is set: (n & mask) | ||
Bit shifts for the primary bits: | ||
| bits | trait | shift | | ||
| ---- | ------------------------------------------------------- | ----- | | ||
| 1 | dark mode | 30 | | ||
| 3 | layer: preflight, global, components, utilities, css | 27 | | ||
| 1 | screens: is this a responsive variation of a rule | 26 | | ||
| 4 | responsive based on min-width, max-width or width | 22 | | ||
| 4 | at-rules | 18 | | ||
| 18 | pseudo and group variants | 0 | | ||
Layer: 0 - 7: 3 bits | ||
- defaults: 0 << 27 | ||
- base: 1 << 27 | ||
- components: 2 << 27 | ||
- variants: 3 << 27 | ||
- joints: 4 << 27 | ||
- shortcuts: 5 << 27 | ||
- utilities: 6 << 27 | ||
- overrides: 7 << 27 | ||
These are calculated by serialize and added afterwards: | ||
| bits | trait | | ||
| ---- | ----------------------------------- | | ||
| 4 | number of selectors (descending) | | ||
| 4 | number of declarations (descending) | | ||
| 4 | greatest precedence of properties | | ||
These are added by shifting the primary bits using multiplication as js only | ||
supports bit shift up to 32 bits. | ||
*/ // Colon and dash count of string (ascending) | ||
function seperatorPrecedence(string) { | ||
return string.match(/[-=:;]/g)?.length || 0; | ||
} | ||
function atRulePrecedence(css) { | ||
// 0=none, 1=sm, 2=md, 3=lg, 4=xl, 5=2xl, 6=??, 7=?? | ||
// 0 - 15: 4 bits (max 150rem or 2250px) | ||
// 576px -> 3 | ||
// 1536px -> 10 | ||
// 36rem -> 3 | ||
// 96rem -> 9 | ||
return Math.min(/(?:^|width[^\d]+)(\d+(?:.\d+)?)(p)?/.test(css) ? +RegExp.$1 / (RegExp.$2 ? 15 : 1) / 10 : 0, 15) << 22 | Math.min(seperatorPrecedence(css), 15) << 18; | ||
} | ||
// Pesudo variant presedence | ||
// Chars 3 - 8: Uniquely identifies a pseudo selector | ||
// represented as a bit set for each relevant value | ||
// 18 bits: one for each variant plus one for unknown variants | ||
// | ||
// ':group-*' variants are normalized to their native pseudo class (':group-hover' -> ':hover') | ||
// as they already have a higher selector presedence due to the add '.group' ('.group:hover .group-hover:...') | ||
// Sources: | ||
// - https://bitsofco.de/when-do-the-hover-focus-and-active-pseudo-classes-apply/#orderofstyleshoverthenfocusthenactive | ||
// - https://developer.mozilla.org/docs/Web/CSS/:active#Active_links | ||
// - https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js#L931 | ||
const PRECEDENCES_BY_PSEUDO_CLASS = [ | ||
/* fi */ 'rst-c' /* hild: 0 */ , | ||
/* la */ 'st-ch' /* ild: 1 */ , | ||
// even and odd use: nth-child | ||
/* nt */ 'h-chi' /* ld: 2 */ , | ||
/* an */ 'y-lin' /* k: 3 */ , | ||
/* li */ 'nk' /* : 4 */ , | ||
/* vi */ 'sited' /* : 5 */ , | ||
/* ch */ 'ecked' /* : 6 */ , | ||
/* em */ 'pty' /* : 7 */ , | ||
/* re */ 'ad-on' /* ly: 8 */ , | ||
/* fo */ 'cus-w' /* ithin : 9 */ , | ||
/* ho */ 'ver' /* : 10 */ , | ||
/* fo */ 'cus' /* : 11 */ , | ||
/* fo */ 'cus-v' /* isible : 12 */ , | ||
/* ac */ 'tive' /* : 13 */ , | ||
/* di */ 'sable' /* d : 14 */ , | ||
/* op */ 'tiona' /* l: 15 */ , | ||
/* re */ 'quire' /* d: 16 */ , | ||
]; | ||
function pseudoPrecedence(selector) { | ||
// use first found pseudo-class | ||
return 1 << ~(/:([a-z-]+)/.test(selector) && ~PRECEDENCES_BY_PSEUDO_CLASS.indexOf(RegExp.$1.slice(2, 7)) || ~17); | ||
} | ||
// https://github.com/kripod/otion/blob/main/packages/otion/src/propertyMatchers.ts | ||
// "+1": [ | ||
// /* ^border-.*(w|c|sty) */ | ||
// "border-.*(width,color,style)", | ||
// /* ^[tlbr].{2,4}m?$ */ | ||
// "top", | ||
// "left", | ||
// "bottom", | ||
// "right", | ||
// /* ^c.{7}$ */ | ||
// "continue", | ||
// ], | ||
// "-1": [ | ||
// /* ^[fl].{5}l */ | ||
// "flex-flow", | ||
// "line-clamp", | ||
// /* ^g.{8}$ */ | ||
// "grid-area", | ||
// /* ^pl */ | ||
// "place-content", | ||
// "place-items", | ||
// "place-self", | ||
// ], | ||
// group: 1 => +1 | ||
// group: 2 => -1 | ||
// 0 - 15 => 4 bits | ||
// Ignore vendor prefixed and custom properties | ||
function declarationPropertyPrecedence(property) { | ||
return property[0] == '-' ? 0 : seperatorPrecedence(property) + (/^(?:(border-(?!w|c|sty)|[tlbr].{2,4}m?$|c.{7}$)|([fl].{5}l|g.{8}$|pl))/.test(property) ? +!!RegExp.$1 /* +1 */ || -!!RegExp.$2 /* -1 */ : 0) + 1; | ||
} | ||
function convert({ n: name , i: important , v: variants = [] }, context, precedence, conditions) { | ||
if (name) { | ||
name = toClassName({ | ||
n: name, | ||
i: important, | ||
v: variants | ||
}); | ||
} | ||
conditions = [ | ||
...asArray(conditions) | ||
]; | ||
for (const variant of variants){ | ||
const screen = context.theme('screens', variant); | ||
const condition = screen && mql(screen) || context.v(variant); | ||
conditions.push(condition); | ||
precedence |= screen ? 1 << 26 | atRulePrecedence(condition) : variant == 'dark' ? 1 << 30 /* Shifts.darkMode */ : condition[0] == '@' ? atRulePrecedence(condition) : pseudoPrecedence(condition); | ||
} | ||
return { | ||
n: name, | ||
p: precedence, | ||
r: conditions, | ||
i: important | ||
}; | ||
} | ||
function stringify$1(rule) { | ||
if (rule.d) { | ||
const groups = []; | ||
const selector1 = rule.r['reduce' + (rule.n ? 'Right' : '')]((selector, condition)=>{ | ||
if (condition[0] == '@') { | ||
groups.unshift(condition); | ||
return selector; | ||
} | ||
// Go over the selector and replace the matching multiple selectors if any | ||
return selector.replace(/^$| *((?:\\,|\(.+?\)|\[.+?\]|[^,])+) *(,|$)/g, (_, selectorPart = _, comma1 = '')=>// Return the current selector with the key matching multiple selectors if any | ||
condition.replace(/ *((?:\\,|\(.+?\)|\[.+?\]|[^,])+) *(,|$)/g, // If the current condition has a nested selector replace it | ||
(_, conditionPart, comma = '')=>conditionPart.replace(/&/g, selectorPart) + comma | ||
) + comma1 | ||
); | ||
}, rule.n ? '.' + escape(rule.n) : ''); | ||
if (selector1) { | ||
groups.push(selector1); | ||
} | ||
return groups.reduceRight((body, grouping)=>grouping + '{' + body + '}' | ||
, rule.d); | ||
} | ||
} | ||
function format(rules, space = ' ') { | ||
// TODO generate minified shortcut name: | ||
// input: hover:~(!text-(3xl center) !underline italic focus:not-italic) | ||
// current: ~(hover:!text-3xl,hover:!text-center,hover:!underline,hover:italic,hover:focus:not-italic) | ||
// minified: hover:~(!text-(3xl,center),!underline,italic,focus:not-italic) | ||
// const input = [ | ||
// {name: 'text-3xl', variants: ['hover'], important: true}, | ||
// {name: 'text-center', variants: ['hover'], important: true}, | ||
// {name: 'underline', variants: ['hover'], important: true}, | ||
// {name: 'italic', variants: ['hover'], important: false}, | ||
// {name: 'not-italic', variants: ['hover', 'focus'], important: false}, | ||
// ] | ||
return rules.map((rule)=>Array.isArray(rule) ? (space == ',' ? '' : '~(') + format(rule, ',') + (space == ',' ? '' : ')') : toClassName(rule) | ||
).join(space); | ||
} | ||
function merge(rules, name) { | ||
// merge: | ||
// - same conditions | ||
// - replace name with hash of name + condititions + declarations | ||
// - precedence: | ||
// - combine bits or use max precendence | ||
// - set layer bit to merged | ||
const result = []; | ||
let current; | ||
for (const rule of rules){ | ||
if (current?.p == rule.p && '' + current.r == '' + rule.r) { | ||
current.c = [ | ||
current.c, | ||
rule.c | ||
].filter(Boolean).join(' '); | ||
current.d = [ | ||
current.d, | ||
rule.d | ||
].filter(Boolean).join(';'); | ||
} else { | ||
// only set name for named rules eg not for global or className propagation rules | ||
result.push(current = { | ||
...rule, | ||
n: rule.n && name | ||
}); | ||
} | ||
} | ||
return result; | ||
} | ||
function define(className, layer, rules) { | ||
return register(className, (rule1, context)=>{ | ||
const { n: name , p: precedence , r: conditions , i: important } = convert(rule1, context, layer); | ||
return rules && merge(translate(rules, context, precedence, conditions, important, name).map((rule)=>rule.n ? { | ||
...rule, | ||
p: moveToLayer(rule.p, layer), | ||
o: 0 | ||
} : rule | ||
), name); | ||
}); | ||
} | ||
function createRule(active, current) { | ||
if (active[active.length - 1] != '(') { | ||
const variants = []; | ||
let important = false; | ||
let negated = false; | ||
let name = ''; | ||
for (let value of active){ | ||
if (value == '(' || value.endsWith('~')) continue; | ||
if (value[0] == '!') { | ||
value = value.slice(1); | ||
important = !important; | ||
} | ||
if (value.endsWith(':')) { | ||
variants.push(value.slice(0, -1)); | ||
continue; | ||
} | ||
if (value[0] == '-') { | ||
value = value.slice(1); | ||
negated = !negated; | ||
} | ||
if (value.endsWith('-')) { | ||
value = value.slice(0, -1); | ||
} | ||
if (value && value != '&') { | ||
name += (name && '-') + value; | ||
} | ||
} | ||
if (name) { | ||
if (negated) name = '-' + name; | ||
current[0].push({ | ||
n: name, | ||
v: variants, | ||
i: important | ||
}); | ||
} | ||
} | ||
} | ||
// Remove comments (multiline and single line) | ||
function removeComments(tokens) { | ||
return tokens.replace(/\/\*[^]*?\*\/|\/\/[^]*?$|\s\s+|\n/gm, ' '); | ||
} | ||
// (?=[ ,)(:[]|$) | ||
const parts = /([ ,)])|\(|[^ ,)(:[]*(?:\[[^ ]+])?:*/g; | ||
const cache = new Map(); | ||
function parse(token) { | ||
let parsed = cache.get(token); | ||
if (!parsed) { | ||
token = removeComments(token); | ||
// Stack of active groupings (`(`), variants, or nested (`~`) | ||
const active = []; | ||
// Stack of current rule list to put new rules in | ||
// the first `0` element is the current list | ||
const current = [ | ||
[] | ||
]; | ||
let rule; | ||
let match; | ||
parts.lastIndex = 0; | ||
while((match = parts.exec(token)) && match[0]){ | ||
if (match[1]) { | ||
// whitespace, comma or closing brace | ||
// create rule | ||
createRule(active, current); | ||
let lastGroup = active.lastIndexOf('('); | ||
let shortcut; | ||
let rules; | ||
if (match[1] == ')') { | ||
// Close nested block | ||
shortcut = active[lastGroup - 1]; | ||
if (shortcut?.endsWith('~')) { | ||
rules = current.shift(); | ||
} | ||
lastGroup = active.lastIndexOf('(', lastGroup - 1); | ||
} | ||
active.length = lastGroup + 1; | ||
if (rules && shortcut != '~') { | ||
// Create named shortcut | ||
// remove existing anonymous shortcut | ||
current[0].pop(); | ||
// ... and replace with new named shortcut | ||
createRule([ | ||
...active, | ||
define(shortcut.slice(0, -1) + hash(JSON.stringify(rules)), Layer.s, rules), | ||
], current); | ||
} | ||
} else { | ||
// - open brace | ||
// - new variant: `focus:`, `after::`, `[...]:` | ||
// - new rule | ||
// Start nested block | ||
// ~(...) or button~(...) | ||
if (match[0].endsWith('~')) { | ||
rule = []; | ||
current[0].push(rule); | ||
current.unshift(rule); | ||
} | ||
active.push(match[0]); | ||
} | ||
} | ||
// Consume remaining stack | ||
createRule(active, current); | ||
cache.set(token, parsed = current[0]); | ||
} | ||
return parsed; | ||
} | ||
const collator = new Intl.Collator('en', { | ||
numeric: true | ||
}); | ||
/** | ||
* Find the array index of where to add an element to keep it sorted. | ||
* | ||
* @returns The insertion index | ||
*/ function sortedInsertionIndex(array, element) { | ||
// Find position using binary search | ||
// eslint-disable-next-line no-var | ||
for(var low = 0, high = array.length; low < high;){ | ||
const pivot = high + low >> 1; | ||
// Less-Then-Equal to add new equal element after all existing equal elements (stable sort) | ||
if (compareTwindRules(array[pivot], element) <= 0) { | ||
low = pivot + 1; | ||
} else { | ||
high = pivot; | ||
} | ||
} | ||
return high; | ||
} | ||
function compareTwindRules(a, b) { | ||
// base and overrides (css) layers are kept in order they are declared | ||
const layer = a.p & Layer.o; | ||
if (layer == (b.p & Layer.o) && (layer == Layer.b || layer == Layer.o)) { | ||
return 0; | ||
} | ||
return a.p - b.p || a.o - b.o || collator.compare(a.r, b.r) || collator.compare(a.n, b.n); | ||
} | ||
function translate(rules, context, precedence = Layer.u, conditions, important, name) { | ||
// Sorted by precedence | ||
const result = []; | ||
for (const rule of rules){ | ||
for (const cssRule of Array.isArray(rule) ? merge(translate(rule, context, // TODO handle shortcuts and `apply()` by moving them into shortcuts layer | ||
(precedence & Layer.o) == Layer.u ? moveToLayer(precedence, Layer.s) : precedence, conditions, important), name || format([ | ||
rule | ||
])) : translate$(rule, context, precedence, conditions, important)){ | ||
result.splice(sortedInsertionIndex(result, cssRule), 0, cssRule); | ||
} | ||
} | ||
return result; | ||
} | ||
function translate$(rule1, context, precedence, conditions, important) { | ||
rule1 = { | ||
...rule1, | ||
i: rule1.i || important | ||
}; | ||
const resolved = resolve(rule1, context); | ||
if (!resolved) { | ||
// propagate className as is | ||
return [ | ||
{ | ||
c: toClassName(rule1), | ||
p: 0, | ||
o: 0, | ||
r: [] | ||
} | ||
]; | ||
} | ||
if (typeof resolved == 'string') { | ||
({ r: conditions , p: precedence } = convert(rule1, context, precedence, conditions)); | ||
return translate([ | ||
parse(resolved) | ||
], context, precedence, conditions, rule1.i, rule1.n); | ||
} | ||
if (Array.isArray(resolved)) { | ||
return resolved.map((rule)=>({ | ||
o: 0, | ||
...rule, | ||
r: [ | ||
...asArray(conditions), | ||
...asArray(rule.r) | ||
], | ||
p: moveToLayer(precedence, rule.p || precedence) | ||
}) | ||
); | ||
} | ||
return serialize(resolved, rule1, context, precedence, conditions); | ||
} | ||
function serialize(style, rule, context, precedence, conditions = []) { | ||
return serialize$(style, convert(rule, context, precedence, conditions), context); | ||
} | ||
function serialize$(style, { n: name , p: precedence , r: conditions = [] , i: important }, context) { | ||
const rules = []; | ||
// The generated declaration block eg body of the css rule | ||
let declarations = ''; | ||
// This ensures that 'border-top-width' has a higher precedence than 'border-top' | ||
let maxPropertyPrecedence = 0; | ||
// More specific utilities have less declarations and a higher precedence | ||
let numberOfDeclarations = 0; | ||
for(let key in style || {}){ | ||
const value1 = style[key]; | ||
if (key[0] == '@') { | ||
if (!value1) continue; | ||
// at rules: https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule | ||
switch(key[1]){ | ||
// @apply ...; | ||
case 'a': | ||
{ | ||
rules.push(...translate(// @apply rules are always merged | ||
[ | ||
parse(value1) | ||
], context, precedence, conditions, important).map((rule)=>({ | ||
...rule, | ||
n: name | ||
}) | ||
)); | ||
continue; | ||
} | ||
// @layer <layer> | ||
case 'l': | ||
{ | ||
for (const css of asArray(value1)){ | ||
rules.push(...serialize$(css, { | ||
n: name, | ||
p: moveToLayer(precedence, Layer[key[7]]), | ||
r: conditions, | ||
i: important | ||
}, context)); | ||
} | ||
continue; | ||
} | ||
// @import | ||
case 'i': | ||
{ | ||
rules.push({ | ||
// before all layers | ||
p: -1, | ||
o: 0, | ||
r: [], | ||
d: asArray(value1).filter(Boolean).map((value)=>key + ' ' + value | ||
).join(';') | ||
}); | ||
continue; | ||
} | ||
// @keyframes | ||
// @font-face | ||
// TODO @font-feature-values | ||
case 'k': | ||
case 'f': | ||
{ | ||
// Use base layer | ||
rules.push({ | ||
p: Layer.d, | ||
o: 0, | ||
r: [ | ||
key | ||
], | ||
d: serialize$(value1, { | ||
p: Layer.d | ||
}, context).map(stringify$1).join('') | ||
}); | ||
continue; | ||
} | ||
} | ||
} | ||
// @media | ||
// @supports | ||
// selector | ||
if (typeof value1 == 'object' && !Array.isArray(value1)) { | ||
// at-rule or non-global selector | ||
if (key[0] == '@' || key.includes('&')) { | ||
let rulePrecedence = precedence; | ||
if (key[0] == '@') { | ||
// Handle `@media screen(sm)` and `@media (screen(sm) or ...)` | ||
key = key.replace(/\bscreen\(([^)]+)\)/g, (_, screenKey)=>{ | ||
const screen = context.theme('screens', screenKey); | ||
if (screen) { | ||
rulePrecedence |= 1 << 26 /* Shifts.screens */ ; | ||
return mql(screen, ''); | ||
} | ||
return _; | ||
}); | ||
rulePrecedence |= atRulePrecedence(key); | ||
} | ||
rules.push(...serialize$(value1, { | ||
n: name, | ||
p: rulePrecedence, | ||
r: [ | ||
...conditions, | ||
key | ||
], | ||
i: important | ||
}, context)); | ||
} else { | ||
// global selector | ||
rules.push(...serialize$(value1, { | ||
p: precedence, | ||
r: [ | ||
key | ||
] | ||
}, context)); | ||
} | ||
} else if (key == 'label' && value1) { | ||
name = value1 + hash(JSON.stringify([ | ||
precedence, | ||
important, | ||
style | ||
])); | ||
} else if (value1 || value1 === 0) { | ||
// property -> hyphenate | ||
key = key.replace(/[A-Z]/g, '-$&').toLowerCase(); | ||
// Update precedence | ||
numberOfDeclarations += 1; | ||
maxPropertyPrecedence = Math.max(maxPropertyPrecedence, declarationPropertyPrecedence(key)); | ||
declarations += (declarations ? ';' : '') + asArray(value1).map((value)=>context.s(key, // support theme(...) function in values | ||
// calc(100vh - theme('spacing.12')) | ||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands | ||
resolveThemeFunction('' + value, context) + (important ? ' !important' : '')) | ||
).join(';'); | ||
} | ||
} | ||
rules.unshift({ | ||
n: name && context.h(name), | ||
p: precedence, | ||
o: // number of declarations (descending) | ||
Math.max(0, 15 - numberOfDeclarations) + // greatest precedence of properties | ||
// if there is no property precedence this is most likely a custom property only declaration | ||
// these have the highest precedence | ||
Math.min(maxPropertyPrecedence || 15, 15) * 1.5, | ||
r: conditions, | ||
// stringified declarations | ||
d: declarations | ||
}); | ||
// only keep layer bits for merging | ||
return rules.sort(compareTwindRules); | ||
} | ||
function resolveThemeFunction(value3, context) { | ||
// support theme(...) function in values | ||
// calc(100vh - theme('spacing.12')) | ||
// theme('borderColor.DEFAULT', 'currentColor') | ||
return value3.replace(/theme\((["'`])?(.+?)\1(?:\s*,\s*(["'`])?(.+?)\3)?\)/g, (_, __, key, ___, value)=>context.theme(key, value) | ||
); | ||
} | ||
function interleave(strings, interpolations, handle) { | ||
return interpolations.reduce((result, interpolation, index)=>result + handle(interpolation) + strings[index + 1] | ||
, strings[0]); | ||
} | ||
function css(strings, ...interpolations) { | ||
const { label ='css' , ...ast } = Array.isArray(strings) ? astish(interleave(strings, interpolations, (interpolation)=>interpolation != null && typeof interpolation != 'boolean' ? interpolation : '' | ||
)) : typeof strings == 'string' ? astish(strings) : strings; | ||
const className = label + hash(JSON.stringify(ast)); | ||
return register(className, (rule, context)=>serialize(ast, rule, context, Layer.o) | ||
); | ||
} | ||
// Based on https://github.com/cristianbote/goober/blob/master/src/core/astish.js | ||
const newRule = / *(?:(?:([\u0080-\uFFFF\w-%@]+) *:? *([^{;]+?);|([^;}{]*?) *{)|(}))/g; | ||
/** | ||
* Convert a css style string into a object | ||
*/ function astish(css1) { | ||
css1 = removeComments(css1); | ||
const tree = [ | ||
{} | ||
]; | ||
let block; | ||
while(block = newRule.exec(css1)){ | ||
// Remove the current entry | ||
if (block[4]) tree.shift(); | ||
if (block[3]) { | ||
tree.unshift(tree[0][block[3]] = tree[0][block[3]] || {}); | ||
} else if (!block[4]) { | ||
tree[0][block[1]] = block[2]; | ||
} | ||
} | ||
return tree[0]; | ||
} | ||
// based on https://github.com/lukeed/clsx and https://github.com/jorgebucaran/classcat | ||
function interpolate(strings, interpolations) { | ||
return Array.isArray(strings) && Array.isArray(strings.raw) ? interleave(strings, interpolations, (value)=>toString(value).trim() | ||
) : interpolations.filter(Boolean).reduce((result, value)=>result + toString(value) | ||
, strings ? toString(strings) : ''); | ||
} | ||
function toString(value) { | ||
let result = ''; | ||
let tmp; | ||
if (value && typeof value == 'object') { | ||
if (Array.isArray(value)) { | ||
if (tmp = interpolate(value[0], value.slice(1))) { | ||
result += ' ' + tmp; | ||
} | ||
} else { | ||
for(const key in value){ | ||
if (value[key]) result += ' ' + key; | ||
} | ||
} | ||
} else if (value != null && typeof value != 'boolean') { | ||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands | ||
result += ' ' + value; | ||
} | ||
return result; | ||
} | ||
function cx(strings, ...interpolations) { | ||
return format(parse(interpolate(strings, interpolations))); | ||
} | ||
function defineConfig({ presets =[] , ...userConfig }) { | ||
// most user config values go first to have precendence over preset config | ||
// only `preflight` and `theme` are applied as last preset to override all presets | ||
let config = { | ||
preflight: userConfig.preflight !== false && [], | ||
theme: {}, | ||
variants: asArray(userConfig.variants), | ||
rules: asArray(userConfig.rules), | ||
ignorelist: asArray(userConfig.ignorelist), | ||
hash: userConfig.hash, | ||
stringify: userConfig.stringify || noprefix | ||
}; | ||
for (const preset of asArray([ | ||
...presets, | ||
{ | ||
preflight: userConfig.preflight !== false && asArray(userConfig.preflight), | ||
theme: userConfig.theme | ||
}, | ||
])){ | ||
const { preflight , theme , variants , rules , hash =config.hash , ignorelist , stringify =config.stringify , } = typeof preset == 'function' ? preset(config) : preset; | ||
config = { | ||
// values defined by user or previous presets take precedence | ||
preflight: config.preflight !== false && preflight !== false && [ | ||
...config.preflight, | ||
...asArray(preflight) | ||
], | ||
theme: { | ||
...config.theme, | ||
...theme, | ||
extend: { | ||
...config.theme.extend, | ||
...theme?.extend | ||
} | ||
}, | ||
variants: [ | ||
...config.variants, | ||
...asArray(variants) | ||
], | ||
rules: [ | ||
...config.rules, | ||
...asArray(rules) | ||
], | ||
ignorelist: [ | ||
...config.ignorelist, | ||
...asArray(ignorelist) | ||
], | ||
hash, | ||
stringify | ||
}; | ||
} | ||
return config; | ||
} | ||
function noprefix(property, value) { | ||
return property + ':' + value; | ||
} | ||
function createStyleElement(// 1. look for existing style element — usually from SSR | ||
// 2. append to document.head — this assumes that document.head has at least one child node | ||
referenceNode = document.querySelector('style[data-twind]') || document.head.lastChild) { | ||
// insert new style element after existing element which allows to override styles | ||
return referenceNode.parentNode.insertBefore(document.createElement('style'), referenceNode.nextSibling); | ||
} | ||
function cssom(target = createStyleElement().sheet) { | ||
return { | ||
target, | ||
clear () { | ||
// remove all added rules | ||
for(let index = target.cssRules.length; index--;){ | ||
target.deleteRule(index); | ||
} | ||
}, | ||
destroy () { | ||
target.ownerNode.remove(); | ||
}, | ||
insert (css, index) { | ||
try { | ||
// Insert | ||
target.insertRule(css, index); | ||
} catch (error) { | ||
// Empty rule to keep index valid — not using `*{}` as that would show up in all rules (DX) | ||
target.insertRule(':root{}', index); | ||
// Some thrown errors are because of specific pseudo classes | ||
// lets filter them to prevent unnecessary warnings | ||
// ::-moz-focus-inner | ||
// :-moz-focusring | ||
if (!/:-[mwo]/.test(css)) { | ||
console.warn(error, css); | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
function dom(target = createStyleElement()) { | ||
return { | ||
target, | ||
clear () { | ||
// remove all added nodes | ||
while(target.childNodes.length){ | ||
target.removeChild(target.lastChild); | ||
} | ||
}, | ||
destroy () { | ||
target.remove(); | ||
}, | ||
insert (css, index) { | ||
target.insertBefore(document.createTextNode(css), target.childNodes[index] || null); | ||
} | ||
}; | ||
} | ||
function virtual(target = []) { | ||
return { | ||
target, | ||
clear () { | ||
target.length = 0; | ||
}, | ||
destroy () { | ||
this.clear(); | ||
}, | ||
insert (css, index) { | ||
target.splice(index, 0, css); | ||
} | ||
}; | ||
} | ||
function stringify(target) { | ||
// string[] | CSSStyleSheet | HTMLStyleElement | ||
if (target.cssRules) { | ||
target = Array.from(target.cssRules, (rule)=>rule.cssText | ||
); | ||
} | ||
return target.innerHTML ?? // eslint-disable-next-line @typescript-eslint/restrict-plus-operands | ||
(Array.isArray(target) ? target.join('') : '' + target); | ||
} | ||
/** | ||
* Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
* | ||
* **Note**: This {@link Twind.clear clears} the Twind instance before processing the HTML. | ||
* | ||
* 1. parse the markup and process element classes with the provided Twind instance | ||
* 2. update the class attributes _if_ necessary | ||
* 3. return the HTML string with the final element classes | ||
* | ||
* ```js | ||
* import { twind, virtual, extract } from '@twind/core' | ||
* | ||
* // can be re-used | ||
* const tw = twind(config, virtual()} | ||
* | ||
* function render() { | ||
* const { html, css } = extract(renderApp(), tw) | ||
* | ||
* // inject as last element into the head | ||
* return html.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
* } | ||
* ``` | ||
* | ||
* @param markup HTML to process | ||
* @param tw a {@link Twind} instance | ||
* @returns the possibly modified html and css | ||
*/ function extract(html, tw) { | ||
tw.clear(); | ||
return { | ||
html: consume(html, tw), | ||
css: stringify(tw.target) | ||
}; | ||
} | ||
function observe(tw, target1 = typeof document != 'undefined' && document.documentElement) { | ||
if (!target1) return tw; | ||
const observer = new MutationObserver(handleMutations); | ||
handleMutations([ | ||
{ | ||
target: target1, | ||
addedNodes: document.querySelectorAll('[class]') | ||
} | ||
]); | ||
observer.observe(target1, { | ||
attributes: true, | ||
attributeFilter: [ | ||
'class' | ||
], | ||
subtree: true, | ||
childList: true | ||
}); | ||
return Object.create(tw, { | ||
destroy: { | ||
enumerable: true, | ||
value: ()=>{ | ||
observer.disconnect(); | ||
tw.destroy(); | ||
} | ||
} | ||
}); | ||
function handleMutation({ target , addedNodes }) { | ||
// Not using target.classList.value (not supported in all browsers) or target.class (this is an SVGAnimatedString for svg) | ||
const tokens = target?.getAttribute?.('class'); | ||
let className; | ||
// try do keep classNames unmodified | ||
if (tokens && changed(tokens, className = tw(tokens))) { | ||
target.setAttribute('class', className); | ||
} | ||
for(let index = addedNodes.length; index--;){ | ||
const node = addedNodes[index]; | ||
handleMutations([ | ||
{ | ||
target: node, | ||
addedNodes: node.children || [] | ||
}, | ||
]); | ||
} | ||
} | ||
function handleMutations(mutations) { | ||
mutations.forEach(handleMutation); | ||
// handle any still-pending mutations | ||
observer.takeRecords().forEach(handleMutation); | ||
} | ||
} | ||
function fromTheme(/** Theme section to use (default: `$1` — The first matched group) */ section1, /** The css property (default: value of {@link section}) */ resolve, convert) { | ||
const factory = !resolve ? ({ 1: $1 , _ }, context, section)=>({ | ||
[$1 || section]: _ | ||
}) | ||
: typeof resolve == 'string' ? (match, context)=>({ | ||
[resolve]: convert ? convert(match, context) : match._ | ||
}) | ||
: resolve; | ||
return (match, context)=>{ | ||
const themeSection = camelize(section1 || match[1]); | ||
// TODO suppport https://github.com/tailwindlabs/tailwindcss/pull/4348 | ||
const value = context.theme(themeSection, match.$$) ?? /** Arbitrary lookup type */ // https://github.com/tailwindlabs/tailwindcss/blob/875c850b37a57bc651e1fed91e3d89af11bdc79f/src/util/pluginUtils.js#L163 | ||
// type?: 'lookup' | 'color' | 'line-width' | 'length' | 'any' | 'shadow' | ||
arbitrary(match.$$, themeSection, context); | ||
if (value != null) { | ||
match._ = match.input[0] == '-' ? `calc(${value} * -1)` : value; | ||
return factory(match, context, themeSection); | ||
} | ||
}; | ||
} | ||
function colorFromTheme(options1 = {}, resolve) { | ||
return (match, context)=>{ | ||
// text- -> textColor | ||
// ring-offset(?:-|$) -> ringOffsetColor | ||
const { section =camelize(match[0]).replace('-', '') + 'Color' } = options1; | ||
// extract color and opacity | ||
// rose-500 -> ['rose-500'] | ||
// [hsl(0_100%_/_50%)] -> ['[hsl(0_100%_/_50%)]'] | ||
// indigo-500/100 -> ['indigo-500', '100'] | ||
// [hsl(0_100%_/_50%)]/[.25] -> ['[hsl(0_100%_/_50%)]', '[.25]'] | ||
// eslint-disable-next-line no-sparse-arrays | ||
if (!/^(\[[^\]]+]|[^/]+?)(?:\/(.+))?$/.test(match.$$)) return; | ||
const { $1: colorMatch , $2: opacityMatch } = RegExp; | ||
const colorValue = context.theme(section, colorMatch) || arbitrary(colorMatch, section, context); | ||
if (!colorValue) return; | ||
const { // text- -> --tw-text-opacity | ||
// ring-offset(?:-|$) -> --tw-ring-offset-opacity | ||
// TODO move this default into preset-tailwind? | ||
opacityVariable =`--tw-${match[0].replace(/-$/, '')}-opacity` , opacitySection =section.replace('Color', 'Opacity') , property =section , selector , } = options1; | ||
const opacityValue = context.theme(opacitySection, opacityMatch || 'DEFAULT') || opacityMatch && arbitrary(opacityMatch, opacitySection, context); | ||
const color = toColorValue(colorValue, { | ||
opacityVariable: opacityVariable || undefined, | ||
opacityValue: opacityValue || undefined | ||
}); | ||
// if (typeof color != 'string') { | ||
// console.warn(`Invalid color ${colorMatch} (from ${match.input}):`, color) | ||
// return | ||
// } | ||
if (resolve) { | ||
match._ = { | ||
value: color, | ||
color: (options)=>toColorValue(colorValue, options) | ||
}; | ||
return resolve(match, context); | ||
} | ||
const properties = {}; | ||
if (opacityVariable && color.includes(opacityVariable)) { | ||
properties[opacityVariable] = opacityValue || '1'; | ||
} | ||
properties[property] = color; | ||
return selector ? { | ||
[selector]: properties | ||
} : properties; | ||
}; | ||
} | ||
function arbitrary(value, section, context) { | ||
if (value[0] == '[' && value.slice(-1) == ']') { | ||
value = resolveThemeFunction(value.slice(1, -1), context); | ||
// TODO remove arbitrary type prefix — we do not need it but user may use it | ||
// https://github.com/tailwindlabs/tailwindcss/blob/master/src/util/dataTypes.js | ||
// url, number, percentage, length, line-width, shadow, color, image, gradient, position, family-name, lookup, any, generic-name, absolute-size, relative-size | ||
// If this is a color section and the value is a hex color, color function or color name | ||
if (/color|fill|stroke/i.test(section)) { | ||
if (/^(#|((hsl|rgb)a?|hwb|lab|lch|color)\(|[a-z]+$)/.test(value)) { | ||
return value; | ||
} | ||
} else if (/image/i.test(section)) { | ||
// url(, [a-z]-gradient(, image(, cross-fade(, image-set( | ||
if (/^[a-z-]+\(/.test(value)) { | ||
return value; | ||
} | ||
} else { | ||
// TODO how to differentiate arbitary values for | ||
// - backgroundSize vs backgroundPosition | ||
// - fontWeight vs fontFamily | ||
if (value.includes('calc(')) { | ||
value = value.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 '); | ||
} | ||
// Convert `_` to ` `, except for escaped underscores `\_` but not between brackets | ||
return value.replace(/(^|[^\\])_+(?![^(]*\))/g, (fullMatch, characterBefore)=>characterBefore + ' '.repeat(fullMatch.length - 1) | ||
).replace(/\\_(?![^(]*\))/g, '_'); | ||
} | ||
} | ||
} | ||
function camelize(value) { | ||
return value.replace(/-./g, (x)=>x[1].toUpperCase() | ||
); | ||
} | ||
const shortcut = /* @__PURE__ */ new Proxy(function shortcut(strings, ...interpolations) { | ||
return format([ | ||
parse(interpolate(strings, interpolations)) | ||
]); | ||
}, { | ||
get: function(target, prop) { | ||
return function namedShortcut(strings, ...interpolations) { | ||
return format(parse(prop + '~(' + interpolate(strings, interpolations) + ')')); | ||
}; | ||
} | ||
}); | ||
const style = (base, config)=>typeof base == 'function' ? createStyle(config, base) : createStyle(base) | ||
; | ||
function createStyle(config = {}, parent) { | ||
const { label ='style' , base , props: variants = {} , defaults: localDefaults , when =[] } = config; | ||
const defaults = { | ||
...parent?.defaults, | ||
...localDefaults | ||
}; | ||
const id = hash(JSON.stringify([ | ||
label, | ||
parent?.className, | ||
base, | ||
variants, | ||
defaults, | ||
when | ||
])); | ||
// Layers: | ||
// component: 0b010 | ||
// props: 0b011 | ||
// when: 0b100 | ||
const className = register('', base || '', Layer.c); | ||
function register(mq, token, layer) { | ||
return define(// `<name>#<id>` or `<parent>~<name>#<id>` | ||
((parent ? parent.className.replace(/#.+$/, '~') : '') + label + mq + id).replace(/[: ,()[\]]/, ''), layer, token && parse(token)); | ||
} | ||
return Object.defineProperties(function style(allProps) { | ||
const props = { | ||
...defaults, | ||
...allProps | ||
}; | ||
let classNames = (parent ? parent(props) + ' ' : '') + className; | ||
let token; | ||
for(const variantKey1 in variants){ | ||
const variant = variants[variantKey1]; | ||
const propsValue = props[variantKey1]; | ||
if (propsValue === Object(propsValue)) { | ||
// inline responsive breakpoints | ||
let mq = ''; | ||
token = ''; | ||
for(const breakpoint in propsValue){ | ||
const breakpointToken = variant[propsValue[breakpoint]]; | ||
if (breakpointToken) { | ||
mq += '@' + breakpoint + '-' + propsValue[breakpoint]; | ||
token += (token && ' ') + (breakpoint == '_' ? breakpointToken : breakpoint + ':(' + breakpointToken + ')'); | ||
} | ||
} | ||
if (token) { | ||
classNames += ' ' + register('--' + variantKey1 + '-' + mq, token, 3 << 27 /* Shifts.layer */ ); | ||
} | ||
} else if (token = variant[propsValue]) { | ||
classNames += ' ' + register('--' + variantKey1 + '-' + propsValue, token, 3 << 27 /* Shifts.layer */ ); | ||
} | ||
} | ||
when.forEach((match, index)=>{ | ||
let mq = ''; | ||
for(const variantKey in match[0]){ | ||
const propsValue = props[variantKey]; | ||
// TODO we ignore inline responsive breakpoints for now — what be the result?? | ||
if (propsValue !== Object(propsValue) && '' + propsValue == '' + match[0][variantKey]) { | ||
mq += (mq && '_') + variantKey + '-' + propsValue; | ||
} else { | ||
mq = ''; | ||
break; | ||
} | ||
} | ||
if (mq && (token = match[1])) { | ||
classNames += ' ' + register('-' + index + '--' + mq, token, 5 << 27 /* Shifts.layer */ ); | ||
} | ||
}); | ||
return classNames; | ||
}, Object.getOwnPropertyDescriptors({ | ||
className, | ||
defaults, | ||
selector: '.' + escape(className) | ||
})); | ||
} | ||
function makeThemeFunction({ extend ={} , ...base }) { | ||
const resolved = {}; | ||
const resolveContext = { | ||
colors: theme('colors'), | ||
theme, | ||
// Stub implementation as negated values are automatically infered and do _not_ need to be in the theme | ||
negative () { | ||
return {}; | ||
}, | ||
breakpoints (screens) { | ||
const breakpoints = {}; | ||
for(const key in screens){ | ||
if (typeof screens[key] == 'string') { | ||
breakpoints['screen-' + key] = screens[key]; | ||
} | ||
} | ||
return breakpoints; | ||
} | ||
}; | ||
return theme; | ||
function theme(sectionKey, key, defaultValue) { | ||
if (sectionKey) { | ||
if (/[.[]/.test(sectionKey)) { | ||
const path = []; | ||
// dotted deep access: colors.gray.500 or or spacing[2.5] | ||
sectionKey.replace(/\[([^\]]+)\]|([^.[]+)/g, (_, $1, $2 = $1)=>path.push($2) | ||
); | ||
sectionKey = path.shift(); | ||
defaultValue = key; | ||
key = path.join('-'); | ||
} | ||
const section = resolved[sectionKey] || // two-step deref to allow extend section to reference base section | ||
Object.assign(Object.assign(// Make sure to not get into recursive calls | ||
(resolved[sectionKey] = {}), deref(base, sectionKey)), deref(extend, sectionKey)); | ||
if (key == null) return section; | ||
return section[key || 'DEFAULT'] ?? defaultValue; | ||
} | ||
// Collect the whole theme | ||
const result = {}; | ||
for(const section in base){ | ||
result[section] = theme(section); | ||
} | ||
return result; | ||
} | ||
function deref(source, section) { | ||
let value = source[section]; | ||
if (typeof value == 'function') { | ||
value = value(resolveContext); | ||
} | ||
if (value && /color/i.test(section)) { | ||
return flattenColorPalette(value); | ||
} | ||
return value; | ||
} | ||
} | ||
function flattenColorPalette(colors, path = []) { | ||
const flattend = {}; | ||
for(const key in colors){ | ||
const value = colors[key]; | ||
const keyPath = key == 'DEFAULT' ? path : [ | ||
...path, | ||
key | ||
]; | ||
if (typeof value == 'object') { | ||
Object.assign(flattend, flattenColorPalette(value, keyPath)); | ||
} | ||
flattend[keyPath.join('-')] = value; | ||
if (key == 'DEFAULT') { | ||
flattend[[ | ||
...path, | ||
key | ||
].join('-')] = value; | ||
} | ||
} | ||
return flattend; | ||
} | ||
function createContext({ theme , variants , rules , hash: hash$1 , stringify , ignorelist }) { | ||
// Used to cache resolved rule values | ||
const variantCache = new Map(); | ||
// lazy created resolve functions | ||
const variantResolvers = new Map(); | ||
// Used to cache resolved rule values | ||
const ruleCache = new Map(); | ||
// lazy created resolve functions | ||
const ruleResolvers = new Map(); | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
const ignored = createRegExpExecutor(ignorelist, (value, condition)=>condition.test(value) | ||
); | ||
return { | ||
theme: makeThemeFunction(theme), | ||
e: escape, | ||
h: typeof hash$1 == 'function' ? hash$1 : hash$1 ? hash : (value)=>value | ||
, | ||
s (property, value) { | ||
return stringify(property, value, this); | ||
}, | ||
v (value) { | ||
if (!ruleCache.has(value)) { | ||
variantCache.set(value, find(value, variants, variantResolvers, getVariantResolver, this) || '&:' + value); | ||
} | ||
return variantCache.get(value); | ||
}, | ||
r (value) { | ||
if (!ruleCache.has(value)) { | ||
ruleCache.set(value, // TODO console.warn(`[twind] unknown rule "${value}"`), | ||
!ignored(value, this) && find(value, rules, ruleResolvers, getRuleResolver, this)); | ||
} | ||
return ruleCache.get(value); | ||
} | ||
}; | ||
} | ||
function find(value, list, cache, getResolver, context) { | ||
for (const item of list){ | ||
let resolver = cache.get(item); | ||
if (!resolver) { | ||
cache.set(item, resolver = getResolver(item)); | ||
} | ||
const resolved = resolver(value, context); | ||
if (resolved) return resolved; | ||
} | ||
} | ||
function getVariantResolver(variant) { | ||
return createVariantFunction(variant[0], variant[1]); | ||
} | ||
function getRuleResolver(rule) { | ||
if (Array.isArray(rule)) { | ||
return createResolveFunction(rule[0], rule[1], rule[2]); | ||
} | ||
return createResolveFunction(rule); | ||
} | ||
function createVariantFunction(condition, resolve) { | ||
return createResolve(condition, typeof resolve == 'function' ? resolve : ()=>resolve | ||
); | ||
} | ||
function createResolveFunction(condition, resolve, convert) { | ||
// This is a shortcuts object | ||
if (Object.getPrototypeOf(condition) === Object.prototype) { | ||
return createExecutor(// eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
Object.keys(condition).map((key)=>{ | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access | ||
const value = condition[key]; | ||
return createResolveFunction(key, typeof value == 'function' ? value : ()=>value | ||
); | ||
}), (value, resolver, context)=>resolver(value, context) | ||
); | ||
} | ||
return createResolve(condition, !resolve ? (match)=>({ | ||
[match[1]]: maybeNegate(match.input, match.slice(2).find(Boolean) || match.$$ || match.input) | ||
}) | ||
: typeof resolve == 'string' ? (match, context)=>({ | ||
[resolve]: convert ? convert(match, context) : maybeNegate(match.input, match.slice(1).find(Boolean) || match.$$ || match.input) | ||
}) | ||
: typeof resolve == 'function' ? resolve : ()=>resolve | ||
); | ||
} | ||
function maybeNegate($_, value) { | ||
return $_[0] == '-' ? `calc(${value} * -1)` : value; | ||
} | ||
function createResolve(condition1, resolve) { | ||
return createRegExpExecutor(condition1, (value, condition, context)=>exec(value, condition, resolve, context) | ||
); | ||
} | ||
function exec(value, condition, resolve, context) { | ||
const match = condition.exec(value); | ||
if (match) { | ||
// MATCH.$_ = value | ||
match.$$ = value.slice(match[0].length); | ||
return resolve(match, context); | ||
} | ||
} | ||
function createRegExpExecutor(condition, run) { | ||
return createExecutor(asArray(condition).map(asRegExp), run); | ||
} | ||
function createExecutor(conditions, run) { | ||
return (value, context)=>{ | ||
for (const condition of conditions){ | ||
const result = run(value, condition, context); | ||
if (result) return result; | ||
} | ||
}; | ||
} | ||
function asRegExp(value) { | ||
// "visible" -> /^visible$/ | ||
// "(float)-(left|right|none)" -> /^(float)-(left|right|none)$/ | ||
// "auto-rows-" -> /^auto-rows-/ | ||
// "gap(-|$)" -> /^gap(-|$)/ | ||
return typeof value == 'string' ? new RegExp('^' + value + (value.includes('$') || value.slice(-1) == '-' ? '' : '$')) : value; | ||
} | ||
function twind(userConfig, sheet) { | ||
const config = defineConfig(userConfig); | ||
const context = createContext(config); | ||
// Map of tokens to generated className | ||
const cache = new Map(); | ||
// An array of precedence by index within the sheet | ||
// always sorted | ||
const sortedPrecedences = []; | ||
// Cache for already inserted css rules | ||
// to prevent double insertions | ||
const insertedRules = new Set(); | ||
function insert(rule) { | ||
rule = { | ||
...rule, | ||
n: rule.n && context.h(rule.n) | ||
}; | ||
const css = stringify$1(rule); | ||
// If not already inserted | ||
if (css && !insertedRules.has(css)) { | ||
// Mark rule as inserted | ||
insertedRules.add(css); | ||
// Find the correct position | ||
const index = sortedInsertionIndex(sortedPrecedences, rule); | ||
// Insert | ||
sheet.insert(css, index, rule); | ||
// Update sorted index | ||
sortedPrecedences.splice(index, 0, rule); | ||
} | ||
return rule.n; | ||
} | ||
return Object.defineProperties(function tw(strings, ...interpolations) { | ||
if (!cache.size) { | ||
for (let preflight of asArray(config.preflight)){ | ||
if (typeof preflight == 'function') { | ||
preflight = preflight(context); | ||
} | ||
if (preflight) { | ||
serialize(preflight, {}, context, Layer.b).forEach(insert); | ||
} | ||
} | ||
} | ||
const tokens = interpolate(strings, interpolations); | ||
let className = cache.get(tokens); | ||
if (!className) { | ||
const classNames = new Set(); | ||
for (const rule of translate(parse(tokens), context)){ | ||
classNames.add(rule.c).add(insert(rule)); | ||
} | ||
// TODO try do keep classNames unmodified or same order | ||
className = [ | ||
...classNames | ||
].filter(Boolean).join(' '); | ||
// Remember the generated class name | ||
cache.set(tokens, className).set(className, className); | ||
} | ||
return className; | ||
}, Object.getOwnPropertyDescriptors({ | ||
get target () { | ||
return sheet.target; | ||
}, | ||
theme: context.theme, | ||
clear () { | ||
sheet.clear(); | ||
insertedRules.clear(); | ||
cache.clear(); | ||
sortedPrecedences.length = 0; | ||
}, | ||
destroy () { | ||
this.clear(); | ||
sheet.destroy(); | ||
} | ||
})); | ||
} | ||
export { arbitrary, asArray, colorFromTheme, consume, css, cssom, cx, defineConfig, dom, escape, extract, fromTheme, hash, mql, observe, shortcut, stringify, style, toColorValue, twind, virtual }; | ||
//# sourceMappingURL=core.esnext.js.map | ||
export * from "./core.js"; |
@@ -1,1 +0,1 @@ | ||
const twind_core=function(a){"use strict";function b(a,b){return Math.round(parseInt(a,16)*b)}function c(a,c={}){if("function"==typeof a)return a(c);const{opacityValue:d="1",opacityVariable:e}=c,f=e?`var(${e})`:d;if("1"==f)return a;if("0"==f)return"#0000";if("#"==a[0]&&(4==a.length||7==a.length)){const g=(a.length-1)/3,h=[17,1,0.062272][g-1];return`rgba(${[b(a.substr(1,g),h),b(a.substr(1+g,g),h),b(a.substr(1+2*g,g),h),f,]})`}return a}function d(a,b){return a!=b&&""+a.split(" ").sort()!=""+b.split(" ").sort()}function e(a,b){let c="",e=0;return f(a,(f,g,h)=>{const i=a.slice(f,g),j=b(i);d(i,j)&&(h=h?"":"\"",c+=a.slice(e,f)+h+j+h,e=g)}),c+a.slice(e,a.length)}function f(a,b){let c=1,d=0,e="",f="",g="";const h=a=>{5==c&&"class"==g&&b(d,a,e)};for(let i=0;i<a.length;i++)(f=a[i],1==c)?"<"==f&&(c="!--"==a.substr(i+1,3)?4:3):4==c?">"==f&&"--"==a.slice(i-2,i)&&(c=1):e?f==e&&"\\"!=a[i-1]&&(h(i),c=2,e=""):"\""==f||"'"==f?(e=f,d+=1):">"==f?(h(i),c=1):c&&("="==f?(g=a.slice(d,i),c=5,d=i+1):"/"==f&&(c<5||">"==a[i+1])?(h(i),c=0):/\s/.test(f)&&(h(i),c=2,d=i+1))}function g(a,b,c){return b in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function h(a){for(var b=1;b<arguments.length;b++){var c=null!=arguments[b]?arguments[b]:{},d=Object.keys(c);"function"==typeof Object.getOwnPropertySymbols&&(d=d.concat(Object.getOwnPropertySymbols(c).filter(function(a){return Object.getOwnPropertyDescriptor(c,a).enumerable}))),d.forEach(function(b){g(a,b,c[b])})}return a}function i(a,b){if(null==a)return{};var c,d,e=function(a,b){if(null==a)return{};var c,d,e={},f=Object.keys(a);for(d=0;d<f.length;d++)c=f[d],b.indexOf(c)>=0||(e[c]=a[c]);return e}(a,b);if(Object.getOwnPropertySymbols){var f=Object.getOwnPropertySymbols(a);for(d=0;d<f.length;d++)c=f[d],!(b.indexOf(c)>=0)&&Object.prototype.propertyIsEnumerable.call(a,c)&&(e[c]=a[c])}return e}const j=new Map();function k(a,b){return j.set(a,b),a}const l="undefined"!=typeof CSS&&CSS.escape||(a=>a.replace(/[!"'`*+.,;:\\/<=>?@#$%&^|~()[\]{}]/g,"\\$&").replace(/^\d/,"\\3$& "));function m(a){for(var b=9,c=a.length;c--;)b=Math.imul(b^a.charCodeAt(c),1597334677);return"#"+((b^b>>>9)>>>0).toString(36)}function n(a,b="@media "){return b+o(a).map(a=>("string"==typeof a&&(a={min:a}),a.raw||Object.keys(a).map(b=>`(${b}-width:${a[b]})`).join(" and "))).join(",")}function o(a=[]){return Array.isArray(a)?a:null==a?[]:[a]}function p(a){return[...a.v,(a.i?"!":"")+a.n].join(":")}const q={d:0,b:134217728,c:268435456,s:671088640,u:805306368,o:939524096};function r(a,b){return a& ~q.o|b}function s(a){var b;return(null===(b=a.match(/[-=:;]/g))|| void 0===b?void 0:b.length)||0}function t(a){return Math.min(/(?:^|width[^\d]+)(\d+(?:.\d+)?)(p)?/.test(a)?+RegExp.$1/(RegExp.$2?15:1)/10:0,15)<<22|Math.min(s(a),15)<<18}const u=["rst-c","st-ch","h-chi","y-lin","nk","sited","ecked","pty","ad-on","cus-w","ver","cus","cus-v","tive","sable","tiona","quire",];function v(a){return 1<< ~(/:([a-z-]+)/.test(a)&& ~u.indexOf(RegExp.$1.slice(2,7))|| -18)}function w(a){return"-"==a[0]?0:s(a)+(/^(?:(border-(?!w|c|sty)|[tlbr].{2,4}m?$|c.{7}$)|([fl].{5}l|g.{8}$|pl))/.test(a)?+!!RegExp.$1||-!!RegExp.$2:0)+1}function x({n:a,i:b,v:c=[]},d,e,f){for(const g of(a&&(a=p({n:a,i:b,v:c})),f=[...o(f)],c)){const h=d.theme("screens",g),i=h&&n(h)||d.v(g);f.push(i),e|=h?67108864|t(i):"dark"==g?1073741824:"@"==i[0]?t(i):v(i)}return{n:a,p:e,r:f,i:b}}function y(a){if(a.d){const b=[],c=a.r["reduce"+(a.n?"Right":"")]((a,c)=>"@"==c[0]?(b.unshift(c),a):a.replace(/^$| *((?:\\,|\(.+?\)|\[.+?\]|[^,])+) *(,|$)/g,(a,b=a,d="")=>c.replace(/ *((?:\\,|\(.+?\)|\[.+?\]|[^,])+) *(,|$)/g,(a,c,d="")=>c.replace(/&/g,b)+d)+d),a.n?"."+l(a.n):"");return c&&b.push(c),b.reduceRight((a,b)=>b+"{"+a+"}",a.d)}}function z(a,b=" "){return a.map(a=>Array.isArray(a)?(","==b?"":"~(")+z(a,",")+(","==b?"":")"):p(a)).join(b)}function A(a,b){const c=[];let d;for(const e of a)(null==d?void 0:d.p)==e.p&&""+d.r==""+e.r?(d.c=[d.c,e.c].filter(Boolean).join(" "),d.d=[d.d,e.d].filter(Boolean).join(";")):c.push(d=h({},e,{n:e.n&&b}));return c}function B(a,b,c){return k(a,(a,d)=>{const{n:e,p:f,r:g,i:i}=x(a,d,b);return c&&A(K(c,d,f,g,i,e).map(a=>a.n?h({},a,{p:r(a.p,b),o:0}):a),e)})}function C(a,b){if("("!=a[a.length-1]){const c=[];let d=!1,e=!1,f="";for(let g of a)if(!("("==g||g.endsWith("~"))){if("!"==g[0]&&(g=g.slice(1),d=!d),g.endsWith(":")){c.push(g.slice(0,-1));continue}"-"==g[0]&&(g=g.slice(1),e=!e),g.endsWith("-")&&(g=g.slice(0,-1)),g&&"&"!=g&&(f+=(f&&"-")+g)}f&&(e&&(f="-"+f),b[0].push({n:f,v:c,i:d}))}}function D(a){return a.replace(/\/\*[^]*?\*\/|\/\/[^]*?$|\s\s+|\n/gm," ")}const E=/([ ,)])|\(|[^ ,)(:[]*(?:\[[^ ]+])?:*/g,F=new Map();function G(a){let b=F.get(a);if(!b){a=D(a);const c=[],d=[[]];let e,f;for(E.lastIndex=0;(f=E.exec(a))&&f[0];)if(f[1]){C(c,d);let g=c.lastIndexOf("("),h,i;")"==f[1]&&((null==(h=c[g-1])?void 0:h.endsWith("~"))&&(i=d.shift()),g=c.lastIndexOf("(",g-1)),c.length=g+1,i&&"~"!=h&&(d[0].pop(),C([...c,B(h.slice(0,-1)+m(JSON.stringify(i)),q.s,i),],d))}else f[0].endsWith("~")&&(e=[],d[0].push(e),d.unshift(e)),c.push(f[0]);C(c,d),F.set(a,b=d[0])}return b}const H=new Intl.Collator("en",{numeric:!0});function I(a,b){for(var c=0,d=a.length;c<d;){const e=d+c>>1;0>=J(a[e],b)?c=e+1:d=e}return d}function J(a,b){const c=a.p&q.o;return c==(b.p&q.o)&&(c==q.b||c==q.o)?0:a.p-b.p||a.o-b.o||H.compare(a.r,b.r)||H.compare(a.n,b.n)}function K(a,b,c=q.u,d,e,f){const g=[];for(const h of a)for(const i of Array.isArray(h)?A(K(h,b,(c&q.o)==q.u?r(c,q.s):c,d,e),f||z([h])):L(h,b,c,d,e))g.splice(I(g,i),0,i);return g}function L(a,b,c,d,e){a=h({},a,{i:a.i||e});const f=function(a,b){const c=j.get(a.n);return c?c(a,b):b.r(a.n)}(a,b);return f?"string"==typeof f?({r:d,p:c}=x(a,b,c,d),K([G(f)],b,c,d,a.i,a.n)):Array.isArray(f)?f.map(a=>h({o:0},a,{r:[...o(d),...o(a.r)],p:r(c,a.p||c)})):M(f,a,b,c,d):[{c:p(a),p:0,o:0,r:[]}]}function M(a,b,c,d,e=[]){return N(a,x(b,c,d,e),c)}function N(a,{n:b,p:c,r:d=[],i:e},f){const g=[];let i="",j=0,k=0;for(let l in a||{}){const p=a[l];if("@"==l[0]){if(!p)continue;switch(l[1]){case"a":g.push(...K([G(p)],f,c,d,e).map(a=>h({},a,{n:b})));continue;case"l":for(const s of o(p))g.push(...N(s,{n:b,p:r(c,q[l[7]]),r:d,i:e},f));continue;case"i":g.push({p:-1,o:0,r:[],d:o(p).filter(Boolean).map(a=>l+" "+a).join(";")});continue;case"k":case"f":g.push({p:q.d,o:0,r:[l],d:N(p,{p:q.d},f).map(y).join("")});continue}}if("object"!=typeof p||Array.isArray(p))"label"==l&&p?b=p+m(JSON.stringify([c,e,a])):(p||0===p)&&(k+=1,j=Math.max(j,w(l=l.replace(/[A-Z]/g,"-$&").toLowerCase())),i+=(i?";":"")+o(p).map(a=>f.s(l,O(""+a,f)+(e?" !important":""))).join(";"));else if("@"==l[0]||l.includes("&")){let u=c;"@"==l[0]&&(u|=t(l=l.replace(/\bscreen\(([^)]+)\)/g,(a,b)=>{const c=f.theme("screens",b);return c?(u|=67108864,n(c,"")):a}))),g.push(...N(p,{n:b,p:u,r:[...d,l],i:e},f))}else g.push(...N(p,{p:c,r:[l]},f))}return g.unshift({n:b&&f.h(b),p:c,o:Math.max(0,15-k)+1.5*Math.min(j||15,15),r:d,d:i}),g.sort(J)}function O(a,b){return a.replace(/theme\((["'`])?(.+?)\1(?:\s*,\s*(["'`])?(.+?)\3)?\)/g,(a,c,d,e,f)=>b.theme(d,f))}function P(a,b,c){return b.reduce((b,d,e)=>b+c(d)+a[e+1],a[0])}const Q=/ *(?:(?:([\u0080-\uFFFF\w-%@]+) *:? *([^{;]+?);|([^;}{]*?) *{)|(}))/g;function R(a){a=D(a);const b=[{}];let c;for(;c=Q.exec(a);)c[4]&&b.shift(),c[3]?b.unshift(b[0][c[3]]=b[0][c[3]]||{}):c[4]||(b[0][c[1]]=c[2]);return b[0]}function S(a,b){return Array.isArray(a)&&Array.isArray(a.raw)?P(a,b,a=>T(a).trim()):b.filter(Boolean).reduce((a,b)=>a+T(b),a?T(a):"")}function T(a){let b="",c;if(a&&"object"==typeof a)if(Array.isArray(a))(c=S(a[0],a.slice(1)))&&(b+=" "+c);else for(const d in a)a[d]&&(b+=" "+d);else null!=a&&"boolean"!=typeof a&&(b+=" "+a);return b}function U(a){var{presets:b=[]}=a,c=i(a,["presets"]);let d={preflight:!1!==c.preflight&&[],theme:{},variants:o(c.variants),rules:o(c.rules),ignorelist:o(c.ignorelist),hash:c.hash,stringify:c.stringify||V};for(const e of o([...b,{preflight:!1!==c.preflight&&o(c.preflight),theme:c.theme},])){const{preflight:f,theme:g,variants:j,rules:k,hash:l=d.hash,ignorelist:m,stringify:n=d.stringify}="function"==typeof e?e(d):e;d={preflight:!1!==d.preflight&& !1!==f&&[...d.preflight,...o(f)],theme:h({},d.theme,g,{extend:h({},d.theme.extend,null==g?void 0:g.extend)}),variants:[...d.variants,...o(j)],rules:[...d.rules,...o(k)],ignorelist:[...d.ignorelist,...o(m)],hash:l,stringify:n}}return d}function V(a,b){return a+":"+b}function W(a=document.querySelector("style[data-twind]")||document.head.lastChild){return a.parentNode.insertBefore(document.createElement("style"),a.nextSibling)}function X(a){var b;return a.cssRules&&(a=Array.from(a.cssRules,a=>a.cssText)),null!==(b=a.innerHTML)&& void 0!==b?b:Array.isArray(a)?a.join(""):""+a}function Y(a,b,c){if("["==a[0]&&"]"==a.slice(-1)){if(a=O(a.slice(1,-1),c),/color|fill|stroke/i.test(b)){if(/^(#|((hsl|rgb)a?|hwb|lab|lch|color)\(|[a-z]+$)/.test(a))return a}else if(!/image/i.test(b))return a.includes("calc(")&&(a=a.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,"$1 $2 ")),a.replace(/(^|[^\\])_+(?![^(]*\))/g,(a,b)=>b+" ".repeat(a.length-1)).replace(/\\_(?![^(]*\))/g,"_");else if(/^[a-z-]+\(/.test(a))return a}}function Z(a){return a.replace(/-./g,a=>a[1].toUpperCase())}const $=new Proxy(function(a,...b){return z([G(S(a,b))])},{get:function(a,b){return function(a,...c){return z(G(b+"~("+S(a,c)+")"))}}});function _(a={},b){const{label:c="style",base:d,props:e={},defaults:f,when:g=[]}=a,i=h({},null==b?void 0:b.defaults,f),j=m(JSON.stringify([c,null==b?void 0:b.className,d,e,i,g])),k=n("",d||"",q.c);function n(a,d,e){return B(((b?b.className.replace(/#.+$/,"~"):"")+c+a+j).replace(/[: ,()[\]]/,""),e,d&&G(d))}return Object.defineProperties(function(a){const c=h({},i,a);let d=(b?b(c)+" ":"")+k,f;for(const j in e){const l=e[j],m=c[j];if(m===Object(m)){let o="";for(const p in f="",m){const q=l[m[p]];q&&(o+="@"+p+"-"+m[p],f+=(f&&" ")+("_"==p?q:p+":("+q+")"))}f&&(d+=" "+n("--"+j+"-"+o,f,402653184))}else(f=l[m])&&(d+=" "+n("--"+j+"-"+m,f,402653184))}return g.forEach((a,b)=>{let e="";for(const g in a[0]){const h=c[g];if(h!==Object(h)&&""+h==""+a[0][g])e+=(e&&"_")+g+"-"+h;else{e="";break}}e&&(f=a[1])&&(d+=" "+n("-"+b+"--"+e,f,671088640))}),d},Object.getOwnPropertyDescriptors({className:k,defaults:i,selector:"."+l(k)}))}function aa(a,b=[]){const c={};for(const d in a){const e=a[d],f="DEFAULT"==d?b:[...b,d];"object"==typeof e&&Object.assign(c,aa(e,f)),c[f.join("-")]=e,"DEFAULT"==d&&(c[[...b,d].join("-")]=e)}return c}function ba(a,b,c,d,e){for(const f of b){let g=c.get(f);g||c.set(f,g=d(f));const h=g(a,e);if(h)return h}}function ca(a){return ea(a[0],a[1])}function da(a){return Array.isArray(a)?fa(a[0],a[1],a[2]):fa(a)}function ea(a,b){return ha(a,"function"==typeof b?b:()=>b)}function fa(a,b,c){return Object.getPrototypeOf(a)===Object.prototype?ka(Object.keys(a).map(b=>{const c=a[b];return fa(b,"function"==typeof c?c:()=>c)}),(a,b,c)=>b(a,c)):ha(a,b?"string"==typeof b?(a,d)=>({[b]:c?c(a,d):ga(a.input,a.slice(1).find(Boolean)||a.$$||a.input)}):"function"==typeof b?b:()=>b:a=>({[a[1]]:ga(a.input,a.slice(2).find(Boolean)||a.$$||a.input)}))}function ga(a,b){return"-"==a[0]?`calc(${b} * -1)`:b}function ha(a,b){return ja(a,(a,c,d)=>ia(a,c,b,d))}function ia(a,b,c,d){const e=b.exec(a);if(e)return e.$$=a.slice(e[0].length),c(e,d)}function ja(a,b){return ka(o(a).map(la),b)}function ka(a,b){return(c,d)=>{for(const e of a){const f=b(c,e,d);if(f)return f}}}function la(a){return"string"==typeof a?new RegExp("^"+a+(a.includes("$")||"-"==a.slice(-1)?"":"$")):a}return a.arbitrary=Y,a.asArray=o,a.colorFromTheme=function(a={},b){return(d,e)=>{const{section:f=Z(d[0]).replace("-","")+"Color"}=a;if(/^(\[[^\]]+]|[^/]+?)(?:\/(.+))?$/.test(d.$$)){const{$1:g,$2:h}=RegExp,i=e.theme(f,g)||Y(g,f,e);if(i){const{opacityVariable:j=`--tw-${d[0].replace(/-$/,"")}-opacity`,opacitySection:k=f.replace("Color","Opacity"),property:l=f,selector:m}=a,n=e.theme(k,h||"DEFAULT")||h&&Y(h,k,e),o=c(i,{opacityVariable:j||void 0,opacityValue:n||void 0});if(b)return d._={value:o,color:a=>c(i,a)},b(d,e);const p={};return j&&o.includes(j)&&(p[j]=n||"1"),p[l]=o,m?{[m]:p}:p}}}},a.consume=e,a.css=function(a,...b){const c=Array.isArray(a)?R(P(a,b,a=>null!=a&&"boolean"!=typeof a?a:"")):"string"==typeof a?R(a):a,{label:d="css"}=c,e=i(c,["label"]),f=d+m(JSON.stringify(e));return k(f,(a,b)=>M(e,a,b,q.o))},a.cssom=function(a=W().sheet){return{target:a,clear(){for(let b=a.cssRules.length;b--;)a.deleteRule(b)},destroy(){a.ownerNode.remove()},insert(b,c){try{a.insertRule(b,c)}catch(d){a.insertRule(":root{}",c),/:-[mwo]/.test(b)||console.warn(d,b)}}}},a.cx=function(a,...b){return z(G(S(a,b)))},a.defineConfig=U,a.dom=function(a=W()){return{target:a,clear(){for(;a.childNodes.length;)a.removeChild(a.lastChild)},destroy(){a.remove()},insert(b,c){a.insertBefore(document.createTextNode(b),a.childNodes[c]||null)}}},a.escape=l,a.extract=function(a,b){return b.clear(),{html:e(a,b),css:X(b.target)}},a.fromTheme=function(a,b,c){const d=b?"string"==typeof b?(a,d)=>({[b]:c?c(a,d):a._}):b:({1:a,_:b},c,d)=>({[a||d]:b});return(b,c)=>{var e;const f=Z(a||b[1]),g=null!==(e=c.theme(f,b.$$))&& void 0!==e?e:Y(b.$$,f,c);if(null!=g)return b._="-"==b.input[0]?`calc(${g} * -1)`:g,d(b,c,f)}},a.hash=m,a.mql=n,a.observe=function(a,b=document.documentElement){if(!b)return a;const c=new MutationObserver(f);function e({target:b,addedNodes:c}){var e,g;const h=null===(e=b)|| void 0===e?void 0:null===(g=e.getAttribute)|| void 0===g?void 0:g.call(e,"class");let i;h&&d(h,i=a(h))&&b.setAttribute("class",i);for(let j=c.length;j--;){const k=c[j];f([{target:k,addedNodes:k.children||[]},])}}function f(a){a.forEach(e),c.takeRecords().forEach(e)}return f([{target:b,addedNodes:document.querySelectorAll("[class]")}]),c.observe(b,{attributes:!0,attributeFilter:["class"],subtree:!0,childList:!0}),Object.create(a,{destroy:{enumerable:!0,value(){c.disconnect(),a.destroy()}}})},a.shortcut=$,a.stringify=X,a.style=(a,b)=>"function"==typeof a?_(b,a):_(a),a.toColorValue=c,a.twind=function(a,b){const c=U(a),d=function({theme:a,variants:b,rules:c,hash:d,stringify:e,ignorelist:f}){const g=new Map(),h=new Map(),j=new Map(),k=new Map(),n=ja(f,(a,b)=>b.test(a));return{theme:(function(a){var{extend:b={}}=a,c=i(a,["extend"]);const d={},e={colors:f("colors"),theme:f,negative(){return{}},breakpoints(a){const b={};for(const c in a)"string"==typeof a[c]&&(b["screen-"+c]=a[c]);return b}};function f(a,e,h){if(a){var i;if(/[.[]/.test(a)){const j=[];a.replace(/\[([^\]]+)\]|([^.[]+)/g,(a,b,c=b)=>j.push(c)),a=j.shift(),h=e,e=j.join("-")}const k=d[a]||Object.assign(Object.assign(d[a]={},g(c,a)),g(b,a));return null==e?k:null!==(i=k[e||"DEFAULT"])&& void 0!==i?i:h}const l={};for(const m in c)l[m]=f(m);return l}function g(a,b){let c=a[b];return("function"==typeof c&&(c=c(e)),c&&/color/i.test(b))?aa(c):c}return f})(a),e:l,h:"function"==typeof d?d:d?m:a=>a,s(a,b){return e(a,b,this)},v(a){return j.has(a)||g.set(a,ba(a,b,h,ca,this)||"&:"+a),g.get(a)},r(a){return j.has(a)||j.set(a,!n(a,this)&&ba(a,c,k,da,this)),j.get(a)}}}(c),e=new Map(),f=[],g=new Set();function j(a){a=h({},a,{n:a.n&&d.h(a.n)});const c=y(a);if(c&&!g.has(c)){g.add(c);const e=I(f,a);b.insert(c,e,a),f.splice(e,0,a)}return a.n}return Object.defineProperties(function(a,...b){if(!e.size)for(let f of o(c.preflight))"function"==typeof f&&(f=f(d)),f&&M(f,{},d,q.b).forEach(j);const g=S(a,b);let h=e.get(g);if(!h){const i=new Set();for(const k of K(G(g),d))i.add(k.c).add(j(k));h=[...i].filter(Boolean).join(" "),e.set(g,h).set(h,h)}return h},Object.getOwnPropertyDescriptors({get target(){return b.target},theme:d.theme,clear(){b.clear(),g.clear(),e.clear(),f.length=0},destroy(){this.clear(),b.destroy()}}))},a.virtual=function(a=[]){return{target:a,clear(){a.length=0},destroy(){this.clear()},insert(b,c){a.splice(c,0,b)}}},a}({})//# sourceMappingURL=core.global.js.map | ||
var twind=function(e){"use strict";let t;function r(e){return[...e.v,(e.i?"!":"")+e.n].join(":")}function n(e,t=","){return e.map(r).join(t)}let i="undefined"!=typeof CSS&&CSS.escape||(e=>e.replace(/[!"'`*+.,;:\\/<=>?@#$%&^|~()[\]{}]/g,"\\$&").replace(/^\d/,"\\3$& "));function o(e){for(var t=9,r=e.length;r--;)t=Math.imul(t^e.charCodeAt(r),1597334677);return"#"+((t^t>>>9)>>>0).toString(36)}function l(e,t="@media "){return t+u(e).map(e=>("string"==typeof e&&(e={min:e}),e.raw||Object.keys(e).map(t=>`(${t}-width:${e[t]})`).join(" and "))).join(",")}function u(e=[]){return Array.isArray(e)?e:null==e?[]:[e]}function s(e){return e}function a(){}let c={d:0,b:134217728,c:268435456,a:671088640,u:805306368,o:939524096};function f(e){var t;return(null==(t=e.match(/[-=:;]/g))?void 0:t.length)||0}function p(e){return Math.min(/(?:^|width[^\d]+)(\d+(?:.\d+)?)(p)?/.test(e)?+RegExp.$1/(RegExp.$2?15:1)/10:0,15)<<22|Math.min(f(e),15)<<18}let h=["rst-c","st-ch","h-chi","y-lin","nk","sited","ecked","pty","ad-on","cus-w","ver","cus","cus-v","tive","sable","tiona","quire"];function d({n:e,i:t,v:n=[]},i,o,s){for(let a of(e&&(e=r({n:e,i:t,v:n})),s=[...u(s)],n)){let c=i.theme("screens",a);for(let f of u(c&&l(c)||i.v(a))){var d;s.push(f),o|=c?67108864|p(f):"dark"==a?1073741824:"@"==f[0]?p(f):(d=f,1<<~(/:([a-z-]+)/.test(d)&&~h.indexOf(RegExp.$1.slice(2,7))||-18))}}return{n:e,p:o,r:s,i:t}}let g=new Map;function y(){return(y=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function m(){return y.apply(this,arguments)}function v(e){if(e.d){let t=[],r=b(e.r.reduce((e,r)=>"@"==r[0]?(t.push(r),e):r?b(e,e=>b(r,t=>{let r=/(:merge\(.+?\))(:[a-z-]+|\\[.+])/.exec(t);if(r){let n=e.indexOf(r[1]);return~n?e.slice(0,n)+r[0]+e.slice(n+r[1].length):$(e,t)}return $(t,e)})):e,"&"),t=>$(t,e.n?"."+i(e.n):""));return r&&t.push(r.replace(/:merge\((.+?)\)/g,"$1")),t.reduceRight((e,t)=>t+"{"+e+"}",e.d)}}function b(e,t){return e.replace(/ *((?:\(.+?\)|\[.+?\]|[^,])+) *(,|$)/g,(e,r,n)=>t(r)+n)}function $(e,t){return e.replace(/&/g,t)}let w=new Intl.Collator("en",{numeric:!0});function x(e,t){for(var r=0,n=e.length;r<n;){let i=n+r>>1;0>=A(e[i],t)?r=i+1:n=i}return n}function A(e,t){let r=e.p&c.o;return r==(t.p&c.o)&&(r==c.b||r==c.o)?0:e.p-t.p||e.o-t.o||w.compare(e.n,t.n)}function j(e,t){return Math.round(parseInt(e,16)*t)}function k(e,t={}){if("function"==typeof e)return e(t);let{opacityValue:r="1",opacityVariable:n}=t,i=n?`var(${n})`:r;if(e.includes("<alpha-value>"))return e.replace("<alpha-value>",i);if("#"==e[0]&&(4==e.length||7==e.length)){let o=(e.length-1)/3,l=[17,1,.062272][o-1];return`rgba(${[j(e.substr(1,o),l),j(e.substr(1+o,o),l),j(e.substr(1+2*o,o),l),i]})`}return"1"==i?e:"0"==i?"#0000":e.replace(/^(rgb|hsl)(\([^)]+)\)$/,`$1a$2,${i})`)}function O(e,t,r,n,i=[]){return function e(t,{n:r,p:n,r:i=[],i:s},a){let h=[],d="",g=0,y=0;for(let m in t||{}){var b,$;let w=t[m];if("@"==m[0]){if(!w)continue;if("a"==m[1]){h.push(...E(r,n,P(""+w),a,n,i,s,!0));continue}if("l"==m[1]){for(let x of u(w))h.push(...e(x,{n:r,p:(b=c[m[7]],n&~c.o|b),r:i,i:s},a));continue}if("i"==m[1]){h.push(...u(w).map(e=>({p:-1,o:0,r:[],d:m+" "+e})));continue}if("k"==m[1]){h.push({p:c.d,o:0,r:[m],d:e(w,{p:c.d},a).map(v).join("")});continue}if("f"==m[1]){h.push(...u(w).map(t=>({p:c.d,o:0,r:[m],d:e(t,{p:c.d},a).map(v).join("")})));continue}}if("object"!=typeof w||Array.isArray(w))"label"==m&&w?r=w+o(JSON.stringify([n,s,t])):(w||0===w)&&(m=m.replace(/[A-Z]/g,e=>"-"+e.toLowerCase()),y+=1,g=Math.max(g,"-"==($=m)[0]?0:f($)+(/^(?:(border-(?!w|c|sty)|[tlbr].{2,4}m?$|c.{7}$)|([fl].{5}l|g.{8}$|pl))/.test($)?+!!RegExp.$1||-!!RegExp.$2:0)+1),d+=(d?";":"")+u(w).map(e=>a.s(m,S(""+e,a.theme)+(s?" !important":""))).join(";"));else if("@"==m[0]||m.includes("&")){let j=n;"@"==m[0]&&(m=m.replace(/\bscreen\(([^)]+)\)/g,(e,t)=>{let r=a.theme("screens",t);return r?(j|=67108864,l(r,"")):e}),j|=p(m)),h.push(...e(w,{n:r,p:j,r:[...i,m],i:s},a))}else h.push(...e(w,{p:n,r:[...i,m]},a))}return h.unshift({n:r,p:n,o:Math.max(0,15-y)+1.5*Math.min(g||15,15),r:i,d:d}),h.sort(A)}(e,d(t,r,n,i),r)}function S(e,t){return e.replace(/theme\((["'`])?(.+?)\1(?:\s*,\s*(["'`])?(.+?)\3)?\)/g,(e,r,n,i,o)=>{let l=t(n,o);return"function"==typeof l&&/color|fill|stroke/i.test(n)?k(l):""+l})}function M(e,t){let r;let n=[];for(let i of e)i.d&&i.n?(null==r?void 0:r.p)==i.p&&""+r.r==""+i.r?(r.c=[r.c,i.c].filter(Boolean).join(" "),r.d=r.d+";"+i.d):n.push(r=m({},i,{n:i.n&&t})):n.push(m({},i,{n:i.n&&t}));return n}function C(e,t,n=c.u,i,o){let l=[];for(let s of e)for(let a of function(e,t,n,i,o){var l;e=m({},e,{i:e.i||o});let s=function(e,t){let r=g.get(e.n);return r?r(e,t):t.r(e.n,"dark"==e.v[0])}(e,t);return s?"string"==typeof s?({r:i,p:n}=d(e,t,n,i),M(C(P(s),t,n,i,e.i),e.n)):Array.isArray(s)?s.map(e=>{var t,r;return m({o:0},e,{r:[...u(i),...u(e.r)],p:(t=n,r=null!=(l=e.p)?l:n,t&~c.o|r)})}):O(s,e,t,n,i):[{c:r(e),p:0,o:0,r:[]}]}(s,t,n,i,o))l.splice(x(l,a),0,a);return l}function E(e,t,r,n,i,o,l,u){return M((u?r.flatMap(e=>C([e],n,i,o,l)):C(r,n,i,o,l)).map(e=>e.p&c.o&&(e.n||t==c.b)?m({},e,{p:e.p&~c.o|t,o:0}):e),e)}function R(e,t,r,n){var i;return i=(e,i)=>{let{n:o,p:l,r:u,i:s}=d(e,i,t);return r&&E(o,t,r,i,l,u,s,n)},g.set(e,i),e}function N(e,t){if("("!=e[e.length-1]){let r=[],n=!1,i=!1,o="";for(let l of e)if(!("("==l||/[~@]$/.test(l))){if("!"==l[0]&&(l=l.slice(1),n=!n),l.endsWith(":")){r["dark:"==l?"unshift":"push"](l.slice(0,-1));continue}"-"==l[0]&&(l=l.slice(1),i=!i),l.endsWith("-")&&(l=l.slice(0,-1)),l&&"&"!=l&&(o+=(o&&"-")+l)}o&&(i&&(o="-"+o),t[0].push({n:o,v:r.filter(V),i:n}))}}function V(e,t,r){return r.indexOf(e)==t}let z=new Map;function P(e){let t=z.get(e);if(!t){let r=[],i=[[]],l=0,u=0,s=null,a=0,f=(t,n=0)=>{l!=a&&(r.push(e.slice(l,a+n)),t&&N(r,i)),l=a+1};for(;a<e.length;a++){let p=e[a];if(u)"\\"!=e[a-1]&&(u+=+("["==p)||-("]"==p));else if("["==p)u+=1;else if(s)"\\"!=e[a-1]&&s.test(e.slice(a))&&(s=null,l=a+RegExp.lastMatch.length);else if("/"==p&&"\\"!=e[a-1]&&("*"==e[a+1]||"/"==e[a+1]))s="*"==e[a+1]?/^\*\//:/^[\r\n]/;else if("("==p)f(),r.push(p);else if(":"==p)":"!=e[a+1]&&f(!1,1);else if(/[\s,)]/.test(p)){f(!0);let h=r.lastIndexOf("(");if(")"==p){let d=r[h-1];if(/[~@]$/.test(d)){let g=i.shift();r.length=h,N([...r,"#"],i);let{v:y}=i[0].pop();for(let m of g)m.v.splice(+("dark"==m.v[0])-+("dark"==y[0]),y.length);N([...r,R(d.length>1?d.slice(0,-1)+o(JSON.stringify([d,g])):d+"("+n(g)+")",c.a,g,/@$/.test(d))],i)}h=r.lastIndexOf("(",h-1)}r.length=h+1}else/[~@]/.test(p)&&"("==e[a+1]&&i.unshift([])}f(!0),z.set(e,t=i[0])}return t}function T(e,t,r){return t.reduce((t,n,i)=>t+r(n)+e[i+1],e[0])}function F(e,t){return Array.isArray(e)&&Array.isArray(e.raw)?T(e,t,e=>_(e).trim()):t.filter(Boolean).reduce((e,t)=>e+_(t),e?_(e):"")}function _(e){let t,r="";if(e&&"object"==typeof e){if(Array.isArray(e))(t=F(e[0],e.slice(1)))&&(r+=" "+t);else for(let n in e)e[n]&&(r+=" "+n)}else null!=e&&"boolean"!=typeof e&&(r+=" "+e);return r}let I=q("@"),L=q("~");function q(e){return new Proxy(function(e,...r){return t("",e,r)},{get:(e,r)=>r in e?e[r]:function(e,...n){return t(r,e,n)}});function t(t,r,i){return n(P(t+e+"("+F(r,i)+")"))}}function D(e,t){return Array.isArray(e)?B(T(e,t,e=>null!=e&&"boolean"!=typeof e?e:"")):"string"==typeof e?B(e):[e]}let J=/ *(?:(?:([\u0080-\uFFFF\w-%@]+) *:? *([^{;]+?);|([^;}{]*?) *{)|(}))/g;function B(e){let t;e=e.replace(/\/\*[^]*?\*\/|\s\s+|\n/gm," ");let r=[{}],n=[r[0]],i=[];for(;t=J.exec(e);)t[4]&&(r.shift(),i.shift()),t[3]?(i.unshift(t[3]),r.unshift({}),n.push(i.reduce((e,t)=>({[t]:e}),r[0]))):t[4]||(r[0][t[1]]&&(r.unshift({}),n.push(i.reduce((e,t)=>({[t]:e}),r[0]))),r[0][t[1]]=t[2]);return n}function U(e,...t){var r,n;let i=D(e,t),l=((null==(r=i.find(e=>e.label))?void 0:r.label)||"css")+o(JSON.stringify(i));return n=(e,t)=>M(i.flatMap(r=>O(r,e,t,c.o)),l),g.set(l,n),l}let W=new Proxy(function(e,t){return G("animation",e,t)},{get:(e,t)=>t in e?e[t]:function(e,r){return G(t,e,r)}});function G(e,t,r){return{toString:()=>U({label:e,"@layer components":m({},"object"==typeof t?t:{animation:t},{animationName:""+r})})}}let Y=Symbol();function Z(e,t){if(null==e)return{};var r,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}function H(e){var{presets:t=[]}=e,r=Z(e,["presets"]);let n={preflight:!1!==r.preflight&&[],darkMode:void 0,darkColor:void 0,theme:{},variants:u(r.variants),rules:u(r.rules),ignorelist:u(r.ignorelist),hash:r.hash,stringify:r.stringify||K};for(let i of u([...t,{darkMode:r.darkMode,darkColor:r.darkColor,preflight:!1!==r.preflight&&u(r.preflight),theme:r.theme,hash:r.hash,stringify:r.stringify}])){let{preflight:o,darkMode:l=n.darkMode,darkColor:s=n.darkColor,theme:a,variants:c,rules:f,ignorelist:p,hash:h=n.hash,stringify:d=n.stringify}="function"==typeof i?i(n):i;n={preflight:!1!==n.preflight&&!1!==o&&[...n.preflight,...u(o)],darkMode:l,darkColor:s,theme:m({},n.theme,a,{extend:m({},n.theme.extend,null==a?void 0:a.extend)}),variants:[...n.variants,...u(c)],rules:[...n.rules,...u(f)],ignorelist:[...n.ignorelist,...u(p)],hash:h,stringify:d}}return n}function K(e,t){return e+":"+t}function Q(e,t){return"function"==typeof e?e:"string"==typeof e&&/^[\w-]+$/.test(e)?(r,n)=>({[e]:t?t(r,n):X(r,1)}):t=>e||{[t[1]]:X(t,2)}}function X(e,t,r=e.slice(t).find(Boolean)||e.$$||e.input){return"-"==e.input[0]?`calc(${r} * -1)`:r}function ee(e,t,r){let n="string"==typeof t?(e,n)=>({[t]:r?r(e,n):e._}):t||(({1:e,_:t},r,n)=>({[e||n]:t}));return(t,r)=>{var i;let o=ei(e||t[1]),l=null!=(i=r.theme(o,t.$$))?i:en(t.$$,o,r);if(null!=l)return t._=X(t,0,l),n(t,r,o)}}function et(e={},t){return(r,n)=>{let{section:i=ei(r[0]).replace("-","")+"Color"}=e;if(!/^(\[[^\]]+]|[^/]+?)(?:\/(.+))?$/.test(r.$$))return;let{$1:o,$2:l}=RegExp,u=n.theme(i,o)||en(o,i,n);if(!u||"object"==typeof u)return;let{opacityVariable:s=`--tw-${r[0].replace(/-$/,"")}-opacity`,opacitySection:a=i.replace("Color","Opacity"),property:c=i,selector:f}=e,p=n.theme(a,l||"DEFAULT")||l&&en(l,a,n),h=t||(({_:e})=>{let t=er(c,e);return f?{[f]:t}:t});r._={value:k(u,{opacityVariable:s||void 0,opacityValue:p||void 0}),color:e=>k(u,e),opacityVariable:s||void 0,opacityValue:p||void 0};let d=h(r,n);if(!r.dark){let g=n.d(i,o,u);g&&g!==u&&(r._={value:k(g,{opacityVariable:s||void 0,opacityValue:p||"1"}),color:e=>k(g,e),opacityVariable:s||void 0,opacityValue:p||void 0},d={"&":d,[n.v("dark")]:h(r,n)})}return d}}function er(e,t){let r={};return"string"==typeof t?r[e]=t:(t.opacityVariable&&t.value.includes(t.opacityVariable)&&(r[t.opacityVariable]=t.opacityValue||"1"),r[e]=t.value),r}function en(e,t,r){if("["==e[0]&&"]"==e.slice(-1)&&(e=eo(S(e.slice(1,-1),r.theme)),!(/color|fill|stroke/i.test(t)&&!(/^color:/.test(e)||/^(#|((hsl|rgb)a?|hwb|lab|lch|color)\(|[a-z]+$)/.test(e))||/image/i.test(t)&&!(/^image:/.test(e)||/^[a-z-]+\(/.test(e))||/weight/i.test(t)&&!(/^(number|any):/.test(e)||/^\d+$/.test(e))||/position/i.test(t)&&/^(length|size):/.test(e))))return e.replace(/^[a-z-]+:/,"")}function ei(e){return e.replace(/-./g,e=>e[1].toUpperCase())}function eo(e){return e.includes("url(")?e.replace(/(.*?)(url\(.*?\))(.*?)/g,(e,t="",r,n="")=>eo(t)+r+eo(n)):e.replace(/(^|[^\\])_+/g,(e,t)=>t+" ".repeat(e.length-t.length)).replace(/\\_/g,"_").replace(/(calc|min|max|clamp)\(.+\)/g,e=>e.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,"$1 $2 "))}function el(e,t,r,n,i,o){for(let l of t){let u=r.get(l);u||r.set(l,u=n(l));let s=u(e,i,o);if(s)return s}}function eu(e){var t;return ea(e[0],"function"==typeof(t=e[1])?t:()=>t)}function es(e){var t,r;return Array.isArray(e)?ea(e[0],Q(e[1],e[2])):ea(e,Q(t,r))}function ea(e,t){return ec(e,(e,r,n,i)=>{let o=r.exec(e);if(o)return o.$$=e.slice(o[0].length),o.dark=i,t(o,n)})}function ec(e,t){let r=u(e).map(ef);return(e,n,i)=>{for(let o of r){let l=t(e,o,n,i);if(l)return l}}}function ef(e){return"string"==typeof e?RegExp("^"+e+(e.includes("$")||"-"==e.slice(-1)?"":"$")):e}function ep(e,t){return e.replace(/--(tw(?:-[\w-]+)?)\b/g,(e,r)=>"--"+t(r).replace("#",""))}function eh(e,t){let r=H(e),n=function({theme:e,darkMode:t,darkColor:r,variants:n,rules:l,hash:a,stringify:c,ignorelist:f}){let p=new Map,h=new Map,d=new Map,g=new Map,y=ec(f,(e,t)=>t.test(e));n.push(["dark",Array.isArray(t)||"class"==t?`${u(t)[1]||".dark"} &`:"string"==typeof t&&"media"!=t?t:"@media (prefers-color-scheme:dark)"]);let m="function"==typeof a?e=>a(e,o):a?o:s;return{theme:function(e){var{extend:t={}}=e,r=Z(e,["extend"]);let n={},i={get colors(){return o("colors")},theme:o,negative:()=>({}),breakpoints(e){let t={};for(let r in e)"string"==typeof e[r]&&(t["screen-"+r]=e[r]);return t}};return o;function o(e,i,u,s){if(e){var a;if({1:e,2:s}=/^(\S+?)(?:\s*\/\s*([^/]+))?$/.exec(e)||[,e],/[.[]/.test(e)){let c=[];e.replace(/\[([^\]]+)\]|([^.[]+)/g,(e,t,r=t)=>c.push(r)),e=c.shift(),u=i,i=c.join("-")}let f=n[e]||Object.assign(Object.assign(n[e]={},l(r,e)),l(t,e));if(null==i)return f;let p=null!=(a=f[i||"DEFAULT"])?a:u;return s?k(p,{opacityValue:S(s,o)}):p}let h={};for(let d of[...Object.keys(r),...Object.keys(t)])h[d]=o(d);return h}function l(e,t){let r=e[t];return("function"==typeof r&&(r=r(i)),r&&/color|fill|stroke/i.test(t))?function e(t,r=[]){let n={};for(let i in t){let o=t[i],l=[...r,i];n[l.join("-")]=o,"DEFAULT"==i&&(l=r,n[r.join("-")]=o),"object"==typeof o&&Object.assign(n,e(o,l))}return n}(r):r}}(e),e:i,h:m,s(e,t){return c(ep(e,m),ep(t,m),this)},d(e,t,n){return null==r?void 0:r(e,t,this,n)},v(e){return p.has(e)||p.set(e,el(e,n,h,eu,this)||"&:"+e),p.get(e)},r(e,t){let r=JSON.stringify([e,t]);return d.has(r)||d.set(r,!y(e,this)&&el(e,l,g,es,this,t)),d.get(r)}}}(r),l=new Map,a=[],f=new Set;function p(e){let r=e.n&&n.h(e.n),i=v(r?m({},e,{n:r}):e);if(i&&!f.has(i)){f.add(i);let o=x(a,e);t.insert(i,o,e),a.splice(o,0,e)}return r}return t.resume(e=>l.set(e,e),(e,r)=>{t.insert(e,a.length,r),a.push(r),f.add(e)}),Object.defineProperties(function(e){if(!l.size)for(let t of u(r.preflight))"function"==typeof t&&(t=t(n)),t&&("string"==typeof t?E("",c.b,P(t),n,c.b,[],!1,!0):O(t,{},n,c.b)).forEach(p);e=""+e;let i=l.get(e);if(!i){let o=new Set;for(let s of C(P(e),n))o.add(s.c).add(p(s));i=[...o].filter(Boolean).join(" "),l.set(e,i).set(i,i)}return i},Object.getOwnPropertyDescriptors({get target(){return t.target},theme:n.theme,config:r,snapshot(){let e=t.snapshot(),r=new Set(f),n=new Map(l),i=[...a];return()=>{e(),f=r,l=n,a=i}},clear(){t.clear(),f=new Set,l=new Map,a=[]},destroy(){this.clear(),t.destroy()}}))}function ed(e,t){return e!=t&&""+e.split(" ").sort()!=""+t.split(" ").sort()}function eg(e=ex,t=document.documentElement){if(!t)return e;let r=new MutationObserver(i);r.observe(t,{attributeFilter:["class"],subtree:!0,childList:!0}),o(t),i([{target:t,type:""}]);let{destroy:n}=e;return e.destroy=()=>{r.disconnect(),n.call(e)},e;function i(e){for(let{type:t,target:n}of e)if("a"==t[0])o(n);else for(let i of n.querySelectorAll("[class]"))o(i);r.takeRecords()}function o(t){let r;let n=t.getAttribute("class");n&&ed(n,r=e(n))&&t.setAttribute("class",r)}}function ey(e){let t=document.querySelector(e||"style[data-twind]");return t&&"STYLE"==t.tagName||((t=document.createElement("style")).dataset.twind="",document.head.prepend(t)),t}function em(e){let t=(null==e?void 0:e.cssRules)?e:(e&&"string"!=typeof e?e:ey(e)).sheet;return{target:t,snapshot(){let e=Array.from(t.cssRules,e=>e.cssText);return()=>{this.clear(),e.forEach(this.insert)}},clear(){for(let e=t.cssRules.length;e--;)t.deleteRule(e)},destroy(){var e;null==(e=t.ownerNode)||e.remove()},insert(e,r){try{t.insertRule(e,r)}catch(n){t.insertRule(":root{}",r),/:-[mwo]/.test(e)}},resume:a}}function ev(e){let t=e&&"string"!=typeof e?e:ey(e);return{target:t,snapshot(){let e=Array.from(t.childNodes,e=>e.textContent);return()=>{this.clear(),e.forEach(this.insert)}},clear(){t.textContent=""},destroy(){t.remove()},insert(e,r){t.insertBefore(document.createTextNode(e),t.childNodes[r]||null)},resume:a}}function eb(e,t){let r=e?ev():em();return t||(r.resume=ew),r}function e$(e){return(e.ownerNode||e).textContent||(e.cssRules?Array.from(e.cssRules,e=>e.cssText):u(e)).join("")}function ew(e,t){let r=e$(this.target),n=/\/\*!([\da-z]+),([\da-z]+)(?:,(.+?))?\*\//g;if(n.test(r)){var i;let o;for(let l of(n.lastIndex=0,this.clear(),document.querySelectorAll("[class]")))e(l.getAttribute("class"));for(;i=n.exec(r),o&&t(r.slice(o.index+o[0].length,null==i?void 0:i.index),{p:parseInt(o[1],36),o:parseInt(o[2],36)/2,n:o[3]}),o=i;);}}let ex=new Proxy(a,{apply:(e,r,n)=>t(n[0]),get(e,r){let n=t[r];return"function"==typeof n?function(){return n.apply(t,arguments)}:n}});function eA(e={},r=eb,n){return null==t||t.destroy(),t=eg(eh(e,"function"==typeof r?r():r),n)}let ej=function e(t){return new Proxy(function(e,...r){return ek(t,"",e,r)},{get:(r,n)=>"bind"===n?e:n in r?r[n]:function(e,...r){return ek(t,n,e,r)}})}();function ek(e,t,r,n){return{toString(){let l=D(r,n),u=i(t+o(JSON.stringify([t,l])));return("function"==typeof e?e:ex)(U({[`@keyframes ${u}`]:D(r,n)})),u}}}function eO(e,t=ex){let r=t.snapshot(),n={html:eS(e,t),css:e$(t.target)};return r(),n}function eS(e,t=ex){let r="",n=0;return!function(e,t){let r=1,n=0,i="",o="",l=l=>{5==r&&"class"==o&&!1===t(n,l,i)&&(e="")};for(let u=0;u<e.length;u++){let s=e[u];1==r?"<"==s&&(r="!--"==e.substr(u+1,3)?4:3):4==r?">"==s&&"--"==e.slice(u-2,u)&&(r=1):i?s==i&&"\\"!=e[u-1]&&(l(u),r=2,i=""):'"'==s||"'"==s?(i=s,n+=1):">"==s?(l(u),r=1):r&&("="==s?(o=e.slice(n,u),r=5,n=u+1):"/"==s&&(r<5||">"==e[u+1])?(l(u),r=0):/\s/.test(s)&&(l(u),r=2,n=u+1))}}(e,(i,o,l)=>{var u;let s=e.slice(i,o),a=t(('"'==(u=l)?s.replace(/(=|\[)(?:'|'|')|(?:'|'|')(])/g,"$1'$2"):"'"==u?s.replace(/(=|\[)(?:"|"|")|(?:"|"|")(])/g,'$1"$2'):s).replace(/(&|&|&)/g,"&"));ed(s,a)&&(l=l?"":'"',r+=e.slice(n,i)+l+a+l,n=o)}),r+e.slice(n,e.length)}let eM=(e,t)=>"function"==typeof e?eC(t,e):eC(e);function eC(e={},t){let{label:r="style",base:n,props:l={},defaults:u,when:s=[]}=e,a=m({},null==t?void 0:t.defaults,u),f=o(JSON.stringify([r,null==t?void 0:t.className,n,l,a,s])),p=h("",n||"",c.c);function h(e,n,i){return R(((t?t.className.replace(/#.+$/,"~"):"")+r+e+f).replace(/[: ,()[\]]/,""),i,n&&P(n))}return Object.defineProperties(function(e){let r,n;Array.isArray(e)&&(r=!0,e=Object.fromEntries(new URLSearchParams(e[1]).entries()));let i=m({},a,e),o=r?"":(t?t(i)+" ":"")+p;for(let u in l){let c=l[u],f=i[u];if(f===Object(f)){let d="";for(let g in n="",f){let y=c[f[g]];y&&(d+="@"+g+"-"+f[g],n+=(n&&" ")+("_"==g?y:g+":("+y+")"))}n&&(o+=" "+h("--"+u+"-"+d,n,402653184))}else(n=c[f])&&(o+=" "+h("--"+u+"-"+f,n,402653184))}return s.forEach((e,t)=>{let r="";for(let l in e[0]){let u=i[l];if(u!==Object(u)&&""+u==""+e[0][l])r+=(r&&"_")+l+"-"+u;else{r="";break}}r&&(n=e[1])&&(o+=" "+h("-"+t+"--"+r,n,536870912))}),o},Object.getOwnPropertyDescriptors({className:p,defaults:a,selector:"."+i(p)}))}return e.animation=W,e.apply=I,e.arbitrary=en,e.asArray=u,e.auto=function(e){if(document.currentScript){let t=()=>r.disconnect(),r=new MutationObserver(r=>{for(let{target:n}of r)if(n===document.body)return e(),t()});return r.observe(document.documentElement,{childList:!0,subtree:!0}),t}return a},e.autoDarkColor=function(e,t,{theme:r}){return r(e,t=t.replace(/\d+$/,e=>100*(9-~~(parseInt(e,10)/100)||.5)))},e.colorFromTheme=et,e.consume=eS,e.css=U,e.cssom=em,e.cx=function(e,...t){return n(P(F(e,t))," ")},e.defineConfig=H,e.dom=ev,e.escape=i,e.extract=eO,e.fromMatch=Q,e.fromTheme=ee,e.getAutocompleteProvider=function(e){return e[Y]},e.getSheet=eb,e.hash=o,e.identity=s,e.injectGlobal=function(e,...t){("function"==typeof this?this:ex)(U({"@layer base":D(e,t)}))},e.inline=function(e,t={}){let{tw:r=ex,minify:n=s}="function"==typeof t?{tw:t}:t,{html:i,css:o}=eO(e,r);return i.replace("</head>",`<style data-twind>${n(o,i)}</style></head>`)},e.install=function(e,t=!0){var r;let n=H(e);return eA(m({},n,{hash:null!=(r=n.hash)?r:t}),()=>eb(!t))},e.keyframes=ej,e.match=function(e,t,r){return[e,Q(t,r)]},e.matchColor=function(e,t={},r){return[e,et(t,r)]},e.matchTheme=function(e,t,r,n){return[e,ee(t,r,n)]},e.mql=l,e.noop=a,e.normalize=eo,e.observe=eg,e.parse=P,e.setup=eA,e.shortcut=L,e.stringify=e$,e.style=eM,e.toCSS=er,e.toColorValue=k,e.tw=ex,e.twind=eh,e.tx=function(e,...t){return("function"==typeof this?this:ex)(F(e,t))},e.virtual=function(e){let t=[];return{target:t,snapshot(){let e=[...t];return()=>{t.splice(0,t.length,...e)}},clear(){t.length=0},destroy(){this.clear()},insert(r,n,i){t.splice(n,0,e?`/*!${i.p.toString(36)},${(2*i.o).toString(36)}${i.n?","+i.n:""}*/${r}`:r)},resume:a}},e.withAutocomplete=function(e){return e},e}({});//# sourceMappingURL=core.global.js.map |
{ | ||
"name": "@twind/core", | ||
"version": "1.0.0-next.14", | ||
"description": "compiles tailwind like shorthand syntax into CSS", | ||
"version": "1.0.1-next-20221118224314", | ||
"description": "The core engine without any presets.", | ||
"type": "module", | ||
"homepage": "https://twind.dev", | ||
"homepage": "https://twind.style", | ||
"bugs": { | ||
@@ -27,35 +27,38 @@ "url": "https://github.com/tw-in-js/twind/issues" | ||
}, | ||
"funding": { | ||
"type": "opencollective", | ||
"url": "https://opencollective.com/twind" | ||
}, | ||
"engines": { | ||
"node": ">=12.4" | ||
}, | ||
"dependencies": { | ||
"@swc/helpers": "^0.3.2", | ||
"csstype": "^3.0.10" | ||
}, | ||
"publishConfig": { | ||
"tag": "next", | ||
"access": "public", | ||
"directory": "dist" | ||
}, | ||
"contributors": [ | ||
"funding": [ | ||
{ | ||
"name": "Luke Jackson", | ||
"url": "lukejacksonn.github.io" | ||
"type": "Open Collective", | ||
"url": "https://opencollective.com/twind" | ||
}, | ||
{ | ||
"name": "Sascha Tandel", | ||
"url": "https://github.com/sastan" | ||
"type": "Github Sponsor", | ||
"url": "https://github.com/sponsors/tw-in-js" | ||
}, | ||
{ | ||
"type": "Ko-fi", | ||
"url": "https://ko-fi.com/twind" | ||
} | ||
], | ||
"engines": { | ||
"node": ">=14.15.0" | ||
}, | ||
"main": "./core.cjs", | ||
"exports": { | ||
".": { | ||
"types": "./core.d.ts", | ||
"development": { | ||
"esnext": "./core.esnext.dev.js", | ||
"module": "./core.dev.js", | ||
"browser": "./core.browser.dev.js", | ||
"script": "./core.global.dev.js", | ||
"node": { | ||
"import": "./core.dev.mjs", | ||
"require": "./core.dev.cjs" | ||
}, | ||
"default": "./core.dev.js" | ||
}, | ||
"esnext": "./core.esnext.js", | ||
"module": "./core.js", | ||
"browser": "./core.browser.js", | ||
"script": "./core.global.js", | ||
"types": "./core.d.ts", | ||
"node": { | ||
@@ -69,5 +72,10 @@ "import": "./core.mjs", | ||
}, | ||
"globalName": "twind", | ||
"sideEffects": false, | ||
"dependencies": { | ||
"csstype": "^3.1.1", | ||
"@swc/helpers": "^0.4.11" | ||
}, | ||
"peerDependencies": { | ||
"typescript": "^4.4.0" | ||
"typescript": "^4.8.4" | ||
}, | ||
@@ -79,2 +87,5 @@ "peerDependenciesMeta": { | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"module": "./core.js", | ||
@@ -84,4 +95,4 @@ "esnext": "./core.esnext.js", | ||
"jsdelivr": "./core.global.js", | ||
"types": "./core.d.ts", | ||
"readme": "# @twind/core\n\nMinimal implementation of a tailwind-compatible CSS-in-JS framework.\n\n**This package does not contain any Tailwindcss rules. These are defined in [@twind/preset-tailwind](../preset-tailwind).**\n\n---\n\n## READ THIS FIRST!\n\n**Twind v1 is still in beta. Expect bugs!**\n\n---\n\n## Installation\n\nInstall from npm:\n\n```sh\n# Using npm\nnpm install @twind/core@next\n\n# Using Yarn\nyarn add @twind/core@next\n```\n\n## Usage\n\n```js\nimport { twind, cssom, observe } from '@twind/core'\n\nconst tw = observe(\n twind(\n {\n theme: {\n /* .. */\n },\n rules: [\n /* ... */\n ],\n },\n cssom(),\n ),\n)\n```\n\n## API\n\n### `twind`\n\nTDB\n\n### `cx`\n\n```js\nimport { cx } from '@twind/core'\n\n// Set a className\nelement.className = cx`\n underline\n /* multi\n line\n comment\n */\n hover:focus:!{\n sm:{italic why}\n lg:-{px}\n -mx-1\n }\n // Position\n !top-1 !-bottom-2\n text-{xl black}\n`\n```\n\n### `shortcut`\n\nTDB\n\n### `style`\n\nTDB\n\n### `extract(html, tw)`\n\nUsed for static HTML processing (usually to provide SSR support for your javascript-powered web apps) — powered by [consume(html, tw)](#consumehtml-tw)\n\n**Note**: This clears the Twind instance before processing the HTML.\n\n```js\nimport { twind, virtual, extract } from '@twind/core'\n\n// can be re-used\nconst tw = twind(\n {\n /* config */\n },\n virtual(),\n)\n\nfunction render() {\n const { html, css } = extract(renderApp(), tw)\n\n // inject as last element into the head\n return html.replace('</head>', `<style data-twind>${css}</style></head>`)\n}\n```\n\n### `consume(html, tw)`\n\nUsed for static HTML processing (usually to provide SSR support for your javascript-powered web apps)\n\n1. parse the markup and process element classes with the provided Twind instance\n2. update the class attributes _if_ necessary\n3. return the HTML string with the final element classes\n\n```js\nimport { twind, virtual, consume, stringify } from '@twind/core'\n\n// can be re-used\nconst tw = twind(\n {\n /* config */\n },\n virtual(),\n)\n\nfunction render() {\n const html = renderApp()\n\n // clear all styles\n tw.clear()\n\n // generated markup\n const markup = comsume(html, tw)\n\n // create CSS\n const css = stringify(tw.target)\n\n // inject as last element into the head\n return markup.replace('</head>', `<style data-twind>${css}</style></head>`)\n}\n```\n" | ||
"browser": "./core.browser.js", | ||
"types": "./core.d.ts" | ||
} |
148
README.md
@@ -1,143 +0,31 @@ | ||
# @twind/core | ||
# twind [![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/core?icon=npm&label&cache=10800&color=blue)](https://www.npmjs.com/package/@twind/core) [![Github](https://flat.badgen.net/badge/icon/tw-in-js%2Ftwind%23core?icon=github&label)](https://github.com/tw-in-js/twind/tree/main/packages/core) | ||
Minimal implementation of a tailwind-compatible CSS-in-JS framework. | ||
Utility-first CSS without any build step right in the browser or any other environment like Node.js, deno, workers, ... | ||
**This package does not contain any Tailwindcss rules. These are defined in [@twind/preset-tailwind](../preset-tailwind).** | ||
- 📖 Study [the documentation](https://twind.style) | ||
- 🤖 Try [the playground](https://twind.run) | ||
- 🧭 Explore [the examples](https://twind.style/examples) | ||
- 📓 Consult [the API reference](https://twind.style/packages/@twind/core) | ||
- 📜 Read [the changelog](https://github.com/tw-in-js/twind/tree/main/packages/core/CHANGELOG.md) | ||
--- | ||
## 📖 Documentation | ||
## READ THIS FIRST! | ||
The full documentation is available at [twind.style](https://twind.style). | ||
**Twind v1 is still in beta. Expect bugs!** | ||
## 💬 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). | ||
## Installation | ||
To ask questions and discuss with other Twind users in real time use [Discord Chat](https://chat.twind.style). | ||
Install from npm: | ||
## 🧱 Contribute | ||
```sh | ||
# Using npm | ||
npm install @twind/core@next | ||
See the [Contributing Guide](../../CONTRIBUTING.md) for information on how to contribute to this project. | ||
# Using Yarn | ||
yarn add @twind/core@next | ||
``` | ||
## 📜 Changelog | ||
## Usage | ||
The Changelog for this package is [available on GitHub](https://github.com/tw-in-js/twind/tree/main/packages/twind/CHANGELOG.md). | ||
```js | ||
import { twind, cssom, observe } from '@twind/core' | ||
## ⚖️ License | ||
const tw = observe( | ||
twind( | ||
{ | ||
theme: { | ||
/* .. */ | ||
}, | ||
rules: [ | ||
/* ... */ | ||
], | ||
}, | ||
cssom(), | ||
), | ||
) | ||
``` | ||
## API | ||
### `twind` | ||
TDB | ||
### `cx` | ||
```js | ||
import { cx } from '@twind/core' | ||
// Set a className | ||
element.className = cx` | ||
underline | ||
/* multi | ||
line | ||
comment | ||
*/ | ||
hover:focus:!{ | ||
sm:{italic why} | ||
lg:-{px} | ||
-mx-1 | ||
} | ||
// Position | ||
!top-1 !-bottom-2 | ||
text-{xl black} | ||
` | ||
``` | ||
### `shortcut` | ||
TDB | ||
### `style` | ||
TDB | ||
### `extract(html, tw)` | ||
Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) — powered by [consume(html, tw)](#consumehtml-tw) | ||
**Note**: This clears the Twind instance before processing the HTML. | ||
```js | ||
import { twind, virtual, extract } from '@twind/core' | ||
// can be re-used | ||
const tw = twind( | ||
{ | ||
/* config */ | ||
}, | ||
virtual(), | ||
) | ||
function render() { | ||
const { html, css } = extract(renderApp(), tw) | ||
// inject as last element into the head | ||
return html.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
} | ||
``` | ||
### `consume(html, tw)` | ||
Used for static HTML processing (usually to provide SSR support for your javascript-powered web apps) | ||
1. parse the markup and process element classes with the provided Twind instance | ||
2. update the class attributes _if_ necessary | ||
3. return the HTML string with the final element classes | ||
```js | ||
import { twind, virtual, consume, stringify } from '@twind/core' | ||
// can be re-used | ||
const tw = twind( | ||
{ | ||
/* config */ | ||
}, | ||
virtual(), | ||
) | ||
function render() { | ||
const html = renderApp() | ||
// clear all styles | ||
tw.clear() | ||
// generated markup | ||
const markup = comsume(html, tw) | ||
// create CSS | ||
const css = stringify(tw.target) | ||
// inject as last element into the head | ||
return markup.replace('</head>', `<style data-twind>${css}</style></head>`) | ||
} | ||
``` | ||
The [MIT license](https://github.com/tw-in-js/twind/blob/main/LICENSE) governs your use of Twind. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
2247393
27
12667
0
32
1
+ Added@swc/helpers@0.4.36(transitive)
- Removed@swc/helpers@0.3.17(transitive)
Updated@swc/helpers@^0.4.11
Updatedcsstype@^3.1.1