├── .changeset ├── README.md ├── changelog-github-custom.cjs └── config.json ├── .codesandbox └── ci.json ├── .devcontainer └── devcontainer.json ├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── docs.yml │ ├── feature_request.yml │ └── support.md ├── PULL_REQUEST_TEMPLATE.md ├── actions │ ├── publish-pages │ │ └── action.yml │ ├── publish-prerelease │ │ └── action.yml │ └── setup │ │ └── action.yml ├── dependabot.yml ├── labels.json ├── stale.yml └── workflows │ ├── ci.yml │ ├── deploy-cdn.yml │ ├── deploy-mdn.yml │ └── generate-sponsors.yml ├── .gitignore ├── .husky ├── .gitignore ├── pre-commit └── prepare.cjs ├── .npmrc ├── .nvmrc ├── .stackblitz └── codeflow.json ├── .stackblitzrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── ROADMAP.md ├── documentation ├── README.md ├── aliases.md ├── cdns.md ├── comparison.md ├── component-styles.md ├── examples.md ├── features.md ├── grouping-syntax.md ├── installation.md ├── integrations.md ├── intellisense.md ├── introduction.md ├── library-mode.md ├── migration.md ├── preset-autoprefix.md ├── preset-container-queries.md ├── preset-ext.md ├── preset-line-clamp.md ├── preset-radix-ui.md ├── preset-tailwind-forms.md ├── preset-tailwind.md ├── preset-typography.md ├── presets.md ├── reference.md ├── rules.md ├── variants.md ├── with-gatsby.md ├── with-lit.md ├── with-next.md ├── with-react.md ├── with-remix.md ├── with-sveltekit.md └── with-web-components.md ├── examples ├── README.md ├── basic │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── favicon.ico │ ├── index.html │ ├── index.js │ ├── package.json │ └── sandbox.config.json ├── playground │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── favicon.ico │ ├── img │ │ ├── beams.jpg │ │ ├── grid.svg │ │ └── logo.svg │ ├── index.html │ ├── index.js │ ├── package.json │ ├── sandbox.config.json │ └── twind.config.js ├── using-tailwind-forms │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── favicon.ico │ ├── index.html │ ├── index.js │ ├── package.json │ ├── sandbox.config.json │ └── twind.config.js ├── using-twind-cdn │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── favicon.ico │ ├── index.html │ ├── package.json │ └── sandbox.config.json ├── with-gatsby │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── gatsby-browser.js │ ├── gatsby-config.js │ ├── gatsby-node.js │ ├── gatsby-ssr.js │ ├── package.json │ ├── sandbox.config.json │ ├── src │ │ ├── components │ │ │ ├── header.jsx │ │ │ ├── layout.jsx │ │ │ └── seo.jsx │ │ ├── images │ │ │ ├── abduction-illustration.svg │ │ │ ├── cat-and-human-illustration.svg │ │ │ ├── dog-illustration.svg │ │ │ └── favicon.png │ │ └── pages │ │ │ ├── 404.jsx │ │ │ ├── about.jsx │ │ │ ├── contact.jsx │ │ │ └── index.jsx │ └── twind.config.js ├── with-lit │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── favicon.ico │ ├── index.html │ ├── package.json │ ├── sandbox.config.json │ ├── src │ │ ├── index.ts │ │ └── twind.config.ts │ └── tsconfig.json ├── with-next │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ │ ├── _app.js │ │ ├── _document.js │ │ ├── about.jsx │ │ ├── index.jsx │ │ └── ssg.jsx │ ├── public │ │ ├── assets │ │ │ ├── github.svg │ │ │ └── vercel.svg │ │ └── favicon.ico │ ├── sandbox.config.json │ ├── tsconfig.json │ └── twind.config.js ├── with-remix │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── app │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── root.tsx │ │ ├── routes │ │ │ ├── anything.tsx │ │ │ └── index.tsx │ │ └── twind.ts │ ├── package.json │ ├── public │ │ └── favicon.ico │ ├── remix.config.js │ ├── remix.env.d.ts │ ├── sandbox.config.json │ ├── tsconfig.json │ └── twind.config.ts ├── with-remix_react-v18 │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── app │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── root.tsx │ │ ├── routes │ │ │ ├── anything.tsx │ │ │ └── index.tsx │ │ └── twind.ts │ ├── package.json │ ├── public │ │ └── favicon.ico │ ├── remix.config.js │ ├── remix.env.d.ts │ ├── sandbox.config.json │ ├── tsconfig.json │ └── twind.config.ts ├── with-sveltekit │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── sandbox.config.json │ ├── src │ │ ├── app.d.ts │ │ ├── app.html │ │ ├── hooks.server.js │ │ ├── lib │ │ │ └── twind.js │ │ ├── routes │ │ │ ├── +layout.js │ │ │ ├── +layout.svelte │ │ │ └── +page.svelte │ │ └── twind.config.js │ ├── static │ │ └── favicon.ico │ ├── svelte.config.js │ ├── tsconfig.json │ └── vite.config.ts └── with-web-components │ ├── .stackblitzrc │ ├── CHANGELOG.md │ ├── README.md │ ├── favicon.ico │ ├── index.html │ ├── index.js │ ├── package.json │ ├── sandbox.config.json │ └── twind.config.js ├── package.json ├── packages ├── README.md ├── cdn │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── core │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── alias.ts │ │ ├── animation.ts │ │ ├── autocomplete.ts │ │ ├── colors.ts │ │ ├── css.ts │ │ ├── cx.ts │ │ ├── define-config.ts │ │ ├── index.ts │ │ ├── inject-global.ts │ │ ├── install.ts │ │ ├── internal │ │ │ ├── astish.ts │ │ │ ├── changed.ts │ │ │ ├── context.ts │ │ │ ├── define.ts │ │ │ ├── format.ts │ │ │ ├── interleave.ts │ │ │ ├── interpolate.ts │ │ │ ├── merge.ts │ │ │ ├── parse-html.ts │ │ │ ├── precedence.ts │ │ │ ├── registry.ts │ │ │ ├── serialize.ts │ │ │ ├── sorted-insertion-index.ts │ │ │ ├── stringify.ts │ │ │ ├── theme.test.ts │ │ │ ├── theme.ts │ │ │ ├── to-class-name.ts │ │ │ ├── translate.ts │ │ │ └── warn.ts │ │ ├── keyframes.ts │ │ ├── observe.ts │ │ ├── parse.test.ts │ │ ├── parse.ts │ │ ├── rules.ts │ │ ├── runtime.ts │ │ ├── sheets.ts │ │ ├── ssr.ts │ │ ├── style.ts │ │ ├── tests │ │ │ ├── alias.test.ts │ │ │ ├── animation.test.ts │ │ │ ├── apply.test.ts │ │ │ ├── auto-dark-colors.test.ts │ │ │ ├── consume.test.ts │ │ │ ├── css.test.ts │ │ │ ├── cx.test.ts │ │ │ ├── dark-mode.test.ts │ │ │ ├── extract.test.ts │ │ │ ├── hash.test.ts │ │ │ ├── inject-global.test.ts │ │ │ ├── inline.test.ts │ │ │ ├── keyframes.test.ts │ │ │ ├── observe.test.ts │ │ │ ├── rules.test.ts │ │ │ ├── sheet-cssom.test.ts │ │ │ ├── sheet-dom.test.ts │ │ │ ├── shortcut.test.ts │ │ │ ├── style.test.ts │ │ │ ├── theme.test.ts │ │ │ ├── twind.test.ts │ │ │ └── tx.test.ts │ │ ├── twind.ts │ │ ├── tx.ts │ │ ├── types.ts │ │ └── utils.ts │ └── tsconfig.json ├── intellisense │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __snapshots__ │ │ │ ├── enumerate.test.ts.snap │ │ │ ├── suggest-at.test.ts.snap │ │ │ └── suggest.test.ts.snap │ │ ├── enumerate.test.ts │ │ ├── index.ts │ │ ├── internal │ │ │ ├── adjust-rule-location.ts │ │ │ ├── color.ts │ │ │ ├── compare-suggestion.ts │ │ │ ├── constants.ts │ │ │ ├── create-context.ts │ │ │ ├── simple-pseudo-classes.ts │ │ │ ├── spacify.ts │ │ │ └── types.ts │ │ ├── languages │ │ │ ├── html.test.ts │ │ │ └── html.ts │ │ ├── modules.d.ts │ │ ├── suggest-at.test.ts │ │ ├── suggest.test.ts │ │ └── types.ts │ └── tsconfig.json ├── preset-autoprefix │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── preset-container-queries │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── container-queries.test.ts │ │ └── container-queries.ts │ └── tsconfig.json ├── preset-ext │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── preset-ext.test.json │ │ ├── preset-ext.test.ts │ │ ├── rules.ts │ │ └── variants.ts │ └── tsconfig.json ├── preset-line-clamp │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── line-clamp.ts │ └── tsconfig.json ├── preset-radix-ui │ ├── CHANGELOG.md │ ├── README.md │ ├── colors.d.ts │ ├── darkColor.d.ts │ ├── defaultTheme.d.ts │ ├── index.d.ts │ ├── package.json │ ├── scripts │ │ └── generate-colors.js │ ├── src │ │ ├── colors.ts │ │ ├── darkColor.ts │ │ ├── defaultTheme.ts │ │ └── index.ts │ └── tsconfig.json ├── preset-tailwind-forms │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── preset-tailwind-forms.test.ts │ │ └── preset-tailwind-forms.ts │ └── tsconfig.json ├── preset-tailwind │ ├── CHANGELOG.md │ ├── README.md │ ├── base.d.ts │ ├── baseTheme.d.ts │ ├── colors.d.ts │ ├── defaultTheme.d.ts │ ├── index.d.ts │ ├── package.json │ ├── preflight.d.ts │ ├── src │ │ ├── base.ts │ │ ├── baseTheme.ts │ │ ├── colors.ts │ │ ├── defaultTheme.ts │ │ ├── index.ts │ │ ├── preflight.test.ts │ │ ├── preflight.ts │ │ ├── rules.test.json │ │ ├── rules.test.ts │ │ ├── rules.ts │ │ ├── types.ts │ │ └── variants.ts │ └── tsconfig.json ├── preset-typography │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── typography.test.ts │ └── tsconfig.json ├── twind │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── with-gatsby │ ├── CHANGELOG.md │ ├── README.md │ ├── index.d.ts │ ├── package.json │ ├── src │ │ ├── config.d.ts │ │ ├── gatsby-browser.ts │ │ ├── gatsby-node.ts │ │ ├── gatsby-ssr.ts │ │ ├── index.ts │ │ └── install-twind.ts │ └── tsconfig.json ├── with-next │ ├── CHANGELOG.md │ ├── README.md │ ├── app.d.ts │ ├── document.d.ts │ ├── index.d.ts │ ├── package.json │ ├── src │ │ ├── app.ts │ │ └── document.ts │ └── tsconfig.json ├── with-react │ ├── CHANGELOG.md │ ├── README.md │ ├── index.d.ts │ ├── inline.d.ts │ ├── package.json │ ├── pipeableStream.d.ts │ ├── readableStream.d.ts │ ├── src │ │ ├── __snapshots__ │ │ │ ├── pipeableStream.test.tsx.snap │ │ │ └── readableStream.test.tsx.snap │ │ ├── index.ts │ │ ├── inline.ts │ │ ├── internal.ts │ │ ├── modules.d.ts │ │ ├── pipeableStream.test.tsx │ │ ├── pipeableStream.ts │ │ ├── readableStream.test.tsx │ │ └── readableStream.ts │ └── tsconfig.json ├── with-remix │ ├── CHANGELOG.md │ ├── README.md │ ├── index.d.ts │ ├── package.json │ ├── server.d.ts │ ├── src │ │ ├── index.ts │ │ └── server.ts │ └── tsconfig.json ├── with-sveltekit │ ├── CHANGELOG.md │ ├── README.md │ ├── hooks.d.ts │ ├── index.d.ts │ ├── package.json │ ├── src │ │ ├── hooks.ts │ │ └── index.ts │ └── tsconfig.json └── with-web-components │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ └── tsconfig.json ├── patches ├── @jsenv__importmap@1.2.1.patch ├── @jsenv__logger@4.1.1.patch ├── @jspm__generator@1.0.0-beta.38.patch ├── @size-limit__esbuild@8.1.0.patch ├── monaco-editor@0.34.1.patch └── prettier@2.8.1.patch ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── sandbox.config.json ├── scripts ├── package.json └── sponsor.config.js ├── sites ├── cdn.twind.style │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── wrangler.toml ├── mdn.twind.run │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── wrangler.toml ├── twind.run │ ├── .env │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── app.d.ts │ │ ├── app.html │ │ ├── hooks.server.ts │ │ ├── lib │ │ │ ├── assets │ │ │ │ ├── favicon.ico │ │ │ │ ├── icon.png │ │ │ │ └── icon.svg │ │ │ ├── base64.ts │ │ │ ├── components │ │ │ │ ├── head.svelte │ │ │ │ ├── header.svelte │ │ │ │ └── theme-switcher.svelte │ │ │ ├── icons │ │ │ │ ├── bootstrap.js │ │ │ │ ├── fluent-solid.js │ │ │ │ ├── heroicons │ │ │ │ │ ├── index.js │ │ │ │ │ ├── mini.js │ │ │ │ │ ├── outline.js │ │ │ │ │ └── solid.js │ │ │ │ ├── icon.svelte │ │ │ │ ├── index.ts │ │ │ │ ├── loading.js │ │ │ │ ├── octicons.js │ │ │ │ ├── twind.js │ │ │ │ └── types.ts │ │ │ ├── intellisense.api.ts │ │ │ ├── intellisense.ts │ │ │ ├── intellisense.worker.ts │ │ │ ├── monaco.ts │ │ │ ├── prettier.api.ts │ │ │ ├── prettier.ts │ │ │ ├── prettier.worker.ts │ │ │ ├── stores │ │ │ │ ├── index.ts │ │ │ │ ├── match-media-query.ts │ │ │ │ ├── matches-media-query.ts │ │ │ │ ├── mounted.ts │ │ │ │ ├── on.ts │ │ │ │ ├── reduced-motion.ts │ │ │ │ └── storage.ts │ │ │ ├── system.ts │ │ │ ├── templates │ │ │ │ ├── bug-report │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ │ ├── default │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ │ ├── index.ts │ │ │ │ ├── preset-container-queries │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ │ ├── preset-line-clamp │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ │ ├── preset-radix-ui │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ │ ├── preset-tailwind-forms │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ │ ├── preset-tailwind │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ │ └── preset-typography │ │ │ │ │ ├── config.tpl │ │ │ │ │ ├── html.tpl │ │ │ │ │ ├── index.ts │ │ │ │ │ └── script.tpl │ │ │ ├── transpile.api.ts │ │ │ ├── transpile.ts │ │ │ ├── transpile.worker.ts │ │ │ ├── turnstile.ts │ │ │ ├── twind.ts │ │ │ ├── types.ts │ │ │ └── versions.ts │ │ ├── routes │ │ │ ├── +error.svelte │ │ │ ├── +layout.js │ │ │ ├── +layout.server.js │ │ │ ├── +layout.svelte │ │ │ ├── [[key]] │ │ │ │ ├── +page.server.ts │ │ │ │ ├── +page.svelte │ │ │ │ ├── code.svelte │ │ │ │ ├── discover.svelte │ │ │ │ ├── info.svelte │ │ │ │ ├── loader.svelte │ │ │ │ ├── preview.html │ │ │ │ ├── preview.svelte │ │ │ │ ├── preview.ts │ │ │ │ └── wordlist.txt │ │ │ ├── manifest.json │ │ │ │ └── +server.ts │ │ │ └── msapplication-config.xml │ │ │ │ └── +server.ts │ │ └── twind.config.ts │ ├── static │ │ ├── _headers │ │ ├── favicon.ico │ │ └── robots.txt │ ├── svelte.config.js │ ├── tsconfig.json │ ├── vite.config.ts │ └── wrangler.toml └── twind.style │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ ├── _worker.ts │ ├── app.d.ts │ ├── app.html │ ├── hooks.server.ts │ ├── lib │ │ ├── actions │ │ │ ├── clipboard-copy.ts │ │ │ ├── index.ts │ │ │ ├── mutation-observer.ts │ │ │ ├── scrollspy.ts │ │ │ ├── shortcut.ts │ │ │ ├── types.ts │ │ │ └── wicked.ts │ │ ├── assets │ │ │ ├── favicon.ico │ │ │ ├── flexsearch-logo-glass.svg │ │ │ ├── icon.png │ │ │ └── icon.svg │ │ ├── constants.ts │ │ ├── documentation.ts │ │ ├── icons │ │ │ ├── bootstrap.js │ │ │ ├── fluent-solid.js │ │ │ ├── heroicons │ │ │ │ ├── index.js │ │ │ │ ├── mini.js │ │ │ │ ├── outline.js │ │ │ │ └── solid.js │ │ │ ├── icon.svelte │ │ │ ├── index.ts │ │ │ ├── loading.js │ │ │ ├── octicons.js │ │ │ ├── twind.js │ │ │ └── types.ts │ │ ├── markdown │ │ │ ├── index.ts │ │ │ ├── read-cache.ts │ │ │ ├── remark-code.ts │ │ │ ├── themes │ │ │ │ ├── moonlight-ii.json │ │ │ │ ├── night-owl-dark.json │ │ │ │ ├── night-owl-light.json │ │ │ │ ├── tokyo-night-dark.json │ │ │ │ ├── tokyo-night-light.json │ │ │ │ └── tokyo-night-storm.json │ │ │ └── transform.ts │ │ ├── search.ts │ │ ├── stores │ │ │ ├── index.ts │ │ │ ├── match-media-query.ts │ │ │ ├── matches-media-query.ts │ │ │ ├── mounted.ts │ │ │ ├── on.ts │ │ │ ├── reduced-motion.ts │ │ │ ├── search.ts │ │ │ └── storage.ts │ │ ├── template │ │ │ ├── footer.svelte │ │ │ ├── head.svelte │ │ │ ├── header.svelte │ │ │ ├── layout.svelte │ │ │ ├── nav.svelte │ │ │ ├── redirect.svelte │ │ │ ├── search.svelte │ │ │ ├── skip-to.svelte │ │ │ └── theme-switcher.svelte │ │ └── twind.ts │ ├── routes │ │ ├── 404 │ │ │ └── +page.svelte │ │ ├── +error.svelte │ │ ├── +layout.js │ │ ├── +layout.server.js │ │ ├── +layout.svelte │ │ ├── +page.server.js │ │ ├── +page.svelte │ │ ├── - │ │ │ ├── search.json │ │ │ │ └── +server.js │ │ │ └── search │ │ │ │ └── +server.js │ │ ├── [...slug] │ │ │ ├── +layout.server.js │ │ │ ├── +layout.svelte │ │ │ ├── +page.server.js │ │ │ └── +page.svelte │ │ ├── manifest.json │ │ │ └── +server.ts │ │ └── msapplication-config.xml │ │ │ └── +server.ts │ ├── service-worker │ │ ├── index.ts │ │ └── register.ts │ └── twind.config.ts │ ├── static │ ├── _headers │ ├── _redirects │ ├── favicon.ico │ ├── robots.txt │ ├── sponsors.png │ ├── sponsors.svg │ └── twind-logo-animated.svg │ ├── svelte.config.js │ ├── tsconfig.json │ ├── typedoc.json │ ├── typedoc │ ├── plugin.cjs │ └── theme.cjs │ ├── vite.config.ts │ └── wrangler.toml ├── tsconfig.base.json └── vitest.config.js /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", 3 | "changelog": ["./changelog-github-custom.cjs", { "repo": "tw-in-js/twind" }], 4 | "commit": false, 5 | "access": "public", 6 | "baseBranch": "main", 7 | "updateInternalDependencies": "patch", 8 | "snapshot": { 9 | "useCalculatedVersion": true 10 | }, 11 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 12 | "onlyUpdatePeerDependentsWhenOutOfRange": true, 13 | "updateInternalDependents": "always" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Contribute to Twind CodeSpaces", 3 | "image": "mcr.microsoft.com/devcontainers/universal:2", 4 | "features": { 5 | "ghcr.io/devcontainers/features/node:1": {}, 6 | "ghcr.io/NicoVIII/devcontainer-features/pnpm:1": { 7 | "version": "7.16.0" 8 | } 9 | }, 10 | "postCreateCommand": ". ${NVM_DIR}/nvm.sh && nvm install" 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to always use LF line endings 2 | * text=auto eol=lf 3 | 4 | # Denote all files that are truly binary and should not be modified. 5 | *.ico binary 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sastan 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: tw-in-js 4 | # patreon: # Replace with a single Patreon username 5 | open_collective: twind 6 | ko_fi: twind 7 | # tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | # community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | # liberapay: # Replace with a single Liberapay username 10 | # issuehunt: # Replace with a single IssueHunt username 11 | # otechie: # Replace with a single Otechie username 12 | # custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Documentation 4 | url: https://twind.style 5 | about: Learn how to integrate Twind with your website or app. 6 | - name: Questions & Discussions 7 | url: https://github.com/tw-in-js/twind/discussions 8 | about: Use GitHub discussions for message-board style questions and discussions. 9 | - name: Chat 10 | url: https://chat.twind.style 11 | about: Ask questions and discuss with other Twind users in real time. 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | You might find our contributing section about [Submitting Pull Requests](https://github.com/tw-in-js/twind/blob/main/CONTRIBUTING.md#submitting-pull-requests) helpful. 2 | 3 | ### Please don't delete this checklist! Before submitting the PR, please make sure you do the following: 4 | 5 | - [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. 6 | - [ ] This message body should clearly illustrate what problems it solves. 7 | - [ ] Ideally, include a test that fails without this PR but passes with it. 8 | 9 | ### Tests 10 | 11 | - [ ] Run the tests with `pnpm test` and verify the project with `pnpm check` 12 | 13 | ### Changesets 14 | 15 | - [ ] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpx changeset` and following the prompts. All changesets should be `patch` until Twind 1.0 16 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: 'github-actions' 5 | directory: '/' 6 | schedule: 7 | interval: 'weekly' 8 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # all settings listed here - https://github.com/probot/stale#usage 2 | 3 | daysUntilStale: 270 4 | daysUntilClose: 30 5 | exemptAssignees: true 6 | # use this property to disable stale bot when we apply the wontfix label, prevents users from playing stale bot ping pong and keeping an issue open with no intent of action 7 | exemptLabels: 8 | - 🛑 Abandoned 9 | - 🙅 Hold 10 | only: issues 11 | staleLabel: 🛑 Abandoned 12 | markComment: false 13 | closeComment: > 14 | Hey folks. This issue hasn't received any traction for 90 days, so we're going to close this for housekeeping. 15 | If this is still an ongoing issue, please do consider contributing a Pull Request to resolve it. Further 16 | discussion is always welcome even with the issue closed. If anything actionable is posted in the comments, 17 | we'll consider reopening it. [ⓘ](https://github.com/probot/stale#is-closing-stale-issues-really-a-good-idea) 18 | -------------------------------------------------------------------------------- /.github/workflows/deploy-cdn.yml: -------------------------------------------------------------------------------- 1 | name: Deploy cdn.twind.style 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | paths: 9 | - 'sites/cdn.twind.style/**' 10 | 11 | jobs: 12 | deploy: 13 | runs-on: ubuntu-latest 14 | if: github.repository == 'tw-in-js/twind' 15 | steps: 16 | - name: 📥 Checkout 17 | uses: actions/checkout@v3 18 | 19 | - name: 🔧 Setup 20 | uses: ./.github/actions/setup 21 | with: 22 | installArgs: --filter="." --filter="./sites/cdn.twind.style" 23 | 24 | - name: 🌎 Deploy cdn.twind.style 25 | shell: bash 26 | run: pnpm run deploy 27 | working-directory: sites/cdn.twind.style 28 | env: 29 | CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} 30 | CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} 31 | -------------------------------------------------------------------------------- /.github/workflows/deploy-mdn.yml: -------------------------------------------------------------------------------- 1 | name: Deploy mdn.twind.run 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | paths: 9 | - 'sites/mdn.twind.style/**' 10 | 11 | jobs: 12 | deploy: 13 | runs-on: ubuntu-latest 14 | if: github.repository == 'tw-in-js/twind' 15 | steps: 16 | - name: 📥 Checkout 17 | uses: actions/checkout@v3 18 | 19 | - name: 🔧 Setup 20 | uses: ./.github/actions/setup 21 | with: 22 | installArgs: --filter="." --filter="./sites/mdn.twind.style" 23 | 24 | - name: 🌎 Deploy mdn.twind.style 25 | shell: bash 26 | run: pnpm run deploy 27 | working-directory: sites/mdn.twind.style 28 | env: 29 | CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} 30 | CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} 31 | -------------------------------------------------------------------------------- /.github/workflows/generate-sponsors.yml: -------------------------------------------------------------------------------- 1 | name: Generate Sponsors 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | # run every 5 days at 4:03 am 7 | - cron: '3 4 */5 * *' 8 | 9 | jobs: 10 | update-sponsors: 11 | runs-on: ubuntu-latest 12 | if: github.repository == 'tw-in-js/twind' 13 | steps: 14 | - name: 📥 Checkout 15 | uses: actions/checkout@v3 16 | 17 | - name: 🔧 Setup 18 | uses: ./.github/actions/setup 19 | with: 20 | installArgs: --filter="." --filter="./scripts" 21 | 22 | - name: Update sponsors 23 | run: pnpm run sponsors 24 | working-directory: scripts 25 | env: 26 | SPONSORKIT_GITHUB_TOKEN: ${{ secrets.SPONSORS_TOKEN }} 27 | SPONSORKIT_OPENCOLLECTIVE_KEY: ${{ secrets.OPENCOLLECTIVE_KEY }} 28 | 29 | - name: Commit 30 | uses: EndBug/add-and-commit@v9 31 | with: 32 | message: 'chore: update sponsors images' 33 | add: 'sites/twind.style/static/sponsors.*' 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.husky/prepare.cjs: -------------------------------------------------------------------------------- 1 | // prepare.js 2 | // do not run on CI env and non-git (codesandbox) 3 | const isCI = require('is-ci') 4 | const hasGit = require('fs').existsSync('.git') 5 | 6 | if (!isCI && hasGit) { 7 | require('husky').install() 8 | } 9 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # pnpm will automatically install the specified version of Node.js and use it for running pnpm run commands or the pnpm node command. 2 | # use-node-version=18.12.0 3 | 4 | # The primary branch of the repository which is used for publishing the latest changes. 5 | publish-branch=main 6 | 7 | # Do not use `workspace:` protocal — to allow forks of examples outside of this monorepo 8 | save-workspace-protocol=false 9 | 10 | # Local packages from the workspace are preferred over packages from the registry, 11 | # even if there is a newer version of the package in the registry. 12 | prefer-workspace-packages=true 13 | 14 | # Automatically installs any missing peer dependencies as dev dependencies 15 | auto-install-peers=true 16 | 17 | strict-peer-dependencies=false 18 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.stackblitz/codeflow.json: -------------------------------------------------------------------------------- 1 | { 2 | "pnpm": { 3 | "overrides": { 4 | "@twind/cdn": "./packages/cdn", 5 | "@twind/core": "./packages/core", 6 | "@twind/intellisense": "./packages/intellisense", 7 | "@twind/preset-autoprefix": "./packages/preset-autoprefix", 8 | "@twind/preset-container-queries": "./packages/preset-container-queries", 9 | "@twind/preset-ext": "./packages/preset-ext", 10 | "@twind/preset-line-clamp": "./packages/preset-line-clamp", 11 | "@twind/preset-radix-ui": "./packages/preset-radix-ui", 12 | "@twind/preset-tailwind": "./packages/preset-tailwind", 13 | "@twind/preset-tailwind-forms": "./packages/preset-tailwind-forms", 14 | "@twind/preset-typography": "./packages/preset-typography", 15 | "gatsby-plugin-twind": "./packages/with-gatsby", 16 | "@twind/with-next": "./packages/with-next", 17 | "@twind/with-react": "./packages/with-react", 18 | "@twind/with-sveltekit": "./packages/with-sveltekit", 19 | "@twind/with-web-components": "./packages/with-web-components" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "search.exclude": { 4 | "**/.mf": true, 5 | "**/.svelte-kit": true, 6 | "**/build": true, 7 | "**/dist": true, 8 | "coverage": true, 9 | "sites/twind.style/typedoc/data.json": true 10 | }, 11 | "npm.exclude": ["**/dist", "**/.svelte-kit/**"] 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | - [@twind/cdn](./packages/cdn/CHANGELOG.md) 4 | - [@twind/core](./packages/core/CHANGELOG.md) 5 | - [@twind/intellisense](./packages/intellisense/CHANGELOG.md) 6 | 7 | ## Presets 8 | 9 | - [@twind/preset-autoprefix](./packages/preset-autoprefix/CHANGELOG.md) 10 | - [@twind/preset-conatiner-queries](./packages/preset-conatiner-queries/CHANGELOG.md) 11 | - [@twind/preset-ext](./packages/preset-ext/CHANGELOG.md) 12 | - [@twind/preset-line-clamp](./packages/preset-line-clamp/CHANGELOG.md) 13 | - [@twind/preset-radix-ui](./packages/preset-radix-ui/CHANGELOG.md) 14 | - [@twind/preset-tailwind](./packages/preset-tailwind/CHANGELOG.md) 15 | - [@twind/preset-tailwind-forms](./packages/preset-tailwind-forms/CHANGELOG.md) 16 | - [@twind/preset-typography](./packages/preset-typography/CHANGELOG.md) 17 | 18 | ## Integrations 19 | 20 | - [@twind/with-next](./packages/with-next/CHANGELOG.md) 21 | - [@twind/with-react](./packages/with-remix/CHANGELOG.md) 22 | - ~~[@twind/with-remix](./packages/with-remix/CHANGELOG.md)~~ 23 | - [@twind/with-sveltekit](./packages/with-sveltekit/CHANGELOG.md) 24 | - [@twind/with-web-components](./packages/with-web-components/CHANGELOG.md) 25 | - [gatsby-plugin-twind](./packages/with-gatsby/CHANGELOG.md) 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 [these people](https://github.com/tw-in-js/twind/graphs/contributors) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /documentation/README.md: -------------------------------------------------------------------------------- 1 | > The source for [twind.style](https://twind.style) which is generated by [sites/twind.style](../sites/twind.style). 2 | 3 | ## Examples 4 | 5 | ### [GitHub beta blockquote-based](https://github.com/myl7/remark-github-beta-blockquote-admonitions) 6 | 7 | > **Note** 8 | > This is a note 9 | 10 | > **Tip** 11 | > This is a tip 12 | 13 | > **Hint** 14 | > This is a hint 15 | 16 | > **Important** 17 | > This is important 18 | 19 | > **Caution/Don't try this at home** 20 | > This is a caution 21 | 22 | To add a title to an admonition, add a colon after the admonition type and then the title. 23 | 24 | > **Caution/Don't try this at home** 25 | > This is a caution 26 | 27 | ### Code blocks 28 | 29 | - `js title="..." showLineNumbers {1-3,4} /needle/3-5` 30 | - `diff-js title focus=1-3,5` 31 | - `[(diff-)?lang]? [title|title="..."]? [showLineNumbers|line-numbers]? [highlightLines]* [highlightTerm]* [focusLines]*` 32 | 33 | - highlight lines: `{1-3,5}` or `highlight=1-3,5` 34 | - focus lines: `[1-3,5]` or `focus=1-3,5` 35 | - highlight term: `/needle/` or `/needle/3-5` (Highlight only the third to fifth instances) 36 | - `line-numbers` or `showLineNumber` 37 | -------------------------------------------------------------------------------- /documentation/comparison.md: -------------------------------------------------------------------------------- 1 | --- 2 | section: Getting Started 3 | title: Comparison 4 | next: ./rules.md 5 | --- 6 | 7 | ## tailwindcss 8 | 9 | CDN: 106kB (brotli) vs 17kB (brotli) -> 6 times smaller 10 | 11 | - no implicit ordering of utilities: https://play.tailwindcss.com/EsRtpBotox 12 | - if two utilities use the same CSS property, the one used first anywhere in the document will be used 13 | - twind ensures that the order of the utilities is always predictable, no matter which one is used first 14 | - darkMode: custom selectors like `.dark-mode` or `[theme=dark]` 15 | - auto dark colors 16 | 17 | ## twind v0.x 18 | 19 | ### New Features 20 | 21 | - simplified API 22 | - helpers return strings that can be used as-is — no need to pass through `tw` 23 | - hot module reloading (HMR) support 24 | - working `apply` — and new `shortcut`s 25 | - theme: 26 | - dotted deep access: `colors.gray.500` or `spacing[2.5]` 27 | 28 | ## twind.macro 29 | 30 | ## Windy CSS 31 | 32 | ## UnoCSS 33 | 34 | ## Stitches 35 | -------------------------------------------------------------------------------- /documentation/component-styles.md: -------------------------------------------------------------------------------- 1 | --- 2 | section: Core Concepts 3 | title: Component Styles 4 | next: ./grouping-syntax.md 5 | --- 6 | -------------------------------------------------------------------------------- /documentation/features.md: -------------------------------------------------------------------------------- 1 | --- 2 | section: Getting Started 3 | title: Features 4 | next: ./migration.md 5 | --- 6 | 7 | - grouping syntax 8 | - inline shortcut: `~` to apply/merge utilities -> `~(text(5xl,red-700),bg-red-100)` 9 | - comments (single and multiline) 10 | - styles (the generated CSS rules) are sorted predictably and stable — no matter in which order the rules are injected 11 | 12 | - `shortcuts` vs `apply` 13 | 14 | `shortcut` is a way to group a known design — I develop a component with utilities and then extract it into a shortcut. In that case, I want the order to be as they were when I designed it with utilities. 15 | 16 | `apply` is re-using utilities, but _apply_ them in the order you have declared them. 17 | 18 | Short summary: 19 | 20 | - `shortcut`: `p-2 p-0` -> `p-2` wins 21 | - `apply`: `p-2 p-0` -> `p-0` wins 22 | -------------------------------------------------------------------------------- /documentation/intellisense.md: -------------------------------------------------------------------------------- 1 | --- 2 | section: Advanced 3 | label: IntelliSense 4 | package: '@twind/intellisense' 5 | excerpt: | 6 | IntelliSense utilities for [twind](https://twind.style) 7 | --- 8 | 9 | ## 📦 Installation 10 | 11 | Install from npm: 12 | 13 | ```sh 14 | npm install @twind/core @twind/intellisense 15 | ``` 16 | 17 | ## 🙇 Usage 18 | 19 | TODO: Write usage instructions 20 | -------------------------------------------------------------------------------- /documentation/preset-autoprefix.md: -------------------------------------------------------------------------------- 1 | --- 2 | section: Presets 3 | label: Autoprefix 4 | package: '@twind/preset-autoprefix' 5 | excerpt: | 6 | CSS vendor prefixer and property alias mapper preset. 7 | next: ./preset-container-queries.md 8 | --- 9 | 10 | ## 📦 Installation 11 | 12 | **with [@twind/core](./installation#local--bundler)** 13 | 14 | Install from npm: 15 | 16 | ```sh 17 | npm install @twind/core @twind/preset-autoprefix 18 | ``` 19 | 20 | Add the preset to your twind config: 21 | 22 | ```js title="twind.config.js" 23 | import { defineConfig } from '@twind/core' 24 | import presetAutoprefix from '@twind/preset-autoprefix' 25 | 26 | export default defineConfig({ 27 | presets: [presetAutoprefix()], 28 | /* config */ 29 | }) 30 | ``` 31 | 32 |
Usage with a script tag 33 | 34 | ```html 35 | 36 | 40 | 46 | 47 | ``` 48 | 49 |
50 | 51 | **with [Twind CDN](./installation#twind-cdn)** 52 | 53 | _Already included in `@twind/cdn`_ 54 | -------------------------------------------------------------------------------- /examples/basic/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Example: Basic 2 | 3 | > Try it live at [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/basic) or [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/basic). 4 | 5 | This example uses 6 | 7 | - [@twind/core](https://github.com/tw-in-js/twind/tree/main/packages/core) 8 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 9 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 10 | -------------------------------------------------------------------------------- /examples/basic/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/basic/favicon.ico -------------------------------------------------------------------------------- /examples/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Twind Example — Basic 8 | 9 | 10 | 11 | 12 |
13 |

16 | This is Twind! 17 |

18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/basic/index.js: -------------------------------------------------------------------------------- 1 | import { install } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | // You must call install at least once, but can call it multiple times 6 | install({ 7 | /* config */ 8 | presets: [presetAutoprefix(), presetTailwind()], 9 | }) 10 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/basic", 3 | "description": "basic twind example", 4 | "version": "1.0.8", 5 | "private": true, 6 | "main": "index.js", 7 | "license": "MIT", 8 | "bugs": "https://github.com/tw-in-js/twind/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tw-in-js/twind.git", 12 | "directory": "examples/basic" 13 | }, 14 | "engines": { 15 | "node": ">=14" 16 | }, 17 | "type": "module", 18 | "scripts": { 19 | "start": "vite", 20 | "build": "vite build", 21 | "preview": "vite preview" 22 | }, 23 | "dependencies": { 24 | "@twind/core": "1.1.3", 25 | "@twind/preset-autoprefix": "1.0.7", 26 | "@twind/preset-tailwind": "1.1.4" 27 | }, 28 | "devDependencies": { 29 | "vite": "^4.0.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/basic/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/playground/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/playground/README.md: -------------------------------------------------------------------------------- 1 | # Playground 2 | 3 | > Try it live at [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/playground) or [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/playground). 4 | 5 | This example uses 6 | 7 | - [@twind/core](https://github.com/tw-in-js/twind/tree/main/packages/core) 8 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 9 | - [@twind/preset-ext](https://github.com/tw-in-js/twind/tree/main/packages/preset-ext) 10 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 11 | - [@twind/preset-tailwind-forms](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind-forms) 12 | -------------------------------------------------------------------------------- /examples/playground/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/playground/favicon.ico -------------------------------------------------------------------------------- /examples/playground/img/beams.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/playground/img/beams.jpg -------------------------------------------------------------------------------- /examples/playground/img/grid.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/playground", 3 | "description": "playground with all presets enabled", 4 | "version": "1.0.8", 5 | "private": true, 6 | "main": "index.js", 7 | "license": "MIT", 8 | "bugs": "https://github.com/tw-in-js/twind/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tw-in-js/twind.git", 12 | "directory": "examples/playground" 13 | }, 14 | "engines": { 15 | "node": ">=14" 16 | }, 17 | "type": "module", 18 | "scripts": { 19 | "start": "vite", 20 | "build": "vite build", 21 | "preview": "vite preview" 22 | }, 23 | "dependencies": { 24 | "@twind/core": "1.1.3", 25 | "@twind/preset-autoprefix": "1.0.7", 26 | "@twind/preset-ext": "1.0.7", 27 | "@twind/preset-line-clamp": "1.0.7", 28 | "@twind/preset-tailwind": "1.1.4", 29 | "@twind/preset-tailwind-forms": "1.1.2" 30 | }, 31 | "devDependencies": { 32 | "vite": "^4.0.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/playground/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/playground/twind.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetExt from '@twind/preset-ext' 4 | import presetLineClamp from '@twind/preset-line-clamp' 5 | import presetTailwind from '@twind/preset-tailwind' 6 | import presetTailwindForms from '@twind/preset-tailwind-forms' 7 | 8 | // `defineConfig` is not required, but adds types 9 | export default defineConfig({ 10 | presets: [ 11 | presetAutoprefix(), 12 | presetExt(), 13 | presetLineClamp(), 14 | presetTailwind(), 15 | presetTailwindForms(), 16 | ], 17 | }) 18 | -------------------------------------------------------------------------------- /examples/using-tailwind-forms/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/using-tailwind-forms/README.md: -------------------------------------------------------------------------------- 1 | # Example: tailwind-forms 2 | 3 | > Try it live at [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/using-tailwind-forms) or [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/using-tailwind-forms). 4 | 5 | This example uses 6 | 7 | - [@twind/core](https://github.com/tw-in-js/twind/tree/main/packages/core) 8 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 9 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 10 | - [@twind/preset-tailwind-forms](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind-forms) 11 | -------------------------------------------------------------------------------- /examples/using-tailwind-forms/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/using-tailwind-forms/favicon.ico -------------------------------------------------------------------------------- /examples/using-tailwind-forms/index.js: -------------------------------------------------------------------------------- 1 | import { install } from '@twind/core' 2 | import config from './twind.config' 3 | 4 | // You must call install at least once, but can call it multiple times 5 | install(config) 6 | -------------------------------------------------------------------------------- /examples/using-tailwind-forms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/using-tailwind-forms", 3 | "description": "tailwind-forms example", 4 | "version": "1.0.8", 5 | "private": true, 6 | "main": "index.js", 7 | "license": "MIT", 8 | "bugs": "https://github.com/tw-in-js/twind/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tw-in-js/twind.git", 12 | "directory": "examples/using-tailwind-forms" 13 | }, 14 | "engines": { 15 | "node": ">=14" 16 | }, 17 | "type": "module", 18 | "scripts": { 19 | "start": "vite", 20 | "build": "vite build", 21 | "preview": "vite preview" 22 | }, 23 | "dependencies": { 24 | "@twind/core": "1.1.3", 25 | "@twind/preset-autoprefix": "1.0.7", 26 | "@twind/preset-tailwind": "1.1.4", 27 | "@twind/preset-tailwind-forms": "1.1.2" 28 | }, 29 | "devDependencies": { 30 | "vite": "^4.0.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/using-tailwind-forms/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/using-tailwind-forms/twind.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | import presetTailwindForms from '@twind/preset-tailwind-forms' 5 | 6 | export default defineConfig({ 7 | presets: [presetAutoprefix(), presetTailwind(), presetTailwindForms()], 8 | /* config */ 9 | }) 10 | -------------------------------------------------------------------------------- /examples/using-twind-cdn/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/using-twind-cdn/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @example/tailwind-cdn 2 | 3 | ## 1.0.1 4 | 5 | ### Patch Changes 6 | 7 | - create dedicated worker and deno bundles, and downgrade module to es2019 (fixes [#426](https://github.com/tw-in-js/twind/issues/426)) ([`02ea227a`](https://github.com/tw-in-js/twind/commit/02ea227afffe474cde5e843c3519f0836ee18f8a)) 8 | 9 | ## 1.0.0 10 | 11 | ### Patch Changes 12 | 13 | - big documentation update ([`a63ca2cb`](https://github.com/tw-in-js/twind/commit/a63ca2cbf450d8a6f72f4d60f5856cee88d16911)) 14 | 15 | ## 0.0.1-next.2 16 | 17 | ### Patch Changes 18 | 19 | - perf: optimize observe to only handle changes on element with class attribute ([`88eeb077`](https://github.com/tw-in-js/twind/commit/88eeb07798e70860c840278ac97e7a2ba6ee8366)) 20 | 21 | * revert: remove dom sheet ([`6d50cf5f`](https://github.com/tw-in-js/twind/commit/6d50cf5f7bd8fb79caf02a81c30060c8abf2382e)) 22 | 23 | ## 0.0.1-next.1 24 | 25 | ### Patch Changes 26 | 27 | - bump to same version ([`ca157601`](https://github.com/tw-in-js/twind/commit/ca1576017f172bfb0ba61e936f0f44d36102016c)) 28 | 29 | ## 0.0.1-next.0 30 | 31 | ### Patch Changes 32 | 33 | - adding examples that can be forked in stackblitz and codesandbox ([#244](https://github.com/tw-in-js/twind/pull/244)) 34 | -------------------------------------------------------------------------------- /examples/using-twind-cdn/README.md: -------------------------------------------------------------------------------- 1 | # Example: Twind CDN 2 | 3 | > Try it live at [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/using-twind-cdn) or [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/using-twind-cdn). 4 | 5 | Twind CDN is a drop-in replacement for [Tailwind CSS Play CDN](https://tailwindcss.com/docs/installation/play-cdn) that is almost 5.5 times smaller (104kb vs 17kB) without any build step right in the browser or any other environment like Node.js, deno, workers, ... 6 | 7 | This example uses 8 | 9 | - [@twind/cdn](https://github.com/tw-in-js/twind/tree/main/packages/cdn) — which includes 10 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 11 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 12 | -------------------------------------------------------------------------------- /examples/using-twind-cdn/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/using-twind-cdn/favicon.ico -------------------------------------------------------------------------------- /examples/using-twind-cdn/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Twind Example — Tailwind CDN 8 | 9 | 10 | 11 |
12 |

15 | This is Twind! 16 |

17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/using-twind-cdn/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.1", 3 | "name": "@example/using-twind-cdn", 4 | "description": "twind cdn twind example", 5 | "private": true, 6 | "main": "index.html", 7 | "bugs": "https://github.com/tw-in-js/twind/issues", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/tw-in-js/twind.git", 11 | "directory": "examples/using-twind-cdn" 12 | }, 13 | "engines": { 14 | "node": ">=14" 15 | }, 16 | "license": "MIT", 17 | "type": "module", 18 | "scripts": { 19 | "start": "serve", 20 | "build": "echo This is a static template, there is no bundler or bundling involved!" 21 | }, 22 | "devDependencies": { 23 | "serve": "^13.0.4" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/using-twind-cdn/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "static" 3 | } 4 | -------------------------------------------------------------------------------- /examples/with-gatsby/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/with-gatsby/README.md: -------------------------------------------------------------------------------- 1 | # Example: Gatsby 2 | 3 | > Try it live at [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/with-gatsby). 4 | 5 | _Does not work in [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/with-gatsby) until [sharp is supported](https://github.com/stackblitz/webcontainer-core/issues/147)._ 6 | 7 | ## How does this work? 8 | 9 | 1. configure [gatsby-plugin-twind](https://github.com/tw-in-js/twind/tree/main/packages/with-gatsby) in [gatsby-config.js](./gatsby-config.js) — to enable server-side rendering (SSR) and injecting of twind styles in the browser 10 | 2. a dedicated [twind.config](./twind.config.js) 11 | 12 | ## What is included? 13 | 14 | - [gatsby](https://www.npmjs.com/package/gatsby) 15 | - [gatsby-plugin-twind](https://github.com/tw-in-js/twind/tree/main/packages/with-gatsby) 16 | - [@twind/core](https://github.com/tw-in-js/twind/tree/main/packages/core) 17 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 18 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 19 | 20 | ## Credits 21 | 22 | Based on [Gatsby Starter Tailwind](https://github.com/taylorbryant/gatsby-starter-tailwind) 23 | -------------------------------------------------------------------------------- /examples/with-gatsby/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Browser APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/browser-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /examples/with-gatsby/gatsby-config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | // ONLY REQUIRED WITHIN THE TWIND MONOREPO 4 | try { 5 | require('jiti/register') 6 | } catch { 7 | // IGNORE 8 | } 9 | 10 | const { white, green } = require('@twind/preset-tailwind/colors') 11 | 12 | module.exports = { 13 | siteMetadata: { 14 | title: `Gatsby Starter Twind`, 15 | description: `Gatsby starter styled with Twind`, 16 | author: `@taylorbryant`, 17 | }, 18 | plugins: [ 19 | `gatsby-plugin-react-helmet`, 20 | { 21 | resolve: `gatsby-plugin-manifest`, 22 | options: { 23 | name: `gatsby-starter-twind`, 24 | short_name: `starter`, 25 | start_url: `/`, 26 | background_color: white, 27 | theme_color: green['500'], 28 | display: `minimal-ui`, 29 | icon: `src/images/favicon.png`, 30 | }, 31 | }, 32 | `gatsby-plugin-twind`, 33 | // { 34 | // resolve: `gatsby-plugin-twind`, 35 | // options: { 36 | // config: `./path/to/twind.config` 37 | // } 38 | // }, 39 | `gatsby-plugin-offline`, 40 | ], 41 | } 42 | -------------------------------------------------------------------------------- /examples/with-gatsby/gatsby-node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Node APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/node-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /examples/with-gatsby/gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /examples/with-gatsby/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-gatsby/src/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/with-gatsby/src/images/favicon.png -------------------------------------------------------------------------------- /examples/with-gatsby/src/pages/404.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import Layout from '../components/layout' 4 | import SEO from '../components/seo' 5 | import abductionIllustration from '../images/abduction-illustration.svg' 6 | 7 | function NotFoundPage() { 8 | return ( 9 | 10 | 11 |
12 | Ghost getting abducted by aliens 17 |

18 | Looks like this page is a ghost that got abducted by aliens... 19 |

20 |
21 |
22 | ) 23 | } 24 | 25 | export default NotFoundPage 26 | -------------------------------------------------------------------------------- /examples/with-gatsby/src/pages/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import Layout from '../components/layout' 4 | import SEO from '../components/seo' 5 | import catAndHumanIllustration from '../images/cat-and-human-illustration.svg' 6 | 7 | function IndexPage() { 8 | return ( 9 | 10 | 11 | 12 |
13 | Cat and human sitting on a couch 18 | 19 |

20 | Hey there! Welcome to your first Gatsby site. 21 |

22 | 23 |

24 | This is a barebones starter for Gatsby styled using{` `} 25 | 31 | Twind 32 | 33 | , a utility-first CSS framework. 34 |

35 |
36 |
37 | ) 38 | } 39 | 40 | export default IndexPage 41 | -------------------------------------------------------------------------------- /examples/with-gatsby/twind.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | export default defineConfig({ 6 | presets: [presetAutoprefix(), presetTailwind()], 7 | /* config */ 8 | }) 9 | -------------------------------------------------------------------------------- /examples/with-lit/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/with-lit/README.md: -------------------------------------------------------------------------------- 1 | # Example: Lit 2 | 3 | > Try it live at [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/with-lit) or [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/with-lit). 4 | 5 | This example uses 6 | 7 | - [lit](https://lit.dev) 8 | - [@twind/with-web-components](https://github.com/tw-in-js/twind/tree/main/packages/with-web-components) 9 | - [@twind/core](https://github.com/tw-in-js/twind/tree/main/packages/core) 10 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 11 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 12 | -------------------------------------------------------------------------------- /examples/with-lit/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/with-lit/favicon.ico -------------------------------------------------------------------------------- /examples/with-lit/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Using Lit with Twind 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/with-lit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/with-lit", 3 | "description": "Lit example", 4 | "version": "1.0.8", 5 | "private": true, 6 | "main": "index.js", 7 | "license": "MIT", 8 | "bugs": "https://github.com/tw-in-js/twind/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tw-in-js/twind.git", 12 | "directory": "examples/with-lit" 13 | }, 14 | "engines": { 15 | "node": ">=14" 16 | }, 17 | "type": "module", 18 | "scripts": { 19 | "start": "vite", 20 | "build": "vite build", 21 | "preview": "vite preview" 22 | }, 23 | "dependencies": { 24 | "@twind/core": "1.1.3", 25 | "@twind/preset-autoprefix": "1.0.7", 26 | "@twind/preset-tailwind": "1.1.4", 27 | "@twind/with-web-components": "1.1.3", 28 | "lit": "^2.5.0" 29 | }, 30 | "devDependencies": { 31 | "typescript": "~4.8.4", 32 | "vite": "^4.0.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/with-lit/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-lit/src/index.ts: -------------------------------------------------------------------------------- 1 | import { LitElement, html } from 'lit' 2 | import { customElement } from 'lit/decorators.js' 3 | 4 | import install from '@twind/with-web-components' 5 | import config from './twind.config' 6 | 7 | @customElement('twind-element') 8 | @install(config) 9 | export class TwindElement extends LitElement /* install(config)(LitElement) */ { 10 | override render() { 11 | return html` 12 |
13 |

This is Twind!

14 |
15 | ` 16 | 17 | // Alternativly use tw function directly (required `class extends withTwind(config)(LitElement) { }`) 18 | // return html` 19 | //
20 | //

21 | // This is Twind! 22 | //

23 | //
24 | // ` 25 | } 26 | } 27 | 28 | document.body.innerHTML = '' 29 | -------------------------------------------------------------------------------- /examples/with-lit/src/twind.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | export default defineConfig({ 6 | presets: [presetAutoprefix(), presetTailwind()], 7 | /* config */ 8 | }) 9 | -------------------------------------------------------------------------------- /examples/with-lit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2019", 4 | "module": "es2020", 5 | "lib": ["es2020", "DOM", "DOM.Iterable"], 6 | "declaration": true, 7 | "declarationMap": true, 8 | "sourceMap": true, 9 | "inlineSources": true, 10 | "outDir": "./", 11 | "rootDir": "./src", 12 | "strict": true, 13 | "noUnusedLocals": true, 14 | "noUnusedParameters": true, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "noImplicitAny": true, 18 | "noImplicitThis": true, 19 | "moduleResolution": "node", 20 | "allowSyntheticDefaultImports": true, 21 | "experimentalDecorators": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "noImplicitOverride": true, 24 | "plugins": [ 25 | { 26 | "name": "ts-lit-plugin", 27 | "strict": true 28 | } 29 | ] 30 | }, 31 | "include": ["src/**/*.ts"], 32 | "exclude": [] 33 | } 34 | -------------------------------------------------------------------------------- /examples/with-next/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/with-next/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @example/with-next 2 | 3 | ## 1.1.0 4 | 5 | ### Minor Changes 6 | 7 | - update to `next@13` and `react@18` ([`33380650`](https://github.com/tw-in-js/twind/commit/333806502d2d9f6367d2ba9b3e36a6c071b45a05)) 8 | 9 | ### Patch Changes 10 | 11 | - create dedicated worker and deno bundles, and downgrade module to es2019 (fixes [#426](https://github.com/tw-in-js/twind/issues/426)) ([`02ea227a`](https://github.com/tw-in-js/twind/commit/02ea227afffe474cde5e843c3519f0836ee18f8a)) 12 | 13 | ## 1.0.1 14 | 15 | ### Patch Changes 16 | 17 | - introduce new @twind/core package to prevent issue with existing code that imports from CDNs without a version ([`4cab9d2f`](https://github.com/tw-in-js/twind/commit/4cab9d2fc573dd2a91cc6667510ff1b7b890854b)) 18 | 19 | ## 1.0.0 20 | 21 | ### Patch Changes 22 | 23 | - big documentation update ([`a63ca2cb`](https://github.com/tw-in-js/twind/commit/a63ca2cbf450d8a6f72f4d60f5856cee88d16911)) 24 | -------------------------------------------------------------------------------- /examples/with-next/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /examples/with-next/next.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | // @ts-check 3 | 4 | /** next@12 config — see below for a next@13 config */ 5 | // THIS IS ONLY NEEDED WHEN USED INSIDE THE TWIND MONOREPO 6 | const withPlugins = require('next-compose-plugins') 7 | const withTM = require('next-transpile-modules') 8 | 9 | /** 10 | * @type {import('next').NextConfig} 11 | **/ 12 | module.exports = withPlugins( 13 | [ 14 | withTM([ 15 | '@twind/core', 16 | '@twind/preset-autoprefix', 17 | '@twind/preset-tailwind', 18 | '@twind/with-next', 19 | ]), 20 | ], 21 | { 22 | /* regular next.js config options here */ 23 | reactStrictMode: true, 24 | }, 25 | ) 26 | 27 | /** next@13 config */ 28 | /** 29 | * @type {import('next').NextConfig} 30 | **/ 31 | // module.exports = { 32 | // reactStrictMode: true, 33 | // experimental: { 34 | // // THIS IS ONLY NEEDED WHEN USED INSIDE THE TWIND MONOREPO 35 | // transpilePackages: [ 36 | // '@twind/core', 37 | // '@twind/preset-autoprefix', 38 | // '@twind/preset-tailwind', 39 | // '@twind/with-next', 40 | // ], 41 | // }, 42 | // } 43 | -------------------------------------------------------------------------------- /examples/with-next/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/with-next", 3 | "description": "next with twind example", 4 | "version": "1.1.0", 5 | "private": true, 6 | "license": "MIT", 7 | "bugs": "https://github.com/tw-in-js/twind/issues", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/tw-in-js/twind.git", 11 | "directory": "examples/with-next" 12 | }, 13 | "engines": { 14 | "node": ">=14" 15 | }, 16 | "scripts": { 17 | "start": "npm run dev", 18 | "dev": "next", 19 | "build": "next build", 20 | "serve": "next start", 21 | "export": "next export" 22 | }, 23 | "devDependencies": { 24 | "@twind/core": "1.1.3", 25 | "@twind/preset-autoprefix": "1.0.7", 26 | "@twind/preset-tailwind": "1.1.4", 27 | "@twind/with-next": "1.2.2", 28 | "@types/node": "^14.18.33", 29 | "@types/react": "^17.0.52", 30 | "next": "^12.3.4", 31 | "next-compose-plugins": "^2.2.1", 32 | "next-transpile-modules": "^9.1.0", 33 | "react": "^17.0.2", 34 | "react-dom": "^17.0.2", 35 | "typescript": "^4.8.4" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/with-next/pages/_app.js: -------------------------------------------------------------------------------- 1 | import install from '@twind/with-next/app' 2 | import config from '../twind.config' 3 | 4 | export default install(config) 5 | -------------------------------------------------------------------------------- /examples/with-next/pages/_document.js: -------------------------------------------------------------------------------- 1 | import install from '@twind/with-next/document' 2 | 3 | export default install() 4 | -------------------------------------------------------------------------------- /examples/with-next/pages/about.jsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | 3 | export default function About() { 4 | return ( 5 |
6 | About us — Home 7 |
8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /examples/with-next/pages/ssg.jsx: -------------------------------------------------------------------------------- 1 | export default function SSG({ framework }) { 2 | return
{framework} ssg example
3 | } 4 | 5 | export function getStaticProps() { 6 | return { 7 | props: { framework: 'preact' }, 8 | } 9 | } 10 | 11 | // export const config = { 12 | // unstable_runtimeJS: false 13 | // }; 14 | -------------------------------------------------------------------------------- /examples/with-next/public/assets/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/with-next/public/assets/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /examples/with-next/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/with-next/public/favicon.ico -------------------------------------------------------------------------------- /examples/with-next/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "downlevelIteration": true /* THIS IS ONLY NEEDED WHEN USED INSIDE THE TWIND MONOREPO */, 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "incremental": true, 12 | "esModuleInterop": true, 13 | "module": "esnext", 14 | "moduleResolution": "node", 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "jsx": "preserve", 18 | "plugins": [ 19 | { 20 | "name": "next" 21 | } 22 | ] 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /examples/with-next/twind.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | export default defineConfig({ 6 | presets: [presetAutoprefix(), presetTailwind()], 7 | /* config */ 8 | }) 9 | -------------------------------------------------------------------------------- /examples/with-remix/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/with-remix/app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | // for the side effect of creating the global twind instance 2 | import './twind' 3 | 4 | import { hydrate } from 'react-dom' 5 | import { RemixBrowser } from '@remix-run/react' 6 | 7 | hydrate(, document) 8 | -------------------------------------------------------------------------------- /examples/with-remix/app/entry.server.tsx: -------------------------------------------------------------------------------- 1 | import { renderToString } from 'react-dom/server' 2 | 3 | import type { EntryContext } from '@remix-run/node' 4 | import { Response } from '@remix-run/node' 5 | import { RemixServer } from '@remix-run/react' 6 | 7 | import inline from '@twind/with-react/inline' 8 | 9 | import tw from './twind' 10 | 11 | export default function handleRequest( 12 | request: Request, 13 | responseStatusCode: number, 14 | responseHeaders: Headers, 15 | remixContext: EntryContext, 16 | ) { 17 | let markup = renderToString() 18 | 19 | // Add twind styles to the markup 20 | markup = inline(markup, tw) 21 | 22 | responseHeaders.set('Content-Type', 'text/html') 23 | 24 | return new Response('' + markup, { 25 | status: responseStatusCode, 26 | headers: responseHeaders, 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /examples/with-remix/app/root.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from '@remix-run/node' 2 | import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react' 3 | 4 | export const meta: MetaFunction = () => { 5 | return { title: 'New Remix App' } 6 | } 7 | 8 | export default function App() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {process.env.NODE_ENV === 'development' && } 22 | 23 | 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /examples/with-remix/app/routes/anything.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from '@remix-run/react' 2 | import { cx } from '@twind/core' 3 | 4 | const linkClass = cx('transition-all duration-300 opacity-75 hover:(opacity-100 text-indigo-500)') 5 | 6 | export default function Index() { 7 | return ( 8 |
9 |

This works

10 | 11 | Back to Home 12 | 13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /examples/with-remix/app/twind.ts: -------------------------------------------------------------------------------- 1 | import install from '@twind/with-react' 2 | import config from '../twind.config' 3 | 4 | export default install(config) 5 | -------------------------------------------------------------------------------- /examples/with-remix/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/with-remix", 3 | "description": "remix with twind example", 4 | "version": "0.0.10", 5 | "private": true, 6 | "license": "MIT", 7 | "bugs": "https://github.com/tw-in-js/twind/issues", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/tw-in-js/twind.git", 11 | "directory": "examples/with-remix" 12 | }, 13 | "engines": { 14 | "node": ">=14" 15 | }, 16 | "sideEffetcs": false, 17 | "scripts": { 18 | "start": "npm run dev", 19 | "dev": "remix dev", 20 | "build": "remix build", 21 | "serve": "remix-serve build" 22 | }, 23 | "dependencies": { 24 | "@remix-run/node": "^1.8.2", 25 | "@remix-run/react": "^1.8.2", 26 | "@remix-run/serve": "^1.8.2", 27 | "@twind/core": "1.1.3", 28 | "@twind/preset-autoprefix": "1.0.7", 29 | "@twind/preset-tailwind": "1.1.4", 30 | "@twind/with-react": "1.1.3", 31 | "react": "^17.0.2", 32 | "react-dom": "^17.0.2", 33 | "remix": "^1.8.2" 34 | }, 35 | "devDependencies": { 36 | "@remix-run/dev": "^1.8.2", 37 | "@types/react": "^17.0.39", 38 | "@types/react-dom": "^17.0.18", 39 | "typescript": "^4.8.4" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/with-remix/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/with-remix/public/favicon.ico -------------------------------------------------------------------------------- /examples/with-remix/remix.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | // ONLY REQUIRED WITHIN THE TWIND MONOREPO 3 | try { 4 | require('jiti/register') 5 | } catch { 6 | // IGNORE 7 | } 8 | 9 | /** 10 | * @type {import('@remix-run/dev/config').AppConfig} 11 | */ 12 | module.exports = { 13 | ignoredRouteFiles: ['**/.*'], 14 | appDirectory: 'app', 15 | assetsBuildDirectory: 'public/build', 16 | serverBuildPath: 'build/index.js', 17 | publicPath: '/build/', 18 | serverDependenciesToBundle: [ 19 | '@twind/core', 20 | '@twind/preset-autoprefix', 21 | '@twind/preset-tailwind', 22 | '@twind/with-remix', 23 | ], 24 | } 25 | -------------------------------------------------------------------------------- /examples/with-remix/remix.env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /examples/with-remix/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-remix/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "lib": ["DOM", "DOM.Iterable", "ES2019"], 5 | "isolatedModules": true, 6 | "esModuleInterop": true, 7 | "jsx": "react-jsx", 8 | "moduleResolution": "node", 9 | "resolveJsonModule": true, 10 | "target": "ES2019", 11 | "strict": true, 12 | "baseUrl": ".", 13 | "paths": { 14 | "~/*": ["./app/*"] 15 | }, 16 | "noEmit": true, 17 | "allowJs": true, 18 | "forceConsistentCasingInFileNames": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/with-remix/twind.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | export default defineConfig({ 6 | presets: [presetAutoprefix(), presetTailwind()], 7 | /* config */ 8 | }) 9 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | // for the side effect of creating the global twind instance 2 | import './twind' 3 | 4 | import { RemixBrowser } from '@remix-run/react' 5 | import { startTransition, StrictMode } from 'react' 6 | import { hydrateRoot } from 'react-dom/client' 7 | 8 | const hydrate = () => 9 | startTransition(() => { 10 | hydrateRoot( 11 | document, 12 | 13 | 14 | , 15 | ) 16 | }) 17 | 18 | if (typeof requestIdleCallback == 'function') { 19 | requestIdleCallback(hydrate) 20 | } else { 21 | // Safari doesn't support requestIdleCallback 22 | // https://caniuse.com/requestidlecallback 23 | setTimeout(hydrate, 1) 24 | } 25 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/app/root.tsx: -------------------------------------------------------------------------------- 1 | import type { MetaFunction } from '@remix-run/node' 2 | import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react' 3 | 4 | export const meta: MetaFunction = () => { 5 | return { title: 'New Remix App' } 6 | } 7 | 8 | export default function App() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {process.env.NODE_ENV === 'development' && } 22 | 23 | 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/app/routes/anything.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from '@remix-run/react' 2 | import { cx } from '@twind/core' 3 | import { Suspense } from 'react' 4 | 5 | let fullfilled = false 6 | let promise: Promise | null = null 7 | 8 | const useTimeout = (ms: number) => { 9 | if (!fullfilled) { 10 | throw (promise ||= new Promise((res) => { 11 | setTimeout(() => { 12 | fullfilled = true 13 | res() 14 | }, ms) 15 | })) 16 | } 17 | } 18 | 19 | const linkClass = cx('transition-all duration-300 opacity-75 hover:(opacity-100 text-indigo-500)') 20 | 21 | const BackHome = () => { 22 | useTimeout(2000) 23 | return ( 24 | 25 | Back to Home 26 | 27 | ) 28 | } 29 | 30 | export default function Index() { 31 | return ( 32 |
33 |

This works

34 | 35 | 36 | 37 |
38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/app/twind.ts: -------------------------------------------------------------------------------- 1 | import install from '@twind/with-react' 2 | import config from '../twind.config' 3 | 4 | export default install(config) 5 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/with-remix_react-v18", 3 | "description": "remix with twind example", 4 | "version": "0.0.9", 5 | "private": true, 6 | "license": "MIT", 7 | "bugs": "https://github.com/tw-in-js/twind/issues", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/tw-in-js/twind.git", 11 | "directory": "examples/with-remix+react@18" 12 | }, 13 | "engines": { 14 | "node": ">=14" 15 | }, 16 | "sideEffetcs": false, 17 | "scripts": { 18 | "start": "npm run dev", 19 | "dev": "remix dev", 20 | "build": "remix build", 21 | "serve": "remix-serve build" 22 | }, 23 | "dependencies": { 24 | "@remix-run/node": "^1.8.2", 25 | "@remix-run/react": "^1.8.2", 26 | "@remix-run/serve": "^1.8.2", 27 | "@twind/core": "1.1.3", 28 | "@twind/preset-autoprefix": "1.0.7", 29 | "@twind/preset-tailwind": "1.1.4", 30 | "@twind/with-react": "1.1.3", 31 | "react": "^18.2.0", 32 | "react-dom": "^18.2.0", 33 | "remix": "^1.8.2" 34 | }, 35 | "devDependencies": { 36 | "@remix-run/dev": "^1.8.2", 37 | "@types/react": "^18.0.26", 38 | "@types/react-dom": "^18.0.9", 39 | "typescript": "^4.8.4" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/with-remix_react-v18/public/favicon.ico -------------------------------------------------------------------------------- /examples/with-remix_react-v18/remix.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | // ONLY REQUIRED WITHIN THE TWIND MONOREPO 3 | try { 4 | require('jiti/register') 5 | } catch { 6 | // IGNORE 7 | } 8 | 9 | /** 10 | * @type {import('@remix-run/dev/config').AppConfig} 11 | */ 12 | module.exports = { 13 | ignoredRouteFiles: ['**/.*'], 14 | appDirectory: 'app', 15 | assetsBuildDirectory: 'public/build', 16 | serverBuildPath: 'build/index.js', 17 | publicPath: '/build/', 18 | serverDependenciesToBundle: [ 19 | '@twind/core', 20 | '@twind/preset-autoprefix', 21 | '@twind/preset-tailwind', 22 | '@twind/with-react', 23 | ], 24 | } 25 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/remix.env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "lib": ["DOM", "DOM.Iterable", "ES2019"], 5 | "isolatedModules": true, 6 | "esModuleInterop": true, 7 | "jsx": "react-jsx", 8 | "moduleResolution": "node", 9 | "resolveJsonModule": true, 10 | "target": "ES2019", 11 | "strict": true, 12 | "baseUrl": ".", 13 | "paths": { 14 | "~/*": ["./app/*"] 15 | }, 16 | "noEmit": true, 17 | "allowJs": true, 18 | "forceConsistentCasingInFileNames": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/with-remix_react-v18/twind.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | export default defineConfig({ 6 | presets: [presetAutoprefix(), presetTailwind()], 7 | /* config */ 8 | }) 9 | -------------------------------------------------------------------------------- /examples/with-sveltekit/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/with-sveltekit/README.md: -------------------------------------------------------------------------------- 1 | # Example: Sveltekit 2 | 3 | > Try it live at [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/with-sveltekit) or [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/with-sveltekit). 4 | 5 | ## How does this work? 6 | 7 | 1. use twind in [src/routes/+layout.ts](./src/routes/+layout.svelte) 8 | 2. use [@twind/with-sveltekit](https://github.com/tw-in-js/twind/tree/main/packages/with-sveltekit) in [src/hooks.server.ts](./src/hooks.server.ts) to enable server-side rendering (SSR) of styles 9 | 3. (optional) a dedicated [src/twind.config](./src/twind.config.ts) 10 | 11 | ## What is included? 12 | 13 | - [sveltekit](https://www.npmjs.com/package/@sveltejs/kit) 14 | - [@twind/core](https://github.com/tw-in-js/twind/tree/main/packages/core) 15 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 16 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 17 | - [@twind/with-sveltekit](https://github.com/tw-in-js/twind/tree/main/packages/with-sveltekit) 18 | -------------------------------------------------------------------------------- /examples/with-sveltekit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/with-sveltekit", 3 | "description": "sveltekit with twind example", 4 | "version": "1.0.3", 5 | "private": true, 6 | "license": "MIT", 7 | "bugs": "https://github.com/tw-in-js/twind/issues", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/tw-in-js/twind.git", 11 | "directory": "examples/with-sveltekit" 12 | }, 13 | "engines": { 14 | "node": ">=14" 15 | }, 16 | "type": "module", 17 | "scripts": { 18 | "postinstall": "svelte-kit sync", 19 | "start": "npm run dev", 20 | "dev": "vite dev", 21 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 22 | "build": "vite build", 23 | "preview": "vite preview" 24 | }, 25 | "devDependencies": { 26 | "@sveltejs/adapter-node": "^1.0.0", 27 | "@sveltejs/kit": "^1.0.0", 28 | "@twind/core": "^1.1.3", 29 | "@twind/preset-autoprefix": "^1.0.7", 30 | "@twind/preset-tailwind": "^1.1.4", 31 | "@twind/with-sveltekit": "^1.1.3", 32 | "svelte": "^3.54.0", 33 | "svelte-check": "^2.10.2", 34 | "svelte-preprocess": "^4.10.7", 35 | "typescript": "~4.8.4", 36 | "vite": "^4.0.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/with-sveltekit/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | /// 5 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/hooks.server.js: -------------------------------------------------------------------------------- 1 | import handleTwind from '@twind/with-sveltekit/hooks' 2 | 3 | export const handle = handleTwind() 4 | 5 | /* If you have other handles use the `sequence` helper */ 6 | // import { sequence } from '@sveltejs/kit/hooks'; 7 | // export const handle = sequence(handleTwind(), ...otherHandles) 8 | 9 | /* Using a custom Twind instance */ 10 | // import { tw } from './custom/twind/instance' 11 | // export const handle = handleTwind({ tw }) 12 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/lib/twind.js: -------------------------------------------------------------------------------- 1 | // ensure any twind methods are called after twind has been installed 2 | 3 | import install from '@twind/with-sveltekit' 4 | import config from '../twind.config' 5 | 6 | export const tw = install(config, import.meta.env.PROD) 7 | export * from '@twind/core' 8 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/routes/+layout.js: -------------------------------------------------------------------------------- 1 | import '$lib/twind' 2 | 3 | // /** @type {import('./$types').LayoutLoad} */ 4 | // export function load() { 5 | // return { 6 | // // ... 7 | // }; 8 | // } 9 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 |
2 |

5 | Welcome to SvelteKit 6 |

7 |

8 | Visit kit.svelte.dev to read 9 | the documentation 10 |

11 |
12 | -------------------------------------------------------------------------------- /examples/with-sveltekit/src/twind.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | export default defineConfig({ 6 | presets: [presetAutoprefix(), presetTailwind()], 7 | /* config */ 8 | }) 9 | -------------------------------------------------------------------------------- /examples/with-sveltekit/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/with-sveltekit/static/favicon.ico -------------------------------------------------------------------------------- /examples/with-sveltekit/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-node' 2 | import preprocess from 'svelte-preprocess' 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | preprocess: preprocess(), 7 | 8 | kit: { 9 | adapter: adapter({ 10 | precompress: true, 11 | }), 12 | }, 13 | } 14 | 15 | export default config 16 | -------------------------------------------------------------------------------- /examples/with-sveltekit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /examples/with-sveltekit/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite' 2 | import type { UserConfig } from 'vite' 3 | 4 | const config: UserConfig = { 5 | plugins: [sveltekit()], 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /examples/with-web-components/.stackblitzrc: -------------------------------------------------------------------------------- 1 | { 2 | "installDependencies": true, 3 | "startCommand": "npm start" 4 | } 5 | -------------------------------------------------------------------------------- /examples/with-web-components/README.md: -------------------------------------------------------------------------------- 1 | # Example: Web Components 2 | 3 | > Try it live at [Stackblitz](https://stackblitz.com/fork/github/tw-in-js/twind/tree/main/examples/with-web-components) or [Codesandbox](https://githubbox.com/tw-in-js/twind/tree/main/examples/with-web-components). 4 | 5 | This example uses 6 | 7 | - [@twind/with-web-components](https://github.com/tw-in-js/twind/tree/main/packages/with-web-components) 8 | - [@twind/core](https://github.com/tw-in-js/twind/tree/main/packages/core) 9 | - [@twind/preset-autoprefix](https://github.com/tw-in-js/twind/tree/main/packages/preset-autoprefix) 10 | - [@twind/preset-tailwind](https://github.com/tw-in-js/twind/tree/main/packages/preset-tailwind) 11 | -------------------------------------------------------------------------------- /examples/with-web-components/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/examples/with-web-components/favicon.ico -------------------------------------------------------------------------------- /examples/with-web-components/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Using Web Components with Twind 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/with-web-components/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | 3 | import install from '@twind/with-web-components' 4 | import config from './twind.config' 5 | 6 | customElements.define( 7 | 'twind-element', 8 | class TwindElement extends install(config)(HTMLElement) { 9 | constructor() { 10 | super() 11 | 12 | const shadow = this.attachShadow({ mode: 'open' }) 13 | 14 | shadow.innerHTML = ` 15 |
16 |

17 | This is Twind! 18 |

19 |
20 | ` 21 | 22 | // shadow.innerHTML = ` 23 | //
24 | //

25 | // This is Twind! 26 | //

27 | //
28 | // ` 29 | } 30 | }, 31 | ) 32 | 33 | document.body.innerHTML = '' 34 | -------------------------------------------------------------------------------- /examples/with-web-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/with-web-components", 3 | "description": "Web Components example", 4 | "version": "1.0.8", 5 | "private": true, 6 | "main": "index.js", 7 | "license": "MIT", 8 | "bugs": "https://github.com/tw-in-js/twind/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tw-in-js/twind.git", 12 | "directory": "examples/with-web-components" 13 | }, 14 | "engines": { 15 | "node": ">=14" 16 | }, 17 | "type": "module", 18 | "scripts": { 19 | "start": "vite", 20 | "build": "vite build", 21 | "preview": "vite preview" 22 | }, 23 | "dependencies": { 24 | "@twind/core": "1.1.3", 25 | "@twind/preset-autoprefix": "1.0.7", 26 | "@twind/preset-tailwind": "1.1.4", 27 | "@twind/with-web-components": "1.1.3" 28 | }, 29 | "devDependencies": { 30 | "vite": "^4.0.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/with-web-components/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-web-components/twind.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@twind/core' 2 | import presetAutoprefix from '@twind/preset-autoprefix' 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | export default defineConfig({ 6 | presets: [presetAutoprefix(), presetTailwind()], 7 | /* config */ 8 | }) 9 | -------------------------------------------------------------------------------- /packages/README.md: -------------------------------------------------------------------------------- 1 | # Packages 2 | 3 | This folder contains all the packages that are published to npm. 4 | 5 | ## How to add a package 6 | 7 | - [ ] add folder and make sure it's a unique "name" field in `package.json` following these conventions: 8 | - for presets: `@twind/preset-` 9 | - for integrations: `@twind/with-` _except_ there is a specific naming convention like `-plugin-twind` 10 | - [ ] add to link in [`CHANGELOG.md`](../CHANGELOG.md) 11 | - [ ] add to `publishDirectory` in [`.codesandbox/ci.json`](../.codesandbox/ci.json) 12 | - [ ] add an example to [`examples`](../examples) 13 | - [ ] add a documentation page [`documentation/`](../documentation) with the following frontmatter: 14 | - for presets: `section: Presets` 15 | - for integrations: `section: Twind with` 16 | -------------------------------------------------------------------------------- /packages/cdn/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/src/alias.ts: -------------------------------------------------------------------------------- 1 | import type { Class, Nested } from './types' 2 | import { format } from './internal/format' 3 | import { parse } from './parse' 4 | import { interpolate } from './internal/interpolate' 5 | 6 | /** 7 | * @group Class Name Generators 8 | */ 9 | export const apply = /* #__PURE__ */ alias('@') 10 | 11 | /** 12 | * @group Class Name Generators 13 | */ 14 | export const shortcut = /* #__PURE__ */ alias('~') 15 | 16 | function alias(marker: string): Nested { 17 | return new Proxy( 18 | function alias(strings: TemplateStringsArray | Class, ...interpolations: Class[]): string { 19 | return alias$('', strings, interpolations) 20 | } as Nested, 21 | { 22 | get(target, name) { 23 | if (name in target) return target[name as string] 24 | 25 | return function namedAlias( 26 | strings: TemplateStringsArray | Class, 27 | ...interpolations: Class[] 28 | ): string { 29 | return alias$(name as string, strings, interpolations) 30 | } 31 | }, 32 | }, 33 | ) 34 | 35 | function alias$( 36 | name: string, 37 | strings: TemplateStringsArray | Class, 38 | interpolations: Class[], 39 | ): string { 40 | return format(parse(name + marker + '(' + interpolate(strings, interpolations) + ')')) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/core/src/css.ts: -------------------------------------------------------------------------------- 1 | import type { CSSObject, CSSValue } from './types' 2 | 3 | import { register } from './internal/registry' 4 | import { serialize } from './internal/serialize' 5 | import { hash } from './utils' 6 | import { Layer } from './internal/precedence' 7 | import { merge } from './internal/merge' 8 | import { astish } from './internal/astish' 9 | 10 | /** 11 | * @group Class Name Generators 12 | * @param strings 13 | * @param interpolations 14 | */ 15 | export function css(strings: TemplateStringsArray, ...interpolations: readonly CSSValue[]): string 16 | 17 | export function css(style: CSSObject | string): string 18 | 19 | export function css( 20 | strings: CSSObject | string | TemplateStringsArray, 21 | ...interpolations: readonly CSSValue[] 22 | ): string { 23 | const ast = astish(strings, interpolations) 24 | 25 | const className = (ast.find((o) => o.label)?.label || 'css') + hash(JSON.stringify(ast)) 26 | 27 | return register(className, (rule, context) => 28 | merge( 29 | ast.flatMap((css) => serialize(css, rule, context, Layer.o)), 30 | className, 31 | ), 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './alias' 2 | export * from './animation' 3 | export * from './autocomplete' 4 | export * from './colors' 5 | export * from './css' 6 | export * from './cx' 7 | export * from './define-config' 8 | export * from './inject-global' 9 | export * from './install' 10 | export * from './keyframes' 11 | export * from './observe' 12 | export * from './parse' 13 | export * from './rules' 14 | export * from './runtime' 15 | export * from './sheets' 16 | export * from './ssr' 17 | export * from './style' 18 | export * from './twind' 19 | export * from './tx' 20 | export * from './types' 21 | export * from './utils' 22 | -------------------------------------------------------------------------------- /packages/core/src/install.ts: -------------------------------------------------------------------------------- 1 | import type { Twind, BaseTheme, TwindConfig, TwindUserConfig, Preset, ExtractThemes } from './types' 2 | 3 | import { PROD } from 'distilt/env' 4 | 5 | import { defineConfig } from './define-config' 6 | import { setup } from './runtime' 7 | import { getSheet } from './sheets' 8 | 9 | /** 10 | * @group Runtime 11 | * @param config 12 | * @param isProduction 13 | */ 14 | export function install( 15 | config: TwindConfig, 16 | isProduction?: boolean, 17 | ): Twind 18 | 19 | export function install[] = Preset[]>( 20 | config: TwindUserConfig, 21 | isProduction?: boolean, 22 | ): Twind> 23 | 24 | export function install(config: TwindConfig | TwindUserConfig, isProduction = PROD): Twind { 25 | const config$ = defineConfig(config as TwindUserConfig) 26 | 27 | return setup( 28 | { 29 | ...config$, 30 | // in production use short hashed class names 31 | hash: config$.hash ?? isProduction, 32 | }, 33 | () => getSheet(!isProduction), 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /packages/core/src/internal/changed.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Determines if two class name strings contain the same classes. 3 | * 4 | * @param a first class names 5 | * @param b second class names 6 | * @returns are they different 7 | */ 8 | export function changed(a: string, b: string): boolean { 9 | return a != b && '' + a.split(' ').sort() != '' + b.split(' ').sort() 10 | } 11 | -------------------------------------------------------------------------------- /packages/core/src/internal/define.ts: -------------------------------------------------------------------------------- 1 | import type { Falsey } from '../types' 2 | import type { ParsedRule } from '../parse' 3 | import { convert } from './precedence' 4 | import { register } from './registry' 5 | import { translateWith } from './translate' 6 | 7 | export function define( 8 | className: string, 9 | layer: number, 10 | rules: Falsey | ParsedRule[], 11 | useOrderOfRules?: boolean, 12 | ): string { 13 | return register(className, (rule, context) => { 14 | const { n: name, p: precedence, r: conditions, i: important } = convert(rule, context, layer) 15 | 16 | return ( 17 | rules && 18 | translateWith( 19 | name as string, 20 | layer, 21 | rules, 22 | context, 23 | precedence, 24 | conditions, 25 | important, 26 | useOrderOfRules, 27 | ) 28 | ) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /packages/core/src/internal/format.ts: -------------------------------------------------------------------------------- 1 | import type { ParsedRule } from '../parse' 2 | import { toClassName } from './to-class-name' 3 | 4 | export function format(rules: ParsedRule[], seperator = ','): string { 5 | return rules.map(toClassName).join(seperator) 6 | } 7 | -------------------------------------------------------------------------------- /packages/core/src/internal/interleave.ts: -------------------------------------------------------------------------------- 1 | export function interleave( 2 | strings: TemplateStringsArray, 3 | interpolations: readonly Interpolations[], 4 | handle: (interpolation: Interpolations) => string, 5 | ): string { 6 | return interpolations.reduce( 7 | (result: string, interpolation, index) => result + handle(interpolation) + strings[index + 1], 8 | strings[0], 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /packages/core/src/internal/merge.ts: -------------------------------------------------------------------------------- 1 | import type { TwindRule } from '../types' 2 | 3 | export function merge(rules: TwindRule[], name: string): TwindRule[] { 4 | // merge: 5 | // - same conditions 6 | // - replace name with hash of name + condititions + declarations 7 | // - precedence: 8 | // - combine bits or use max precendence 9 | // - set layer bit to merged 10 | const result: TwindRule[] = [] 11 | 12 | let current: TwindRule | undefined 13 | 14 | for (const rule of rules) { 15 | // only merge rules with declarations and names (eg no global rules) 16 | if (!(rule.d && rule.n)) { 17 | result.push({ ...rule, n: rule.n && name }) 18 | } else if (current?.p == rule.p && '' + current.r == '' + rule.r) { 19 | current.c = [current.c, rule.c].filter(Boolean).join(' ') 20 | current.d = current.d + ';' + rule.d 21 | } else { 22 | // only set name for named rules eg not for global or className propagation rules 23 | result.push((current = { ...rule, n: rule.n && name })) 24 | } 25 | } 26 | 27 | return result 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/src/internal/registry.ts: -------------------------------------------------------------------------------- 1 | import type { BaseTheme, Context, Falsey, RuleResult, TwindRule } from '../types' 2 | import type { ParsedRule } from '../parse' 3 | 4 | const registry = new Map() 5 | 6 | export type RegisterCallback = (rule: ParsedRule, context: Context) => Falsey | TwindRule[] 7 | 8 | export function register(className: string, factory: RegisterCallback): string { 9 | registry.set(className, factory) 10 | return className 11 | } 12 | 13 | export function resolve( 14 | rule: ParsedRule, 15 | context: Context, 16 | ): RuleResult | TwindRule[] { 17 | const factory = registry.get(rule.n) 18 | 19 | return factory ? factory(rule, context as any) : context.r(rule.n, rule.v[0] == 'dark') 20 | } 21 | -------------------------------------------------------------------------------- /packages/core/src/internal/to-class-name.ts: -------------------------------------------------------------------------------- 1 | import type { ParsedRule } from '../parse' 2 | 3 | export function toClassName(rule: ParsedRule): string { 4 | return [...rule.v, (rule.i ? '!' : '') + rule.n].join(':') 5 | } 6 | -------------------------------------------------------------------------------- /packages/core/src/tests/alias.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test, afterEach } from 'vitest' 2 | 3 | import { twind, virtual, apply } from '..' 4 | 5 | const tw = twind({}, virtual()) 6 | 7 | afterEach(() => tw.clear()) 8 | 9 | test('alias proxy passthrough - func', () => { 10 | assert.strictEqual(apply.func('bg-red text-white'), 'func#g069dp') 11 | assert.strictEqual( 12 | apply.func.toString().replace(/[\s]/g, ''), 13 | `functionnamedAlias(strings,...interpolations){returnalias$(name,strings,interpolations);}`, 14 | ) 15 | }) 16 | 17 | test('alias proxy passthrough - bind', () => { 18 | assert.strictEqual(apply.bind(apply)('bg-red text-white'), '@(bg-red,text-white)') 19 | assert.strictEqual(apply.bind(apply).toString().replace(/[\s]/g, ''), 'function(){[nativecode]}') 20 | }) 21 | 22 | test('alias proxy passthrough - toString', () => { 23 | assert.strictEqual(apply('bg-red text-white'), '@(bg-red,text-white)') 24 | assert.strictEqual(apply.toString().replace(/[\s]/g, ''), 'function(){[nativecode]}') 25 | }) 26 | -------------------------------------------------------------------------------- /packages/core/src/tests/rules.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test, afterEach } from 'vitest' 2 | 3 | import { twind, virtual, css } from '..' 4 | 5 | const tw = twind( 6 | { 7 | rules: [ 8 | [ 9 | 'bg-', 10 | ({ $$ }) => 11 | css` 12 | background-color: ${$$}; 13 | `, 14 | ], 15 | ], 16 | }, 17 | virtual(), 18 | ) 19 | 20 | afterEach(() => tw.clear()) 21 | 22 | test('css in rule', () => { 23 | assert.strictEqual(tw('bg-red'), 'bg-red') 24 | 25 | assert.deepEqual(tw.target, ['.bg-red{background-color:red}']) 26 | }) 27 | -------------------------------------------------------------------------------- /packages/core/src/tests/sheet-cssom.test.ts: -------------------------------------------------------------------------------- 1 | // @vitest-environment happy-dom 2 | 3 | import { assert, test } from 'vitest' 4 | 5 | import { cssom, stringify } from '..' 6 | 7 | test('uses CSSOM', () => { 8 | // we need at least one node within head 9 | document.head.append(document.createTextNode('')) 10 | 11 | assert.lengthOf(document.styleSheets, 0) 12 | 13 | const sheet = cssom() 14 | 15 | // is already injected 16 | assert.lengthOf(document.styleSheets, 1) 17 | 18 | sheet.insert('*{}', 0, { p: 0, o: 0 }) 19 | 20 | assert.strictEqual(document.styleSheets[0], sheet.target) 21 | assert.strictEqual(stringify(sheet.target).replace(/ /g, ''), '*{}') 22 | }) 23 | -------------------------------------------------------------------------------- /packages/core/src/tests/sheet-dom.test.ts: -------------------------------------------------------------------------------- 1 | // @vitest-environment happy-dom 2 | 3 | import { assert, test } from 'vitest' 4 | 5 | import { dom, stringify } from '..' 6 | 7 | test('uses DOM nodes', () => { 8 | // we need at least one node within head 9 | document.head.append(document.createTextNode('')) 10 | 11 | assert.lengthOf(document.styleSheets, 0) 12 | 13 | const sheet = dom() 14 | 15 | // is already injected 16 | assert.lengthOf(document.styleSheets, 1) 17 | 18 | sheet.insert('*{}', 0, { p: 0, o: 0 }) 19 | 20 | assert.strictEqual(stringify(sheet.target), '*{}') 21 | }) 22 | -------------------------------------------------------------------------------- /packages/core/src/tests/twind.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test, afterEach } from 'vitest' 2 | 3 | import { twind, virtual } from '..' 4 | 5 | const tw = twind( 6 | { 7 | rules: [['bg-', 'background']], 8 | }, 9 | virtual(), 10 | ) 11 | 12 | afterEach(() => tw.clear()) 13 | 14 | test('the config can accessed', () => { 15 | assert.isFunction(tw.config.stringify) 16 | assert.deepEqual(tw.config, { 17 | preflight: [], 18 | darkMode: undefined, 19 | darkColor: undefined, 20 | theme: { extend: {} }, 21 | variants: [['dark', '@media (prefers-color-scheme:dark)']], 22 | rules: [['bg-', 'background']], 23 | ignorelist: [], 24 | hash: undefined, 25 | stringify: tw.config.stringify, 26 | finalize: [], 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/intellisense/src/enumerate.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from 'vitest' 2 | 3 | import presetTailwind from '@twind/preset-tailwind' 4 | 5 | import { createIntellisense } from '.' 6 | 7 | test('enumerate', () => { 8 | const intellisense = createIntellisense({ 9 | presets: [presetTailwind()], 10 | theme: { 11 | data: { 12 | checked: 'ui~="checked"', 13 | }, 14 | supports: { 15 | grid: 'display: grid', 16 | }, 17 | extend: { 18 | aria: { 19 | asc: 'sort="ascending"', 20 | desc: 'sort="descending"', 21 | }, 22 | }, 23 | }, 24 | }) 25 | 26 | expect(Array.from(intellisense.enumerate(), ({ name }) => name)).toMatchSnapshot() 27 | }) 28 | -------------------------------------------------------------------------------- /packages/intellisense/src/internal/adjust-rule-location.ts: -------------------------------------------------------------------------------- 1 | import type { ParsedDevRule } from '@twind/core' 2 | 3 | export function adjustRuleLocation( 4 | token: string, 5 | rule: ParsedDevRule, 6 | offset: number, 7 | ): { start: number; end: number } { 8 | let start = rule.l[0] 9 | const end = rule.l[1] 10 | let index = rule.a.length 11 | let value = rule.a[--index] 12 | 13 | while (index--) { 14 | const active = rule.a[index] 15 | 16 | if (active == '(' || active == '&' || /[~@]$/.test(active)) { 17 | break 18 | } 19 | 20 | value = active + value 21 | if (token.slice(start - active.length, end) === value) { 22 | start -= active.length 23 | } else { 24 | break 25 | } 26 | } 27 | 28 | return { 29 | start: offset + start, 30 | end: offset + end, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/intellisense/src/internal/color.ts: -------------------------------------------------------------------------------- 1 | import type { ColorInformation } from '../types' 2 | 3 | import QuickLRU from 'quick-lru' 4 | import { names as namedColors, TinyColor } from '@ctrl/tinycolor' 5 | 6 | const colorNames = Object.keys(namedColors) 7 | export const editabelColorRe = new RegExp( 8 | `-\\[(${colorNames.join('|')}|(?:(?:#|(?:(?:hsl|rgb)a?|hwb|lab|lch|color)\\())[^]\\(]+)\\]$`, 9 | 'i', 10 | ) 11 | 12 | const colorCache = new QuickLRU({ maxSize: 1000 }) 13 | 14 | export function parseColor(value: string): ColorInformation['rgba'] | null { 15 | let result = colorCache.get(value) 16 | 17 | if (!result) { 18 | const color = new TinyColor(value) 19 | 20 | colorCache.set(value, (result = color.isValid ? color.toRgb() : null)) 21 | } 22 | 23 | return result 24 | } 25 | -------------------------------------------------------------------------------- /packages/intellisense/src/internal/constants.ts: -------------------------------------------------------------------------------- 1 | export const VARIANT_MARKER_RULE = /^…$/ 2 | -------------------------------------------------------------------------------- /packages/intellisense/src/internal/spacify.ts: -------------------------------------------------------------------------------- 1 | export function spacify(value: string): string { 2 | return (value[0] === '-' ? '- ' : '') + value.replace(/[-\s]+/g, ' ') 3 | } 4 | -------------------------------------------------------------------------------- /packages/intellisense/src/internal/types.ts: -------------------------------------------------------------------------------- 1 | import type { AutocompleteItem, Twind } from '@twind/core' 2 | import type { SuggestionCommon, SuggestionVariant, SuggestionClass } from '../types' 3 | 4 | export interface IntellisenseCommon extends SuggestionCommon { 5 | source: string 6 | index: number 7 | position: number 8 | filter: string 9 | theme?: AutocompleteItem['theme'] 10 | } 11 | 12 | export interface IntellisenseVariant extends IntellisenseCommon, SuggestionVariant { 13 | modifiers?: IntellisenseVariant[] 14 | } 15 | 16 | export interface IntellisenseClass extends IntellisenseCommon, SuggestionClass { 17 | modifiers?: IntellisenseClass[] 18 | } 19 | 20 | export interface IntellisenseContext { 21 | tw: Twind 22 | variants: Map 23 | classes: Map 24 | suggestions: (IntellisenseVariant | IntellisenseClass)[] 25 | isIgnored: (className: string) => boolean 26 | generateCSS: (token: string) => string 27 | } 28 | 29 | export interface Boundary { 30 | start: number 31 | end: number 32 | content: string 33 | } 34 | -------------------------------------------------------------------------------- /packages/intellisense/src/modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'css-tree/parser' { 2 | export { parse as default } from 'css-tree' 3 | } 4 | 5 | declare module 'css-tree/walker' { 6 | export { walk as default } from 'css-tree' 7 | } 8 | 9 | declare module 'css-tree/generator' { 10 | export { generate as default } from 'css-tree' 11 | } 12 | -------------------------------------------------------------------------------- /packages/intellisense/src/suggest.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect, beforeAll } from 'vitest' 2 | 3 | import presetTailwind, { TailwindTheme } from '@twind/preset-tailwind' 4 | 5 | import { Intellisense, createIntellisense, Suggestion } from '.' 6 | 7 | let intellisense: Intellisense 8 | 9 | beforeAll(() => { 10 | intellisense = createIntellisense({ 11 | presets: [presetTailwind()], 12 | }) 13 | }) 14 | 15 | const $ = (suggestions: Promise) => 16 | suggestions.then((suggestions) => suggestions.map(({ value }) => value)) 17 | 18 | test('suggest with empty input', async () => { 19 | await expect(intellisense.suggest('')).resolves.toHaveLength(14733) 20 | }) 21 | 22 | test('suggest with single char input', async () => { 23 | await expect($(intellisense.suggest('u'))).resolves.toMatchSnapshot() 24 | }) 25 | 26 | test('suggest with two chars', async () => { 27 | await expect($(intellisense.suggest('ma'))).resolves.toMatchSnapshot() 28 | }) 29 | 30 | test('suggest negated', async () => { 31 | await expect($(intellisense.suggest('-mb'))).resolves.toMatchSnapshot() 32 | }) 33 | 34 | test('suggest when additional modifiers exist', async () => { 35 | await expect($(intellisense.suggest('shadow-zinc-700/'))).resolves.toMatchSnapshot() 36 | }) 37 | -------------------------------------------------------------------------------- /packages/intellisense/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-autoprefix/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-container-queries/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-ext/src/rules.ts: -------------------------------------------------------------------------------- 1 | import type { CSSObject, Rule } from '@twind/core' 2 | import { arbitrary } from '@twind/core' 3 | 4 | const rules: Rule[] = [ 5 | // short css feature that allows any css properties to be added 6 | // `background-color[#1da1f1]` -> `{ background-color: #1da1f1 }` 7 | // TODO arbitrary values 8 | // TODO $ prefix for variables 9 | [ 10 | /^([-\w]+\w)\[([^ ]+)]$/, 11 | ({ 1: $1, 2: $2 }, context) => 12 | ({ 13 | [$1]: arbitrary(`[${$2}]`, $1, context), 14 | } as CSSObject), 15 | ], 16 | ] 17 | 18 | export default rules 19 | -------------------------------------------------------------------------------- /packages/preset-ext/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-line-clamp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @twind/preset-radix-ui 2 | 3 | ## 1.0.7 4 | 5 | ## 1.0.6 6 | 7 | ### Patch Changes 8 | 9 | - do not replace window and document for deno bundles ([`5fd4bb08`](https://github.com/tw-in-js/twind/commit/5fd4bb082857c6f5504a23a641a2b61a33e7db88)) 10 | 11 | ## 1.0.5 12 | 13 | ### Patch Changes 14 | 15 | - create dedicated worker and deno bundles, and downgrade module to es2019 (fixes [#426](https://github.com/tw-in-js/twind/issues/426)) ([`02ea227a`](https://github.com/tw-in-js/twind/commit/02ea227afffe474cde5e843c3519f0836ee18f8a)) 16 | 17 | - bump @twind/core peerDependency to latest ([`a26657cf`](https://github.com/tw-in-js/twind/commit/a26657cf025aa7ad207372b30034d81417ad41c7)) 18 | 19 | ## 1.0.4 20 | 21 | ### Patch Changes 22 | 23 | - add radix-ui example to twind.run ([#419](https://github.com/tw-in-js/twind/pull/419)) 24 | 25 | - add radix ui preset ([#419](https://github.com/tw-in-js/twind/pull/419)) 26 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/colors.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-radix-ui/colors 2 | 3 | export * from './src/colors' 4 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/darkColor.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-radix-ui/darkColor 2 | 3 | export { default } from './src/darkColor' 4 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/defaultTheme.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-radix-ui/defaultTheme 2 | 3 | export { default } from './src/defaultTheme' 4 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/index.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) 2 | 3 | export { default } from './src/index' 4 | export * from './src/index' 5 | 6 | export * as colors from './src/colors' 7 | export * as darkColor from './src/darkColor' 8 | export * as defaultTheme from './src/defaultTheme' 9 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/src/darkColor.ts: -------------------------------------------------------------------------------- 1 | import type { BaseTheme, ColorValue, Context } from '@twind/core' 2 | 3 | export default function darkColor( 4 | section: string, 5 | key: string, 6 | { theme }: Context, 7 | ): ColorValue | undefined { 8 | return theme(section, key.replace(/^([a-z]+)($|[.-])/, '$1Dark$2')) as ColorValue 9 | } 10 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/src/defaultTheme.ts: -------------------------------------------------------------------------------- 1 | import * as colors from './colors' 2 | 3 | export default { colors } 4 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { Preset } from '@twind/core' 2 | 3 | import theme from './defaultTheme' 4 | import darkColor from './darkColor' 5 | 6 | export default function presetRadixUI(): Preset { 7 | return { theme, darkColor } 8 | } 9 | -------------------------------------------------------------------------------- /packages/preset-radix-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-tailwind-forms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-tailwind/base.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-tailwind/base 2 | 3 | export { default } from './src/base' 4 | export * from './src/base' 5 | -------------------------------------------------------------------------------- /packages/preset-tailwind/baseTheme.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-tailwind/baseTheme 2 | 3 | export { default } from './src/baseTheme' 4 | export * from './src/baseTheme' 5 | -------------------------------------------------------------------------------- /packages/preset-tailwind/colors.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-tailwind/colors 2 | 3 | export * from './src/colors' 4 | -------------------------------------------------------------------------------- /packages/preset-tailwind/defaultTheme.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-tailwind/defaultTheme 2 | 3 | export { default } from './src/defaultTheme' 4 | -------------------------------------------------------------------------------- /packages/preset-tailwind/index.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) 2 | 3 | export { default } from './src/index' 4 | export * from './src/index' 5 | 6 | export * as base from './src/base' 7 | export * as baseTheme from './src/baseTheme' 8 | export * as colors from './src/colors' 9 | export * as defaultTheme from './src/defaultTheme' 10 | export * as rules from './src/rules' 11 | export * as variants from './src/variants' 12 | -------------------------------------------------------------------------------- /packages/preset-tailwind/preflight.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/preset-tailwind/defaultTheme 2 | 3 | export { default } from './src/preflight' 4 | -------------------------------------------------------------------------------- /packages/preset-tailwind/src/defaultTheme.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @module @twind/preset-tailwind/defaultTheme 3 | */ 4 | 5 | import type { BaseTheme } from './baseTheme' 6 | 7 | import * as colors from './colors' 8 | 9 | import baseTheme from './baseTheme' 10 | 11 | export type DefaultTheme = { colors: typeof colors } & BaseTheme 12 | 13 | const theme: DefaultTheme = { ...baseTheme, colors } 14 | 15 | export default theme 16 | -------------------------------------------------------------------------------- /packages/preset-tailwind/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { Preset } from '@twind/core' 2 | import type { TailwindTheme } from './types' 3 | 4 | import presetTailwindBase from './base' 5 | import * as colors from './colors' 6 | 7 | export * from './types' 8 | 9 | export interface TailwindPresetOptions { 10 | /** Allows to disable to tailwind preflight (default: `false` eg include the tailwind preflight ) */ 11 | disablePreflight?: boolean | undefined 12 | } 13 | 14 | export default function presetTailwind({ 15 | disablePreflight, 16 | }: TailwindPresetOptions = {}): Preset { 17 | return presetTailwindBase({ colors, disablePreflight }) 18 | } 19 | -------------------------------------------------------------------------------- /packages/preset-tailwind/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-typography/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/twind/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twind", 3 | "version": "1.0.7", 4 | "description": "Proxy package for @twind/core", 5 | "keywords": [ 6 | "twind", 7 | "tailwind", 8 | "tailwindcss", 9 | "tw-in-js", 10 | "tailwind-in-js" 11 | ], 12 | "type": "module", 13 | "// The 'module', 'unpkg' and 'types' fields are added by distilt": "", 14 | "main": "src/index.ts", 15 | "// Each entry is expanded into several bundles (types, esnext, module, script, node, and default)": "", 16 | "exports": { 17 | ".": "./src/index.ts", 18 | "./package.json": "./package.json" 19 | }, 20 | "// These are relative from within the dist/ folder": "", 21 | "sideEffects": false, 22 | "dependencies": { 23 | "@twind/core": "^1.1.3" 24 | }, 25 | "peerDependencies": { 26 | "typescript": "^4.8.4" 27 | }, 28 | "peerDependenciesMeta": { 29 | "typescript": { 30 | "optional": true 31 | } 32 | }, 33 | "devDependencies": { 34 | "typescript": "^4.8.4" 35 | }, 36 | "scripts": { 37 | "build": "distilt" 38 | }, 39 | "publishConfig": { 40 | "access": "public", 41 | "directory": "dist" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/twind/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@twind/core' 2 | -------------------------------------------------------------------------------- /packages/twind/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/with-gatsby/index.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) 2 | 3 | export {} 4 | 5 | // export * as browser from './src/gatsby-browser' 6 | // export * as node from './src/gatsby-node' 7 | // export * as ssr from './src/gatsby-ssr' 8 | -------------------------------------------------------------------------------- /packages/with-gatsby/src/config.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'gatsby-plugin-twind/config' { 2 | const config: import('twind').TwindConfig 3 | export default config 4 | } 5 | -------------------------------------------------------------------------------- /packages/with-gatsby/src/gatsby-browser.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | 3 | import install from './install-twind' 4 | install() 5 | -------------------------------------------------------------------------------- /packages/with-gatsby/src/gatsby-node.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | import type { PluginOptionsSchemaArgs, CreateWebpackConfigArgs } from 'gatsby' 3 | 4 | import { resolve } from 'path' 5 | 6 | export function pluginOptionsSchema({ 7 | Joi, 8 | }: PluginOptionsSchemaArgs): ReturnType { 9 | return Joi.object({ 10 | config: Joi.string().default('twind.config.js').description(`Path to twind config module.`), 11 | }) 12 | } 13 | 14 | export function onCreateWebpackConfig( 15 | { actions }: CreateWebpackConfigArgs, 16 | { config = 'twind.config.js' }: { config?: string }, 17 | ): void { 18 | actions.setWebpackConfig({ 19 | resolve: { 20 | alias: { 21 | 'gatsby-plugin-twind/config$': resolve(process.cwd(), config), 22 | }, 23 | }, 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /packages/with-gatsby/src/gatsby-ssr.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | import type { ReactElement } from 'react' 4 | import type { ReplaceRendererArgs } from 'gatsby' 5 | 6 | import { renderToString } from 'react-dom/server' 7 | import { createElement } from 'react' 8 | import { extract } from '@twind/core' 9 | 10 | import install from './install-twind' 11 | install() 12 | 13 | export function replaceRenderer({ 14 | bodyComponent, 15 | replaceBodyHTMLString, 16 | setHeadComponents, 17 | }: ReplaceRendererArgs): void { 18 | const bodyHTML = renderToString(bodyComponent as ReactElement) 19 | const { html, css } = extract(bodyHTML) 20 | 21 | replaceBodyHTMLString(html) 22 | setHeadComponents([ 23 | // 24 | createElement('style', { 25 | 'data-twind': true, 26 | dangerouslySetInnerHTML: { 27 | __html: css, 28 | }, 29 | }), 30 | ]) 31 | } 32 | -------------------------------------------------------------------------------- /packages/with-gatsby/src/index.ts: -------------------------------------------------------------------------------- 1 | // nope 2 | export {} 3 | -------------------------------------------------------------------------------- /packages/with-gatsby/src/install-twind.ts: -------------------------------------------------------------------------------- 1 | import { install as install$ } from '@twind/core' 2 | 3 | import config from 'gatsby-plugin-twind/config' 4 | 5 | export default function install() { 6 | return install$(config, process.env.NODE_ENV == 'production') 7 | } 8 | -------------------------------------------------------------------------------- /packages/with-gatsby/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./index.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/with-next/app.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/with-next/app 2 | 3 | export { default } from './src/app' 4 | export * from './src/app' 5 | -------------------------------------------------------------------------------- /packages/with-next/document.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/with-next/document 2 | 3 | export { default } from './src/document' 4 | export * from './src/document' 5 | -------------------------------------------------------------------------------- /packages/with-next/index.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) 2 | 3 | export * as app from './src/app' 4 | export * as document from './src/document' 5 | -------------------------------------------------------------------------------- /packages/with-next/src/app.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env node, browser */ 2 | import type { ComponentType } from 'react' 3 | import type { AppProps } from 'next/app' 4 | import type { TwindConfig, TwindUserConfig } from '@twind/core' 5 | 6 | import { createElement } from 'react' 7 | import { install as install$ } from '@twind/core' 8 | 9 | export default install 10 | 11 | function install( 12 | config: TwindConfig | TwindUserConfig, 13 | ): React.JSXElementConstructor 14 | 15 | function install( 16 | config: TwindConfig | TwindUserConfig, 17 | AppComponent: React.JSXElementConstructor & Component, 18 | isProduction?: boolean, 19 | ): Component 20 | 21 | function install( 22 | config: TwindConfig | TwindUserConfig, 23 | AppComponent: React.JSXElementConstructor & Component = TwindApp as any, 24 | isProduction = process.env.NODE_ENV == 'production', 25 | ): Component { 26 | install$(config as TwindUserConfig, isProduction) 27 | 28 | return AppComponent 29 | } 30 | 31 | function TwindApp(props: AppProps) { 32 | return createElement(props.Component as ComponentType, props.pageProps) 33 | } 34 | -------------------------------------------------------------------------------- /packages/with-next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/with-react/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @twind/with-react 2 | 3 | ## 1.1.3 4 | 5 | ## 1.1.2 6 | 7 | ### Patch Changes 8 | 9 | - do not replace window and document for deno bundles ([`5fd4bb08`](https://github.com/tw-in-js/twind/commit/5fd4bb082857c6f5504a23a641a2b61a33e7db88)) 10 | 11 | ## 1.1.1 12 | 13 | ### Patch Changes 14 | 15 | - create dedicated worker and deno bundles, and downgrade module to es2019 (fixes [#426](https://github.com/tw-in-js/twind/issues/426)) ([`02ea227a`](https://github.com/tw-in-js/twind/commit/02ea227afffe474cde5e843c3519f0836ee18f8a)) 16 | 17 | - add `@twind/with-react` package with support for React v18 streamed responses (fixes [#409](https://github.com/tw-in-js/twind/issues/409)) ([`6521e678`](https://github.com/tw-in-js/twind/commit/6521e678821f05de8cd3a87b0176083efee43405)) 18 | 19 | - the `@twind/with-remix` package is deprecated in favor of the `@twind/with-react` package 20 | - added a Remix with React v18 and [renderToPipeableStream](https://reactjs.org/docs/react-dom-server.html#rendertopipeablestream) example: [examples/with-remix_react-v18](https://github.com/tw-in-js/twind/tree/main/examples/with-remix_react-v18) (related to #400 & #408) 21 | -------------------------------------------------------------------------------- /packages/with-react/index.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) 2 | 3 | export { default } from './src/index' 4 | export * from './src/index' 5 | 6 | export * as inline from './src/inline' 7 | export * as pipeableStream from './src/pipeableStream' 8 | export * as readableStream from './src/readableStream' 9 | -------------------------------------------------------------------------------- /packages/with-react/inline.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/with-react/pipeable-stream 2 | 3 | export { default } from './src/inline' 4 | export * from './src/inline' 5 | -------------------------------------------------------------------------------- /packages/with-react/pipeableStream.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/with-react/pipeable-stream 2 | 3 | export { default } from './src/pipeableStream' 4 | export * from './src/pipeableStream' 5 | -------------------------------------------------------------------------------- /packages/with-react/readableStream.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/with-react/pipeable-stream 2 | 3 | export { default } from './src/pipeableStream' 4 | export * from './src/pipeableStream' 5 | -------------------------------------------------------------------------------- /packages/with-react/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | Twind, 3 | BaseTheme, 4 | TwindConfig, 5 | TwindUserConfig, 6 | Preset, 7 | ExtractThemes, 8 | } from '@twind/core' 9 | 10 | import { install as install$ } from '@twind/core' 11 | 12 | export default install 13 | 14 | function install( 15 | config: TwindConfig, 16 | isProduction?: boolean, 17 | ): Twind 18 | 19 | function install[] = Preset[]>( 20 | config: TwindUserConfig, 21 | isProduction?: boolean, 22 | ): Twind> 23 | 24 | function install( 25 | config: TwindConfig | TwindUserConfig, 26 | isProduction = process.env.NODE_ENV == 'production', 27 | ): Twind { 28 | return install$(config as TwindConfig, isProduction) 29 | } 30 | -------------------------------------------------------------------------------- /packages/with-react/src/inline.ts: -------------------------------------------------------------------------------- 1 | export { inline as default } from '@twind/core' 2 | 3 | export type { InlineOptions, InlineMinify } from '@twind/core' 4 | -------------------------------------------------------------------------------- /packages/with-react/src/modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-dom/server.browser' { 2 | export * from 'react-dom/server' 3 | } 4 | 5 | declare module 'react-dom/server.node' { 6 | export * from 'react-dom/server' 7 | } 8 | -------------------------------------------------------------------------------- /packages/with-react/src/pipeableStream.ts: -------------------------------------------------------------------------------- 1 | import { Transform } from 'node:stream' 2 | 3 | import type { InlineOptions, InlineMinify } from '@twind/core' 4 | 5 | import { createState } from './internal' 6 | 7 | export type { InlineOptions, InlineMinify } 8 | 9 | export default class InlineStream extends Transform { 10 | constructor(options?: InlineOptions['tw'] | InlineOptions) { 11 | const state = createState(options) 12 | 13 | super({ 14 | transform(chunk: Buffer, encoding, callback) { 15 | if (state.push(chunk.toString())) { 16 | this._flush(callback) 17 | } else { 18 | callback() 19 | } 20 | }, 21 | flush(callback) { 22 | const markup = state.flush() 23 | if (markup) { 24 | this.push(markup) 25 | } 26 | callback() 27 | }, 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/with-react/src/readableStream.ts: -------------------------------------------------------------------------------- 1 | import type { InlineOptions, InlineMinify } from '@twind/core' 2 | 3 | import { createState } from './internal' 4 | 5 | export type { InlineOptions, InlineMinify } 6 | 7 | const encoder = /* #__PURE__ */ new TextEncoder() 8 | const decoder = /* #__PURE__ */ new TextDecoder() 9 | 10 | export default class InlineStream extends TransformStream { 11 | constructor(options?: InlineOptions['tw'] | InlineOptions) { 12 | const state = createState(options) 13 | 14 | const flush: TransformerFlushCallback = (controller) => { 15 | const markup = state.flush() 16 | if (markup) { 17 | controller.enqueue(encoder.encode(markup)) 18 | } 19 | } 20 | 21 | super({ 22 | transform(chunk, controller) { 23 | if (state.push(decoder.decode(chunk))) { 24 | return flush(controller) 25 | } 26 | }, 27 | flush, 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/with-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "importsNotUsedAsValues": "preserve" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/with-remix/index.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) 2 | 3 | export { default } from './src/index' 4 | export * from './src/index' 5 | 6 | export * as server from './src/server' 7 | -------------------------------------------------------------------------------- /packages/with-remix/server.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/with-remix/server 2 | 3 | export { default } from './src/server' 4 | export * from './src/server' 5 | -------------------------------------------------------------------------------- /packages/with-remix/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | Twind, 3 | BaseTheme, 4 | TwindConfig, 5 | TwindUserConfig, 6 | Preset, 7 | ExtractThemes, 8 | } from '@twind/core' 9 | 10 | import { install as install$ } from '@twind/core' 11 | 12 | export default install 13 | 14 | function install( 15 | config: TwindConfig, 16 | isProduction?: boolean, 17 | ): Twind 18 | 19 | function install[] = Preset[]>( 20 | config: TwindUserConfig, 21 | isProduction?: boolean, 22 | ): Twind> 23 | 24 | function install( 25 | config: TwindConfig | TwindUserConfig, 26 | isProduction = process.env.NODE_ENV == 'production', 27 | ): Twind { 28 | return install$(config as TwindConfig, isProduction) 29 | } 30 | -------------------------------------------------------------------------------- /packages/with-remix/src/server.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | export { inline as default } from '@twind/core' 4 | 5 | export type { InlineOptions, InlineMinify } from '@twind/core' 6 | -------------------------------------------------------------------------------- /packages/with-remix/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/with-sveltekit/hooks.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPESCRIPT TO FIND @twind/with-sveltekit/hooks 2 | 3 | export { default } from './src/hooks' 4 | -------------------------------------------------------------------------------- /packages/with-sveltekit/index.d.ts: -------------------------------------------------------------------------------- 1 | // ONLY FOR TYPEDOC TO FIND the exports (https://github.com/TypeStrong/typedoc/issues/1937) 2 | 3 | export { default } from './src/index' 4 | export * from './src/index' 5 | 6 | export * as hooks from './src/hooks' 7 | -------------------------------------------------------------------------------- /packages/with-sveltekit/src/hooks.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit' 2 | 3 | import type { InlineOptions } from '@twind/core' 4 | 5 | import { inline } from '@twind/core' 6 | 7 | export type { InlineOptions } 8 | 9 | export default function handleTwind(options: InlineOptions['tw'] | InlineOptions = {}): Handle { 10 | return async function handleTwind$({ event, resolve }) { 11 | return resolve(event, { 12 | transformPageChunk: ({ html, done }) => (done ? inline(html, options) : html), 13 | }) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/with-sveltekit/src/index.ts: -------------------------------------------------------------------------------- 1 | export { install as default } from '@twind/core' 2 | -------------------------------------------------------------------------------- /packages/with-sveltekit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/with-web-components/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @twind/with-web-components 2 | 3 | ## 1.1.3 4 | 5 | ## 1.1.2 6 | 7 | ### Patch Changes 8 | 9 | - do not replace window and document for deno bundles ([`5fd4bb08`](https://github.com/tw-in-js/twind/commit/5fd4bb082857c6f5504a23a641a2b61a33e7db88)) 10 | 11 | ## 1.1.1 12 | 13 | ### Patch Changes 14 | 15 | - create dedicated worker and deno bundles, and downgrade module to es2019 (fixes [#426](https://github.com/tw-in-js/twind/issues/426)) ([`02ea227a`](https://github.com/tw-in-js/twind/commit/02ea227afffe474cde5e843c3519f0836ee18f8a)) 16 | 17 | - bump @twind/core peerDependency to latest ([`a26657cf`](https://github.com/tw-in-js/twind/commit/a26657cf025aa7ad207372b30034d81417ad41c7)) 18 | 19 | ## 1.1.0 20 | 21 | ### Minor Changes 22 | 23 | - add new web components integration ([`c64fb457`](https://github.com/tw-in-js/twind/commit/c64fb4577267b5e339ae86d5f96179fdf764465b)) 24 | -------------------------------------------------------------------------------- /packages/with-web-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@twind/with-web-components", 3 | "version": "1.1.3", 4 | "description": "Seamless integration of Twind with Web Components", 5 | "publishConfig": { 6 | "access": "public", 7 | "directory": "dist" 8 | }, 9 | "keywords": [ 10 | "twind", 11 | "twind-with", 12 | "tailwind", 13 | "tailwindcss", 14 | "tw-in-js", 15 | "tailwind-in-js", 16 | "web-components" 17 | ], 18 | "type": "module", 19 | "// The 'module', 'unpkg' and 'types' fields are added by distilt": "", 20 | "main": "src/index.ts", 21 | "// Each entry is expanded into several bundles (types, esnext, module, script, node, and default)": "", 22 | "exports": { 23 | ".": "./src/index.ts", 24 | "./package.json": "./package.json" 25 | }, 26 | "// These are relative from within the dist/ folder": "", 27 | "sideEffects": false, 28 | "peerDependencies": { 29 | "@twind/core": "^1.1.0", 30 | "typescript": "^4.8.4" 31 | }, 32 | "peerDependenciesMeta": { 33 | "typescript": { 34 | "optional": true 35 | } 36 | }, 37 | "devDependencies": { 38 | "@twind/core": "^1.1.3", 39 | "typescript": "^4.8.4" 40 | }, 41 | "scripts": { 42 | "build": "distilt" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/with-web-components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["./src", "./*.d.ts"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /patches/@jsenv__importmap@1.2.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/package.json b/package.json 2 | index 8618f4e5b739f44d89681b8e5415ddd269222861..5a7029c0bd6503b68bdc94362663b9cdf27856fd 100644 3 | --- a/package.json 4 | +++ b/package.json 5 | @@ -15,10 +15,7 @@ 6 | }, 7 | "type": "module", 8 | "exports": { 9 | - ".": { 10 | - "import": "./main.js", 11 | - "require": "./dist/commonjs/jsenv_importmap.cjs" 12 | - }, 13 | + ".": "./main.js", 14 | "./*": "./*" 15 | }, 16 | "main": "./dist/commonjs/jsenv_importmap.cjs", -------------------------------------------------------------------------------- /patches/@jsenv__logger@4.1.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/package.json b/package.json 2 | index 5395f77460c0d7aad353c4d77632f44b3c920887..3802d2572f8a734a42e6ee1839909e2a086661a6 100644 3 | --- a/package.json 4 | +++ b/package.json 5 | @@ -20,12 +20,7 @@ 6 | }, 7 | "type": "module", 8 | "exports": { 9 | - ".": { 10 | - "require": "./dist/commonjs/jsenv_logger.cjs", 11 | - "browser": "./main.browser.js", 12 | - "node": "./main.node.js", 13 | - "import": "./main.node.js" 14 | - }, 15 | + ".": "./main.shared.js", 16 | "./*": "./*" 17 | }, 18 | "files": [ -------------------------------------------------------------------------------- /patches/monaco-editor@0.34.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/esm/vs/language/typescript/ts.worker.js b/esm/vs/language/typescript/ts.worker.js 2 | index d3285d4dc35229d5b556f489ad12d2df13c3c914..784f2cc89eec80c77decd83c04165f143fef8718 100644 3 | --- a/esm/vs/language/typescript/ts.worker.js 4 | +++ b/esm/vs/language/typescript/ts.worker.js 5 | @@ -5472,7 +5472,7 @@ var ts; 6 | ts2.getNormalizedAbsolutePathWithoutRoot = getNormalizedAbsolutePathWithoutRoot; 7 | function toPath(fileName, basePath, getCanonicalFileName) { 8 | var nonCanonicalizedPath = isRootedDiskPath(fileName) ? normalizePath(fileName) : getNormalizedAbsolutePath(fileName, basePath); 9 | - return getCanonicalFileName(nonCanonicalizedPath); 10 | + return getCanonicalFileName(decodeURIComponent(nonCanonicalizedPath)); 11 | } 12 | ts2.toPath = toPath; 13 | function normalizePathAndParts(path) { -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - examples/* 3 | - packages/* 4 | - sites/* 5 | - scripts 6 | -------------------------------------------------------------------------------- /sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "// https://github.com/codesandbox/codesandbox-importers/blob/master/packages/types/index.d.ts#L39-L64": "", 3 | "template": "node", 4 | "container": { 5 | "node": "16" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scripts", 3 | "version": "1.0.0-next.39", 4 | "private": true, 5 | "scripts": { 6 | "sponsors": "sponsorkit" 7 | }, 8 | "license": "ISC", 9 | "devDependencies": { 10 | "sponsorkit": "^0.6.1" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /sites/cdn.twind.style/README.md: -------------------------------------------------------------------------------- 1 | # cdn.twind.style 2 | 3 | This is the [Twind CDN](https://twind.style/installation#twind-cdn). 4 | 5 | ## Developing 6 | 7 | Once you've [set up the repo](../../CONTRIBUTING.md), `cd` into this directory and start the dev server: 8 | 9 | ```bash 10 | cd sites/twind.run 11 | pnpm start 12 | ``` 13 | -------------------------------------------------------------------------------- /sites/cdn.twind.style/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sites/cdn.twind.style", 3 | "version": "1.0.5", 4 | "description": "Twind CDN", 5 | "private": true, 6 | "license": "MIT", 7 | "homepage": "https://cdn.twind.style", 8 | "bugs": "https://github.com/tw-in-js/twind/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tw-in-js/twind.git", 12 | "directory": "sites/cdn.twind.style" 13 | }, 14 | "type": "module", 15 | "engines": { 16 | "node": ">=18.12.0" 17 | }, 18 | "scripts": { 19 | "start": "wrangler dev", 20 | "deploy": "wrangler publish" 21 | }, 22 | "devDependencies": { 23 | "@cloudflare/workers-types": "^3.18.0", 24 | "typescript": "~4.8.4", 25 | "wrangler": "^2.2.1" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sites/cdn.twind.style/wrangler.toml: -------------------------------------------------------------------------------- 1 | # https://developers.cloudflare.com/workers/wrangler/ci-cd/ 2 | # npx wrangler publlish 3 | 4 | name = "cdn-twind-style" 5 | type = "javascript" 6 | main = "src/index.ts" 7 | workers_dev = true 8 | 9 | # https://developers.cloudflare.com/workers/platform/compatibility-dates/ 10 | compatibility_date = "2022-11-11" 11 | 12 | # Also opt into an upcoming fix to the FormData API. 13 | compatibility_flags = [ "transformstream_enable_standard_constructor", "streams_enable_constructors" ] 14 | 15 | [vars] 16 | # https://developers.cloudflare.com/pages/platform/build-configuration/#language-support-and-tools 17 | NODE_VERSION = "16" 18 | -------------------------------------------------------------------------------- /sites/mdn.twind.run/README.md: -------------------------------------------------------------------------------- 1 | # cdn.twind.style 2 | 3 | This is the [Twind CDN](https://twind.style/installation#twind-cdn). 4 | 5 | ## Developing 6 | 7 | Once you've [set up the repo](../../CONTRIBUTING.md), `cd` into this directory and start the dev server: 8 | 9 | ```bash 10 | cd sites/twind.run 11 | pnpm start 12 | ``` 13 | -------------------------------------------------------------------------------- /sites/mdn.twind.run/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sites/mdn.twind.run", 3 | "version": "1.1.1", 4 | "description": "MDn proxy for twind.run CDN", 5 | "private": true, 6 | "license": "MIT", 7 | "homepage": "https://mdn.twind.run", 8 | "bugs": "https://github.com/tw-in-js/twind/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/tw-in-js/twind.git", 12 | "directory": "sites/mdn.twind.run" 13 | }, 14 | "type": "module", 15 | "engines": { 16 | "node": ">=18.12.0" 17 | }, 18 | "scripts": { 19 | "start": "wrangler dev", 20 | "deploy": "wrangler publish" 21 | }, 22 | "devDependencies": { 23 | "@cloudflare/workers-types": "^3.18.0", 24 | "typescript": "~4.8.4", 25 | "wrangler": "^2.2.1" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sites/mdn.twind.run/wrangler.toml: -------------------------------------------------------------------------------- 1 | # https://developers.cloudflare.com/workers/wrangler/ci-cd/ 2 | # npx wrangler publlish 3 | 4 | name = "mdn-twind-run" 5 | type = "javascript" 6 | main = "src/index.ts" 7 | workers_dev = true 8 | 9 | # https://developers.cloudflare.com/workers/platform/compatibility-dates/ 10 | compatibility_date = "2022-11-11" 11 | 12 | # Also opt into an upcoming fix to the FormData API. 13 | compatibility_flags = [ "transformstream_enable_standard_constructor", "streams_enable_constructors" ] 14 | 15 | [vars] 16 | # https://developers.cloudflare.com/pages/platform/build-configuration/#language-support-and-tools 17 | NODE_VERSION = "16" 18 | -------------------------------------------------------------------------------- /sites/twind.run/.env: -------------------------------------------------------------------------------- 1 | PUBLIC_TURNSTILE_SITE="1x00000000000000000000AA" # Always passes 2 | #PUBLIC_TURNSTILE_SITE="2x00000000000000000000AB" # Always blocks 3 | #PUBLIC_TURNSTILE_SITE="3x00000000000000000000FF" # Forces an interactive challenge 4 | 5 | TURNSTILE_SECRET="1x0000000000000000000000000000000AA" # Always passes 6 | #TURNSTILE_SECRET="2x0000000000000000000000000000000AA" # Always blocks 7 | #TURNSTILE_SECRET="3x0000000000000000000000000000000AA" # Yields a “token already spent” error 8 | -------------------------------------------------------------------------------- /sites/twind.run/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/sites/twind.run/src/lib/assets/favicon.ico -------------------------------------------------------------------------------- /sites/twind.run/src/lib/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/sites/twind.run/src/lib/assets/icon.png -------------------------------------------------------------------------------- /sites/twind.run/src/lib/assets/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/icons/heroicons/index.js: -------------------------------------------------------------------------------- 1 | export * from './outline' 2 | export * from './solid' 3 | export * from './mini' 4 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/icons/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './icon.svelte' 2 | 3 | export * from './bootstrap' 4 | export * from './fluent-solid' 5 | export * from './octicons' 6 | export * from './heroicons' 7 | export * from './loading' 8 | export * from './twind' 9 | 10 | export * from './types' 11 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/icons/twind.js: -------------------------------------------------------------------------------- 1 | /** 2 | * **twind logo** 3 | * 4 | * @type {import('./types').IconSource} 5 | */ 6 | export const TwindLogo = /* @__PURE__ */ JSON.parse( 7 | '{"viewbox":"0 0 176.99 163.4","circles":[{"fill":"#f5f5f5","cx":"95.31","cy":"81.67","r":"81.67"}],"lines":[{"fill":"none","stroke":"#000","stroke-linecap":"round","stroke-width":"6px","x1":"139.75","y1":"33.48","x2":"139.75","y2":"160.4"},{"fill":"none","stroke":"#000","stroke-width":"5px","x1":"114.36","y1":"77.15","x2":"140.42","y2":"44.76"},{"fill":"none","stroke":"#000","stroke-width":"5px","x1":"102.63","y1":"47.45","x2":"140.57","y2":"45.44"}],"paths":[{"stroke":"#000","fill":"#80cbc4","stroke-width":"5px","stroke-linecap":"round","d":"M12.14,107.09,101.07,55s13.3,9.74,19.6,25.14a73.21,73.21,0,0,1,5.17,30L28.63,144.73s-10.77-7.93-14-15.43S12.14,107.09,12.14,107.09Z","transform":"translate(-9.57 -18.17)"},{"stroke":"#000","stroke-width":"4px","fill":"#ee999c","d":"M55.8,134.93,37,92.54l14-8.29,19.12,45.26Z","transform":"translate(-9.57 -18.17)"},{"stroke":"#000","stroke-width":"4px","fill":"#ee999c","d":"M70.84,129.93,51,85.19l14.8-8.75L86,124.21Z","transform":"translate(-9.57 -18.17)"}]}', 8 | ) 9 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/icons/types.ts: -------------------------------------------------------------------------------- 1 | export interface IconSource { 2 | viewbox?: string 3 | fill?: string 4 | stroke?: string 5 | paths?: Record[] 6 | rects?: Record[] 7 | circles?: Record[] 8 | polygons?: Record[] 9 | lines?: Record[] 10 | } 11 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/intellisense.worker.ts: -------------------------------------------------------------------------------- 1 | import * as Comlink from 'comlink' 2 | import api from './intellisense.api' 3 | 4 | Comlink.expose(api) 5 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/prettier.worker.ts: -------------------------------------------------------------------------------- 1 | import * as Comlink from 'comlink' 2 | import api from './prettier.api' 3 | 4 | Comlink.expose(api) 5 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/stores/index.ts: -------------------------------------------------------------------------------- 1 | export * from './match-media-query' 2 | export * from './matches-media-query' 3 | export * from './mounted' 4 | export * from './on' 5 | export * from './reduced-motion' 6 | export * from './storage' 7 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/stores/match-media-query.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { readable } from 'svelte/store' 3 | import { on } from './on' 4 | 5 | export interface MediaQueryStoreValue { 6 | readonly matches: boolean 7 | readonly media: string 8 | } 9 | 10 | export function matchMediaQuery(query: string): Readable { 11 | return typeof matchMedia == 'undefined' 12 | ? readable({ matches: false, media: query }) 13 | : on(matchMedia(query), 'change') 14 | } 15 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/stores/matches-media-query.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { derived } from 'svelte/store' 3 | import { matchMediaQuery } from './match-media-query' 4 | 5 | export function matchesMediaQuery(query: string): Readable { 6 | return derived(matchMediaQuery(query), (match) => match.matches) 7 | } 8 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/stores/mounted.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { onMount } from 'svelte' 3 | import { noop } from 'svelte/internal' 4 | 5 | export const mounted: Readable = { 6 | subscribe(set) { 7 | set(false) 8 | onMount(() => { 9 | set(true) 10 | return () => set(false) 11 | }) 12 | return noop 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/stores/on.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { readable } from 'svelte/store' 3 | 4 | export interface EventSource { 5 | addEventListener(event: Event, listener: (value: Value) => void): void 6 | removeEventListener(event: Event, listener: (value: Value) => void): void 7 | } 8 | 9 | export function on( 10 | source: StoreValue & EventSource, 11 | event: Event, 12 | ): Readable 13 | 14 | export function on( 15 | source: EventSource, 16 | event: Event, 17 | initialValue: StoreValue, 18 | ): Readable 19 | 20 | export function on(source: EventSource, event: string, initialValue = source) { 21 | return readable(initialValue, (set) => { 22 | source.addEventListener(event, set) 23 | 24 | return () => source.removeEventListener(event, set) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/stores/reduced-motion.ts: -------------------------------------------------------------------------------- 1 | import { matchesMediaQuery } from './matches-media-query' 2 | 3 | /** 4 | * A store to detect if the user has requested the system minimize the amount of animation or motion it uses. 5 | */ 6 | export const reducedMotion = /*#__PURE__*/ matchesMediaQuery('(prefers-reduced-motion: reduce)') 7 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/system.ts: -------------------------------------------------------------------------------- 1 | import 'systemjs/dist/system.js' 2 | // import 'systemjs/dist/extras/named-register.js' 3 | 4 | export interface ImportMap { 5 | resolutions?: Record 6 | imports?: Record 7 | scopes?: { 8 | [scope: string]: Record 9 | } 10 | integrity?: Record 11 | preload?: string[] 12 | prefetch?: string[] 13 | } 14 | 15 | type ISystem = typeof System & { 16 | onload?: ( 17 | error: Error | null | undefined, 18 | id: string, 19 | dependencies: string[], 20 | isErrorSource: boolean, 21 | ) => void 22 | 23 | addImportMap(map: ImportMap): void 24 | 25 | // from systemjs/dist/extras/named-register 26 | // registerRegistry: Record 27 | // namedRegisterAliases: Record 28 | } 29 | 30 | declare global { 31 | interface Window { 32 | System: ISystem 33 | } 34 | 35 | var importScripts: undefined | ((url: string) => Promise) 36 | } 37 | 38 | if (import.meta.env.DEV && typeof importScripts === 'function') { 39 | System.constructor.prototype.instantiate = async function (url: string) { 40 | await import(/* @vite-ignore */ url) 41 | return this.getRegister(url) 42 | } 43 | } 44 | 45 | export default System as ISystem 46 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/bug-report/config.tpl: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@twind/core" 2 | import presetAutoprefix from "@twind/preset-autoprefix" 3 | // import presetExt from '@twind/preset-ext' 4 | // import presetTypography from "@twind/preset-typography" 5 | import presetTailwind from "@twind/preset-tailwind" 6 | // import presetTailwindForms from "@twind/preset-tailwind-forms" 7 | // import presetLineClamp from "@twind/preset-line-clamp" 8 | 9 | export default defineConfig({ 10 | presets: [ 11 | presetAutoprefix(), 12 | // presetExt(), 13 | // presetTypography(/* options */), 14 | presetTailwind(/* options */), 15 | // presetTailwindForms(/* options */), 16 | // presetLineClamp(/* options */), 17 | ], 18 | }) 19 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/bug-report/html.tpl: -------------------------------------------------------------------------------- 1 | 14 | 15 |
18 | Show the issue here. 19 |
20 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/bug-report/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/bug-report/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/default/config.tpl: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@twind/core" 2 | import presetAutoprefix from "@twind/preset-autoprefix" 3 | // import presetExt from '@twind/preset-ext' 4 | // import presetTypography from '@twind/preset-typography' 5 | import presetTailwind from "@twind/preset-tailwind" 6 | 7 | export default defineConfig({ 8 | presets: [ 9 | presetAutoprefix(), 10 | // presetExt(), 11 | // presetTypography(/* options */), 12 | presetTailwind(/* options */), 13 | ], 14 | }) 15 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/default/html.tpl: -------------------------------------------------------------------------------- 1 |
4 | Twind Logo 9 | 10 |

11 | twind.style 18 |

19 |

20 | The smallest, fastest, most feature complete tailwind-in-js solution in existence. 21 |

22 | 23 | 28 |
29 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/default/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/default/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | const templates = import.meta.glob("./*/index.ts") 4 | 5 | export const loadDefaultTemplate = () => import("./default") 6 | 7 | export async function loadTemplate(id: string): Promise { 8 | const template = templates[`./${id}/index.ts`] 9 | 10 | if (template) { 11 | return (await template()) as { workspace: Workspace } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-container-queries/config.tpl: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@twind/core" 2 | import presetAutoprefix from "@twind/preset-autoprefix" 3 | import presetTailwind from "@twind/preset-tailwind" 4 | import presetContainerQueries from "@twind/preset-container-queries" 5 | 6 | export default defineConfig({ 7 | presets: [ 8 | presetAutoprefix(), 9 | presetContainerQueries(), 10 | presetTailwind(/* options */), 11 | ], 12 | }) 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-container-queries/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-container-queries/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-line-clamp/config.tpl: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@twind/core" 2 | import presetAutoprefix from "@twind/preset-autoprefix" 3 | import presetTailwind from "@twind/preset-tailwind" 4 | import presetLineClamp from "@twind/preset-line-clamp" 5 | 6 | export default defineConfig({ 7 | presets: [ 8 | presetAutoprefix(), 9 | presetLineClamp(), 10 | presetTailwind(/* options */), 11 | ], 12 | }) 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-line-clamp/html.tpl: -------------------------------------------------------------------------------- 1 |
2 |

3 | Et molestiae hic earum repellat aliquid est doloribus delectus. Enim illum odio porro ut omnis 4 | dolor debitis natus. Voluptas possimus deserunt sit delectus est saepe nihil. Qui voluptate 5 | possimus et quia. Eligendi voluptas voluptas dolor cum. Rerum est quos quos id ut molestiae 6 | fugit. 7 |

8 | 9 |

10 | Et molestiae hic earum repellat aliquid est doloribus delectus. Enim illum odio porro ut omnis 11 | dolor debitis natus. Voluptas possimus deserunt sit delectus est saepe nihil. Qui voluptate 12 | possimus et quia. Eligendi voluptas voluptas dolor cum. Rerum est quos quos id ut molestiae 13 | fugit. 14 |

15 |
16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-line-clamp/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-line-clamp/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-radix-ui/html.tpl: -------------------------------------------------------------------------------- 1 |
4 | Twind Logo 9 | 10 |

11 | twind.style 18 |

19 |

20 | The smallest, fastest, most feature complete tailwind-in-js solution in 21 | existence. 22 |

23 | 24 | 29 |
30 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-radix-ui/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-radix-ui/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-tailwind-forms/config.tpl: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@twind/core" 2 | import presetAutoprefix from "@twind/preset-autoprefix" 3 | import presetTailwind from "@twind/preset-tailwind" 4 | import presetTailwindForms from "@twind/preset-tailwind-forms" 5 | 6 | export default defineConfig({ 7 | presets: [ 8 | presetAutoprefix(), 9 | presetTailwind(/* options */), 10 | presetTailwindForms(/* options */), 11 | ], 12 | }) 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-tailwind-forms/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-tailwind-forms/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-tailwind/config.tpl: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@twind/core" 2 | import presetAutoprefix from "@twind/preset-autoprefix" 3 | import presetTailwind from "@twind/preset-tailwind" 4 | 5 | export default defineConfig({ 6 | presets: [ 7 | presetAutoprefix(), 8 | presetTailwind(/* options */), 9 | ], 10 | }) 11 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-tailwind/html.tpl: -------------------------------------------------------------------------------- 1 |
4 | Twind Logo 9 | 10 |

11 | twind.style 18 |

19 |

20 | The smallest, fastest, most feature complete tailwind-in-js solution in existence. 21 |

22 | 23 | 28 |
29 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-tailwind/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-tailwind/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-typography/config.tpl: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@twind/core" 2 | import presetAutoprefix from "@twind/preset-autoprefix" 3 | import presetTypography from "@twind/preset-typography" 4 | import presetTailwind from "@twind/preset-tailwind" 5 | 6 | export default defineConfig({ 7 | presets: [presetAutoprefix(), presetTypography(/* options */), presetTailwind(/* options */)], 8 | }) 9 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-typography/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "$lib/types" 2 | 3 | import config from "./config.tpl?raw" 4 | import html from "./html.tpl?raw" 5 | import script from "./script.tpl?raw" 6 | 7 | export const workspace: Workspace = { 8 | version: "*", 9 | html: { path: "index.html", value: html }, 10 | script: { path: "index.ts", value: script }, 11 | config: { path: "twind.config.ts", value: config }, 12 | } 13 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/templates/preset-typography/script.tpl: -------------------------------------------------------------------------------- 1 | import { tw, cx, tx, css, style } from "@twind/core" 2 | 3 | // imported and executed once after the tw instance has been created but before new document.body is set 4 | 5 | export async function beforeUpdate() { 6 | // runs every time before a new document.body is set 7 | } 8 | 9 | export async function afterUpdate() { 10 | // runs every time after a new document.body is set 11 | } 12 | 13 | export async function dispose() { 14 | // runs before a new script is activated 15 | } 16 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/transpile.ts: -------------------------------------------------------------------------------- 1 | import * as Comlink from 'comlink' 2 | import type { Manifest } from '$lib/types' 3 | 4 | import type { ImportMap } from './system' 5 | 6 | import TranspileWorker from './transpile.worker?worker' 7 | 8 | export interface Transpile { 9 | transform>( 10 | input: Input, 11 | options: { 12 | manifest: Manifest 13 | modules?: Record 14 | preload?: string[] 15 | }, 16 | ): Promise 17 | 18 | findImports( 19 | code: string, 20 | options: { 21 | manifest: Manifest 22 | }, 23 | ): Promise 24 | } 25 | 26 | export default load() 27 | 28 | function load(): Transpile { 29 | if (import.meta.env.SSR) { 30 | return { 31 | async transform(...args) { 32 | const { default: api } = await import('./transpile.api') 33 | return api.transform(...args) 34 | }, 35 | async findImports(...args) { 36 | const { default: api } = await import('./transpile.api') 37 | return api.findImports(...args) 38 | }, 39 | } 40 | } 41 | 42 | return Comlink.wrap(new TranspileWorker()) as Transpile 43 | } 44 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/transpile.worker.ts: -------------------------------------------------------------------------------- 1 | import * as Comlink from 'comlink' 2 | import api from './transpile.api' 3 | 4 | Comlink.expose(api) 5 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/twind.ts: -------------------------------------------------------------------------------- 1 | // ensure any twind methods are called after twind has been setup 2 | export * from '@twind/core' 3 | 4 | import install from '@twind/with-sveltekit' 5 | import config from '../twind.config' 6 | 7 | // in production this file is in same chunk as the preview.api and will be loaded in the preview iframe 8 | // by checking if this script is NOT loaded in the iframe we prevent installing in the preview 9 | if (typeof top !== 'object' || top === self) { 10 | install(config, import.meta.env.PROD) 11 | } 12 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | export interface Manifest { 2 | url: string 3 | version: string 4 | 'dist-tag': 'latest' | 'next' | 'canary' | 'dev' 5 | 'git-sha': string 6 | pr?: string 7 | packages: Record 8 | imports?: Record 9 | scopes?: Record> 10 | integrity?: Record 11 | } 12 | 13 | export interface Workspace { 14 | /** @sites/twind.run version (v1.0.0 or v1.0.0-...) - used to load to importmap */ 15 | version: string 16 | html: WorkspaceFile 17 | script: WorkspaceFile 18 | config: WorkspaceFile 19 | } 20 | 21 | export interface WorkspaceFile { 22 | path: string 23 | value: string 24 | dirty?: boolean 25 | } 26 | -------------------------------------------------------------------------------- /sites/twind.run/src/lib/versions.ts: -------------------------------------------------------------------------------- 1 | import { SemverRange } from 'sver' 2 | import type { Manifest } from './types' 3 | 4 | export function withVersion(specifier: string, manifest: Manifest) { 5 | const match = specifier.match(/^((?:@[^/]+\/)?[^/@]+)(?:@([^/]+))?(\/.+)?$/) 6 | 7 | if (match) { 8 | const { 1: id, 2: version, 3: path = '' } = match 9 | 10 | // check if versions satifies importMap version and use importMap resolution 11 | const manifestVersion = manifest.packages[id] 12 | 13 | if (!version || (manifestVersion && SemverRange.match(version, manifestVersion))) { 14 | return { 15 | found: true, 16 | input: { id, version, path }, 17 | output: { id, version: manifestVersion, path }, 18 | specifier: `${id}@${manifestVersion}${path}`, 19 | } as const 20 | } 21 | 22 | if (version) { 23 | return { 24 | found: false, 25 | input: { id, version, path }, 26 | output: { id, version, path }, 27 | specifier, 28 | } as const 29 | } 30 | } 31 | 32 | return { 33 | found: false, 34 | input: { id: specifier, version: undefined, path: '' }, 35 | output: { id: specifier, version: undefined, path: '' }, 36 | specifier, 37 | } as const 38 | } 39 | -------------------------------------------------------------------------------- /sites/twind.run/src/routes/+error.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

{$page.status}: {$page.error?.message}

6 | 7 | {#if $page.error?.frame} 8 |
 9 |     {$page.error.frame}
10 |   
11 | {/if} 12 | 13 | {#if $page.error?.stack} 14 |
15 |     {$page.error.stack}
16 |   
17 | {/if} 18 | 19 |
20 |   {JSON.stringify($page.error, null, 2)}
21 | 
22 | -------------------------------------------------------------------------------- /sites/twind.run/src/routes/+layout.js: -------------------------------------------------------------------------------- 1 | import '$lib/twind' 2 | -------------------------------------------------------------------------------- /sites/twind.run/src/routes/+layout.server.js: -------------------------------------------------------------------------------- 1 | /** @type {import('./$types').LayoutServerLoad} */ 2 | export async function load({ setHeaders }) { 3 | // Harden security for an application 4 | try { 5 | setHeaders({ 6 | 'X-Content-Type-Options': 'nosniff', 7 | 'X-Frame-Options': 'SAMEORIGIN', 8 | 'X-XSS-Protection': '1; mode=block', 9 | // https://www.permissionspolicy.com 10 | 'Permissions-Policy': [ 11 | `cross-origin-isolated=(self)`, 12 | `fullscreen=(self "https://challenges.cloudflare.com")`, 13 | // `web-share=(self)`, 14 | `clipboard-write=(self)`, 15 | // `focus-without-user-activation=(self)`, 16 | `idle-detection=(self)`, 17 | // `unload=(self)`, 18 | ].join(', '), 19 | 'Feature-Policy': `fullscreen 'self' https://challenges.cloudflare.com`, 20 | // TODO: CSP - https://support.cloudflare.com/hc/en-us/articles/216537517-What-is-Content-Security-Policy-CSP-and-how-can-I-use-it-with-Cloudflare- 21 | }) 22 | } catch {} 23 | } 24 | -------------------------------------------------------------------------------- /sites/twind.run/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sites/twind.run/src/routes/[[key]]/loader.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
18 | {#if !isReady} 19 | 20 |
21 | Loading ... 22 |
23 |
24 | {/if} 25 | 26 | 27 |
28 | -------------------------------------------------------------------------------- /sites/twind.run/src/routes/[[key]]/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Preview 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /sites/twind.run/static/_headers: -------------------------------------------------------------------------------- 1 | # Cloudflare Headers: https://developers.cloudflare.com/pages/platform/headers 2 | 3 | ## Prevent *.pages.dev deployments showing in search results 4 | https:/:project.pages.dev/* 5 | X-Robots-Tag: noindex 6 | 7 | https://:deployment.:project.pages.dev/* 8 | X-Robots-Tag: noindex 9 | -------------------------------------------------------------------------------- /sites/twind.run/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/sites/twind.run/static/favicon.ico -------------------------------------------------------------------------------- /sites/twind.run/static/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /sites/twind.run/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-cloudflare' 2 | 3 | /** @type {import('@sveltejs/kit').Config} */ 4 | const config = { 5 | kit: { 6 | adapter: adapter(), 7 | prerender: { 8 | origin: 'https://twind.run', 9 | entries: ['*', '/manifest.json', '/msapplication-config.xml'], 10 | }, 11 | csrf: { 12 | checkOrigin: true, 13 | }, 14 | }, 15 | } 16 | 17 | export default config 18 | -------------------------------------------------------------------------------- /sites/twind.run/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /sites/twind.run/wrangler.toml: -------------------------------------------------------------------------------- 1 | # https://developers.cloudflare.com/pages/how-to/use-direct-upload-with-continuous-integration/ 2 | # production 3 | # npx wrangler pages publish .svelte-kit/cloudflare --project-name=twind-run --branch=main 4 | # preview 5 | # npx wrangler pages publish .svelte-kit/cloudflare --project-name=twind-run --branch=next 6 | 7 | name = "twind-run" 8 | 9 | # https://developers.cloudflare.com/workers/platform/compatibility-dates/ 10 | compatibility_date = "2022-11-11" 11 | 12 | # Also opt into an upcoming fix to the FormData API. 13 | compatibility_flags = [ "transformstream_enable_standard_constructor", "streams_enable_constructors" ] 14 | 15 | [vars] 16 | # https://developers.cloudflare.com/pages/platform/build-configuration/#language-support-and-tools 17 | NODE_VERSION = "16" 18 | -------------------------------------------------------------------------------- /sites/twind.style/README.md: -------------------------------------------------------------------------------- 1 | # twind.style 2 | 3 | This is the [Twind website](https://twind.style). The docs live [here](../../documentation). 4 | 5 | ## Developing 6 | 7 | Once you've [set up the repo](../../CONTRIBUTING.md), `cd` into this directory and start the dev server: 8 | 9 | ```bash 10 | cd sites/twind.style 11 | pnpm start 12 | ``` 13 | -------------------------------------------------------------------------------- /sites/twind.style/src/_worker.ts: -------------------------------------------------------------------------------- 1 | /// 2 | // import type { EventContext } from '@cloudflare/workers-types' 3 | import { createSearch } from './lib/search' 4 | import data from '../build/-/search.json' 5 | import { version } from '../build/_app/version.json' 6 | 7 | const search = createSearch({ ...data, currentVersion: version }) 8 | 9 | export default { 10 | fetch(request: Request, env: { ASSETS: { fetch: typeof fetch } }, ctx: ExecutionContext) { 11 | const url = new URL(request.url) 12 | 13 | if (url.pathname === '/-/search') { 14 | return search(request) 15 | } 16 | 17 | // Otherwise, serve the static assets. 18 | // Without this, the Worker will error and no assets will be served. 19 | return env.ASSETS.fetch(request) 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /sites/twind.style/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | /// 5 | 6 | declare namespace App { 7 | interface Error { 8 | stack?: string 9 | } 10 | 11 | interface PageData { 12 | docStartHref: string 13 | file?: string 14 | editLink?: boolean 15 | nav?: import('./routes/docs/$types').LayoutServerData['nav'] 16 | } 17 | } 18 | 19 | declare module '*.md' { 20 | // "unknown" would be more detailed depends on how you structure frontmatter 21 | export const frontmatter: Record 22 | 23 | export const toc: { level: 1 | 2 | 3 | 4 | 5 | 6; id: string; content: string }[] 24 | 25 | const toHTML: () => Promise 26 | export default toHTML 27 | } 28 | -------------------------------------------------------------------------------- /sites/twind.style/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /sites/twind.style/src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import type { Handle, HandleServerError } from '@sveltejs/kit' 2 | import { sequence } from '@sveltejs/kit/hooks' 3 | 4 | import handleTwind from '@twind/with-sveltekit/hooks' 5 | 6 | const handlers: Handle[] = [handleTwind()] 7 | 8 | export const handle = handlers.length > 1 ? sequence(...handlers) : handlers[0] 9 | 10 | export const handleError: HandleServerError = ({ error }) => { 11 | return { 12 | message: 'Whoops! ' + (error as Error).message, 13 | stack: (error as Error).stack, 14 | ...(error as any), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/actions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './clipboard-copy' 2 | export { default as clipboardCopy } from './clipboard-copy' 3 | 4 | export * from './shortcut' 5 | export { default as shortcut } from './shortcut' 6 | 7 | export * from './mutation-observer' 8 | export { default as mutationObserver } from './mutation-observer' 9 | 10 | export * from './scrollspy' 11 | export { default as scrollspy } from './scrollspy' 12 | 13 | export * from './wicked' 14 | 15 | export * from './types' 16 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/actions/mutation-observer.ts: -------------------------------------------------------------------------------- 1 | import type { Action } from './types' 2 | 3 | export interface MutationObserverOptions extends MutationObserverInit { 4 | enabled?: boolean 5 | callback?: MutationCallback 6 | } 7 | 8 | export default function mutationObserver( 9 | node: Element, 10 | initialOptions?: MutationObserverOptions, 11 | ): ReturnType { 12 | let observer: MutationObserver | undefined | void 13 | 14 | update(initialOptions) 15 | 16 | function update({ 17 | enabled = true, 18 | callback = (mutations, observer) => { 19 | node.dispatchEvent( 20 | new CustomEvent('mutation', { 21 | bubbles: false, 22 | cancelable: false, 23 | detail: { mutations, observer }, 24 | }), 25 | ) 26 | }, 27 | ...options 28 | }: MutationObserverOptions = {}) { 29 | destroy() 30 | 31 | if (enabled) { 32 | observer = new MutationObserver(callback) 33 | observer.observe(node, options) 34 | } 35 | } 36 | 37 | function destroy() { 38 | observer?.disconnect() 39 | } 40 | 41 | return { update, destroy } 42 | } 43 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/actions/types.ts: -------------------------------------------------------------------------------- 1 | export type PureAction = (node: HTMLElement) => void 2 | 3 | export interface ActionResult { 4 | update: (parameters: Parameters) => void 5 | destroy: () => void 6 | } 7 | 8 | export type Action = ( 9 | node: HTMLElement, 10 | parameters: Parameters, 11 | ) => ActionResult 12 | 13 | export interface UnknownActionResult { 14 | update?: (parameters?: Parameters) => void 15 | destroy?: () => void 16 | } 17 | 18 | export type UnknownAction = ( 19 | node: HTMLElement, 20 | parameters?: Parameters, 21 | ) => void | undefined | null | UnknownActionResult 22 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/sites/twind.style/src/lib/assets/favicon.ico -------------------------------------------------------------------------------- /sites/twind.style/src/lib/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/sites/twind.style/src/lib/assets/icon.png -------------------------------------------------------------------------------- /sites/twind.style/src/lib/assets/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const MOD_KEY = 2 | typeof navigator == 'object' && /* @__PURE__ */ /Mac|iPod|iPhone|iPad/.test(navigator.platform) 3 | ? '⌘' 4 | : 'Ctrl' 5 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/documentation.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs' 2 | import process from 'node:process' 3 | 4 | import { read } from '$lib/markdown' 5 | 6 | // relative to the working directory (sites/twind.style) 7 | const docsPath = '../../documentation' 8 | 9 | export let data = read({ slug: '/', cwd: docsPath }) 10 | 11 | if (!process.env.CI) { 12 | try { 13 | fs.watch(docsPath, { recursive: true, persistent: false }, () => { 14 | data = read({ slug: '/', cwd: docsPath }) 15 | }) 16 | } catch (error) { 17 | if ((error as NodeJS.ErrnoException).code === 'ERR_FEATURE_UNAVAILABLE_ON_PLATFORM') { 18 | console.warn('watching for changes is not supported on this platform') 19 | } else { 20 | throw error 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/icons/heroicons/index.js: -------------------------------------------------------------------------------- 1 | export * from './outline' 2 | export * from './solid' 3 | export * from './mini' 4 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/icons/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './icon.svelte' 2 | 3 | export * from './bootstrap' 4 | export * from './fluent-solid' 5 | export * from './octicons' 6 | export * from './heroicons' 7 | export * from './loading' 8 | export * from './twind' 9 | 10 | export * from './types' 11 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/icons/twind.js: -------------------------------------------------------------------------------- 1 | /** 2 | * **twind logo** 3 | * 4 | * @type {import('./types').IconSource} 5 | */ 6 | export const TwindLogo = /* @__PURE__ */ JSON.parse( 7 | '{"viewbox":"0 0 176.99 163.4","circles":[{"fill":"#f5f5f5","cx":"95.31","cy":"81.67","r":"81.67"}],"lines":[{"fill":"none","stroke":"#000","stroke-linecap":"round","stroke-width":"6px","x1":"139.75","y1":"33.48","x2":"139.75","y2":"160.4"},{"fill":"none","stroke":"#000","stroke-width":"5px","x1":"114.36","y1":"77.15","x2":"140.42","y2":"44.76"},{"fill":"none","stroke":"#000","stroke-width":"5px","x1":"102.63","y1":"47.45","x2":"140.57","y2":"45.44"}],"paths":[{"stroke":"#000","fill":"#80cbc4","stroke-width":"5px","stroke-linecap":"round","d":"M12.14,107.09,101.07,55s13.3,9.74,19.6,25.14a73.21,73.21,0,0,1,5.17,30L28.63,144.73s-10.77-7.93-14-15.43S12.14,107.09,12.14,107.09Z","transform":"translate(-9.57 -18.17)"},{"stroke":"#000","stroke-width":"4px","fill":"#ee999c","d":"M55.8,134.93,37,92.54l14-8.29,19.12,45.26Z","transform":"translate(-9.57 -18.17)"},{"stroke":"#000","stroke-width":"4px","fill":"#ee999c","d":"M70.84,129.93,51,85.19l14.8-8.75L86,124.21Z","transform":"translate(-9.57 -18.17)"}]}', 8 | ) 9 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/icons/types.ts: -------------------------------------------------------------------------------- 1 | export interface IconSource { 2 | viewbox?: string 3 | fill?: string 4 | stroke?: string 5 | paths?: Record[] 6 | rects?: Record[] 7 | circles?: Record[] 8 | polygons?: Record[] 9 | lines?: Record[] 10 | } 11 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/markdown/read-cache.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'node:path' 2 | import { promisify } from 'node:util' 3 | 4 | import fs from 'graceful-fs' 5 | import matter, { type GrayMatterFile } from 'gray-matter' 6 | 7 | import QuickLRU from 'quick-lru' 8 | 9 | const stat = promisify(fs.stat) 10 | const read = promisify(fs.readFile) 11 | 12 | const cache = new QuickLRU< 13 | string, 14 | { mtime: Date; file: GrayMatterFile & { path: string } } 15 | >({ maxSize: 500 }) 16 | 17 | export async function readFile(path: string): Promise> { 18 | path = resolve(path) 19 | 20 | const stats = await stat(path) 21 | 22 | let cached = cache.get(path) 23 | 24 | if (cached?.mtime.getTime() !== stats.mtime.getTime()) { 25 | cache.set( 26 | path, 27 | (cached = { 28 | mtime: stats.mtime, 29 | file: Object.assign(matter(await read(path, { encoding: 'utf8' })), { path }), 30 | }), 31 | ) 32 | } 33 | 34 | return cached.file 35 | } 36 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/stores/index.ts: -------------------------------------------------------------------------------- 1 | export * from './match-media-query' 2 | export * from './matches-media-query' 3 | export * from './mounted' 4 | export * from './on' 5 | export * from './reduced-motion' 6 | export * from './search' 7 | export * from './storage' 8 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/stores/match-media-query.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { readable } from 'svelte/store' 3 | import { on } from './on' 4 | 5 | export interface MediaQueryStoreValue { 6 | readonly matches: boolean 7 | readonly media: string 8 | } 9 | 10 | export function matchMediaQuery(query: string): Readable { 11 | return typeof matchMedia == 'undefined' 12 | ? readable({ matches: false, media: query }) 13 | : on(matchMedia(query), 'change') 14 | } 15 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/stores/matches-media-query.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { derived } from 'svelte/store' 3 | import { matchMediaQuery } from './match-media-query' 4 | 5 | export function matchesMediaQuery(query: string): Readable { 6 | return derived(matchMediaQuery(query), (match) => match.matches) 7 | } 8 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/stores/mounted.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { onMount } from 'svelte' 3 | import { noop } from 'svelte/internal' 4 | 5 | export const mounted: Readable = { 6 | subscribe(set) { 7 | set(false) 8 | onMount(() => { 9 | set(true) 10 | return () => set(false) 11 | }) 12 | return noop 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/stores/on.ts: -------------------------------------------------------------------------------- 1 | import type { Readable } from 'svelte/store' 2 | import { readable } from 'svelte/store' 3 | 4 | export interface EventSource { 5 | addEventListener(event: Event, listener: (value: Value) => void): void 6 | removeEventListener(event: Event, listener: (value: Value) => void): void 7 | } 8 | 9 | export function on( 10 | source: StoreValue & EventSource, 11 | event: Event, 12 | ): Readable 13 | 14 | export function on( 15 | source: EventSource, 16 | event: Event, 17 | initialValue: StoreValue, 18 | ): Readable 19 | 20 | export function on(source: EventSource, event: string, initialValue = source) { 21 | return readable(initialValue, (set) => { 22 | source.addEventListener(event, set) 23 | 24 | return () => source.removeEventListener(event, set) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/stores/reduced-motion.ts: -------------------------------------------------------------------------------- 1 | import { matchesMediaQuery } from './matches-media-query' 2 | 3 | /** 4 | * A store to detect if the user has requested the system minimize the amount of animation or motion it uses. 5 | */ 6 | export const reducedMotion = /*#__PURE__*/ matchesMediaQuery('(prefers-reduced-motion: reduce)') 7 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/stores/search.ts: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store' 2 | 3 | export const searchOpen = writable(false) 4 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/template/footer.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 42 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/template/layout.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | {#if $page.data.nav} 18 |
29 | 30 | {#if browser} 31 | 32 | {/if} 33 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/template/redirect.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | Page Redirection 18 | 19 | 20 |

21 | If you are not redirected automatically, follow this link. 24 |

25 | -------------------------------------------------------------------------------- /sites/twind.style/src/lib/twind.ts: -------------------------------------------------------------------------------- 1 | // ensure any twind methods are called after twind has been setup 2 | 3 | import install from '@twind/with-sveltekit' 4 | import config from '../twind.config' 5 | 6 | export const tw = install(config, import.meta.env.PROD) 7 | export * from '@twind/core' 8 | -------------------------------------------------------------------------------- /sites/twind.style/src/routes/+layout.js: -------------------------------------------------------------------------------- 1 | import '$lib/twind' 2 | 3 | if (import.meta.hot) { 4 | import.meta.hot.on('docs-update', () => { 5 | import('$app/navigation') 6 | .then(({ invalidateAll }) => invalidateAll()) 7 | .catch((error) => console.error(error)) 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /sites/twind.style/src/routes/+layout.server.js: -------------------------------------------------------------------------------- 1 | import { data } from '$lib/documentation' 2 | 3 | export const prerender = true 4 | 5 | /** @type {import('./$types').LayoutServerLoad} */ 6 | export async function load({ setHeaders, request }) { 7 | // Harden security for an application 8 | try { 9 | setHeaders({ 10 | 'X-Content-Type-Options': 'nosniff', 11 | 'X-Frame-Options': 'SAMEORIGIN', 12 | 'X-XSS-Protection': '1; mode=block', 13 | // 'Permissions-Policy': 'document-domain=()', 14 | // TODO: CSP - https://support.cloudflare.com/hc/en-us/articles/216537517-What-is-Content-Security-Policy-CSP-and-how-can-I-use-it-with-Cloudflare- 15 | }) 16 | } catch {} 17 | 18 | const { startHref } = await data 19 | 20 | return { docStartHref: startHref } 21 | } 22 | -------------------------------------------------------------------------------- /sites/twind.style/src/routes/+page.server.js: -------------------------------------------------------------------------------- 1 | import { transformFile } from '$lib/markdown/transform' 2 | 3 | /** @type {import('./$types').PageServerLoad} */ 4 | export async function load() { 5 | const content = await transformFile('../../documentation/introduction.md') 6 | 7 | return { content } 8 | } 9 | -------------------------------------------------------------------------------- /sites/twind.style/src/routes/-/search.json/+server.js: -------------------------------------------------------------------------------- 1 | import { data } from '$lib/documentation' 2 | 3 | export const prerender = true 4 | 5 | /** @type {import('./$types').RequestHandler} */ 6 | export async function GET() { 7 | const { search } = await data 8 | 9 | return new Response(JSON.stringify(search), { 10 | headers: { 11 | 'content-type': 'application/json', 12 | }, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /sites/twind.style/src/routes/-/search/+server.js: -------------------------------------------------------------------------------- 1 | import { dev, building } from '$app/environment' 2 | import { createSearch } from '$lib/search' 3 | 4 | export const prerender = true 5 | 6 | /** @type {import('./$types').RequestHandler} */ 7 | export async function GET({ request, fetch }) { 8 | if (building) { 9 | return new Response(JSON.stringify({ term: '', results: [] }), { 10 | headers: { 11 | 'content-type': 'application/json', 12 | }, 13 | }) 14 | } 15 | 16 | const data = await fetch('/-/search.json') 17 | 18 | if (!(data.ok && data.status === 200)) { 19 | throw new Error(`Loading search index failed: ${data.status}`) 20 | } 21 | 22 | return createSearch({ dev, ...(await data.json()) })(request) 23 | } 24 | -------------------------------------------------------------------------------- /sites/twind.style/src/routes/[...slug]/+layout.server.js: -------------------------------------------------------------------------------- 1 | import { data } from '$lib/documentation' 2 | 3 | /** @type {import('./$types').LayoutServerLoad} */ 4 | export async function load() { 5 | const { sections, pages } = await data 6 | 7 | return { 8 | nav: { 9 | sections: [...sections].filter(([, entries]) => entries.length), 10 | pages: Object.fromEntries( 11 | [...pages] 12 | .filter(([, page]) => page.nav) 13 | .map(([href, { section, label, prev, next }]) => [href, { section, label, prev, next }]), 14 | ), 15 | }, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sites/twind.style/src/routes/[...slug]/+layout.svelte: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sites/twind.style/static/_headers: -------------------------------------------------------------------------------- 1 | # Cloudflare Headers: https://developers.cloudflare.com/pages/platform/headers 2 | 3 | ## Immutable assets 4 | /_app/immutable/* 5 | Cache-Control: public, immutable, max-age=31536000 6 | X-Robots-Tag: noindex 7 | 8 | ## Always revalidate service worker 9 | # https://stackoverflow.com/questions/38843970/service-worker-javascript-update-frequency-every-24-hours 10 | # cache for 1 hour 11 | /service-worker.js 12 | Cache-Control: public, max-age=3600 13 | 14 | ## Allow favicon access from everywhere - used by cdn.twind.style 15 | /favicon.ico 16 | Access-Control-Allow-Origin: * 17 | 18 | ## Prevent *.pages.dev deployments showing in search results 19 | https://:project.pages.dev/* 20 | X-Robots-Tag: noindex 21 | 22 | https://:deployment.:project.pages.dev/* 23 | X-Robots-Tag: noindex 24 | 25 | ## Allow cdn access from everywhere 26 | https://cdn.twind.style/* 27 | Access-Control-Allow-Origin: * 28 | -------------------------------------------------------------------------------- /sites/twind.style/static/_redirects: -------------------------------------------------------------------------------- 1 | # Cloudflare Redirects: https://developers.cloudflare.com/pages/platform/redirects 2 | 3 | /chat https://discord.gg/3fwqsmXNYK 301 4 | /play https://twind.run 301 5 | -------------------------------------------------------------------------------- /sites/twind.style/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/sites/twind.style/static/favicon.ico -------------------------------------------------------------------------------- /sites/twind.style/static/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /sites/twind.style/static/sponsors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tw-in-js/twind/900a758e19bee8bd72ab423c8062b476d90df000/sites/twind.style/static/sponsors.png -------------------------------------------------------------------------------- /sites/twind.style/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-static' 2 | 3 | /** @type {import('@sveltejs/kit').Config} */ 4 | const config = { 5 | kit: { 6 | adapter: adapter(), 7 | prerender: { 8 | origin: 'https://twind.style', 9 | }, 10 | serviceWorker: { 11 | // We are registering the service worker ourself in pages/_layout.svelte 12 | // to delay the registration, reducing Time to Interactive, and show a notification 13 | register: false, 14 | files(file) { 15 | return !['.cache.json', '_headers', '_redirects'].includes(file) 16 | }, 17 | }, 18 | csrf: { 19 | checkOrigin: true, 20 | }, 21 | }, 22 | } 23 | 24 | export default config 25 | -------------------------------------------------------------------------------- /sites/twind.style/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /sites/twind.style/typedoc/plugin.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @param {import('typedoc').Application} app 4 | */ 5 | exports.load = function (app) { 6 | app.renderer.defineTheme('twind', require('./theme.cjs').TwindTheme) 7 | } 8 | -------------------------------------------------------------------------------- /sites/twind.style/wrangler.toml: -------------------------------------------------------------------------------- 1 | # https://developers.cloudflare.com/pages/how-to/use-direct-upload-with-continuous-integration/ 2 | # production 3 | # npx wrangler pages publish build --project-name=twind-style --branch=main 4 | # preview 5 | # npx wrangler pages publish build --project-name=twind-style --branch=next 6 | 7 | name = "twind-style" 8 | 9 | # https://developers.cloudflare.com/workers/platform/compatibility-dates/ 10 | compatibility_date = "2022-11-30" 11 | 12 | # Also opt into an upcoming fix to the FormData API. 13 | compatibility_flags = [ "transformstream_enable_standard_constructor", "streams_enable_constructors" ] 14 | 15 | [vars] 16 | # https://developers.cloudflare.com/pages/platform/build-configuration/#language-support-and-tools 17 | NODE_VERSION = "16" 18 | -------------------------------------------------------------------------------- /vitest.config.js: -------------------------------------------------------------------------------- 1 | import isCI from 'is-ci' 2 | 3 | export default { 4 | test: { 5 | coverage: { 6 | reporter: isCI ? 'lcovonly' : 'html', 7 | }, 8 | api: { port: 3002 }, 9 | }, 10 | } 11 | --------------------------------------------------------------------------------