You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/CLAUDE.md

153 lines
7.1 KiB

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build/Test Commands
```bash
npm run dev # Start dev server
npm run build # Production build (static site via adapter-static)
npm run test # Run all tests once
npm run test:unit # Run tests in watch mode
npx vitest run src/lib/ling/test/ling.test.ts # Run single test file
npx vitest run -t "describe name" # Run tests matching pattern
npm run check # Type check with svelte-check
npm run lint # Check formatting with Prettier
npm run format # Auto-format with Prettier
```
## Code Style
- Tabs for indentation, single quotes, no trailing commas, 100 char print width (Prettier)
- Spanish comments in code are acceptable
- Svelte 5 runes mode enforced globally (`svelte.config.js` `dynamicCompileOptions`)
- DOM event handlers: lowercase (`onclick`, `onfocus`). User callbacks: camelCase (`onComplete`, `onInteractOutside`)
- State fields: `$state()` without `#`. Derived: `readonly x = $derived.by(...)`
- Boolean attrs: always use helpers (`boolToTrueOrUndef`, `boolToEmptyStrOrUndef`, `boolToStr`) — never ternaries
## Path Aliases
Aliases must be synced in BOTH `svelte.config.js` AND `vite.config.ts`:
| Alias | Target |
|---|---|
| `@/` | `src/` |
| `@/ling` | `src/lib/ling` (i18n) |
| `@/logr` | `src/lib/logr` (logging) |
| `@/glob` | `src/lib/glob` (globalization: dates, numbers, locale) |
| `@/actx` | `src/lib/actx` (app context) |
| `@/uiux` | `src/lib/uiux` |
| `$uix` | `src/uix` (UI layers) |
| `$terra` | `src/uix/terra` (headless primitives) |
| `$terra/utils` | `src/uix/terra/utils/sound.svelte.ts` |
| `$terra/config` | `src/uix/terra/config/exports.ts` |
| `$terra/external/dates` | `src/uix/terra/external/dates/sound.svelte.ts` |
| `$glob` | `src/lib/glob` |
| `$lib` | `src/lib` |
## Vitest Two-Project Structure
`vite.config.ts` defines two test projects:
- **client**: Browser tests via Playwright for `*.svelte.{test,spec}.{js,ts}`
- **server**: Node environment for `*.{test,spec}.{js,ts}` (excludes svelte tests)
## Architecture: Three-Layer UI System
```
terra → headless primitives: behavior, accessibility, data-* contracts, context
air → visual layer on top of terra: tokens, themes, recipes, styled components
glob → domain logic: dates, numbers, currency, units, locale
```
The dependency flows one way: `air` → `terra`. Terra never imports from air.
### terra (`src/uix/terra/`)
Headless primitive library. Each component follows `Element.SubElement` pattern (`Dialog.Root`, `Dialog.Trigger`, `Dialog.Content`).
**Key patterns:**
- Thin `.svelte` wrappers + logic in `*.svelte.ts` State classes
- State classes use `static create()` for context registration, `createComposed()` for internal composition without context
- Reactive system: `Active<T>`, `State<T>`, `readableActive()`, `writableActive()` — values travel as boxes with `.current`
- Context via `createTerraContext()` (wraps runed's `Context`)
- Props merging: `mergeProps(restProps, state.props)` in every wrapper
- `data-*` attrs are formal public API, validated via `assertDataContract()` against `utils/contracts.ts`
- `child` snippet replaces the rendered node; `children` fills the interior
**Structure:**
- `[component]/components/` — Svelte wrappers
- `[component]/types.ts` — public props
- `[component]/*.svelte.ts` — State classes
- `[component]/exports.ts` + `sound.svelte.ts` — barrel exports
- `layers/` — shared infra (portal, floating, presence, focus-scope, dismissible, escape, scroll)
- `dom/` — browser-dependent utils (focus, roving focus, arrow navigation)
- `utils/` — pure helpers (state system, attrs, merge-props, events, keyboard, css, datetime)
- `config/` — `TerraConfig` for cross-cutting services (translator, formatters, logger, dir, portalTo)
- `external/dates/` — adapter boundary for date library
**Import rules within terra:** use `$terra/utils` or relative paths internally, never `$uix/terra`.
### air (`src/uix/air/`)
Visual layer built on terra. Consumes terra's public anatomy and `data-*` attrs — never internal classes or incidental DOM structure.
**Three-level token system:**
1. **Primitive tokens** (`tokens/primitive.css`) — absolute scale values, never used directly by components
2. **Semantic tokens** (`tokens/semantic.css`) — theme-aware, switch via `[data-theme]`
3. **Component tokens** (`tokens/components/*.css`) — scoped per component (`--air-button-*`), the only level component CSS writes
**Token naming:**
- Public: `--air-{component}-*` (stable, overridable)
- Private: `--_air-{component}-*` (implementation detail, may change)
**Contracts** (`contracts/`):
- `contract.css` — minimum semantic tokens any theme must implement
- `contract-categorical.css` — optional categorical color families
- `contract-primitives.css` — optional advanced 12-step scales
- `contracts/components/*.css` — per-component public token API
**CSS rules:**
- Tokens and `data-*` selectors must be global CSS (imported `.css` files), not `<style scoped>`
- Svelte scoped styles only for properties that don't depend on `data-*` or terra internals
- Components respond to terra states purely via `data-*` selectors: `[data-disabled]`, `[data-state='open']`, etc.
- Theme activation via `data-theme` attribute on any DOM container (supports nesting)
- Variant dimensions are orthogonal: `size` → dimensions, `variant` → appearance, `state` → transversal overrides
**Structure:**
- `components/` — styled wrappers over terra primitives
- `tokens/` — token implementation (primitive, semantic, per-component)
- `contracts/` — public token interfaces for theme authors
- `themes/` — theme implementations (base light/dark)
- `icons/` — icon system (`Icon` + per-icon components in `icons/lib/`)
### Internal Libraries (`src/lib/`)
- `ling` — i18n system (factory: `createLing`)
- `logr` — logging (factory: `createLogr`, depends on `ling`)
- `glob` — globalization: dates, numbers, currency, locale
- `actx` — app context
- `vice` — app-level utilities
**Important:** `DateValue` and all date utilities come from `@/glob/lib`, never from `@internationalized/date` directly. Within terra, use `$terra/external/dates`.
### Test Pages
Component demos live in `src/routes/test/`. Each terra/air component should have a test page demonstrating its states and variants.
## TerraConfig Integration
```svelte
<TerraConfig {translator} {dateTimeFormatter}>
<Dialog.Root />
</TerraConfig>
```
Priority chain for resolved props: explicit component prop → TerraConfig value → internal fallback. TerraConfig supports nesting (child overrides parent partially).
## Key Conventions
- When creating terra components: follow the checklist in `src/uix/terra/README.md` §21
- When reading existing modules: start with `exports.ts` → `types.ts` → root `.svelte` → `*.svelte.ts` → child wrappers → test page
- `$bindable()` without fallback when parent might pass `undefined`; apply defaults via coalescing (see `SVELTE5_BINDABLE_PATTERN.md`)
- Components that use Portal: consumer must manage `z-index` explicitly (layers don't impose z-indices)

Powered by TurnKey Linux.