From c2c339a9db6128e43c927fde6d29f4135301e609 Mon Sep 17 00:00:00 2001 From: Simon Farshid Date: Tue, 9 Jul 2024 17:07:27 -0700 Subject: [PATCH] feat: react-ui tailwindcss integration (#440) --- packages/react-ui/package.json | 30 +- packages/react-ui/postcss.config.mjs | 1 + packages/react-ui/scripts/build.mts | 47 +++ packages/react-ui/src/markdown-styles.css | 112 ------ packages/react-ui/src/styles.css | 322 ------------------ .../react-ui/src/styles/base-components.css | 53 +++ packages/react-ui/src/styles/base.css | 37 ++ packages/react-ui/src/styles/index.css | 4 + packages/react-ui/src/styles/markdown.css | 107 ++++++ packages/react-ui/src/styles/modal.css | 29 ++ packages/react-ui/src/styles/thread.css | 159 +++++++++ packages/react-ui/src/tailwindcss.ts | 18 +- packages/react-ui/src/themes/shadcn.css | 61 ---- packages/react-ui/tailwind.config.ts | 3 +- packages/react-ui/tsconfig.json | 2 +- packages/react-ui/tsup.config.ts | 22 -- packages/react-ui/tsup.plugin.config.ts | 11 - packages/tailwindcss-transformer/README | 56 --- packages/tailwindcss-transformer/package.json | 16 +- packages/tailwindcss-transformer/src/index.ts | 188 ++-------- .../src/replace-variable-scope.ts | 22 -- .../tailwindcss-transformer/tsconfig.json | 4 +- pnpm-lock.yaml | 85 ++--- 23 files changed, 555 insertions(+), 834 deletions(-) create mode 100644 packages/react-ui/scripts/build.mts delete mode 100644 packages/react-ui/src/markdown-styles.css delete mode 100644 packages/react-ui/src/styles.css create mode 100644 packages/react-ui/src/styles/base-components.css create mode 100644 packages/react-ui/src/styles/base.css create mode 100644 packages/react-ui/src/styles/index.css create mode 100644 packages/react-ui/src/styles/markdown.css create mode 100644 packages/react-ui/src/styles/modal.css create mode 100644 packages/react-ui/src/styles/thread.css delete mode 100644 packages/react-ui/src/themes/shadcn.css delete mode 100644 packages/react-ui/tsup.config.ts delete mode 100644 packages/react-ui/tsup.plugin.config.ts delete mode 100644 packages/tailwindcss-transformer/README delete mode 100644 packages/tailwindcss-transformer/src/replace-variable-scope.ts diff --git a/packages/react-ui/package.json b/packages/react-ui/package.json index 206750764..460ae9474 100644 --- a/packages/react-ui/package.json +++ b/packages/react-ui/package.json @@ -23,21 +23,17 @@ "default": "./dist/tailwindcss.js" } }, - "./styles.css": { - "types": "./dist/styles.css.d.ts", - "default": "./dist/styles.css" + "./styles": { + "default": "./dist/styles/index.css" }, - "./markdown-styles.css": { - "types": "./dist/markdown-styles.css.d.ts", - "default": "./dist/markdown-styles.css" + "./styles/*": { + "default": "./dist/styles/*.css" }, - "./themes/default.css": { - "types": "./dist/themes/default.css.d.ts", - "default": "./dist/themes/default.css" + "./tailwindcss/styles/*.css": { + "default": "./dist/tailwindcss/styles/*.css" }, - "./themes/shadcn.css": { - "types": "./dist/themes/shadcn.css.d.ts", - "default": "./dist/themes/shadcn.css" + "./tailwindcss/themes/*.css": { + "default": "./dist/tailwindcss/themes/*.css" } }, "source": "./src/index.ts", @@ -49,7 +45,7 @@ "README.md" ], "scripts": { - "build": "tsup && tsup --config tsup.plugin.config.ts" + "build": "tsx scripts/build.mts" }, "dependencies": { "@assistant-ui/react-markdown": "workspace:*", @@ -66,15 +62,20 @@ "peerDependencies": { "@assistant-ui/react": "^0.3.5", "@types/react": "*", - "react": "^18" + "react": "^18", + "tailwindcss": "^3.4.4" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "tailwindcss": { + "optional": true } }, "devDependencies": { "@assistant-ui/tsconfig": "workspace:*", + "@assistant-ui/tailwindcss-transformer": "workspace:*", "@types/node": "^20.14.9", "@types/react-syntax-highlighter": "^15.5.13", "autoprefixer": "^10.4.19", @@ -84,6 +85,7 @@ "tailwindcss": "^3.4.4", "tailwindcss-animate": "^1.0.7", "tsup": "^8.1.0", + "tsx": "^4.16.0", "typescript": "^5.5.3" }, "publishConfig": { diff --git a/packages/react-ui/postcss.config.mjs b/packages/react-ui/postcss.config.mjs index 4287b99d6..3679d3a73 100644 --- a/packages/react-ui/postcss.config.mjs +++ b/packages/react-ui/postcss.config.mjs @@ -4,6 +4,7 @@ const config = { tailwindcss: {}, autoprefixer: {}, "postcss-nested": {}, + "@assistant-ui/tailwindcss-transformer": {}, }, }; diff --git a/packages/react-ui/scripts/build.mts b/packages/react-ui/scripts/build.mts new file mode 100644 index 000000000..48bb0a965 --- /dev/null +++ b/packages/react-ui/scripts/build.mts @@ -0,0 +1,47 @@ +import { build } from "tsup"; +import { copyFileSync, mkdirSync } from "node:fs"; + +// JS + +await build({ + entry: ["src/index.ts"], + format: ["cjs", "esm"], + dts: true, + sourcemap: true, + clean: true, + esbuildOptions: (options) => { + options.banner = { + js: '"use client";', + }; + }, +}); + +await build({ + entry: ["src/tailwindcss.ts"], + format: ["cjs", "esm"], + dts: true, + sourcemap: true, +}); + +// css + +await build({ + entry: [ + "src/styles/index.css", + "src/styles/markdown.css", + "src/styles/modal.css", + ], + outDir: "dist/styles", +}); + +mkdirSync("dist/tailwindcss/styles", { recursive: true }); +copyFileSync( + "src/styles/base-components.css", + "dist/tailwindcss/styles/base-components.css", +); +copyFileSync("src/styles/thread.css", "dist/tailwindcss/styles/thread.css"); +copyFileSync("src/styles/markdown.css", "dist/tailwindcss/styles/markdown.css"); +copyFileSync("src/styles/modal.css", "dist/tailwindcss/styles/modal.css"); + +mkdirSync("dist/tailwindcss/themes", { recursive: true }); +copyFileSync("src/themes/default.css", "dist/tailwindcss/themes/default.css"); diff --git a/packages/react-ui/src/markdown-styles.css b/packages/react-ui/src/markdown-styles.css deleted file mode 100644 index 07e83594f..000000000 --- a/packages/react-ui/src/markdown-styles.css +++ /dev/null @@ -1,112 +0,0 @@ -@tailwind components; - -@layer components { - /* in progress indicator */ - .aui-md-in-progress:empty::after, - .aui-md-in-progress > :not(ol):not(ul):not(pre):last-child::after, - .aui-md-in-progress > pre:last-child code::after, - .aui-md-in-progress - > :is(ol, ul):last-child - > li:last-child:not(:has(* > li))::after, - .aui-md-in-progress - > :is(ol, ul):last-child - > li:last-child - > :is(ol, ul):last-child - > li:last-child:not(:has(* > li))::after, - .aui-md-in-progress - > :is(ol, ul):last-child - > li:last-child - > :is(ol, ul):last-child - > li:last-child - > :is(ol, ul):last-child - > li:last-child::after { - @apply font-sans content-['\25CF'] ltr:ml-1 rtl:mr-1; - @apply animate-[aui-pulse_2s_cubic-bezier(0.4,0,0.6,1)_infinite]; - } - - /* typography */ - - .aui-md-root h1 { - @apply mb-8 scroll-m-20 text-4xl font-extrabold tracking-tight last:mb-0; - } - - .aui-md-root h2 { - @apply mb-4 mt-8 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0; - } - - .aui-md-root h3 { - @apply mb-4 mt-6 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0; - } - - .aui-md-root h4 { - @apply mb-4 mt-6 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0; - } - - .aui-md-root h5 { - @apply my-4 text-lg font-semibold first:mt-0 last:mb-0; - } - - .aui-md-root h6 { - @apply my-4 font-semibold first:mt-0 last:mb-0; - } - - .aui-md-root p { - @apply mb-5 mt-5 leading-7 first:mt-0 last:mb-0; - } - - .aui-md-root a { - @apply text-aui-primary font-medium underline underline-offset-4; - } - - .aui-md-root blockquote { - @apply border-l-2 pl-6 italic; - } - - .aui-md-root ul { - @apply my-5 ml-6 list-disc [&>li]:mt-2; - } - - .aui-md-root ol { - @apply my-5 ml-6 list-decimal [&>li]:mt-2; - } - - .aui-md-root hr { - @apply my-5 border-b; - } - - .aui-md-root table { - @apply my-5 w-full border-separate border-spacing-0 overflow-y-auto; - } - - .aui-md-root th { - @apply bg-aui-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [&[align=center]]:text-center [&[align=right]]:text-right; - } - - .aui-md-root td { - @apply border-b border-l px-4 py-2 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right; - } - - .aui-md-root tr { - @apply m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg; - } - - .aui-md-root sup { - @apply [&>a]:text-xs [&>a]:no-underline; - } - - .aui-md-root pre { - @apply overflow-x-auto rounded-b-lg bg-black p-4 text-white; - } - - .aui-md-root :not(pre) code { - @apply bg-aui-muted rounded border font-semibold; - } - - .aui-code-header-root { - @apply flex items-center justify-between gap-4 rounded-t-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white; - } - - .aui-code-header-language { - @apply lowercase [&>span]:text-xs; - } -} diff --git a/packages/react-ui/src/styles.css b/packages/react-ui/src/styles.css deleted file mode 100644 index 4aeb00061..000000000 --- a/packages/react-ui/src/styles.css +++ /dev/null @@ -1,322 +0,0 @@ -.aui-root { - @tailwind base; -} -@tailwind components; - -@layer base { - * { - @apply border-aui-border; - } -} - -@layer components { - .aui-root { - @apply bg-aui-background text-aui-foreground; - } - - .aui-root.aui-modal-content { - @apply bg-aui-popover text-aui-popover-foreground z-50 h-[500px] w-[400px] overflow-clip rounded-xl border p-0 shadow-md outline-none; - @apply [&>.aui-thread-root]:bg-inherit; - - @apply data-[state=closed]:animate-aui-out data-[state=open]:animate-aui-in; - @apply data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0; - @apply data-[state=closed]:zoom-out data-[state=open]:zoom-in; - @apply data-[state=open]:slide-in-from-bottom-1/2 data-[state=open]:slide-in-from-right-1/2 data-[state=closed]:slide-out-to-bottom-1/2 data-[state=closed]:slide-out-to-right-1/2; - } - - .aui-root.aui-modal-anchor { - @apply fixed bottom-4 right-4 size-11; - } - - .aui-root.aui-thread-root { - @apply bg-aui-background box-border h-full; - @apply [&>.aui-thread-viewport]:bg-inherit; - } - - .aui-root .aui-thread-viewport { - @apply bg-aui-background flex h-full flex-col items-center overflow-y-scroll scroll-smooth px-4 pt-8; - } - - .aui-root { - /* shadcn-ui/button */ - - .aui-button { - @apply focus-visible:ring-aui-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50; - } - - .aui-button-primary { - @apply bg-aui-primary text-aui-primary-foreground hover:bg-aui-primary/90 shadow; - } - - .aui-button-outline { - @apply border-aui-input bg-aui-background hover:bg-aui-accent hover:text-aui-accent-foreground border shadow-sm; - } - - .aui-button-ghost { - @apply hover:bg-aui-accent hover:text-aui-accent-foreground; - } - - .aui-button-medium { - @apply h-9 px-4 py-2; - } - - /** tooltip icon button */ - .aui-button-icon { - @apply size-6 p-1; - } - - .aui-sr-only { - @apply sr-only; - } - - /* shadcn-ui/avatar */ - - .aui-avatar-root { - @apply relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full; - } - - .aui-avatar-image { - @apply aspect-square h-full w-full; - } - - .aui-avatar-fallback { - @apply bg-aui-muted flex h-full w-full items-center justify-center rounded-full; - } - - /* shadcn-ui/tooltip */ - - .aui-tooltip-content { - @apply fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 animate-aui-in bg-aui-primary text-aui-primary-foreground data-[state=closed]:animate-aui-out z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs; - } - - /* modal */ - - .aui-modal-button { - @apply size-full rounded-full shadow transition-transform hover:scale-110 active:scale-90; - } - - .aui-modal-button-closed-icon { - @apply absolute size-6 transition-all; - @apply data-[state=closed]:rotate-0 data-[state=open]:rotate-90; - @apply data-[state=closed]:scale-100 data-[state=open]:scale-0; - } - - .aui-modal-button-open-icon { - @apply absolute size-6 transition-all; - @apply data-[state=closed]:-rotate-90 data-[state=open]:rotate-0; - @apply data-[state=closed]:scale-0 data-[state=open]:scale-100; - } - - /* thread */ - - .aui-thread-viewport-footer { - @apply sticky bottom-0 mt-4 flex w-full max-w-2xl flex-grow flex-col items-center justify-end rounded-t-lg bg-inherit pb-4; - } - - .aui-thread-scroll-to-bottom { - @apply absolute -top-8 rounded-full disabled:invisible; - } - - /* thread-welcome */ - - .aui-thread-welcome-root { - @apply flex w-full max-w-2xl flex-grow basis-full flex-col; - } - - .aui-thread-welcome-center { - @apply flex w-full flex-grow flex-col items-center justify-center; - } - - .aui-thread-welcome-message { - @apply mt-4 font-medium; - } - - .aui-thread-welcome-suggestion-container { - @apply mt-4 flex w-full items-stretch justify-center gap-4; - } - - .aui-thread-welcome-suggestion { - @apply flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-lg border px-3 py-3; - } - - .aui-thread-welcome-suggestion-text { - @apply line-clamp-2 text-ellipsis text-sm font-semibold; - } - - /* composer */ - - .aui-composer-root { - @apply relative flex w-full items-end rounded-lg border transition-shadow focus-within:shadow-sm; - } - - .aui-composer-input { - @apply placeholder:text-aui-muted-foreground size-full max-h-40 resize-none bg-transparent p-4 pr-12 text-sm outline-none; - } - - .aui-composer-send, - .aui-composer-cancel { - @apply absolute bottom-0 right-0 m-2.5 size-8 p-2 transition-opacity; - } - - /* user-message */ - - .aui-user-message-root { - @apply grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 [&>*]:col-start-2; - @apply w-full max-w-2xl py-4; - } - - .aui-user-message-root > .aui-user-action-bar-root { - @apply col-start-1 mr-3 mt-2.5; - } - - .aui-user-message-root > .aui-user-message-content { - @apply col-start-2 row-start-1; - } - - .aui-user-message-root > .aui-branch-picker-root { - @apply col-span-full col-start-1 row-start-2; - @apply -mr-1 justify-end; - } - - .aui-user-message-content { - @apply bg-aui-muted text-aui-foreground max-w-xl break-words rounded-3xl px-5 py-2.5; - } - - /* user-action-bar */ - - .aui-user-action-bar-root { - @apply flex flex-col items-end; - } - - /* edit-composer */ - - .aui-edit-composer-root { - @apply bg-aui-muted my-4 flex w-full max-w-2xl flex-col gap-2 rounded-xl; - } - - .aui-edit-composer-input { - @apply text-aui-foreground flex h-8 w-full resize-none bg-transparent p-4 pb-0 outline-none; - } - - .aui-edit-composer-footer { - @apply mx-3 mb-3 flex items-center justify-center gap-2 self-end; - } - - /* assistant-message */ - - .aui-assistant-message-root { - @apply grid grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr]; - @apply relative w-full max-w-2xl py-4; - } - - .aui-assistant-message-root > .aui-avatar-root { - @apply col-start-1 row-span-full row-start-1 mr-4; - } - - .aui-assistant-message-root > .aui-branch-picker-root { - @apply col-start-2 row-start-2; - @apply -ml-2 mr-2; - } - - .aui-assistant-message-root > .aui-assistant-action-bar-root { - @apply col-start-3 row-start-2; - @apply -ml-1; - } - - .aui-assistant-message-root > .aui-assistant-message-content { - @apply col-span-2 col-start-2 row-start-1 my-1.5; - } - - .aui-assistant-message-content { - @apply text-aui-foreground max-w-xl break-words leading-7; - } - - /* assistant-action-bar */ - - .aui-assistant-action-bar-root { - @apply text-aui-muted-foreground flex gap-1; - } - .aui-assistant-action-bar-root[data-floating] { - @apply bg-aui-background absolute rounded-md border p-1 shadow-sm; - } - - /* branch-picker */ - - .aui-branch-picker-root { - @apply text-aui-muted-foreground inline-flex items-center text-xs; - } - - .aui-branch-picker-state { - @apply font-medium; - } - - .aui-text { - @apply whitespace-pre-line; - } - - .aui-text-in-progress::after { - @apply animate-aui-pulse font-sans content-['\25CF'] ltr:ml-1 rtl:mr-1; - } - } - - .animate-aui-pulse { - animation: aui-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; - } - - @keyframes aui-pulse { - 50% { - opacity: 0.5; - } - } - .animate-aui-in { - animation-name: aui-enter; - animation-duration: 150ms; - --tw-enter-opacity: initial; - --tw-enter-scale: initial; - --tw-enter-rotate: initial; - --tw-enter-translate-x: initial; - --tw-enter-translate-y: initial; - } - @keyframes aui-enter { - from { - opacity: var(--tw-enter-opacity, 1); - transform: translate3d( - var(--tw-enter-translate-x, 0), - var(--tw-enter-translate-y, 0), - 0 - ) - scale3d( - var(--tw-enter-scale, 1), - var(--tw-enter-scale, 1), - var(--tw-enter-scale, 1) - ) - rotate(var(--tw-enter-rotate, 0)); - } - } - - .animate-aui-out { - animation-name: aui-exit; - animation-duration: 150ms; - --tw-exit-opacity: initial; - --tw-exit-scale: initial; - --tw-exit-rotate: initial; - --tw-exit-translate-x: initial; - --tw-exit-translate-y: initial; - } - @keyframes aui-exit { - to { - opacity: var(--tw-exit-opacity, 1); - transform: translate3d( - var(--tw-exit-translate-x, 0), - var(--tw-exit-translate-y, 0), - 0 - ) - scale3d( - var(--tw-exit-scale, 1), - var(--tw-exit-scale, 1), - var(--tw-exit-scale, 1) - ) - rotate(var(--tw-exit-rotate, 0)); - } - } -} diff --git a/packages/react-ui/src/styles/base-components.css b/packages/react-ui/src/styles/base-components.css new file mode 100644 index 000000000..0d96e9557 --- /dev/null +++ b/packages/react-ui/src/styles/base-components.css @@ -0,0 +1,53 @@ +.aui-root { + @apply bg-aui-background text-aui-foreground border-aui-border; +} + +/* button */ +.aui-root .aui-button { + @apply focus-visible:ring-aui-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50; +} + +.aui-root .aui-button-primary { + @apply bg-aui-primary text-aui-primary-foreground hover:bg-aui-primary/90 shadow; +} + +.aui-root .aui-button-outline { + @apply border-aui-input bg-aui-background hover:bg-aui-accent hover:text-aui-accent-foreground border shadow-sm; +} + +.aui-root .aui-button-ghost { + @apply hover:bg-aui-accent hover:text-aui-accent-foreground; +} + +.aui-root .aui-button-medium { + @apply h-9 px-4 py-2; +} + +/** tooltip icon button */ +.aui-root .aui-button-icon { + @apply size-6 p-1; +} + +.aui-root .aui-sr-only { + @apply sr-only; +} + +/* shadcn-ui/avatar */ + +.aui-root .aui-avatar-root { + @apply relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full; +} + +.aui-root .aui-avatar-image { + @apply aspect-square h-full w-full; +} + +.aui-root .aui-avatar-fallback { + @apply bg-aui-muted flex h-full w-full items-center justify-center rounded-full; +} + +/* shadcn-ui/tooltip */ + +.aui-root .aui-tooltip-content { + @apply fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 animate-in bg-aui-primary text-aui-primary-foreground data-[state=closed]:animate-out z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs; +} diff --git a/packages/react-ui/src/styles/base.css b/packages/react-ui/src/styles/base.css new file mode 100644 index 000000000..559170215 --- /dev/null +++ b/packages/react-ui/src/styles/base.css @@ -0,0 +1,37 @@ +.aui-root { + @tailwind base; +} + +@keyframes aui-enter { + from { + opacity: var(--tw-enter-opacity, 1); + transform: translate3d( + var(--tw-enter-translate-x, 0), + var(--tw-enter-translate-y, 0), + 0 + ) + scale3d( + var(--tw-enter-scale, 1), + var(--tw-enter-scale, 1), + var(--tw-enter-scale, 1) + ) + rotate(var(--tw-enter-rotate, 0)); + } +} + +@keyframes aui-exit { + to { + opacity: var(--tw-exit-opacity, 1); + transform: translate3d( + var(--tw-exit-translate-x, 0), + var(--tw-exit-translate-y, 0), + 0 + ) + scale3d( + var(--tw-exit-scale, 1), + var(--tw-exit-scale, 1), + var(--tw-exit-scale, 1) + ) + rotate(var(--tw-exit-rotate, 0)); + } +} diff --git a/packages/react-ui/src/styles/index.css b/packages/react-ui/src/styles/index.css new file mode 100644 index 000000000..66f3151ac --- /dev/null +++ b/packages/react-ui/src/styles/index.css @@ -0,0 +1,4 @@ +@import "./base.css"; +@import "./base-components.css"; +@import "./thread.css"; +@import "../themes/default.css"; diff --git a/packages/react-ui/src/styles/markdown.css b/packages/react-ui/src/styles/markdown.css new file mode 100644 index 000000000..2c9a18970 --- /dev/null +++ b/packages/react-ui/src/styles/markdown.css @@ -0,0 +1,107 @@ +/* in progress indicator */ +.aui-md-in-progress:empty::after, +.aui-md-in-progress > :not(ol):not(ul):not(pre):last-child::after, +.aui-md-in-progress > pre:last-child code::after, +.aui-md-in-progress + > :is(ol, ul):last-child + > li:last-child:not(:has(* > li))::after, +.aui-md-in-progress + > :is(ol, ul):last-child + > li:last-child + > :is(ol, ul):last-child + > li:last-child:not(:has(* > li))::after, +.aui-md-in-progress + > :is(ol, ul):last-child + > li:last-child + > :is(ol, ul):last-child + > li:last-child + > :is(ol, ul):last-child + > li:last-child::after { + @apply animate-pulse font-sans content-['\25CF'] ltr:ml-1 rtl:mr-1; +} + +/* typography */ + +.aui-md-root h1 { + @apply mb-8 scroll-m-20 text-4xl font-extrabold tracking-tight last:mb-0; +} + +.aui-md-root h2 { + @apply mb-4 mt-8 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0; +} + +.aui-md-root h3 { + @apply mb-4 mt-6 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0; +} + +.aui-md-root h4 { + @apply mb-4 mt-6 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0; +} + +.aui-md-root h5 { + @apply my-4 text-lg font-semibold first:mt-0 last:mb-0; +} + +.aui-md-root h6 { + @apply my-4 font-semibold first:mt-0 last:mb-0; +} + +.aui-md-root p { + @apply mb-5 mt-5 leading-7 first:mt-0 last:mb-0; +} + +.aui-md-root a { + @apply text-aui-primary font-medium underline underline-offset-4; +} + +.aui-md-root blockquote { + @apply border-l-2 pl-6 italic; +} + +.aui-md-root ul { + @apply my-5 ml-6 list-disc [&>li]:mt-2; +} + +.aui-md-root ol { + @apply my-5 ml-6 list-decimal [&>li]:mt-2; +} + +.aui-md-root hr { + @apply my-5 border-b; +} + +.aui-md-root table { + @apply my-5 w-full border-separate border-spacing-0 overflow-y-auto; +} + +.aui-md-root th { + @apply bg-aui-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [&[align=center]]:text-center [&[align=right]]:text-right; +} + +.aui-md-root td { + @apply border-b border-l px-4 py-2 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right; +} + +.aui-md-root tr { + @apply m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg; +} + +.aui-md-root sup { + @apply [&>a]:text-xs [&>a]:no-underline; +} + +.aui-md-root pre { + @apply overflow-x-auto rounded-b-lg bg-black p-4 text-white; +} + +.aui-md-root :not(pre) code { + @apply bg-aui-muted rounded border font-semibold; +} + +.aui-code-header-root { + @apply flex items-center justify-between gap-4 rounded-t-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white; +} + +.aui-code-header-language { + @apply lowercase [&>span]:text-xs; +} diff --git a/packages/react-ui/src/styles/modal.css b/packages/react-ui/src/styles/modal.css new file mode 100644 index 000000000..9dd238989 --- /dev/null +++ b/packages/react-ui/src/styles/modal.css @@ -0,0 +1,29 @@ +.aui-root.aui-modal-content { + @apply bg-aui-popover text-aui-popover-foreground z-50 h-[500px] w-[400px] overflow-clip rounded-xl border p-0 shadow-md outline-none; + @apply [&>.aui-thread-root]:bg-inherit; + + @apply data-[state=closed]:animate-out data-[state=open]:animate-in; + @apply data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0; + @apply data-[state=closed]:zoom-out data-[state=open]:zoom-in; + @apply data-[state=open]:slide-in-from-bottom-1/2 data-[state=open]:slide-in-from-right-1/2 data-[state=closed]:slide-out-to-bottom-1/2 data-[state=closed]:slide-out-to-right-1/2; +} + +.aui-root.aui-modal-anchor { + @apply fixed bottom-4 right-4 size-11; +} + +.aui-root .aui-modal-button { + @apply size-full rounded-full shadow transition-transform hover:scale-110 active:scale-90; +} + +.aui-root .aui-modal-button-closed-icon { + @apply absolute size-6 transition-all; + @apply data-[state=closed]:rotate-0 data-[state=open]:rotate-90; + @apply data-[state=closed]:scale-100 data-[state=open]:scale-0; +} + +.aui-root .aui-modal-button-open-icon { + @apply absolute size-6 transition-all; + @apply data-[state=closed]:-rotate-90 data-[state=open]:rotate-0; + @apply data-[state=closed]:scale-0 data-[state=open]:scale-100; +} diff --git a/packages/react-ui/src/styles/thread.css b/packages/react-ui/src/styles/thread.css new file mode 100644 index 000000000..2a03ff0e7 --- /dev/null +++ b/packages/react-ui/src/styles/thread.css @@ -0,0 +1,159 @@ +/* thread */ +.aui-root.aui-thread-root { + @apply bg-aui-background box-border h-full; + @apply [&>.aui-thread-viewport]:bg-inherit; +} + +.aui-root .aui-thread-viewport { + @apply bg-aui-background flex h-full flex-col items-center overflow-y-scroll scroll-smooth px-4 pt-8; +} + +.aui-root .aui-thread-viewport-footer { + @apply sticky bottom-0 mt-4 flex w-full max-w-2xl flex-grow flex-col items-center justify-end rounded-t-lg bg-inherit pb-4; +} + +.aui-root .aui-thread-scroll-to-bottom { + @apply absolute -top-8 rounded-full disabled:invisible; +} + +/* thread welcome */ + +.aui-root .aui-thread-welcome-root { + @apply flex w-full max-w-2xl flex-grow basis-full flex-col; +} + +.aui-root .aui-thread-welcome-center { + @apply flex w-full flex-grow flex-col items-center justify-center; +} + +.aui-root .aui-thread-welcome-message { + @apply mt-4 font-medium; +} + +.aui-root .aui-thread-welcome-suggestion-container { + @apply mt-4 flex w-full items-stretch justify-center gap-4; +} + +.aui-root .aui-thread-welcome-suggestion { + @apply flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-lg border px-3 py-3; +} + +.aui-root .aui-thread-welcome-suggestion-text { + @apply line-clamp-2 text-ellipsis text-sm font-semibold; +} + +/* composer */ + +.aui-root .aui-composer-root { + @apply relative flex w-full items-end rounded-lg border transition-shadow focus-within:shadow-sm; +} + +.aui-root .aui-composer-input { + @apply placeholder:text-aui-muted-foreground size-full max-h-40 resize-none bg-transparent p-4 pr-12 text-sm outline-none; +} + +.aui-root .aui-composer-send, +.aui-root .aui-composer-cancel { + @apply absolute bottom-0 right-0 m-2.5 size-8 p-2 transition-opacity; +} + +/* user message */ + +.aui-root .aui-user-message-root { + @apply grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 [&>*]:col-start-2; + @apply w-full max-w-2xl py-4; +} + +.aui-root .aui-user-message-root > .aui-user-action-bar-root { + @apply col-start-1 mr-3 mt-2.5; +} + +.aui-root .aui-user-message-root > .aui-user-message-content { + @apply col-start-2 row-start-1; +} + +.aui-root .aui-user-message-root > .aui-branch-picker-root { + @apply col-span-full col-start-1 row-start-2; + @apply -mr-1 justify-end; +} + +.aui-root .aui-user-message-content { + @apply bg-aui-muted text-aui-foreground max-w-xl break-words rounded-3xl px-5 py-2.5; +} + +/* thread action bar */ + +.aui-root .aui-user-action-bar-root { + @apply flex flex-col items-end; +} + +.aui-root .aui-edit-composer-root { + @apply bg-aui-muted my-4 flex w-full max-w-2xl flex-col gap-2 rounded-xl; +} + +.aui-root .aui-edit-composer-input { + @apply text-aui-foreground flex h-8 w-full resize-none bg-transparent p-4 pb-0 outline-none; +} + +.aui-root .aui-edit-composer-footer { + @apply mx-3 mb-3 flex items-center justify-center gap-2 self-end; +} + +/* assistant message */ + +.aui-root .aui-assistant-message-root { + @apply grid grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr]; + @apply relative w-full max-w-2xl py-4; +} + +.aui-root .aui-assistant-message-root > .aui-avatar-root { + @apply col-start-1 row-span-full row-start-1 mr-4; +} + +.aui-root .aui-assistant-message-root > .aui-branch-picker-root { + @apply col-start-2 row-start-2; + @apply -ml-2 mr-2; +} + +.aui-root .aui-assistant-message-root > .aui-assistant-action-bar-root { + @apply col-start-3 row-start-2; + @apply -ml-1; +} + +.aui-root .aui-assistant-message-root > .aui-assistant-message-content { + @apply col-span-2 col-start-2 row-start-1 my-1.5; +} + +.aui-root .aui-assistant-message-content { + @apply text-aui-foreground max-w-xl break-words leading-7; +} + +/* assistant action bar */ + +.aui-root .aui-assistant-action-bar-root { + @apply text-aui-muted-foreground flex gap-1; +} + +.aui-root .aui-assistant-action-bar-root[data-floating] { + @apply bg-aui-background absolute rounded-md border p-1 shadow-sm; +} + +/* branch picker */ + +.aui-root .aui-branch-picker-root { + @apply text-aui-muted-foreground inline-flex items-center text-xs; +} + +.aui-root .aui-branch-picker-state { + @apply font-medium; +} + +/* text */ + +.aui-root .aui-text { + @apply whitespace-pre-line; +} + +.aui-root .aui-text-in-progress::after { + @apply animate-pulse font-sans content-['\25CF'] ltr:ml-1 rtl:mr-1; +} diff --git a/packages/react-ui/src/tailwindcss.ts b/packages/react-ui/src/tailwindcss.ts index cf5d95693..62b3a7971 100644 --- a/packages/react-ui/src/tailwindcss.ts +++ b/packages/react-ui/src/tailwindcss.ts @@ -15,19 +15,31 @@ const auiPlugin = plugin.withOptions( if (thread) { addComponents({ - '@import "@assistant-ui/react-ui/styles.css"': "", + '@import "@assistant-ui/react-ui/tailwindcss/styles/base-components.css"': + "", + }); + addComponents({ + '@import "@assistant-ui/react-ui/tailwindcss/styles/thread.css"': "", }); if (!shadcn) { addComponents({ - '@import "@assistant-ui/react-ui/themes/default.css"': "", + '@import "@assistant-ui/react-ui/tailwindcss/themes/default.css"': + "", }); } } + if (assistantModal) { + addComponents({ + '@import "@assistant-ui/react-ui/tailwindcss/styles/modal.css"': "", + }); + } + if (markdown) { addComponents({ - '@import "@assistant-ui/react-ui/markdown-styles.css"': "", + '@import "@assistant-ui/react-ui/tailwindcss/styles/markdown.css"': + "", }); } }, diff --git a/packages/react-ui/src/themes/shadcn.css b/packages/react-ui/src/themes/shadcn.css deleted file mode 100644 index 0aead8f80..000000000 --- a/packages/react-ui/src/themes/shadcn.css +++ /dev/null @@ -1,61 +0,0 @@ -:root { - --aui-background: var(--background, 0 0% 100%); - --aui-foreground: var(--foreground, 240 10% 3.9%); - - --aui-card: var(--card, 0 0% 100%); - --aui-card-foreground: var(--card-foreground, 240 10% 3.9%); - - --aui-popover: var(--popover, 0 0% 100%); - --aui-popover-foreground: var(--popover-foreground, 240 10% 3.9%); - - --aui-primary: var(--primary, 240 5.9% 10%); - --aui-primary-foreground: var(--primary-foreground, 0 0% 98%); - - --aui-secondary: var(--secondary, 240 4.8% 95.9%); - --aui-secondary-foreground: var(--secondary-foreground, 240 5.9% 10%); - - --aui-muted: var(--muted, 240 4.8% 95.9%); - --aui-muted-foreground: var(--muted-foreground, 240 3.8% 46.1%); - - --aui-accent: var(--accent, 240 4.8% 95.9%); - --aui-accent-foreground: var(--accent-foreground, 240 5.9% 10%); - - --aui-destructive: var(--destructive, 0 84.2% 60.2%); - --aui-destructive-foreground: var(--destructive-foreground, 0 0% 98%); - - --aui-border: var(--border, 240 5.9% 90%); - --aui-input: var(--input, 240 5.9% 90%); - --aui-ring: var(--ring, 240 10% 3.9%); - - --aui-radius: var(--radius, 0.5rem); -} - -.dark { - --aui-background: var(--background, 0 0% 7%); - --aui-foreground: var(--foreground, 0 0% 98%); - - --aui-card: var(--card, 240 10% 3.9%); - --aui-card-foreground: var(--card-foreground, 0 0% 98%); - - --aui-popover: var(--popover, 240 10% 3.9%); - --aui-popover-foreground: var(--popover-foreground, 0 0% 98%); - - --aui-primary: var(--primary, 0 0% 98%); - --aui-primary-foreground: var(--primary-foreground, 240 5.9% 10%); - - --aui-secondary: var(--secondary, 240 3.7% 15.9%); - --aui-secondary-foreground: var(--secondary-foreground, 0 0% 98%); - - --aui-muted: var(--muted, 240 3.7% 15.9%); - --aui-muted-foreground: var(--muted-foreground, 240 5% 64.9%); - - --aui-accent: var(--accent, 240 3.7% 15.9%); - --aui-accent-foreground: var(--accent-foreground, 0 0% 98%); - - --aui-destructive: var(--destructive, 0 62.8% 30.6%); - --aui-destructive-foreground: var(--destructive-foreground, 0 0% 98%); - - --aui-border: var(--border, 240 3.7% 15.9%); - --aui-input: var(--input, 240 3.7% 15.9%); - --aui-ring: var(--ring, 240 4.9% 83.9%); -} diff --git a/packages/react-ui/tailwind.config.ts b/packages/react-ui/tailwind.config.ts index eb7207732..ab232effb 100644 --- a/packages/react-ui/tailwind.config.ts +++ b/packages/react-ui/tailwind.config.ts @@ -1,4 +1,5 @@ import type { Config } from "tailwindcss"; +import auiPlugin from "./src/tailwindcss"; const config = { content: ["./src/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}"], @@ -48,7 +49,7 @@ const config = { }, }, }, - plugins: [require("tailwindcss-animate"), require("./src/tailwindcss")], + plugins: [require("tailwindcss-animate"), auiPlugin], } satisfies Config; export default config; diff --git a/packages/react-ui/tsconfig.json b/packages/react-ui/tsconfig.json index f5a0a2ff2..5c3cea088 100644 --- a/packages/react-ui/tsconfig.json +++ b/packages/react-ui/tsconfig.json @@ -5,6 +5,6 @@ "@assistant-ui/*": ["../../packages/*/src"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "scripts/build.mts"], "exclude": ["node_modules"] } diff --git a/packages/react-ui/tsup.config.ts b/packages/react-ui/tsup.config.ts deleted file mode 100644 index b28f8b6a5..000000000 --- a/packages/react-ui/tsup.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { defineConfig } from "tsup"; - -export default defineConfig(() => { - return { - entry: [ - "src/index.ts", - "src/styles.css", - "src/markdown-styles.css", - "src/themes/default.css", - "src/themes/shadcn.css", - ], - format: ["cjs", "esm"], - dts: true, - sourcemap: true, - clean: true, - esbuildOptions: (options) => { - options.banner = { - js: '"use client";', - }; - }, - }; -}); diff --git a/packages/react-ui/tsup.plugin.config.ts b/packages/react-ui/tsup.plugin.config.ts deleted file mode 100644 index 6e3119b9c..000000000 --- a/packages/react-ui/tsup.plugin.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from "tsup"; - -export default defineConfig(() => { - return { - entry: ["src/tailwindcss.ts"], - format: ["cjs", "esm"], - dts: true, - sourcemap: true, - external: ["tailwindcss/plugin"], - }; -}); diff --git a/packages/tailwindcss-transformer/README b/packages/tailwindcss-transformer/README deleted file mode 100644 index 2df42c0f2..000000000 --- a/packages/tailwindcss-transformer/README +++ /dev/null @@ -1,56 +0,0 @@ -# `@assistant-ui-tsup/tailwindcss-transformer` - -Input: - -```jsx -export function Example({ flag }) { - let className = cn('absolute inset-0', flag && 'uppercase'); - return
; -} -``` - -Ouput: - -```jsx -export function Example({ flag }) { - let className = cn('cl-7601190e', flag && 'cl-d2cf63c7'); - return
; -} -``` - -```css -.cl-7601190e { - @apply absolute inset-0; -} - -.cl-d2cf63c7 { - @apply uppercase; -} - -.cl-f64ae6a6 { - @apply flex items-center text-sm; -} -``` - -```css -.cl-7601190e { - position: absolute; - inset: 0; -} - -.cl-d2cf63c7 { - text-transform: uppercase; -} - -.cl-f64ae6a6 { - display: flex; - align-items: center; - font-size: 0.875rem; -} -``` - -### Credits and License - -Forked from [@clerk/tailwindcss-transformer](https://github.com/clerk/javascript/tree/main/packages/tailwindcss-transformer). -[Original MIT license](https://github.com/clerk/javascript/blob/main/packages/tailwindcss-transformer/LICENSE) - diff --git a/packages/tailwindcss-transformer/package.json b/packages/tailwindcss-transformer/package.json index bf8f29873..a944ea603 100644 --- a/packages/tailwindcss-transformer/package.json +++ b/packages/tailwindcss-transformer/package.json @@ -1,24 +1,14 @@ { - "name": "@assistant-ui-tsup/tailwindcss-transformer", + "name": "@assistant-ui/tailwindcss-transformer", "version": "0.1.0", "private": true, "license": "MIT", - "main": "./dist/index.js", - "scripts": { - "build": "tsup src/index.ts --format cjs --dts --sourcemap --clean" - }, "dependencies": { - "autoprefixer": "^10.4.19", "postcss": "^8.4.39", - "postcss-value-parser": "^4.2.0", - "recast": "^0.23.9", - "tailwindcss": "^3.4.4" + "postcss-value-parser": "^4.2.0" }, "devDependencies": { "@assistant-ui/tsconfig": "workspace:*", - "@types/node": "^20.14.9", - "eslint-config-next": "14.2.4", - "tsup": "^8.1.0", - "typescript": "^5.5.3" + "eslint-config-next": "14.2.4" } } diff --git a/packages/tailwindcss-transformer/src/index.ts b/packages/tailwindcss-transformer/src/index.ts index f1cc5cc1e..f36ddef97 100644 --- a/packages/tailwindcss-transformer/src/index.ts +++ b/packages/tailwindcss-transformer/src/index.ts @@ -1,164 +1,40 @@ -import { createHash } from "node:crypto"; +import { type Declaration, Plugin } from "postcss"; +import valueParser, { type ParsedValue } from "postcss-value-parser"; -import postcss from "postcss"; -import * as recast from "recast"; -import * as tsParser from "recast/parsers/babel-ts.js"; -import tailwindcss from "tailwindcss"; -import autoprefixer from "autoprefixer"; - -import { replaceVariableScope } from "./replace-variable-scope"; - -/** - * A map of hashed classnames from Tailwind CSS classes and their original values - */ -type StyleCache = Map; - -const clRegex = /^aui-[a-z0-9-]+$/; - -function isBinaryExpression(node: recast.types.namedTypes.BinaryExpression) { - return recast.types.namedTypes.BinaryExpression.check(node); -} - -function isLogicalExpression(node: recast.types.namedTypes.LogicalExpression) { - return recast.types.namedTypes.LogicalExpression.check(node); -} - -function isRightmostOperand(path: any) { - let parentPath = path.parentPath; - while (isLogicalExpression(parentPath.node)) { - if (parentPath.node.right !== path.node) { - return false; - } - parentPath = parentPath.parentPath; - } - return true; -} - -function generateHashedClassName(value: string) { - return ( - "aui-" + - createHash("sha256").update(value, "utf8").digest("hex").slice(0, 8) - ); -} - -function visitNode( - node: recast.types.ASTNode, - ctx: { styleCache: StyleCache }, - visitors?: recast.types.Visitor, -) { - recast.visit(node, { - visitStringLiteral(path) { - if (clRegex.test(path.node.value)) { - return false; - } - if (isBinaryExpression(path.parentPath.node)) { - return false; - } - if ( - isLogicalExpression(path.parentPath.node) && - !isRightmostOperand(path) - ) { - return false; - } - if ( - path.parentPath.node.type === "ObjectProperty" && - path.parentPath.node.key === path.node - ) { - return false; - } - - const cn = generateHashedClassName(path.node.value); - ctx.styleCache.set(cn, path.node.value); - path.node.value = cn; - return false; - }, - ...visitors, - }); -} - -export function transform(code: string, ctx: { styleCache: StyleCache }) { - const ast = recast.parse(code, { parser: tsParser }); - - recast.visit(ast, { - // visit className attributes containing TW classes - visitJSXAttribute(path) { - const node = path.node; - if (node.name.name === "className") { - visitNode(node, ctx, { - // Stop traversal if we encounter a function call - // cn/cx/clsx/cva are handled by the `visitCallExpression` visitor - visitCallExpression() { - return false; - }, - }); +const tailwindcssAui = (): Plugin => ({ + postcssPlugin: "@assistant-ui/tailwindcss-transformer", + AtRule: { + keyframes: (atRule) => { + if (!atRule.params.startsWith("aui-")) { + atRule.params = `aui-${atRule.params}`; } - this.traverse(path); }, - // visit a `className` property within any object containing TW classes - visitObjectProperty(path) { - const node = path.node; - if ( - path.node.key.type === "Identifier" && - path.node.key.name === "className" - ) { - visitNode(node, ctx); - } - this.traverse(path); - }, - // visit function calls containing TW classes - visitCallExpression(path) { - const node = path.node; - // `className` concatenation functions - if ( - node.callee.type === "Identifier" && - ["cn", "cx", "clsx"].includes(node.callee.name) - ) { - visitNode(node, ctx); - } - // cva functions (note: only compatible with cva@1.0) - if ( - node.callee.type === "Identifier" && - node.callee.name === "cva" && - node.arguments[0]?.type === "ObjectExpression" - ) { - for (const property of node.arguments[0].properties) { - if ( - property.type === "ObjectProperty" && - property.key.type === "Identifier" && - ["base", "variants"].includes(property.key.name) - ) { - visitNode(property, ctx); + }, + Declaration(decl: Declaration) { + if (decl.prop.startsWith("--tw-")) { + decl.prop = decl.prop.replace("--tw-", "--aui-"); + } + const value: ParsedValue = valueParser(decl.value); + value.walk((node) => { + if (node.type === "function" && node.value === "var") { + node.nodes.forEach((n) => { + if (n.type === "word" && n.value.startsWith("--tw-")) { + n.value = n.value.replace("--tw-", "--aui-"); } - } + }); } - this.traverse(path); - }, - }); - - return recast.print(ast).code; -} + }); + decl.value = value.toString(); -export async function generateStylesheet( - styleCache: StyleCache, - ctx: { globalCss: string }, -) { - let stylesheet = "@tailwind base;\n\n"; - - if (ctx.globalCss) { - stylesheet += ctx.globalCss + "\n"; - } - - for (const [cn, value] of styleCache) { - stylesheet += `.${cn} { @apply ${value} }\n`; - } + if ( + (decl.prop === "animation" || decl.prop === "animation-name") && + !decl.value.startsWith("aui-") + ) { + decl.value = `aui-${decl.value}`; + } + }, +}); - const result = await postcss([ - tailwindcss(), - replaceVariableScope, - autoprefixer(), - ]).process(stylesheet, { - from: "styles.css", - }); +tailwindcssAui.postcss = true; - return result.css.replace(/\n\n/g, "\n"); -} +export = tailwindcssAui; diff --git a/packages/tailwindcss-transformer/src/replace-variable-scope.ts b/packages/tailwindcss-transformer/src/replace-variable-scope.ts deleted file mode 100644 index ff7c9543b..000000000 --- a/packages/tailwindcss-transformer/src/replace-variable-scope.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { type Declaration, type Plugin } from "postcss"; -import valueParser, { type ParsedValue } from "postcss-value-parser"; - -export const replaceVariableScope: Plugin = { - postcssPlugin: "Replace variable scope", - Declaration(decl: Declaration) { - if (decl.prop.startsWith("--tw-")) { - decl.prop = decl.prop.replace("--tw-", "--aui-"); - } - const value: ParsedValue = valueParser(decl.value); - value.walk((node) => { - if (node.type === "function" && node.value === "var") { - node.nodes.forEach((n) => { - if (n.type === "word" && n.value.startsWith("--tw-")) { - n.value = n.value.replace("--tw-", "--aui-"); - } - }); - } - }); - decl.value = value.toString(); - }, -}; diff --git a/packages/tailwindcss-transformer/tsconfig.json b/packages/tailwindcss-transformer/tsconfig.json index 09a74b1dc..4526d80fc 100644 --- a/packages/tailwindcss-transformer/tsconfig.json +++ b/packages/tailwindcss-transformer/tsconfig.json @@ -4,7 +4,9 @@ "paths": { "@assistant-ui/*": ["../../packages/*/src"], "@assistant-ui/react/*": ["../../packages/react/src/*"] - } + }, + "moduleResolution": "Node", + "module": "CommonJS" }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ee81cad49..8219d6fff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,22 +82,22 @@ importers: version: 2.1.1 fumadocs-core: specifier: 12.4.1 - version: 12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fumadocs-mdx: specifier: 8.2.33 - version: 8.2.33(fumadocs-core@12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + version: 8.2.33(fumadocs-core@12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6)) fumadocs-ui: specifier: 12.4.1 - version: 12.4.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.4) + version: 12.4.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.4) geist: specifier: ^1.3.0 - version: 1.3.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + version: 1.3.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6)) lucide-react: specifier: ^0.400.0 version: 0.400.0(react@18.3.1) next: specifier: ^14.2.4 - version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) react: specifier: ^18.3.1 version: 18.3.1 @@ -188,7 +188,7 @@ importers: version: 5.0.7 next: specifier: 14.2.4 - version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) react: specifier: ^18.3.1 version: 18.3.1 @@ -267,7 +267,7 @@ importers: version: 0.400.0(react@18.3.1) next: specifier: 14.2.4 - version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) react: specifier: ^18 version: 18.3.1 @@ -337,7 +337,7 @@ importers: version: 0.400.0(react@18.3.1) next: specifier: 14.2.4 - version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) openai: specifier: ^4.52.3 version: 4.52.3 @@ -437,7 +437,7 @@ importers: version: 0.400.0(react@18.3.1) next: specifier: 14.2.4 - version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) react: specifier: ^18 version: 18.3.1 @@ -534,7 +534,7 @@ importers: version: 5.0.7 next: specifier: 14.2.4 - version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) react: specifier: ^18.3.1 version: 18.3.1 @@ -849,6 +849,9 @@ importers: specifier: ^15.5.0 version: 15.5.0(react@18.3.1) devDependencies: + '@assistant-ui/tailwindcss-transformer': + specifier: workspace:* + version: link:../tailwindcss-transformer '@assistant-ui/tsconfig': specifier: workspace:* version: link:../tsconfig @@ -879,6 +882,9 @@ importers: tsup: specifier: ^8.1.0 version: 8.1.0(postcss@8.4.39)(typescript@5.5.3) + tsx: + specifier: ^4.16.0 + version: 4.16.0 typescript: specifier: ^5.5.3 version: 5.5.3 @@ -972,37 +978,19 @@ importers: packages/tailwindcss-transformer: dependencies: - autoprefixer: - specifier: ^10.4.19 - version: 10.4.19(postcss@8.4.39) postcss: specifier: ^8.4.39 version: 8.4.39 postcss-value-parser: specifier: ^4.2.0 version: 4.2.0 - recast: - specifier: ^0.23.9 - version: 0.23.9 - tailwindcss: - specifier: ^3.4.4 - version: 3.4.4 devDependencies: '@assistant-ui/tsconfig': specifier: workspace:* version: link:../tsconfig - '@types/node': - specifier: ^20.14.9 - version: 20.14.9 eslint-config-next: specifier: 14.2.4 version: 14.2.4(eslint@8.57.0)(typescript@5.5.3) - tsup: - specifier: ^8.1.0 - version: 8.1.0(postcss@8.4.39)(typescript@5.5.3) - typescript: - specifier: ^5.5.3 - version: 5.5.3 packages/tsconfig: dependencies: @@ -3869,6 +3857,9 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} + immutable@4.3.6: + resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==} + import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -5145,6 +5136,11 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sass@1.77.6: + resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==} + engines: {node: '>=14.0.0'} + hasBin: true + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -8794,7 +8790,7 @@ snapshots: fsevents@2.3.3: optional: true - fumadocs-core@12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + fumadocs-core@12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@formatjs/intl-localematcher': 0.5.4 '@shikijs/rehype': 1.10.2 @@ -8802,7 +8798,7 @@ snapshots: flexsearch: 0.7.21 github-slugger: 2.0.0 negotiator: 0.6.3 - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) npm-to-yarn: 2.2.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -8818,20 +8814,20 @@ snapshots: - '@types/react' - supports-color - fumadocs-mdx@8.2.33(fumadocs-core@12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): + fumadocs-mdx@8.2.33(fumadocs-core@12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6)): dependencies: '@mdx-js/mdx': 3.0.1 cross-spawn: 7.0.3 estree-util-value-to-estree: 3.1.2 fast-glob: 3.3.2 - fumadocs-core: 12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + fumadocs-core: 12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) gray-matter: 4.0.3 - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) zod: 3.23.8 transitivePeerDependencies: - supports-color - fumadocs-ui@12.4.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.4): + fumadocs-ui@12.4.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.4): dependencies: '@radix-ui/react-accordion': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-collapsible': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -8843,9 +8839,9 @@ snapshots: '@tailwindcss/typography': 0.5.13(tailwindcss@3.4.4) class-variance-authority: 0.7.0 cmdk: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - fumadocs-core: 12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + fumadocs-core: 12.4.1(@types/react@18.3.3)(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lucide-react: 0.400.0(react@18.3.1) - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) next-themes: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -8868,9 +8864,9 @@ snapshots: functions-have-names@1.2.3: {} - geist@1.3.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): + geist@1.3.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6)): dependencies: - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6) gensync@1.0.0-beta.2: {} @@ -9133,6 +9129,9 @@ snapshots: ignore@5.3.1: {} + immutable@4.3.6: + optional: true + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 @@ -10019,7 +10018,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.6): dependencies: '@next/env': 14.2.4 '@swc/helpers': 0.5.5 @@ -10040,6 +10039,7 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.4 '@next/swc-win32-ia32-msvc': 14.2.4 '@next/swc-win32-x64-msvc': 14.2.4 + sass: 1.77.6 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -10685,6 +10685,13 @@ snapshots: safer-buffer@2.1.2: {} + sass@1.77.6: + dependencies: + chokidar: 3.6.0 + immutable: 4.3.6 + source-map-js: 1.2.0 + optional: true + scheduler@0.23.2: dependencies: loose-envify: 1.4.0