diff --git a/AGENTS.md b/AGENTS.md index 38bb0cf..4917323 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,6 +38,16 @@ The `pnpm test` script intentionally runs `build` first so `tsnapi` snapshots co - Utility imports use the package-path form `devframe/utils/*`, never relative `../utils/*`. - Dependencies go through the pnpm catalogs in `pnpm-workspace.yaml` (`cli`, `inlined`, `testing`, `types`) — add to a catalog and reference as `catalog:`, don't pin versions in `package.json`. +### Design system + +The built-in plugins share one design system, `@internal/design`, so they look and feel like one product across frameworks (the Git dashboard is React/Next, terminals is Svelte, code-server is vanilla DOM). It's an optional package plugins opt into — devframe core stays headless and ships no styling. + +- **One preset to extend.** Each plugin's `uno.config.ts` is just `presets: [presetDevframe()]` (imported from `@internal/design/preset`). The preset bundles `presetWind4` + `presetIcons` + the directive/variant-group transformers, the semantic token theme, and the shared `df-*` component shortcuts. Don't re-declare presets, palettes, or shortcuts per plugin. +- **One token source.** Import `@internal/design/theme.css` once on the page (after the generated UnoCSS stylesheet so its base layer wins). Token *values* (the `--df-*` custom properties, light + dark via the `.dark` class) live only there — never hardcode a palette in a plugin. +- **Shared component vocabulary.** Build UI from the `df-*` classes (`df-btn`, `df-badge`, `df-tab`, `df-navtab`, `df-nav`, `df-toolbar`, `df-card`, `df-input`, `df-dot`, `df-tag-*`, …) and the semantic token utilities (`bg-primary`, `text-muted-foreground`, `bg-card`, `border-border`, …). Markup differs per framework; the classes resolve identically, which is what keeps the surfaces consistent. Non-UnoCSS consumers can link the prebuilt `@internal/design/style.css`. +- **Component builders.** Prefer the framework-neutral recipes from `@internal/design/components` (`button`, `badge`, `tab`, `navTab`, `nav`, `toolbar`, `card`, `panel`, `input`, `link`, `dot`, `spinner`, `tag`) over hand-written class strings — they return the canonical `df-*` classes and read the same in React (`className=`), Svelte (`class=`) and vanilla DOM. Because these classes are assembled at runtime, the preset safelists the `df-*` vocabulary so UnoCSS always emits it; add new component classes to `DF_SAFELIST` when you extend the set. +- **Plain `.ts`/vanilla views** must opt `.ts` into UnoCSS extraction (`content.pipeline.include`), since UnoCSS only scans framework files by default. + ### Devframe design principles These reinforce devframe's positioning as "the container for one devtool integration, portable to multiple viewers". When in doubt, err on the side of "devframe provides primitives, the hub provides UX". diff --git a/alias.ts b/alias.ts index cb28bf8..eddbddf 100644 --- a/alias.ts +++ b/alias.ts @@ -45,6 +45,11 @@ export const alias = { '@devframes/hub': r('hub/src/index.ts'), '@devframes/nuxt/runtime/plugin.client': r('nuxt/src/runtime/plugin.client.ts'), '@devframes/nuxt': r('nuxt/src/index.ts'), + '@internal/design/preset': r('design/src/preset.ts'), + '@internal/design/components': r('design/src/components.ts'), + '@internal/design/tokens': r('design/src/tokens.ts'), + '@internal/design/theme.css': r('design/src/theme.css'), + '@internal/design': r('design/src/index.ts'), '@devframes/plugin-code-server/client': p('code-server/src/client/index.ts'), '@devframes/plugin-code-server/node': p('code-server/src/node/index.ts'), '@devframes/plugin-code-server/constants': p('code-server/src/constants.ts'), @@ -65,11 +70,14 @@ export const alias = { 'devframe': r('devframe/src'), } -// update tsconfig.base.json +// update tsconfig.base.json — CSS aliases exist for Vite resolution only; +// TypeScript resolves `*.css` side-effect imports through ambient shims. const raw = fs.readFileSync(join(root, 'tsconfig.base.json'), 'utf-8').trim() const tsconfig = JSON.parse(raw) tsconfig.compilerOptions.paths = Object.fromEntries( - Object.entries(alias).map(([key, value]) => [key, [`./${relative(root, value)}`]]), + Object.entries(alias) + .filter(([key]) => !key.endsWith('.css')) + .map(([key, value]) => [key, [`./${relative(root, value)}`]]), ) const newRaw = JSON.stringify(tsconfig, null, 2) if (newRaw !== raw) diff --git a/packages/design/package.json b/packages/design/package.json new file mode 100644 index 0000000..002fc87 --- /dev/null +++ b/packages/design/package.json @@ -0,0 +1,43 @@ +{ + "name": "@internal/design", + "type": "module", + "version": "0.5.4", + "private": true, + "description": "Internal, unpublished design system for devframe's built-in plugins — one UnoCSS preset, one token set, one shared component vocabulary, portable across frameworks.", + "author": "Anthony Fu ", + "license": "MIT", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": "./dist/index.mjs", + "./preset": "./dist/preset.mjs", + "./components": "./dist/components.mjs", + "./tokens": "./dist/tokens.mjs", + "./theme.css": "./dist/theme.css", + "./style.css": "./dist/style.css", + "./package.json": "./package.json" + }, + "types": "./dist/index.d.mts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsdown && tsx scripts/build-css.ts", + "watch": "tsdown --watch", + "typecheck": "tsc --noEmit", + "prepack": "pnpm run build" + }, + "peerDependencies": { + "unocss": "^66.0.0" + }, + "dependencies": { + "@iconify-json/ph": "catalog:frontend" + }, + "devDependencies": { + "@types/node": "catalog:types", + "tsdown": "catalog:build", + "tsx": "catalog:build", + "unocss": "catalog:frontend" + } +} diff --git a/packages/design/scripts/build-css.ts b/packages/design/scripts/build-css.ts new file mode 100644 index 0000000..710087f --- /dev/null +++ b/packages/design/scripts/build-css.ts @@ -0,0 +1,48 @@ +import { mkdir, readFile, writeFile } from 'node:fs/promises' +import { resolve } from 'node:path' +import process from 'node:process' +import { fileURLToPath } from 'node:url' +import { createGenerator } from 'unocss' +import { presetDevframe, shortcuts } from '../src/preset' + +/** + * Emit the design package's shipped CSS: + * + * - `dist/theme.css` — the `--df-*` token values + base layer, verbatim. + * - `dist/style.css` — a standalone stylesheet (UnoCSS preflights + every + * `df-*` component class + the tokens) for consumers that don't run UnoCSS + * themselves but still want the shared component vocabulary. + */ + +const root = fileURLToPath(new URL('..', import.meta.url)) +const distDir = resolve(root, 'dist') + +async function main(): Promise { + await mkdir(distDir, { recursive: true }) + + const theme = await readFile(resolve(root, 'src/theme.css'), 'utf8') + await writeFile(resolve(distDir, 'theme.css'), theme) + + // Materialize every named `df-*` shortcut (and a few palette tags) so the + // standalone stylesheet carries the full shared component vocabulary. + const names = new Set() + for (const entry of shortcuts) { + if (Array.isArray(entry)) + continue + for (const key of Object.keys(entry)) + names.add(key) + } + for (const color of ['blue', 'amber', 'green', 'red', 'sky', 'violet', 'rose']) + names.add(`df-tag-${color}`) + + const generator = await createGenerator({ presets: [presetDevframe()] }) + const { css } = await generator.generate(names, { preflights: true }) + + const banner = '/* @internal/design — prebuilt stylesheet. Generated by scripts/build-css.ts; do not edit. */\n' + await writeFile(resolve(distDir, 'style.css'), `${banner}${css}\n${theme}`) +} + +main().catch((error) => { + console.error(error) + process.exit(1) +}) diff --git a/packages/design/src/components.ts b/packages/design/src/components.ts new file mode 100644 index 0000000..2bcc22a --- /dev/null +++ b/packages/design/src/components.ts @@ -0,0 +1,166 @@ +/** + * Shared component recipes. + * + * These framework-neutral builders are the devframe "components": each returns + * the canonical `df-*` class string for an element, so React (`className=`), + * Svelte (`class=`) and vanilla DOM (`el.className =`) all describe the same + * button, panel, tab or nav the same way and render identically. + * + * Because the class strings are assembled at runtime, the `df-*` vocabulary is + * safelisted by the preset (see {@link DF_SAFELIST}) so UnoCSS always emits it + * regardless of static extraction. + */ + +/** Join truthy class fragments into a single class string. */ +export function cx(...parts: Array): string { + return parts.filter(Boolean).join(' ') +} + +export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link' +export type ButtonSize = 'md' | 'sm' | 'lg' | 'icon' | 'icon-sm' + +export interface ButtonProps { + variant?: ButtonVariant + size?: ButtonSize + /** Extra classes appended after the recipe. */ + class?: string +} + +/** A button. `df-btn` + a variant, optionally a non-default size. */ +export function button({ variant = 'primary', size = 'md', class: extra }: ButtonProps = {}): string { + return cx('df-btn', `df-btn-${variant}`, size !== 'md' && `df-btn-${size}`, extra) +} + +export type BadgeVariant = 'primary' | 'secondary' | 'success' | 'warning' | 'destructive' | 'outline' + +export interface BadgeProps { + variant?: BadgeVariant + class?: string +} + +/** A solid/semantic badge (the variant class already includes the `df-badge` base). */ +export function badge({ variant = 'secondary', class: extra }: BadgeProps = {}): string { + return cx(`df-badge-${variant}`, extra) +} + +/** A soft, palette-driven tag (`df-tag-blue`, `df-tag-amber`, …). */ +export function tag(color: string, extra?: string): string { + return cx(`df-tag-${color}`, extra) +} + +/** The container for a set of segmented tabs. */ +export function tabsList(extra?: string): string { + return cx('df-tabs-list', extra) +} + +/** A segmented tab (active state is driven by `data-state="active"` on the element). */ +export function tab(extra?: string): string { + return cx('df-tab', extra) +} + +export interface NavTabProps { + active?: boolean + class?: string +} + +/** A closeable navigation tab (terminal sessions, open documents, …). */ +export function navTab({ active = false, class: extra }: NavTabProps = {}): string { + return cx('df-navtab', active && 'df-navtab-active', extra) +} + +/** A top navigation bar. */ +export function nav(extra?: string): string { + return cx('df-nav', extra) +} + +/** A secondary toolbar bar. */ +export function toolbar(extra?: string): string { + return cx('df-toolbar', extra) +} + +/** A card surface. */ +export function card(extra?: string): string { + return cx('df-card', extra) +} + +/** A flat panel surface. */ +export function panel(extra?: string): string { + return cx('df-panel', extra) +} + +/** A text input / textarea. */ +export function input(extra?: string): string { + return cx('df-input', extra) +} + +/** An inline link. */ +export function link(extra?: string): string { + return cx('df-link', extra) +} + +export type DotState = 'running' | 'idle' | 'error' + +/** A status dot for a lifecycle state. */ +export function dot(state: DotState, extra?: string): string { + return cx('df-dot', `df-dot-${state}`, extra) +} + +/** An indeterminate spinner. */ +export function spinner(extra?: string): string { + return cx('df-spinner', extra) +} + +/** + * The full fixed `df-*` vocabulary. The preset safelists this so the runtime + * builders above always have CSS to resolve to, even though their class strings + * never appear literally in scanned source. A representative set of palette + * tags is included for {@link tag}. + */ +export const DF_SAFELIST: string[] = [ + // buttons + 'df-btn', + 'df-btn-primary', + 'df-btn-secondary', + 'df-btn-outline', + 'df-btn-ghost', + 'df-btn-destructive', + 'df-btn-link', + 'df-btn-sm', + 'df-btn-lg', + 'df-btn-icon', + 'df-btn-icon-sm', + // badges + 'df-badge', + 'df-badge-primary', + 'df-badge-secondary', + 'df-badge-success', + 'df-badge-warning', + 'df-badge-destructive', + 'df-badge-outline', + // tabs + bars + 'df-tabs-list', + 'df-tab', + 'df-navtab', + 'df-navtab-active', + 'df-nav', + 'df-toolbar', + // surfaces + controls + 'df-card', + 'df-panel', + 'df-input', + 'df-link', + // status + 'df-dot', + 'df-dot-running', + 'df-dot-idle', + 'df-dot-error', + 'df-spinner', + // common palette tags + 'df-tag-blue', + 'df-tag-amber', + 'df-tag-green', + 'df-tag-red', + 'df-tag-sky', + 'df-tag-violet', + 'df-tag-rose', +] diff --git a/packages/design/src/index.ts b/packages/design/src/index.ts new file mode 100644 index 0000000..ccdf55f --- /dev/null +++ b/packages/design/src/index.ts @@ -0,0 +1,14 @@ +export * from './components' +export { presetDevframe, shortcuts } from './preset' +export type { PresetDevframeOptions } from './preset' +export { presetDevframe as default } from './preset' +export { + cssVar, + PAIRED_TOKENS, + radius, + SOLO_TOKENS, + TOKEN_PREFIX, + tokenColors, +} from './tokens' + +export type { DesignToken, PairedToken, SoloToken } from './tokens' diff --git a/packages/design/src/preset.ts b/packages/design/src/preset.ts new file mode 100644 index 0000000..4da1728 --- /dev/null +++ b/packages/design/src/preset.ts @@ -0,0 +1,149 @@ +import type { Preset } from 'unocss' +import { + definePreset, + presetIcons, + presetWind4, + transformerDirectives, + transformerVariantGroup, +} from 'unocss' +import { DF_SAFELIST } from './components' +import { radius, tokenColors } from './tokens' + +export interface PresetDevframeOptions { + /** + * Options forwarded to `presetIcons`. The default icon scale matches the + * inline-with-text sizing used across the built-in plugins. + */ + icons?: Parameters[0] +} + +/** + * The shared `df-*` component vocabulary. These shortcuts are the cross-frame + * "components": markup differs per framework (React, Svelte, vanilla DOM) but a + * `df-btn df-btn-primary` button — or a `df-badge`, `df-tab`, `df-card`, … — + * resolves to the same CSS everywhere, so they look and feel identical. The + * definitions mirror the flagship shadcn/ui primitives so a hand-written + * `df-btn` and a generated ` - @@ -276,7 +278,7 @@
No sessions. - diff --git a/plugins/terminals/src/client/index.ts b/plugins/terminals/src/client/index.ts index 737fc82..d0e4da9 100644 --- a/plugins/terminals/src/client/index.ts +++ b/plugins/terminals/src/client/index.ts @@ -4,6 +4,7 @@ import { mount, unmount } from 'svelte' import App from './App.svelte' import 'virtual:uno.css' +import '@internal/design/theme.css' import './styles.css' export interface MountTerminalsOptions { diff --git a/plugins/terminals/src/client/styles.css b/plugins/terminals/src/client/styles.css index 2005121..fdb3b95 100644 --- a/plugins/terminals/src/client/styles.css +++ b/plugins/terminals/src/client/styles.css @@ -1,3 +1,6 @@ +/* Terminal-specific surface tweaks. Tokens, base element styling, and the + `color-scheme` light/dark switch come from `@internal/design/theme.css`. */ + html, body, #app { @@ -6,15 +9,6 @@ body, padding: 0; } -html { - --uno: bg-base color-base font-sans; - color-scheme: light; -} - -html.dark { - color-scheme: dark; -} - :root { --term-scrollbar: #8884; --term-scrollbar-hover: #8887; diff --git a/plugins/terminals/uno.config.ts b/plugins/terminals/uno.config.ts index 68a570b..372c162 100644 --- a/plugins/terminals/uno.config.ts +++ b/plugins/terminals/uno.config.ts @@ -1,74 +1,9 @@ -import { - defineConfig, - presetIcons, - presetWind4, - transformerDirectives, - transformerVariantGroup, -} from 'unocss' +import { presetDevframe } from '@internal/design/preset' +import { defineConfig } from 'unocss' +// The terminals panel extends the shared devframe design system — one preset +// carries the token theme, the `df-*` component vocabulary, Phosphor icons, and +// the directive/variant-group transformers. Pair with `@internal/design/theme.css`. export default defineConfig({ - theme: { - colors: { - primary: { - 50: '#E9F4E7', - 100: '#D2E8CF', - 200: '#A9D3A2', - 300: '#7CBC71', - 400: '#49833E', - DEFAULT: '#49833E', - 500: '#3F7236', - 600: '#396831', - 700: '#2C5026', - 800: '#1D3419', - 900: '#0F1C0D', - 950: '#080E07', - }, - }, - }, - shortcuts: [ - { - // Neutral foundations (light + dark together). - 'color-base': 'color-neutral-800 dark:color-neutral-200', - 'bg-base': 'bg-white dark:bg-#111', - 'bg-secondary': 'bg-#f6f6f7 dark:bg-#191919', - 'border-base': 'border-#8882', - - // Accents layered on top of neutrals. - 'bg-active': 'bg-#8881', - 'color-active': 'color-primary-600 dark:color-primary-300', - 'border-active': 'border-primary-600/25 dark:border-primary-400/25', - - 'op-fade': 'op65 dark:op55', - 'op-mute': 'op40 dark:op30', - - // Reusable controls. - 'btn-action': 'inline-flex gap-1.5 items-center border border-base rounded px2 py1 op75 transition-colors hover:(op100 bg-active) disabled:(pointer-events-none op30)', - 'btn-action-sm': 'btn-action text-sm', - 'btn-action-active': 'color-active border-active! bg-active op100!', - 'btn-icon': 'inline-flex h-7 w-7 items-center justify-center rounded op50 transition-colors hover:(op100 bg-active) disabled:(pointer-events-none op30)', - - // Tabs. - 'tab-item': 'relative inline-flex gap-1.5 items-center max-w-52 px2 py1 rounded border border-transparent text-sm op-fade transition-colors hover:(op100 bg-active) cursor-pointer select-none', - 'tab-item-active': 'op100! bg-active border-base! color-base', - - // Status dots (real semantic state only). - 'dot-running': 'bg-primary-500 dark:bg-primary-400', - 'dot-exited': 'bg-neutral-400 dark:bg-neutral-500', - 'dot-error': 'bg-red-500', - - // Named depth layers. - 'z-nav': 'z-30', - 'z-toolbar': 'z-20', - }, - // mode badges: badge-mode- - [/^badge-(\w+)$/, ([, color]) => `bg-${color}-400/15 text-${color}-700 dark:text-${color}-300 border border-${color}-500/20`], - ], - presets: [ - presetWind4(), - presetIcons({ scale: 1.1 }), - ], - transformers: [ - transformerDirectives(), - transformerVariantGroup(), - ], + presets: [presetDevframe()], }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b33039b..25983c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,19 +132,7 @@ catalogs: '@sveltejs/vite-plugin-svelte': specifier: ^5.0.0 version: 5.1.1 - '@tailwindcss/postcss': - specifier: ^4.3.1 - version: 4.3.1 - '@tailwindcss/vite': - specifier: ^4.3.1 - version: 4.3.1 - '@unocss/preset-icons': - specifier: ^66.0.0 - version: 66.7.2 - '@unocss/preset-uno': - specifier: ^66.0.0 - version: 66.7.2 - '@unocss/vite': + '@unocss/postcss': specifier: ^66.0.0 version: 66.7.2 '@xterm/addon-fit': @@ -180,12 +168,6 @@ catalogs: tailwind-merge: specifier: ^3.6.0 version: 3.6.0 - tailwindcss: - specifier: ^4.3.1 - version: 4.3.1 - tw-animate-css: - specifier: ^1.4.0 - version: 1.4.0 unocss: specifier: ^66.0.0 version: 66.7.2 @@ -494,6 +476,25 @@ importers: specifier: catalog:deps version: 8.21.0 + packages/design: + dependencies: + '@iconify-json/ph': + specifier: catalog:frontend + version: 1.2.2 + devDependencies: + '@types/node': + specifier: catalog:types + version: 25.9.1 + tsdown: + specifier: catalog:build + version: 0.22.0(oxc-resolver@11.21.3)(tsx@4.22.3)(typescript@6.0.3) + tsx: + specifier: catalog:build + version: 4.22.3 + unocss: + specifier: catalog:frontend + version: 66.7.2(@unocss/postcss@66.7.2(postcss@8.5.15))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) + packages/devframe: dependencies: '@valibot/to-json-schema': @@ -625,6 +626,12 @@ importers: specifier: catalog:deps version: 1.1.4 devDependencies: + '@iconify-json/ph': + specifier: catalog:frontend + version: 1.2.2 + '@internal/design': + specifier: workspace:* + version: link:../../packages/design '@storybook/html-vite': specifier: catalog:storybook version: 10.4.6(esbuild@0.28.0)(rollup@4.60.3)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) @@ -643,6 +650,9 @@ importers: tsdown: specifier: catalog:build version: 0.22.0(oxc-resolver@11.21.3)(tsx@4.22.3)(typescript@6.0.3) + unocss: + specifier: catalog:frontend + version: 66.7.2(@unocss/postcss@66.7.2(postcss@8.5.15))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) vite: specifier: catalog:build version: 8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) @@ -662,6 +672,9 @@ importers: specifier: catalog:deps version: 2.0.3 devDependencies: + '@internal/design': + specifier: workspace:* + version: link:../../packages/design '@radix-ui/react-scroll-area': specifier: catalog:frontend version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -683,18 +696,15 @@ importers: '@storybook/react-vite': specifier: catalog:storybook version: 10.4.6(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(esbuild@0.28.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.3)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) - '@tailwindcss/postcss': - specifier: catalog:frontend - version: 4.3.1 - '@tailwindcss/vite': - specifier: catalog:frontend - version: 4.3.1(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) '@types/react': specifier: catalog:types version: 19.2.15 '@types/react-dom': specifier: catalog:types version: 19.2.3(@types/react@19.2.15) + '@unocss/postcss': + specifier: catalog:frontend + version: 66.7.2(postcss@8.5.15) '@vitejs/plugin-react-oxc': specifier: catalog:storybook version: 0.4.3(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) @@ -728,15 +738,12 @@ importers: tailwind-merge: specifier: catalog:frontend version: 3.6.0 - tailwindcss: - specifier: catalog:frontend - version: 4.3.1 tsdown: specifier: catalog:build version: 0.22.0(oxc-resolver@11.21.3)(tsx@4.22.3)(typescript@6.0.3) - tw-animate-css: + unocss: specifier: catalog:frontend - version: 1.4.0 + version: 66.7.2(@unocss/postcss@66.7.2(postcss@8.5.15))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) vitest: specifier: catalog:testing version: 4.1.7(@types/node@25.9.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) @@ -765,21 +772,15 @@ importers: '@iconify-json/ph': specifier: catalog:frontend version: 1.2.2 + '@internal/design': + specifier: workspace:* + version: link:../../packages/design '@sveltejs/vite-plugin-svelte': specifier: catalog:frontend version: 5.1.1(svelte@5.56.3(@typescript-eslint/types@8.59.2))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) '@types/node': specifier: catalog:types version: 25.9.1 - '@unocss/preset-icons': - specifier: catalog:frontend - version: 66.7.2 - '@unocss/preset-uno': - specifier: catalog:frontend - version: 66.7.2 - '@unocss/vite': - specifier: catalog:frontend - version: 66.7.2(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) devframe: specifier: workspace:* version: link:../../packages/devframe @@ -797,7 +798,7 @@ importers: version: 0.22.0(oxc-resolver@11.21.3)(tsx@4.22.3)(typescript@6.0.3) unocss: specifier: catalog:frontend - version: 66.7.2(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) + version: 66.7.2(@unocss/postcss@66.7.2(postcss@8.5.15))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) vite: specifier: catalog:build version: 8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) @@ -820,10 +821,6 @@ packages: '@adobe/css-tools@4.5.0': resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - '@antfu/eslint-config@9.0.0': resolution: {integrity: sha512-8aQW0UWHoNMdVxTfzs1+w10t26plsc9oFs8YhCyCtST5nnANJe/VAjqvR3hYI1l3PHBeo4tjVMg8wuu6g3OLlA==} hasBin: true @@ -3514,103 +3511,6 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@tailwindcss/node@4.3.1': - resolution: {integrity: sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A==} - - '@tailwindcss/oxide-android-arm64@4.3.1': - resolution: {integrity: sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [android] - - '@tailwindcss/oxide-darwin-arm64@4.3.1': - resolution: {integrity: sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.3.1': - resolution: {integrity: sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - '@tailwindcss/oxide-freebsd-x64@4.3.1': - resolution: {integrity: sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g==} - engines: {node: '>= 20'} - cpu: [x64] - os: [freebsd] - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1': - resolution: {integrity: sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg==} - engines: {node: '>= 20'} - cpu: [arm] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-gnu@4.3.1': - resolution: {integrity: sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-arm64-musl@4.3.1': - resolution: {integrity: sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-linux-x64-gnu@4.3.1': - resolution: {integrity: sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-x64-musl@4.3.1': - resolution: {integrity: sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-wasm32-wasi@4.3.1': - resolution: {integrity: sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-win32-arm64-msvc@4.3.1': - resolution: {integrity: sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [win32] - - '@tailwindcss/oxide-win32-x64-msvc@4.3.1': - resolution: {integrity: sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [win32] - - '@tailwindcss/oxide@4.3.1': - resolution: {integrity: sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA==} - engines: {node: '>= 20'} - - '@tailwindcss/postcss@4.3.1': - resolution: {integrity: sha512-dNJuNbdEJT/SWRuXTYP1WSamelsz3ztkUsdtWQPjrexysrTpaEPM40P/71knXiXLYEojqPOEGitVLLpPMS5T6A==} - - '@tailwindcss/vite@4.3.1': - resolution: {integrity: sha512-hItDHuIIlEV61R+faXu66s1K36aTurO/Qw0e45Vskz57gXl9pWOT6eg3zmcEui6CZXddbN7zd41bwmvag4JGwQ==} - peerDependencies: - vite: ^5.2.0 || ^6 || ^7 || ^8 - '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -3936,6 +3836,11 @@ packages: '@unocss/inspector@66.7.2': resolution: {integrity: sha512-fvZ8w9dTnu61ZwbXjVMQopxxrQOnFOBN2I6KVPJtoUSMsatrpEYyJHDA9pfLes1a3C4eEJZaSADURHKkON09CA==} + '@unocss/postcss@66.7.2': + resolution: {integrity: sha512-q5gRA/B3f2SZtM/MIWSLqCUSjCYdh8t9iIwsrRY9NGycFBLovbBelhM6ye3Uxa+2jWUO0ZbDPbZgS93lajGQfw==} + peerDependencies: + postcss: ^8.4.21 + '@unocss/preset-attributify@66.7.2': resolution: {integrity: sha512-JnnoRUgOL4O565+jNi8BfzTQDElEny1reaMhrdYQR4P4I7cfdRV89R5DsmND0H2mGtwJjP/gL4cWd1FSX9ShrA==} @@ -7499,9 +7404,6 @@ packages: tailwind-merge@3.6.0: resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} - tailwindcss@4.3.1: - resolution: {integrity: sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q==} - tapable@2.3.3: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} @@ -7663,9 +7565,6 @@ packages: resolution: {integrity: sha512-VpKvD9Z0Hu/xrGUAYX1wnhfpqv835wIwGqeKfulvBPTOcDap0E3nFwyzCAVV85fB1sBcBDEfTP+7FSW7GzwWSQ==} hasBin: true - tw-animate-css@1.4.0: - resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -8310,8 +8209,6 @@ snapshots: '@adobe/css-tools@4.5.0': {} - '@alloc/quick-lru@5.2.0': {} - '@antfu/eslint-config@9.0.0(@typescript-eslint/rule-tester@8.59.2(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(@typescript-eslint/typescript-estree@8.59.2(typescript@6.0.3))(@typescript-eslint/utils@8.59.2(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.34)(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.7(@types/node@25.9.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)))': dependencies: '@antfu/install-pkg': 1.1.0 @@ -10590,82 +10487,6 @@ snapshots: dependencies: tslib: 2.8.1 - '@tailwindcss/node@4.3.1': - dependencies: - '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.21.6 - jiti: 2.7.0 - lightningcss: 1.32.0 - magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.3.1 - - '@tailwindcss/oxide-android-arm64@4.3.1': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.3.1': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.3.1': - optional: true - - '@tailwindcss/oxide-freebsd-x64@4.3.1': - optional: true - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1': - optional: true - - '@tailwindcss/oxide-linux-arm64-gnu@4.3.1': - optional: true - - '@tailwindcss/oxide-linux-arm64-musl@4.3.1': - optional: true - - '@tailwindcss/oxide-linux-x64-gnu@4.3.1': - optional: true - - '@tailwindcss/oxide-linux-x64-musl@4.3.1': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.3.1': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.3.1': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.3.1': - optional: true - - '@tailwindcss/oxide@4.3.1': - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.3.1 - '@tailwindcss/oxide-darwin-arm64': 4.3.1 - '@tailwindcss/oxide-darwin-x64': 4.3.1 - '@tailwindcss/oxide-freebsd-x64': 4.3.1 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.1 - '@tailwindcss/oxide-linux-arm64-gnu': 4.3.1 - '@tailwindcss/oxide-linux-arm64-musl': 4.3.1 - '@tailwindcss/oxide-linux-x64-gnu': 4.3.1 - '@tailwindcss/oxide-linux-x64-musl': 4.3.1 - '@tailwindcss/oxide-wasm32-wasi': 4.3.1 - '@tailwindcss/oxide-win32-arm64-msvc': 4.3.1 - '@tailwindcss/oxide-win32-x64-msvc': 4.3.1 - - '@tailwindcss/postcss@4.3.1': - dependencies: - '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.3.1 - '@tailwindcss/oxide': 4.3.1 - postcss: 8.5.15 - tailwindcss: 4.3.1 - - '@tailwindcss/vite@4.3.1(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4))': - dependencies: - '@tailwindcss/node': 4.3.1 - '@tailwindcss/oxide': 4.3.1 - tailwindcss: 4.3.1 - vite: 8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) - '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.0 @@ -11077,6 +10898,15 @@ snapshots: gzip-size: 6.0.0 sirv: 3.0.2 + '@unocss/postcss@66.7.2(postcss@8.5.15)': + dependencies: + '@unocss/config': 66.7.2 + '@unocss/core': 66.7.2 + '@unocss/rule-utils': 66.7.2 + css-tree: 3.2.1 + postcss: 8.5.15 + tinyglobby: 0.2.16 + '@unocss/preset-attributify@66.7.2': dependencies: '@unocss/core': 66.7.2 @@ -15371,8 +15201,6 @@ snapshots: tailwind-merge@3.6.0: {} - tailwindcss@4.3.1: {} - tapable@2.3.3: {} tar-fs@2.1.4: @@ -15543,8 +15371,6 @@ snapshots: '@turbo/windows-64': 2.9.15 '@turbo/windows-arm64': 2.9.15 - tw-animate-css@1.4.0: {} - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -15653,7 +15479,7 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - unocss@66.7.2(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)): + unocss@66.7.2(@unocss/postcss@66.7.2(postcss@8.5.15))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)): dependencies: '@unocss/cli': 66.7.2 '@unocss/core': 66.7.2 @@ -15672,6 +15498,8 @@ snapshots: '@unocss/transformer-directives': 66.7.2 '@unocss/transformer-variant-group': 66.7.2 '@unocss/vite': 66.7.2(vite@8.0.14(@types/node@25.9.1)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) + optionalDependencies: + '@unocss/postcss': 66.7.2(postcss@8.5.15) transitivePeerDependencies: - vite diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9b15f25..c9b547f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -70,11 +70,7 @@ catalogs: '@radix-ui/react-slot': ^1.3.0 '@radix-ui/react-tabs': ^1.1.15 '@sveltejs/vite-plugin-svelte': ^5.0.0 - '@tailwindcss/postcss': ^4.3.1 - '@tailwindcss/vite': ^4.3.1 - '@unocss/preset-icons': ^66.0.0 - '@unocss/preset-uno': ^66.0.0 - '@unocss/vite': ^66.0.0 + '@unocss/postcss': ^66.0.0 '@xterm/addon-fit': ^0.11.0 '@xterm/xterm': ^6.0.0 class-variance-authority: ^0.7.1 @@ -86,8 +82,6 @@ catalogs: react-dom: ^19.2.6 svelte: ^5.0.0 tailwind-merge: ^3.6.0 - tailwindcss: ^4.3.1 - tw-animate-css: ^1.4.0 unocss: ^66.0.0 vite-plugin-css-injected-by-js: ^3.5.0 inlined: diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/constants.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/constants.snapshot.d.ts index 9f380d2..1fc4fb8 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/constants.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/constants.snapshot.d.ts @@ -1,12 +1,15 @@ /** * Generated by tsnapi — public API snapshot of `@devframes/plugin-code-server/constants` */ -// #region Other -export { DEFAULT_CODE_SERVER_PORT } -export { DEFAULT_PORT } -export { DEFAULT_START_TIMEOUT } -export { getCookieSessionName } -export { PLUGIN_ID } -export { SESSION_COOKIE_BASE } -export { STATE_KEY } +// #region Functions +export declare function getCookieSessionName(_?: string): string; +// #endregion + +// #region Variables +export declare const DEFAULT_CODE_SERVER_PORT: number; +export declare const DEFAULT_PORT: number; +export declare const DEFAULT_START_TIMEOUT: number; +export declare const PLUGIN_ID: string; +export declare const SESSION_COOKIE_BASE: string; +export declare const STATE_KEY: string; // #endregion \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index c5a9ee2..f2899af 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -121,6 +121,18 @@ "@devframes/nuxt": [ "./packages/nuxt/src/index.ts" ], + "@internal/design/preset": [ + "./packages/design/src/preset.ts" + ], + "@internal/design/components": [ + "./packages/design/src/components.ts" + ], + "@internal/design/tokens": [ + "./packages/design/src/tokens.ts" + ], + "@internal/design": [ + "./packages/design/src/index.ts" + ], "@devframes/plugin-code-server/client": [ "./plugins/code-server/src/client/index.ts" ], diff --git a/turbo.json b/turbo.json index e9f47db..0ae5b6e 100644 --- a/turbo.json +++ b/turbo.json @@ -18,14 +18,18 @@ "outputLogs": "new-only", "outputs": ["dist/**"] }, + "@internal/design#build": { + "outputLogs": "new-only", + "outputs": ["dist/**"] + }, "@devframes/plugin-code-server#build": { "outputLogs": "new-only", - "dependsOn": ["devframe#build"], + "dependsOn": ["devframe#build", "@internal/design#build"], "outputs": ["dist/**"] }, "@devframes/plugin-terminals#build": { "outputLogs": "new-only", - "dependsOn": ["devframe#build"], + "dependsOn": ["devframe#build", "@internal/design#build"], "outputs": ["dist/**"] }, "minimal-vite-devframe-hub#build": { @@ -55,7 +59,7 @@ }, "@devframes/plugin-git#build": { "outputLogs": "new-only", - "dependsOn": ["devframe#build"], + "dependsOn": ["devframe#build", "@internal/design#build"], "outputs": ["dist/**"] }, "files-inspector-example#cli:build": {