mirror of
https://github.com/hanzoai/svelte.git
synced 2026-10-01 00:41:47 +00:00
@hanzo/svelte 1.0.0 — the Svelte backend, on its own
Extracted from @hanzo/ui pkg/ui/src/backends/svelte with its history. It lived inside a React component library, which meant every consumer of @hanzo/ui resolved svelte whether they rendered a single Svelte component or not, and the package declared peer svelte>=5 against a dev svelte ^4.2.20 — two answers to one question. Three runtime dependencies, all load-bearing: class-variance-authority for the variants the components already used, and clsx + tailwind-merge behind cn. The cn helper is vendored (17 lines) rather than imported back from @hanzo/ui, because depending on the package this was extracted from would undo the split. No design-system runtime, no icon pack, no CSS-in-JS. svelte-check: 50 files, 0 errors. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
export let variant: BadgeVariant = 'default'
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- Card container — standard-token surface; mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- CardAction — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- CardContent — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- CardDescription — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- CardFooter — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- CardHeader — mirrors the shadcn backend's grid header. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- CardTitle — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
the shadcn backend's data-state token styling. `bind:checked` is supported.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { onDestroy } from 'svelte'
|
||||
import { getDisclosure, DIALOG } from './internal/context'
|
||||
import { portal, trapFocus, dismiss } from './internal/actions'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- DialogDescription — describes the dialog (aria-describedby target). -->
|
||||
<script lang="ts">
|
||||
import { getDisclosure, DIALOG } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
const { descId } = getDisclosure(DIALOG, 'DialogDescription')
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- DialogFooter — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- DialogHeader — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<!-- DialogTitle — labels the dialog for assistive tech (aria-labelledby target). -->
|
||||
<script lang="ts">
|
||||
import { getDisclosure, DIALOG } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
const { labelId } = getDisclosure(DIALOG, 'DialogTitle')
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<script lang="ts">
|
||||
import { getDisclosure, DROPDOWN } from './internal/context'
|
||||
import { rovingFocus } from './internal/actions'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- DropdownMenuItem — a menu item (native button → free Enter/Space activation). -->
|
||||
<script lang="ts">
|
||||
import { getDisclosure, DROPDOWN } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- DropdownMenuLabel — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
export let inset = false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- DropdownMenuSeparator — mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- Input — standard-token text field; class string mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- Label — standard-token form label; mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getDisclosure, POPOVER } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# @hanzo/svelte
|
||||
|
||||
Hanzo UI for Svelte 5.
|
||||
|
||||
These components used to live inside `@hanzo/ui` as `@hanzo/ui/svelte`. They are
|
||||
here now because a component library should be one stack: `@hanzo/ui` is React on
|
||||
`@hanzo/gui`, and shipping a second renderer inside it meant every consumer
|
||||
resolved `svelte` whether or not they used it.
|
||||
|
||||
Nothing about the components changed. Same shapes, same `cva` variants, same
|
||||
tokens.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i @hanzo/svelte svelte
|
||||
```
|
||||
|
||||
Two dependencies, on purpose: `svelte` (peer, yours) and `class-variance-authority`
|
||||
(the variant function). No design-system runtime, no icon pack, no CSS-in-JS.
|
||||
|
||||
## Use
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Button, Card, CardHeader, CardContent } from '@hanzo/svelte'
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<CardHeader>Ship it</CardHeader>
|
||||
<CardContent><Button variant="default">Go</Button></CardContent>
|
||||
</Card>
|
||||
```
|
||||
|
||||
Import one component if you want one component:
|
||||
|
||||
```svelte
|
||||
import Button from '@hanzo/svelte/Button.svelte'
|
||||
```
|
||||
|
||||
## Composition
|
||||
|
||||
Every component takes `class` and spreads the rest onto its root element, so a
|
||||
variant is a function of props and nothing is hidden behind a theme provider.
|
||||
Compose by wrapping, not by configuring.
|
||||
@@ -6,7 +6,7 @@
|
||||
<script lang="ts">
|
||||
import { getSelect } from './internal/context'
|
||||
import { rovingFocus } from './internal/actions'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { getSelect } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- SelectLabel — a group heading. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- SelectSeparator — divides option groups. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
</script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getSelect } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- Separator — standard-token rule; mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
shadcn backend's data-state token styling. `bind:checked` is supported.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createSelection, TABS } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<!-- TabsContent — the panel shown for its `value` (role=tabpanel). -->
|
||||
<script lang="ts">
|
||||
import { getSelection, TABS } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { rovingFocus } from './internal/actions'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getSelection, TABS } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<!-- Textarea — standard-token multiline field; mirrors the shadcn backend. -->
|
||||
<script lang="ts">
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getDisclosure, TOOLTIP } from './internal/context'
|
||||
import { cn } from '../../core/cn'
|
||||
import { cn } from './core/cn'
|
||||
|
||||
let className: string | undefined = undefined
|
||||
export { className as class }
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* `cn` — the one class-name composer.
|
||||
*
|
||||
* `clsx` resolves conditional/array/object class inputs; `tailwind-merge` then
|
||||
* collapses conflicting Tailwind utilities so the LAST wins (a caller's
|
||||
* `bg-background` overrides a component's default `bg-popover`). Every component
|
||||
* here merges through this single function.
|
||||
*
|
||||
* Vendored rather than imported from @hanzo/ui: this package exists so a Svelte
|
||||
* app does not pull in a React component library, and depending back on it for
|
||||
* three lines would undo that.
|
||||
*/
|
||||
import { clsx, type ClassValue } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export function cn(...inputs: ClassValue[]): string {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "@hanzo/svelte",
|
||||
"version": "1.0.0",
|
||||
"description": "Hanzo UI, Svelte 5. The shadcn-shaped components extracted from @hanzo/ui so the core library stays one stack. Same shapes, same variants, same tokens.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/hanzoai/svelte.git"
|
||||
},
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"*.svelte",
|
||||
"index.ts",
|
||||
"core",
|
||||
"README.md"
|
||||
],
|
||||
"svelte": "./index.ts",
|
||||
"types": "./index.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"svelte": "./index.ts",
|
||||
"types": "./index.ts",
|
||||
"default": "./index.ts"
|
||||
},
|
||||
"./*.svelte": "./*.svelte"
|
||||
},
|
||||
"dependencies": {
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"tailwind-merge": "^2.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": ">=5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte": "^5.56.8",
|
||||
"svelte-check": "^4.7.4",
|
||||
"typescript": "^6.0.3"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user