diff --git a/.changeset/corridor-gather.md b/.changeset/corridor-gather.md new file mode 100644 index 00000000..624cb891 --- /dev/null +++ b/.changeset/corridor-gather.md @@ -0,0 +1,14 @@ +--- +"@anarchitecture/ghost": minor +--- + +Recompose `gather` on a corridor + hub-and-spoke model and fix a sibling-surface +context leak. A surface's slice is now: a **spine** of full-body nodes from every +file on the corridor (the package root down to the surface's own folder — folders +are walls, so sibling folders never leak in), the **edges** reachable in one hop +from any spine node's `relates` (so a broad rule authored once high in the tree — +e.g. `relates: { to: arcade }` on `features/` — reaches every descendant), and a +set of **spokes**: pointer entries (id + description) for the surface's own +descendants and any edge hub's subtree, which the agent pulls on demand. The +`GraphSlice` JSON gains a `spokes` array; graph nodes carry their file `folder`. +Grounding for `checks`/`review` remains the full-body spine + edges. diff --git a/.changeset/cross-package-extends.md b/.changeset/cross-package-extends.md index 0c891863..4f06d699 100644 --- a/.changeset/cross-package-extends.md +++ b/.changeset/cross-package-extends.md @@ -2,4 +2,4 @@ "@anarchitecture/ghost": minor --- -Add cross-package inheritance via `extends`. A package's `manifest.yml` can declare `extends: { : }`, mapping another contract's identity to where it lives. Node refs then reference inherited context by identity, never path — `under: brand:core` or `relates: [{ to: brand:core-trust }]` (the `:` form replaces the earlier npm-style `#` ref grammar). Inherited nodes load read-only and flow into gather and validate like local ones. `ghost validate` resolves cross-package refs and reports unresolved refs, packages not declared in `extends`, identity mismatches, and cross-package cycles. This delivers the shared-brand story: one brand contract extended by many products, without copy-paste or merge. One level of `extends` in v1 (no transitive); location is an explicit relative dir (identity-based discovery is a future upgrade that keeps refs unchanged). +Add cross-package inheritance via `extends`. A package's `manifest.yml` can declare `extends: { : }`, mapping another contract's identity to where it lives. Node refs then reference inherited context by identity, never path — `relates: [{ to: brand:core/trust }]` (the `:` form replaces the earlier npm-style `#` ref grammar). Inherited nodes load read-only and flow into gather and validate like local ones. `ghost validate` resolves cross-package refs and reports unresolved refs, packages not declared in `extends`, identity mismatches, and cross-package cycles. This delivers the shared-brand story: one brand contract extended by many products, without copy-paste or merge. One level of `extends` in v1 (no transitive); location is an explicit relative dir (identity-based discovery is a future upgrade that keeps refs unchanged). diff --git a/.changeset/described-nodes.md b/.changeset/described-nodes.md index 60fbe52a..7b695163 100644 --- a/.changeset/described-nodes.md +++ b/.changeset/described-nodes.md @@ -2,4 +2,4 @@ "@anarchitecture/ghost": minor --- -Make `description` a first-class node field — the retrieval payload an agent matches a task against, the way a tool is selected by name + description. `ghost gather` with no argument now lists nodes by id + description (the catalog), built from the graph rather than a separate surface menu. Node frontmatter is now passthrough: free-form descriptive keys (`audience`, `stage`, …) are allowed and ride along untouched. The surface composition-edge vocabulary (`composes`/`governed-by`) is removed — lateral composition lives on node `relates`; `surfaces.yml` is now an optional terse spine file (id + parent + optional description) that folds into the node id space, not a distinct content concept. +Make `description` a first-class node field — the retrieval payload an agent matches a task against, the way a tool is selected by name + description. `ghost gather` with no argument now lists nodes by id + description (the catalog), built from the graph rather than a separate surface menu. Node frontmatter is now passthrough: free-form descriptive keys (`audience`, `stage`, …) are allowed and ride along untouched. The surface composition-edge vocabulary (`composes`/`governed-by`) is removed — lateral composition lives on node `relates`. diff --git a/.changeset/directory-tree-nodes.md b/.changeset/directory-tree-nodes.md new file mode 100644 index 00000000..2b05ddc8 --- /dev/null +++ b/.changeset/directory-tree-nodes.md @@ -0,0 +1,18 @@ +--- +"@anarchitecture/ghost": minor +--- + +Collapse the on-disk node model into the directory tree: the layout *is* the +graph. A node's id is its file path (`marketing/email.md` → `marketing/email`) +and its parent is its containing directory; a surface is just a directory, and a +directory's own prose lives in its `index.md` (the package-root `index.md` is +the implicit `core` node). The `surfaces.yml` spine file and the `nodes/` +directory are removed, along with the node frontmatter `id` and `under` fields — +identity and containment now come from where a file sits, never from frontmatter +or a declared spine. Node frontmatter carries descriptive properties only +(`description`, `relates`, `incarnation`, plus passthrough keys); `relates` and +cross-package `extends` refs are path ids (`core/trust`, `brand:core/trust`). +`ghost init` scaffolds `manifest.yml` + a core `index.md`; `ghost migrate` +writes a directory tree; any `*.md` outside the reserved `checks/` subtree lints +as a node. Moving a node is a rename — `ghost validate` reports `relates` that no +longer resolve. diff --git a/.changeset/docs-node-model-refresh.md b/.changeset/docs-node-model-refresh.md new file mode 100644 index 00000000..b884f37d --- /dev/null +++ b/.changeset/docs-node-model-refresh.md @@ -0,0 +1,6 @@ +--- +"@anarchitecture/ghost": patch +--- + +Refresh the README and docs site onto the current command set (drop the removed +`lint`/`verify`/`relay`/`describe`/`survey`/`emit` commands). diff --git a/.changeset/facet-removal.md b/.changeset/facet-removal.md index 30ccabff..56b0a693 100644 --- a/.changeset/facet-removal.md +++ b/.changeset/facet-removal.md @@ -2,4 +2,4 @@ "@anarchitecture/ghost": minor --- -Remove the facet model — the graph is now the only fingerprint model. The `intent.yml`/`inventory.yml`/`composition.yml` schemas, the `GhostFingerprintDocument`, the facet→node load-time projection, and the dormant facet slice/grounding are deleted; the loader folds `nodes/*.md` + `surfaces.yml` directly into the graph. `ghost lint` and `ghost verify` are replaced by one `ghost validate` verb (artifact shape pass + node-graph pass: links resolve, one root, acyclic); `ghost emit` is removed. `ghost scan` now reports node/surface contribution instead of facet contribution. Legacy facet packages no longer load directly — `ghost validate`/load fail with guidance to run `ghost migrate`. Structured exemplar-path and evidence verification is dropped (evidence lives in node prose, per the prose-node model). +Remove the facet model — the graph is now the only fingerprint model. The `intent.yml`/`inventory.yml`/`composition.yml` schemas, the `GhostFingerprintDocument`, the facet→node load-time projection, and the dormant facet slice/grounding are deleted; the loader folds the package's directory tree of prose nodes directly into the graph. `ghost lint` and `ghost verify` are replaced by one `ghost validate` verb (artifact shape pass + node-graph pass: links resolve, one root, acyclic); `ghost emit` is removed. `ghost scan` now reports node/surface contribution instead of facet contribution. Legacy facet packages no longer load directly — `ghost validate`/load fail with guidance to run `ghost migrate`. Structured exemplar-path and evidence verification is dropped (evidence lives in node prose, per the prose-node model). diff --git a/.changeset/migrate-command.md b/.changeset/migrate-command.md index a0c7180d..79f18982 100644 --- a/.changeset/migrate-command.md +++ b/.changeset/migrate-command.md @@ -2,6 +2,7 @@ "@anarchitecture/ghost": minor --- -Add `ghost migrate`: transform a legacy `.ghost/` package onto the surface model -— derive `surfaces.yml` from old `topology.scopes`, place single-scope nodes via -`surface:`, and report (never guess) any node it cannot place unambiguously. +Add `ghost migrate`: transform a legacy `.ghost/` package onto the directory-tree +node model — derive surface directories from old `topology.scopes`, place +single-scope nodes inside them, and report (never guess) any node it cannot place +unambiguously. diff --git a/.changeset/node-authoring.md b/.changeset/node-authoring.md index d7fa23e9..31f0d4d0 100644 --- a/.changeset/node-authoring.md +++ b/.changeset/node-authoring.md @@ -2,4 +2,4 @@ "@anarchitecture/ghost": minor --- -`ghost init` now scaffolds a node package (`manifest.yml` + `surfaces.yml` spine + a seed `nodes/*.md`) via a template registry (`--template `, `default` for now) instead of emitting `intent.yml`/`inventory.yml`/`composition.yml`; the `--reference` flag is removed. `ghost migrate` now performs a one-way conversion of legacy/facet packages into `surfaces.yml` + `nodes/*.md` (the facet→node projection becomes the writer) and removes the old facet files. The authoring skill (`capture.md`, `SKILL.md`) teaches node authoring with intent/inventory/composition as authoring lenses rather than facet files. +`ghost init` now scaffolds a node package (`manifest.yml` + a core `index.md` node) via a template registry (`--template `, `default` for now) instead of emitting `intent.yml`/`inventory.yml`/`composition.yml`; the `--reference` flag is removed. `ghost migrate` now performs a one-way conversion of legacy/facet packages into a directory tree of nodes (the facet→node projection becomes the writer) and removes the old facet files. The authoring skill (`capture.md`, `SKILL.md`) teaches node authoring with intent/inventory/composition as authoring lenses rather than facet files. diff --git a/.changeset/remove-compare-drift-fleet.md b/.changeset/remove-compare-drift-fleet.md index d1b61dad..64c47989 100644 --- a/.changeset/remove-compare-drift-fleet.md +++ b/.changeset/remove-compare-drift-fleet.md @@ -2,4 +2,4 @@ "@anarchitecture/ghost": minor --- -Remove `compare`, `drift`, `ack`, `track`, and `diverge` commands and the direct `fingerprint.md` machinery (parser, writer, semantic diff, decisions/dimensions, embeddings, perceptual prior). These rested on a quantified visual-design-system model (fixed dimensions + decision embeddings) that the context-graph reframe abandoned; the concepts are parked for a graph-native rethink (see docs/ideas/compare-drift-fleet-rethink.md). The `./compare` and `./drift` package subpaths and the root `compare`/`drift` exports are removed. `ghost lint` now validates `.ghost/` packages and node/surface/check artifacts only (direct `fingerprint.md` is no longer linted); a `nodes/*.md` file lints as a `ghost.node/v1` node. +Remove `compare`, `drift`, `ack`, `track`, and `diverge` commands and the direct `fingerprint.md` machinery (parser, writer, semantic diff, decisions/dimensions, embeddings, perceptual prior). These rested on a quantified visual-design-system model (fixed dimensions + decision embeddings) that the context-graph reframe abandoned; the concepts are parked for a graph-native rethink (see docs/ideas/compare-drift-fleet-rethink.md). The `./compare` and `./drift` package subpaths and the root `compare`/`drift` exports are removed. `ghost lint` now validates `.ghost/` packages and node/surface/check artifacts only (direct `fingerprint.md` is no longer linted); a `*.md` node file lints as a `ghost.node/v1` node. diff --git a/.changeset/skill-bundle-prose.md b/.changeset/skill-bundle-prose.md new file mode 100644 index 00000000..9404422e --- /dev/null +++ b/.changeset/skill-bundle-prose.md @@ -0,0 +1,6 @@ +--- +"@anarchitecture/ghost": patch +--- + +Clean em dashes out of the shipped skill bundle and package README prose, +rewriting them as plain sentences, colons, or parentheticals. diff --git a/.changeset/surface-coordinate-space.md b/.changeset/surface-coordinate-space.md index efbd27a1..582b5fc8 100644 --- a/.changeset/surface-coordinate-space.md +++ b/.changeset/surface-coordinate-space.md @@ -2,7 +2,7 @@ "@anarchitecture/ghost": minor --- -Replace topology/applies_to/surface_type/scope coordinates with a surfaces.yml -coordinate space and a single `surface:` placement per node. Remove the +Replace topology/applies_to/surface_type/scope coordinates with a surface +coordinate space and a single surface placement per node. Remove the `ghost.map/v1` (`map.md`) coordinate and routing system; checks now route by `applies_to.paths`. diff --git a/CLAUDE.md b/CLAUDE.md index 89dd8174..1e18f898 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,10 +4,12 @@ Agents can assemble UI. What they cannot reliably preserve is the product surface composition behind that UI: hierarchy, density, restraint, repetition, trust, flow, and the choices that make a surface feel intentional. -Ghost keeps that surface composition in a repo-local `.ghost/` fingerprint package. The public npm shape -is one package, `@anarchitecture/ghost`, with one user-facing bin, `ghost`. -The CLI validates, computes, compares, and emits deterministic packets. The -host agent does the interpretive BYOA work through the installed `ghost` skill. +Ghost keeps that surface composition in a repo-local `.ghost/` fingerprint +package, a graph of prose nodes. The public npm shape is one package, +`@anarchitecture/ghost`, with one user-facing bin, `ghost`. The CLI validates +the node graph, composes context, routes checks, and emits deterministic +packets. The host agent does the interpretive BYOA work through the installed +`ghost` skill. ## Build & Run @@ -29,74 +31,85 @@ pnpm --filter @anarchitecture/ghost exec ghost ## Architecture Ghost is **BYOA (bring your own agent)**. Claude Code, Codex, Cursor, Goose, or -another host agent reads, decides, and writes. Ghost is the deterministic -calculator the agent reaches for: schema validation, repo-signal helpers, -structural diffs, drift checks, comparison math, and handoff packets. +another host agent reads, decides, and writes. Ghost grounds that work with two +things. A **deterministic CLI** does the repeatable parts with no LLM: schema +and graph validation, repo-signal helpers, context composition, check routing, +and advisory review packets. An **interpretive skill bundle** teaches the agent +how to author and use the fingerprint. -The canonical root `.ghost/` package follows: +The canonical root `.ghost/` package is a directory tree of prose nodes: ```text -manifest.yml -intent.yml -inventory.yml -composition.yml -validate.yml +manifest.yml # schema + id +index.md # the core node, true everywhere (optional) +/index.md # a surface's own prose (the directory is the surface) +/.md # a prose node placed in that surface +checks/*.md # optional ghost.check/v1 checks ``` -The three root facet files are the core model: - -- `intent.yml` for surface intent. -- `inventory.yml` for curated material, exemplars, and source links. -- `composition.yml` for experience patterns. - -`validate.yml` validates output through deterministic checks; it is not -generation input. -Ordinary Git review is the approval boundary for fingerprint edits. - -Legacy `resources.yml`, `map.md`, `survey.json`, and `patterns.yml` may still -appear in older repos or as migration source material. They are not canonical -fingerprint input for new Ghost work. +The **directory tree is the graph**. A node is a markdown file: descriptive +frontmatter (`description`, `relates`, `incarnation`) plus a prose body. A +node's identity is its path (`marketing/email.md` → `marketing/email`) and its +parent is its containing directory. A surface is just a directory, and a +directory's own prose lives in its `index.md`. The package-root `index.md` is +the implicit `core` node. The body is written through three authoring lenses +(they guide what to capture, they are not fields): + +- **intent**: the why and the stance. +- **inventory**: the materials, and pointers to code the agent can inspect. +- **composition**: the patterns that make the surface feel intentional. + +`description` is the retrieval payload; `relates` links nodes laterally; +`incarnation` tags a medium-bound expression. Reserved at the package root: +`manifest.yml` and the `checks/` subtree; every other `*.md` is a node. Moving a +node is a rename. `checks/*.md` validate output, routed by surface; they are not +generation input. Ordinary Git review is the approval boundary for fingerprint +edits. + +A package may `extend` another by identity (the shared-brand pattern): the +manifest's `extends` maps a package id to where it lives, and nodes reference +inherited context by identity (`relates: [{ to: brand:core/trust }]`), never by +path. ## Packages | Package | Published? | Description | | --- | --- | --- | -| `packages/ghost` | yes: `@anarchitecture/ghost` | Unified public package. Ships the `ghost` CLI, fingerprint package authoring, checks, advisory review packets, comparison, drift stance verbs, and the unified skill bundle. | +| `packages/ghost` | yes: `@anarchitecture/ghost` | Unified public package. Ships the `ghost` CLI, node authoring, graph validation, check routing, advisory review packets, and the unified skill bundle. | | `packages/ghost-core` | no | Private historical shared package. Runtime code needed by npm is folded into `packages/ghost/src/ghost-core`. | | `packages/ghost-fleet` | no | Private fleet view across many Ghost bundles. Consumes workspace exports from `@anarchitecture/ghost`. | -| `packages/ghost-ui` | no | Reference design system: shadcn registry plus `ghost-mcp` MCP server. | +| `packages/ghost-ui` | no | Parked. A standalone shadcn component registry plus `ghost-mcp` MCP server, developed in this monorepo. Not coupled to Ghost and not referenced by the docs site or public surfaces. | | `apps/docs` | no | Docs site. | ## CLI Commands +Core workflow: + +| Command | Description | +| --- | --- | +| `ghost init` | Scaffold `.ghost/` with a manifest and a core `index.md` node. | +| `ghost scan` | Report node and surface contribution. | +| `ghost validate` | Validate the package: artifact shape and the node graph (links resolve, one root, acyclic). | +| `ghost gather` | List nodes by id + description, or compose a surface's context slice (own + inherited + edges). | +| `ghost checks` | Select and ground the markdown checks governing the named surfaces. | +| `ghost review` | Emit an advisory review packet: touched surfaces, routed checks, fingerprint grounding, and the diff. | +| `ghost skill install` | Install the unified `ghost` skill bundle. | + +Advanced/maintenance: + | Command | Description | | --- | --- | -| `ghost init` | Create `.ghost/` with manifest, facets, and deterministic checks. | -| `ghost scan` | Report fingerprint contribution facets and BYOA next-step guidance. | | `ghost signals` | Emit raw repo signals as JSON for fingerprint authoring. | -| `ghost lint` | Validate a fingerprint package or single artifact. | -| `ghost verify` | Validate fingerprint evidence and exemplar paths, and typed check refs. | -| `ghost describe` | Print direct markdown section ranges. | -| `ghost diff` | Structural direct-fingerprint prose diff between direct fingerprints. | -| `ghost survey ` | Legacy survey helpers for optional `ghost.survey/v1` workflows. | -| `ghost check` | Run active `ghost.validate/v1` deterministic gates against a diff. | -| `ghost review` | Emit an evidence-routed advisory review packet grounded in fingerprint facets, inventory exemplars, checks, and the diff. | -| `ghost compare` | Pairwise or composite comparison over packages or direct fingerprints. | -| `ghost ack` | Record stance toward the tracked fingerprint in `.ghost-sync.json`. | -| `ghost track` | Shift the tracked fingerprint. | -| `ghost diverge` | Declare intentional divergence on a dimension. | -| `ghost emit ` | Emit `review-command`. | -| `ghost skill install` | Install the unified `ghost` agentskills.io bundle. | - -`ghost scan --format json` is deterministic contribution and source-signal state. -It does not run an LLM. +| `ghost migrate` | Migrate a legacy `.ghost/` package onto the node-graph surface model. | + +`ghost scan --format json` is deterministic contribution state. It does not run +an LLM. ## Public Exports - `@anarchitecture/ghost` for the combined surface. -- `@anarchitecture/ghost/scan` for scan contribution, source signals, and stack discovery. -- `@anarchitecture/ghost/fingerprint` for fingerprint package authoring, linting, verification, parsing, and serialization. -- `@anarchitecture/ghost/drift` for check/review/compare/stance helpers. +- `@anarchitecture/ghost/scan` for scan contribution and source signals. +- `@anarchitecture/ghost/fingerprint` for node package authoring, validation, parsing, and serialization. - `@anarchitecture/ghost/core` for shared schemas, types, and loaders. - `@anarchitecture/ghost/cli` for `buildCli()`. @@ -132,8 +145,10 @@ Use `patch` for fixes and docs, `minor` for new commands/flags/exports, and - Keep publishable runtime code self-contained in `packages/ghost`; no `workspace:*` runtime dependencies in the packed public artifact. -- The canonical on-disk form is a flat `.ghost/` package. -- Direct `fingerprint.md` remains only for legacy/direct compare workflows. +- The canonical on-disk form is a `.ghost/` directory tree: `manifest.yml` plus + prose nodes (`index.md` and `/.md`) and optional `checks/*.md`. + The directory layout is the graph; ids and parents come from paths, never a + spine file. - Skill recipes live in `packages/ghost/src/skill-bundle/references/`; install them with `ghost skill install`. - The CLI manifest at `apps/docs/src/generated/cli-manifest.json` is generated diff --git a/README.md b/README.md index 3aa464c0..04bcca46 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,50 @@ # Ghost -**Ghost captures the composition of a product surface: the intent behind it, -the materials it draws from, and the patterns that make it feel intentional.** +**Agents can assemble UI. They can't reliably preserve the _composition_ behind +it: the hierarchy, density, restraint, copy, trust, and flow that make a +surface feel intentional.** -Ghost gives AI agents a checked-in product fingerprint they can read before -they generate UI and validate after they change it. The public package is -`@anarchitecture/ghost`, and it installs one CLI: `ghost`. +Ghost is a checked-in product-surface fingerprint your agent reads before it +builds and checks after it changes. One package, `@anarchitecture/ghost`. One +CLI, `ghost`. -Agents can assemble components. What they need help preserving is the product -surface behind those components: hierarchy, density, restraint, behavior, copy, -accessibility, trust, and flow. Ghost keeps that surface composition in a -portable `.ghost/` package that ordinary Git review can approve. +[Documentation](https://block.github.io/ghost/) · [npm](https://www.npmjs.com/package/@anarchitecture/ghost) · [Skill](#skill) ## The Shape -The canonical package is intentionally small: +A fingerprint is a small folder of prose. The CLI computes; your agent reads, +writes, and decides. ```text .ghost/ - manifest.yml # ghost.fingerprint-package/v1 anchor - intent.yml # surface intent - inventory.yml # curated material and exemplars - composition.yml # patterns, flows, states, and arrangements - validate.yml # optional deterministic gates + manifest.yml # ghost.fingerprint-package/v1 anchor: schema + id + index.md # the core node, true everywhere (optional) + /index.md # a surface's own prose (the directory is the surface) + /.md # a prose node placed in that surface + checks/*.md # optional ghost.check/v1 checks ``` -A package can be sparse: it contributes whichever facets are locally true. Generation usually uses intent + inventory + composition: - -- `intent.yml` says what the surface is trying to do and for whom. -- `inventory.yml` points agents at materials they can inspect or reuse. -- `composition.yml` captures the patterns that make those materials feel like - one intentional product. - -`validate.yml`, nested packages, custom host-wrapper package locations, and raw repo -signals are supporting features. They do not replace curated fingerprint -facets. `ghost signals` answers what exists; curated fingerprint facets answer +The fingerprint is a graph of **nodes**, and the **directory tree is the graph**. +A node is a markdown file: descriptive frontmatter (`description`, `relates`, +`incarnation`) plus a prose body. A node's identity is its path +(`marketing/email.md` → `marketing/email`) and its parent is its containing +directory. A surface is just a directory, and a directory's own prose lives in +its `index.md`. The package-root `index.md` is the implicit `core` node, true +everywhere. + +The body is written through three authoring lenses. They guide what to capture; +they are not fields: + +- **intent**: what the surface is trying to do and for whom. +- **inventory**: the materials, and pointers to code the agent can inspect. +- **composition**: the patterns that make the surface feel intentional. + +`description` is the retrieval payload; `relates` links nodes laterally; +`incarnation` tags a medium-bound expression (essence is untagged). Reserved at +the package root: `manifest.yml` and the `checks/` subtree; every other `*.md` +is a node. `ghost signals` answers what exists; the curated node graph answers what the surface is trying to preserve. -Older `resources.yml`, `map.md`, `survey.json`, `patterns.yml`, and direct -`fingerprint.yml` artifacts can still inform migration workflows, but new Ghost -work should target `.ghost/`. - ## Project Status: Beta > [!WARNING] @@ -58,132 +62,99 @@ work should target `.ghost/`. ```bash npm install -D @anarchitecture/ghost npx ghost --help -npx ghost --help --all ``` -`ghost --help` shows the core workflow. `ghost --help --all` shows the complete -command index, and each command supports `ghost --help`. - -Install the BYOA skill bundle so Codex, Claude, Cursor, Goose, or another host -agent knows how to author and use the fingerprint: +## Quick Start ```bash -npx ghost skill install -# or choose an explicit destination -npx ghost skill install --dest ~/.codex/skills/ghost +ghost init # scaffold .ghost/ with a manifest + a core index.md node +ghost validate # links resolve, one root, acyclic +ghost gather # list nodes; ghost gather composes a context slice ``` -Then ask your agent in plain English: +A node is a markdown file; its id is its path (`checkout/trust.md` → +`checkout/trust`) and its parent is its directory: -```text -Set up the Ghost fingerprint for this repo. -Brief this work from the Ghost fingerprint. -Review this PR against the Ghost fingerprint. -Compare these two Ghost bundles. -``` - -## Author A Fingerprint +```markdown +--- +description: Trust at the payment moment. +relates: + - to: core/trust + as: reinforces +--- -Ghost authoring is a human-plus-agent workflow. The CLI creates, inspects, and -validates the package; the host agent interviews, reads the repo, drafts facet -edits, and asks you to curate the claims. - -```bash -ghost init -ghost init --package product-surface -ghost scan --format json -ghost signals . -ghost lint .ghost -ghost lint product-surface -ghost verify .ghost --root . +Near the moment of payment, reduce felt risk. Proximity of reassurance to the +action beats completeness. Never introduce a new visual system here. ``` -Use `--reference` when a reference library should seed inventory, `--scope` -for nested product areas, or `--package ` when initializing an exact -package directory such as `product-surface/`. -For monorepos, `ghost init --monorepo` creates or preserves the root package, -detects workspace child roots, and prints proposed `ghost init --scope ...` -commands by default. Run `ghost init --monorepo --apply` to create the detected -child packages. Host wrappers that need Ghost files somewhere other than -`.ghost` may set `GHOST_PACKAGE_DIR=` on the child `ghost` -process. Exact `--package ` values win over the environment default. - -Drafted fingerprint edits are just ordinary file changes until Git review -accepts them. Checked-in Ghost facet files are the Ghost source of truth. +## Skill -## Generate From Ghost - -Before generating or revising UI, gather the Relay brief for the target path: +Ghost is **bring-your-own-agent**. Install the skill bundle so Claude Code, +Codex, Cursor, Goose, or another host agent knows how to author and use the +fingerprint: ```bash -ghost relay gather apps/checkout/review/page.tsx +npx ghost skill install ``` -Relay compiles selected context from the resolved stack as context hits: -fingerprint refs, why they matched, suggested reads, omissions, and gaps. -The important shift is timing: Ghost gives agents surface-composition context -before they build, not only after a review finds drift. +Then ask in plain English: -After implementation, run the deterministic and advisory workflows against the -same fingerprint: - -```bash -ghost check --base main -ghost review --base main +```text +Set up the Ghost fingerprint for this repo. +Brief this work from the Ghost fingerprint. +Review this change against the Ghost fingerprint. ``` -`ghost check` runs active `ghost.validate/v1` gates and can fail. `ghost review` -emits an evidence-routed advisory packet for a human or host adapter to use. +The skill tells the agent what to read, what to write, and which CLI checks to +run. The CLI does the deterministic work; the agent does the interpretation. -## Compare And Govern - -Advanced workflows remain available when a repo needs package stacks, -comparison, or explicit drift stance: +## The Loop ```bash -ghost stack apps/checkout/review/page.tsx -ghost compare market/.ghost dashboard/.ghost -ghost ack --stance aligned --reason "Initial baseline" -ghost track new-tracked.fingerprint.md -ghost diverge typography --reason "Editorial product uses a different type scale" -ghost emit review-command --path apps/checkout/review/page.tsx +ghost gather # before: compose the context slice for the work +ghost checks --surface # route the markdown checks the change touches +ghost review --surface # after: an advisory packet grounded in the diff ``` -`ghost scan --format json` emits deterministic contribution state for `intent`, -`inventory`, `composition`, and `validate`. A sparse package can be useful with -only one contributing facet; absent facets may be inherited from broader stack -context. It does not call an LLM. +The shift is timing: Ghost gives agents surface-composition context **before** +they build, not only after a review finds drift. Checked-in nodes are the source +of truth; ordinary Git review is the approval boundary for fingerprint edits. ## CLI Commands | Command | Description | | --- | --- | -| `ghost init` | Create `.ghost/` package facet files. | -| `ghost scan` | Report sparse fingerprint contribution facets. | -| `ghost lint` | Validate a fingerprint package or individual artifact. | -| `ghost verify` | Validate evidence paths, exemplar paths, and typed check refs. | -| `ghost check` | Run active deterministic gates against a diff. | -| `ghost review` | Emit an evidence-routed advisory packet from fingerprint facets and a diff. | -| `ghost relay gather` | Gather fingerprint-grounded context for an agent target. | -| `ghost emit ` | Emit `review-command` artifacts. | -| `ghost skill install` | Install the unified Ghost skill bundle. | -| `ghost stack` | Inspect resolved root-to-leaf fingerprint stacks. | -| `ghost signals` | Emit raw repo signals as JSON for fingerprint authoring. | -| `ghost describe` | Print markdown section ranges. | -| `ghost compare` | Compare fingerprint packages. | -| `ghost ack` / `track` / `diverge` | Record stance toward tracked drift. | -| `ghost diff` / `survey` | Maintain direct markdown fingerprints or survey/cache files for compatibility workflows. | +| `ghost init` | Scaffold `.ghost/` with a manifest and a core `index.md` node. | +| `ghost scan` | Report node and surface contribution. | +| `ghost validate` | Validate the package: artifact shape and the node graph. | +| `ghost gather` | List nodes, or compose a surface's context slice. | +| `ghost checks` | Select and ground the checks a change touches, by surface. | +| `ghost review` | Emit an advisory review packet grounded in fingerprint + diff. | +| `ghost skill install` | Install the BYOA skill bundle. | +| `ghost signals` | Emit raw repo signals as authoring evidence _(advanced)_. | +| `ghost migrate` | Migrate a legacy `.ghost/` package onto the node model _(maintenance)_. | + +Run `ghost --help` for the core workflow, `ghost --help --all` for everything, +and `ghost --help` for flags. + +## Status: Beta + +> [!WARNING] +> Ghost is pre-1.0 and under active development. The CLI, node schema, on-disk +> `.ghost/` shape, and public exports may change in breaking ways before 1.0. +> Breaking changes may ship in minor versions while pre-1.0; patch versions are +> reserved for fixes that should not require migration. Pin the version you +> depend on and review release notes before upgrading. ## Repo Layout Ghost is a pnpm monorepo. The public package is self-contained for npm; private -workspace packages remain development context. +workspace packages are development context. | Path | Role | Published? | | ---- | ---- | --- | -| [`packages/ghost`](./packages/ghost) | Public package. Ships the `ghost` CLI, folded core runtime, fingerprint package helpers, deterministic checks, advisory review packets, comparison/stance helpers, and the unified skill bundle. | yes: `@anarchitecture/ghost` | +| [`packages/ghost`](./packages/ghost) | Public package: the `ghost` CLI, folded core runtime, node authoring, checks, advisory review, and the skill bundle. | yes: `@anarchitecture/ghost` | | [`packages/ghost-fleet`](./packages/ghost-fleet) | Private fleet view across many Ghost bundles. | no | -| [`packages/ghost-ui`](./packages/ghost-ui) | Reference design system: shadcn registry plus `ghost-mcp` MCP server. | no | | [`apps/docs`](./apps/docs) | Docs site. | no | ## Development @@ -194,17 +165,11 @@ pnpm build pnpm test pnpm check pnpm dump:cli-help -pnpm --filter @anarchitecture/ghost pack ``` No API key is required to run Ghost. `OPENAI_API_KEY` / `VOYAGE_API_KEY` are optional and only used by semantic embedding helpers when a host opts in. -## Resources +## License -| Resource | Description | -| --- | --- | -| [docs/purposes.md](./docs/purposes.md) | What fingerprints are for: one model, many projections. | -| [docs/ideas/](./docs/ideas) | Live design notes, anchored by `fingerprint-first-architecture.md`. | -| [GOVERNANCE.md](./GOVERNANCE.md) | Project governance. | -| [LICENSE](./LICENSE) | Apache License, Version 2.0. | +[Apache License 2.0](./LICENSE) · [Governance](./GOVERNANCE.md) diff --git a/apps/docs/src/App.tsx b/apps/docs/src/App.tsx index cb3515a5..91dfb7cd 100644 --- a/apps/docs/src/App.tsx +++ b/apps/docs/src/App.tsx @@ -1,27 +1,15 @@ import { ThemeProvider } from "ghost-ui"; import { useEffect } from "react"; -import { Navigate, Route, Routes, useLocation, useParams } from "react-router"; +import { Navigate, Route, Routes, useLocation } from "react-router"; import DocsIndex from "@/app/docs/page"; import HomePage from "@/app/page"; import GhostDriftLanding from "@/app/tools/drift/page"; import GhostFleetLanding from "@/app/tools/fleet/page"; import ToolsIndex from "@/app/tools/page"; import GhostScanLanding from "@/app/tools/scan/page"; -import GhostUiLanding from "@/app/tools/ui/page"; -import ComponentPage from "@/app/ui/components/[name]/page"; -import ComponentsIndex from "@/app/ui/components/page"; -import ColorsPage from "@/app/ui/foundations/colors/page"; -import FoundationsIndex from "@/app/ui/foundations/page"; -import TypographyPage from "@/app/ui/foundations/typography/page"; -import DesignLanguageIndex from "@/app/ui/page"; import { Dock } from "@/components/docs/dock"; import { mdxDocsRoutes } from "@/routes/docs-routes"; -function ComponentRedirect() { - const { name } = useParams<{ name: string }>(); - return ; -} - function ScrollToHash() { const { hash, pathname } = useLocation(); @@ -51,7 +39,7 @@ export function App() { } /> - {/* Tools — four-card index plus per-tool landings */} + {/* Tools: four-card index plus per-tool landings */} } /> } /> } /> } /> - } /> {/* Cross-tool docs hub */} } /> @@ -74,17 +61,6 @@ export function App() { {/* MDX-authored doc pages under /docs/* */} {mdxDocsRoutes()} - {/* Design Language (ghost-ui catalogue) */} - } /> - } /> - } /> - } - /> - } /> - } /> - {/* Redirects from the previous /tools/drift/{getting-started,cli} URLs */} } /> - - {/* Redirects from legacy root /foundations and /components URLs */} - } - /> - } - /> - } - /> - } - /> - } /> diff --git a/apps/docs/src/app/docs/page.tsx b/apps/docs/src/app/docs/page.tsx index 2bf96ca0..541383bb 100644 --- a/apps/docs/src/app/docs/page.tsx +++ b/apps/docs/src/app/docs/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useStaggerReveal } from "ghost-ui"; -import { BookOpen, Rocket } from "lucide-react"; +import { BookOpen, FileText, Rocket } from "lucide-react"; import type { ReactNode } from "react"; import { Link } from "react-router"; import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; @@ -20,11 +20,18 @@ const sections: { "Install Ghost, set up the repo fingerprint, and learn the loop around .ghost.", icon: , }, + { + name: "Fingerprint Authoring", + href: "/docs/fingerprint-authoring", + description: + "Co-author nodes through the intent, inventory, and composition lenses, and place them for inheritance.", + icon: , + }, { name: "CLI Reference", href: "/docs/cli", description: - "Commands for checks and comparison, plus the skill recipes your agent runs.", + "Every command around the node-graph fingerprint: init, validate, gather, checks, and review.", icon: , }, ]; diff --git a/apps/docs/src/app/page.tsx b/apps/docs/src/app/page.tsx index 12e77918..8783c2a6 100644 --- a/apps/docs/src/app/page.tsx +++ b/apps/docs/src/app/page.tsx @@ -29,120 +29,85 @@ export default function Home() {

- Agents can assemble UI. What they cannot reliably preserve is the - surface composition that UI belongs to. + Agents can assemble UI. What they can't reliably preserve is the + composition behind it: the hierarchy, density, restraint, copy, + trust, and flow that make a surface feel intentional.

- For years, design systems solved a human assembly problem. They - gave teams shared tokens, components, examples, and usage rules so - new surfaces could be composed from known parts. + Design systems solved a human assembly problem: shared tokens, + components, and usage rules so teams could build from known parts. + That layer still matters. But agents already recombine those + parts. The scarce layer now is the composition that tells them + when and how the parts belong.

- That layer still matters, but agents change the scarce layer. - Models can copy local patterns and recombine components. They do - not consistently preserve the composition that makes a product - surface feel intentional: hierarchy, density, restraint, behavior, - copy, accessibility, trust, and flow. + Ghost captures that composition and checks it into the repo, where + generation happens. It is a{" "} + graph of prose nodes, one + markdown file each, that your agent reads before it builds and + checks after it changes.

-

- Ghost captures the composition of a product surface: the intent - behind it, the materials it draws from, and the patterns that make - it feel intentional. -

-

- It stores that composition as checked-in fingerprint facets: which - intent shapes the surface, which materials agents can draw from, - which situations change the obligation, which patterns hold the - surface together, and which examples show it at its best. -

-

- Components, tokens, and libraries become implementation material. - Ghost does not replace them. It gives agents the surface context - that tells them when and how those materials belong. -

-

Ghost keeps that model compact:

  • - .ghost/ is the default portable fingerprint package + .ghost/ is the portable fingerprint package
  • - intent.yml, inventory.yml, and{" "} - composition.yml store the three facets + the directory tree is the graph: a node's id is + its file path, and its parent is its containing directory
  • - validate.yml stores optional deterministic gates - grounded in fingerprint refs + a surface is just a directory; its own prose lives in that + directory's index.md, and the root{" "} + index.md is the implicit core node
  • - ordinary Git review separates draft fingerprint edits from - checked-in truth + each node is written through intent,{" "} + inventory, and composition: the why, + the materials, the patterns
  • +
  • + checks/*.md validate output; they are never + generation input +
  • +
  • ordinary Git review is the approval boundary for edits

- The split is deliberate. intent.yml captures the - intent behind the surface. inventory.yml captures the - materials it draws from. composition.yml captures the - patterns that make it feel intentional. Checks validate output; - they are not generation input. + A node inherits everything in the directories above it. The brand + soul lives in the root index.md (the{" "} + core node) and reaches every surface; + surface-specific nodes refine it; relates links them + laterally. Asking for context becomes a graph traversal:{" "} + ghost gather <surface> composes the slice that + applies.

-

A typical loop becomes:

+

The loop is small:

    -
  1. Brief from the fingerprint facets and exemplars
  2. -
  3. Generate or edit with the host agent
  4. -
  5. Run active deterministic checks and advisory review
  6. - Fix code, explain intentional divergence, or update the Ghost - package through Git + Gather the composed context for the surface you're touching +
  7. +
  8. Generate or edit with your agent
  9. +
  10. Route checks and emit an advisory review against the diff
  11. +
  12. + Fix code, explain intentional divergence, or update the + fingerprint through Git

Ghost stays bring-your-own-agent. The agent reads, decides, and - writes. Ghost does the repeatable work: initialization, schema - validation, inventory, evidence verification, checks, advisory - review packets, comparison, and upstream handoff packets. -

-

- This is critical because surface composition that cannot be - recalled or evaluated cannot be delegated. A product surface that - only its original author can assess is not transferable: to - agents, to new engineers, or to forks of the product. -

-

- Drift becomes measurable within this system. When generated or - modified UI diverges from checked-in fingerprint facets, the - failure is not just error; it is signal. Drift can originate from: -

-
    -
  • incorrect generation: agent failure
  • -
  • missing-fingerprint: under-specified surface context
  • -
  • intentional product evolution
  • -
-

- Ghost does not eliminate drift; it surfaces and localizes it. The - system's boundary becomes visible where composition fails. -

-

- The fingerprint package must live where generation happens: in the - repository, versioned alongside the code it governs. As the - product changes, fingerprint edits move through the same ordinary - Git review that introduces new UI. -

-

- This leads to a practical governance model. Each repository owns - its product-surface fingerprint. Advanced workflows can add nested - packages for product areas, custom fingerprint directories for - host wrappers, comparison across systems, and declared drift - stances. + writes. Ghost does the repeatable work: scaffolding, schema and + graph validation, context composition, check routing, and advisory + review packets.

- Across an organization, the collection of Ghost packages forms a - higher-order map: a distributed model of product-surface - composition as it is actually practiced, not as it is only - described. + Composition that can't be recalled or evaluated can't be + delegated. A surface only its author can assess won't transfer to + an agent, a new engineer, or a fork. Ghost makes it transferable, + and makes drift measurable: where generated UI diverges from the + fingerprint, the gap is signal, and it is localized.

Design systems were libraries for humans. Ghost is composition - context for agents: every surface can carry the fingerprint it + context for agents: every surface carries the fingerprint it extends, and every deviation can carry evidence.

diff --git a/apps/docs/src/app/tools/page.tsx b/apps/docs/src/app/tools/page.tsx index ffaefd8f..6fd44c69 100644 --- a/apps/docs/src/app/tools/page.tsx +++ b/apps/docs/src/app/tools/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useStaggerReveal } from "ghost-ui"; -import { FileText, Network, Orbit, Palette } from "lucide-react"; +import { FileText, Network, Orbit } from "lucide-react"; import type { ReactNode } from "react"; import { Link } from "react-router"; import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; @@ -31,12 +31,6 @@ const tools: { blurb: "Compare projects", icon: , }, - { - name: "ghost-ui", - href: "/tools/ui", - blurb: "Reference UI library", - icon: , - }, ]; function ToolStrip() { @@ -49,7 +43,7 @@ function ToolStrip() { return (
{tools.map((tool) => ( diff --git a/apps/docs/src/app/tools/scan/page.tsx b/apps/docs/src/app/tools/scan/page.tsx index c4a97f49..6c1dbeb4 100644 --- a/apps/docs/src/app/tools/scan/page.tsx +++ b/apps/docs/src/app/tools/scan/page.tsx @@ -22,16 +22,16 @@ const cards: { }, { name: "CLI reference", - href: "/docs/cli#ghost--fingerprint-layers-and-package-checks", + href: "/docs/cli", description: - "Check fingerprint contribution facets, validate packages, and emit context.", + "Report node and surface contribution, validate the graph, and compose context.", icon: , }, { - name: "Format spec", - href: "https://github.com/block/ghost/blob/main/docs/fingerprint-format.md", + name: "Authoring", + href: "/docs/fingerprint-authoring", description: - "The full package format for fingerprint intent, inventory, composition, and validation.", + "How to write nodes through the intent, inventory, and composition lenses.", icon: , }, ]; @@ -48,7 +48,7 @@ export default function GhostScanLanding() {
, - }, - { - name: `Components (${componentCount})`, - href: "/ui/components", - description: - "Production-ready primitives + AI elements. Distributed via the shadcn registry.json — installed component-by-component, never wholesale.", - icon: , - }, - { - name: "MCP server", - href: "https://github.com/block/ghost/tree/main/packages/ghost-ui#mcp-server", - description: - "ghost-mcp re-exposes the registry to AI assistants — five tools, two resources, so an agent can search components and pull source.", - icon: , - }, -]; - -export default function GhostUiLanding() { - const ref = useStaggerReveal(".tool-card", { - stagger: 0.06, - y: 30, - duration: 0.7, - }); - - return ( - - - -
- {cards.map((item) => ( - -
- {item.icon} -
- - - {item.name} - - - -

- {item.description} -

- - ))} -
-
- ); -} diff --git a/apps/docs/src/app/ui/components/[name]/page.tsx b/apps/docs/src/app/ui/components/[name]/page.tsx deleted file mode 100644 index 4291697f..00000000 --- a/apps/docs/src/app/ui/components/[name]/page.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { Navigate, useParams } from "react-router"; -import { ComponentPageShell } from "@/components/docs/component-page-shell"; -import { getComponentDoc } from "@/lib/component-docs"; -import { - getCategory, - getComponent, - getComponentsByCategory, -} from "@/lib/component-registry"; -import { getComponentSpec } from "@/lib/component-source"; - -// ── Import demo source files as raw strings at build time ── - -const demoSourceModules = import.meta.glob( - [ - "/src/components/docs/primitives/*-demo.tsx", - "/src/components/docs/ai-elements/*-demo.tsx", - ], - { query: "?raw", eager: true }, -) as Record; - -function getDemoSource( - slug: string, - source: "primitives" | "ai-elements", -): string | null { - const key = `/src/components/docs/${source}/${slug}-demo.tsx`; - return demoSourceModules[key]?.default ?? null; -} - -export default function ComponentPage() { - const { name } = useParams<{ name: string }>(); - - if (!name) return ; - - const component = getComponent(name); - if (!component) return ; - - const category = getCategory(component.primaryCategory); - const siblings = getComponentsByCategory(component.primaryCategory); - const currentIndex = siblings.findIndex((c) => c.slug === name); - const prev = currentIndex > 0 ? siblings[currentIndex - 1] : null; - const next = - currentIndex < siblings.length - 1 ? siblings[currentIndex + 1] : null; - - const demoSource = getDemoSource(component.slug, component.demoSource); - const spec = getComponentSpec(component.slug); - const docs = getComponentDoc(name); - - return ( - - ); -} diff --git a/apps/docs/src/app/ui/components/page.tsx b/apps/docs/src/app/ui/components/page.tsx deleted file mode 100644 index 5be57442..00000000 --- a/apps/docs/src/app/ui/components/page.tsx +++ /dev/null @@ -1,170 +0,0 @@ -"use client"; - -import { useStaggerReveal } from "ghost-ui"; -import { useMemo, useState } from "react"; -import { Link } from "react-router"; -import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; -import { SectionWrapper } from "@/components/docs/wrappers"; -import { - categories, - getAllComponents, - getComponentsByCategory, -} from "@/lib/component-registry"; - -/* ── Fuzzy match ─────────────────────────────────────────────────────── */ - -function fuzzyMatch(query: string, target: string): number { - const q = query.toLowerCase(); - const t = target.toLowerCase(); - - // exact substring match scores highest - if (t.includes(q)) return 1; - - // character-by-character fuzzy: every query char must appear in order - let qi = 0; - let score = 0; - let lastIdx = -1; - - for (let ti = 0; ti < t.length && qi < q.length; ti++) { - if (t[ti] === q[qi]) { - // bonus for consecutive matches - score += ti === lastIdx + 1 ? 2 : 1; - lastIdx = ti; - qi++; - } - } - - // all query characters must be found - if (qi < q.length) return 0; - - // normalise to 0–1 range (below 1 so substring match always wins) - return (score / (q.length * 2)) * 0.9; -} - -/* ── Page ─────────────────────────────────────────────────────────────── */ - -export default function ComponentsIndex() { - const [query, setQuery] = useState(""); - const allComponents = useMemo(() => getAllComponents(), []); - - const filtered = useMemo(() => { - if (!query.trim()) return null; - return allComponents - .map((c) => ({ ...c, score: fuzzyMatch(query, c.name) })) - .filter((c) => c.score > 0) - .sort((a, b) => b.score - a.score); - }, [query, allComponents]); - - const isSearching = query.trim().length > 0; - - return ( - - - - {/* Search */} -
- setQuery(e.target.value)} - placeholder="Search components…" - className="w-full max-w-md rounded-full border border-border-card bg-card px-5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground/50 outline-none focus:border-foreground/25 transition-colors duration-200" - /> -
- - {/* Search results */} - {isSearching && ( -
- {filtered && filtered.length > 0 ? ( -
- {filtered.map((item) => ( - - ))} -
- ) : ( -

- No components match "{query}" -

- )} -
- )} - - {/* Category sections */} - {!isSearching && ( -
- {categories.map((cat) => { - const items = getComponentsByCategory(cat.slug); - if (items.length === 0) return null; - return ( - - ); - })} -
- )} -
- ); -} - -/* ── Pill ─────────────────────────────────────────────────────────────── */ - -function ComponentPill({ slug, name }: { slug: string; name: string }) { - return ( - - - - {name} - - - ); -} - -/* ── Category section ─────────────────────────────────────────────────── */ - -function CategorySection({ - name, - description, - items, -}: { - name: string; - description: string; - items: { slug: string; name: string }[]; -}) { - const ref = useStaggerReveal(".component-card", { - stagger: 0.04, - y: 24, - duration: 0.6, - }); - - return ( -
-

- {name} -

-

{description}

-
- {items.map((item) => ( - - ))} -
-
- ); -} diff --git a/apps/docs/src/app/ui/foundations/colors/page.tsx b/apps/docs/src/app/ui/foundations/colors/page.tsx deleted file mode 100644 index ddaa3355..00000000 --- a/apps/docs/src/app/ui/foundations/colors/page.tsx +++ /dev/null @@ -1,32 +0,0 @@ -"use client"; - -import { useScrollReveal } from "ghost-ui"; -import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; -import { ColorsDemos } from "@/components/docs/foundations/colors"; -import { SectionWrapper } from "@/components/docs/wrappers"; - -export default function ColorsPage() { - const contentRef = useScrollReveal({ - y: 50, - duration: 0.9, - ease: "expo.out", - }); - - return ( - <> - - - - - -
- -
-
- - ); -} diff --git a/apps/docs/src/app/ui/foundations/page.tsx b/apps/docs/src/app/ui/foundations/page.tsx deleted file mode 100644 index 1f648342..00000000 --- a/apps/docs/src/app/ui/foundations/page.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client"; - -import { useStaggerReveal } from "ghost-ui"; -import { type ReactNode } from "react"; -import { Link } from "react-router"; -import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; -import { SectionWrapper } from "@/components/docs/wrappers"; - -function ColorsVisual() { - return ( -
- {[ - "bg-foreground", - "bg-foreground/80", - "bg-foreground/60", - "bg-foreground/40", - "bg-foreground/20", - "bg-foreground/10", - ].map((bg, i) => ( -
- ))} -
- ); -} - -function TypographyVisual() { - return ( -
-
-
-
-
-
- ); -} - -const foundations: { - name: string; - href: string; - description: string; - visual: ReactNode; -}[] = [ - { - name: "Colors", - href: "/ui/foundations/colors", - description: - "A pure monochromatic scale with selective semantic color for status and utility.", - visual: , - }, - { - name: "Typography", - href: "/ui/foundations/typography", - description: - "Magazine-grade hierarchy. Display for headers, Regular for body, Mono for data.", - visual: , - }, -]; - -export default function FoundationsIndex() { - const ref = useStaggerReveal(".foundation-card", { - stagger: 0.06, - y: 30, - duration: 0.7, - }); - - return ( - - - -
- {foundations.map((item) => ( - -
{item.visual}
- - - {item.name} - - - -

- {item.description} -

- - ))} -
-
- ); -} diff --git a/apps/docs/src/app/ui/foundations/typography/page.tsx b/apps/docs/src/app/ui/foundations/typography/page.tsx deleted file mode 100644 index d6a8f53c..00000000 --- a/apps/docs/src/app/ui/foundations/typography/page.tsx +++ /dev/null @@ -1,32 +0,0 @@ -"use client"; - -import { useScrollReveal } from "ghost-ui"; -import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; -import { TypographyDemos } from "@/components/docs/foundations/typography"; -import { SectionWrapper } from "@/components/docs/wrappers"; - -export default function TypographyPage() { - const contentRef = useScrollReveal({ - y: 50, - duration: 0.9, - ease: "expo.out", - }); - - return ( - <> - - - - - -
- -
-
- - ); -} diff --git a/apps/docs/src/app/ui/page.tsx b/apps/docs/src/app/ui/page.tsx deleted file mode 100644 index 686405ef..00000000 --- a/apps/docs/src/app/ui/page.tsx +++ /dev/null @@ -1,131 +0,0 @@ -"use client"; - -import { useStaggerReveal } from "ghost-ui"; -import { type ReactNode } from "react"; -import { Link } from "react-router"; -import { AnimatedPageHeader } from "@/components/docs/animated-page-header"; -import { SectionWrapper } from "@/components/docs/wrappers"; -import { getAllComponents } from "@/lib/component-registry"; - -function ColorsVisual() { - return ( -
- {[ - "bg-foreground", - "bg-foreground/80", - "bg-foreground/60", - "bg-foreground/40", - "bg-foreground/20", - "bg-foreground/10", - ].map((bg, i) => ( -
- ))} -
- ); -} - -function TypographyVisual() { - return ( -
-
-
-
-
-
- ); -} - -function ComponentsVisual() { - const count = getAllComponents().length; - return ( -
- {Array.from({ length: 8 }).map((_, i) => ( -
- ))} - - {count} components - -
- ); -} - -const sections: { - name: string; - href: string; - description: string; - visual: ReactNode; -}[] = [ - { - name: "Foundations", - href: "/ui/foundations", - description: - "Color, typography, and the design tokens that underpin every Ghost UI component.", - visual: ( -
-
- -
-
- -
-
- ), - }, - { - name: "Components", - href: "/ui/components", - description: - "Production-ready building blocks. Every component follows Ghost UI — pill-first, monochromatic, accessible.", - visual: , - }, -]; - -export default function DesignLanguageIndex() { - const ref = useStaggerReveal(".dl-card", { - stagger: 0.06, - y: 30, - duration: 0.7, - }); - - return ( - - - -
- {sections.map((item) => ( - -
{item.visual}
- - - {item.name} - - - -

- {item.description} -

- - ))} -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/agent-demo.tsx b/apps/docs/src/components/docs/ai-elements/agent-demo.tsx deleted file mode 100644 index 0b340865..00000000 --- a/apps/docs/src/components/docs/ai-elements/agent-demo.tsx +++ /dev/null @@ -1,89 +0,0 @@ -"use client"; - -import { - Agent, - AgentContent, - AgentHeader, - AgentInstructions, - AgentOutput, - AgentTool, - AgentTools, -} from "ghost-ui"; - -export function AgentDemo() { - return ( -
- - - - - You are a research assistant that helps users find and summarize - academic papers. Use the provided tools to search databases and - retrieve relevant publications. Always cite your sources. - - - - - - - - - - - - - - Review code for best practices, potential bugs, and performance - issues. Provide actionable feedback with specific line references. - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/artifact-demo.tsx b/apps/docs/src/components/docs/ai-elements/artifact-demo.tsx deleted file mode 100644 index ab5105a5..00000000 --- a/apps/docs/src/components/docs/ai-elements/artifact-demo.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import { - Artifact, - ArtifactAction, - ArtifactActions, - ArtifactClose, - ArtifactContent, - ArtifactDescription, - ArtifactHeader, - ArtifactTitle, -} from "ghost-ui"; -import { CopyIcon, DownloadIcon, ShareIcon } from "lucide-react"; - -export function ArtifactDemo() { - return ( -
- - -
- React Component - - A reusable button component with variants - -
- - - - - - -
- -
-            {`export function Button({ variant = "primary", children }) {
-  return (
-    
-  );
-}`}
-          
-
-
- - - -
- SVG Illustration - - Generated logo design concept - -
- - - - -
- -
- AI -
-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/attachments-demo.tsx b/apps/docs/src/components/docs/ai-elements/attachments-demo.tsx deleted file mode 100644 index a5caa72c..00000000 --- a/apps/docs/src/components/docs/ai-elements/attachments-demo.tsx +++ /dev/null @@ -1,83 +0,0 @@ -"use client"; - -import { - Attachment, - AttachmentEmpty, - AttachmentInfo, - AttachmentPreview, - AttachmentRemove, - Attachments, -} from "ghost-ui"; - -const mockAttachments = [ - { - id: "1", - type: "file" as const, - mediaType: "image/png", - filename: "screenshot.png", - url: "https://picsum.photos/seed/attach1/200/200", - }, - { - id: "2", - type: "file" as const, - mediaType: "application/pdf", - filename: "quarterly-report.pdf", - url: "", - }, - { - id: "3", - type: "file" as const, - mediaType: "audio/mp3", - filename: "recording.mp3", - url: "", - }, -]; - -export function AttachmentsDemo() { - return ( -
-
-

Grid variant

- - {mockAttachments.map((file) => ( - {}}> - - - - ))} - -
- -
-

Inline variant

- - {mockAttachments.map((file) => ( - {}}> - - - - - ))} - -
- -
-

List variant

- - {mockAttachments.map((file) => ( - {}}> - - - - - ))} - -
- -
-

Empty state

- -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/audio-player-demo.tsx b/apps/docs/src/components/docs/ai-elements/audio-player-demo.tsx deleted file mode 100644 index eb65a58e..00000000 --- a/apps/docs/src/components/docs/ai-elements/audio-player-demo.tsx +++ /dev/null @@ -1,53 +0,0 @@ -"use client"; - -import { - AudioPlayer, - AudioPlayerControlBar, - AudioPlayerDurationDisplay, - AudioPlayerElement, - AudioPlayerMuteButton, - AudioPlayerPlayButton, - AudioPlayerSeekBackwardButton, - AudioPlayerSeekForwardButton, - AudioPlayerTimeDisplay, - AudioPlayerTimeRange, - AudioPlayerVolumeRange, -} from "ghost-ui"; - -export function AudioPlayerDemo() { - return ( -
-
-

Full audio player

- - - - - - - - - - - - - -
- -
-

- Minimal player (play, time, scrub) -

- - - - - - - - - -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/canvas-demo.tsx b/apps/docs/src/components/docs/ai-elements/canvas-demo.tsx deleted file mode 100644 index 27fc23c1..00000000 --- a/apps/docs/src/components/docs/ai-elements/canvas-demo.tsx +++ /dev/null @@ -1,87 +0,0 @@ -"use client"; - -import { type NodeTypes, ReactFlowProvider } from "@xyflow/react"; -import { - Canvas, - Controls, - Node, - NodeContent, - NodeDescription, - NodeHeader, - NodeTitle, -} from "ghost-ui"; -import { useMemo } from "react"; - -const InputNode = () => ( - - - User Input - Text prompt - - -

- Accepts a natural language query from the user. -

-
-
-); - -const ProcessNode = () => ( - - - LLM Processing - GPT-4o - - -

- Processes the input and generates a response. -

-
-
-); - -const OutputNode = () => ( - - - Response - Markdown output - - -

- Displays the generated response to the user. -

-
-
-); - -const initialNodes = [ - { id: "1", type: "input", position: { x: 0, y: 100 }, data: {} }, - { id: "2", type: "process", position: { x: 500, y: 100 }, data: {} }, - { id: "3", type: "output", position: { x: 1000, y: 100 }, data: {} }, -]; - -const initialEdges = [ - { id: "e1-2", source: "1", target: "2" }, - { id: "e2-3", source: "2", target: "3" }, -]; - -export function CanvasDemo() { - const nodeTypes: NodeTypes = useMemo( - () => ({ - input: InputNode, - output: OutputNode, - process: ProcessNode, - }), - [], - ); - - return ( - -
- - - -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/chain-of-thought-demo.tsx b/apps/docs/src/components/docs/ai-elements/chain-of-thought-demo.tsx deleted file mode 100644 index 5238cc15..00000000 --- a/apps/docs/src/components/docs/ai-elements/chain-of-thought-demo.tsx +++ /dev/null @@ -1,52 +0,0 @@ -"use client"; - -import { - ChainOfThought, - ChainOfThoughtContent, - ChainOfThoughtHeader, - ChainOfThoughtSearchResult, - ChainOfThoughtSearchResults, - ChainOfThoughtStep, -} from "ghost-ui"; -import { DatabaseIcon, FileTextIcon, SearchIcon } from "lucide-react"; - -export function ChainOfThoughtDemo() { - return ( - - Researching climate data - - - - IPCC 2024 - - NASA Climate - - NOAA Data - - - - - - - - - - - ); -} diff --git a/apps/docs/src/components/docs/ai-elements/checkpoint-demo.tsx b/apps/docs/src/components/docs/ai-elements/checkpoint-demo.tsx deleted file mode 100644 index 5073b3d3..00000000 --- a/apps/docs/src/components/docs/ai-elements/checkpoint-demo.tsx +++ /dev/null @@ -1,27 +0,0 @@ -"use client"; - -import { Checkpoint, CheckpointIcon, CheckpointTrigger } from "ghost-ui"; - -export function CheckpointDemo() { - return ( -
- - - - Checkpoint 1 — Initial draft - - - -
- Some conversation content between checkpoints... -
- - - - - Checkpoint 2 — After revisions - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/code-block-demo.tsx b/apps/docs/src/components/docs/ai-elements/code-block-demo.tsx deleted file mode 100644 index 9fa3d01f..00000000 --- a/apps/docs/src/components/docs/ai-elements/code-block-demo.tsx +++ /dev/null @@ -1,79 +0,0 @@ -"use client"; - -import { - CodeBlock, - CodeBlockActions, - CodeBlockCopyButton, - CodeBlockFilename, - CodeBlockHeader, - CodeBlockTitle, -} from "ghost-ui"; - -const typescriptCode = `interface User { - id: string; - name: string; - email: string; - role: "admin" | "user" | "guest"; -} - -async function getUser(id: string): Promise { - const response = await fetch(\`/api/users/\${id}\`); - - if (!response.ok) { - throw new Error(\`Failed to fetch user: \${response.statusText}\`); - } - - return response.json(); -}`; - -const cssCode = `.container { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - gap: 1.5rem; - padding: 2rem; -} - -.card { - border-radius: 0.75rem; - background: var(--card-bg); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -}`; - -const jsonCode = `{ - "name": "@acme/design-system", - "version": "2.4.0", - "dependencies": { - "react": "^19.0.0", - "tailwindcss": "^4.0.0" - } -}`; - -export function CodeBlockDemo() { - return ( -
- - - - lib/api/users.ts - - - - - - - - - - - styles/layout.css - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/commit-demo.tsx b/apps/docs/src/components/docs/ai-elements/commit-demo.tsx deleted file mode 100644 index 73cb521c..00000000 --- a/apps/docs/src/components/docs/ai-elements/commit-demo.tsx +++ /dev/null @@ -1,122 +0,0 @@ -"use client"; - -import { - Commit, - CommitActions, - CommitAuthor, - CommitAuthorAvatar, - CommitContent, - CommitCopyButton, - CommitFile, - CommitFileAdditions, - CommitFileChanges, - CommitFileDeletions, - CommitFileIcon, - CommitFileInfo, - CommitFilePath, - CommitFileStatus, - CommitFiles, - CommitHash, - CommitHeader, - CommitInfo, - CommitMessage, - CommitMetadata, - CommitSeparator, - CommitTimestamp, -} from "ghost-ui"; - -export function CommitDemo() { - return ( -
- - - - - - - - feat: add user authentication with OAuth2 support - - - a1b2c3d - - - - - - - - - - - - - - - src/lib/auth/oauth.ts - - - - - - - - - - - src/middleware.ts - - - - - - - - - - - src/lib/auth/legacy.ts - - - - - - - - - - - src/config/auth.config.ts - - - - - - - - - - - - - - - - - - fix: resolve race condition in data fetching - - - f8e9d0c - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/confirmation-demo.tsx b/apps/docs/src/components/docs/ai-elements/confirmation-demo.tsx deleted file mode 100644 index 772fc14f..00000000 --- a/apps/docs/src/components/docs/ai-elements/confirmation-demo.tsx +++ /dev/null @@ -1,70 +0,0 @@ -"use client"; - -import { - Confirmation, - ConfirmationAccepted, - ConfirmationAction, - ConfirmationActions, - ConfirmationRejected, - ConfirmationRequest, - ConfirmationTitle, -} from "ghost-ui"; - -export function ConfirmationDemo() { - return ( -
-
-

Approval requested

- - - The assistant wants to execute rm -rf ./build - - -

- This action will delete the build directory. Do you want to - proceed? -

-
- - Deny - Approve - -
-
- -
-

Accepted

- - - Executed rm -rf ./build - - -

- Action was approved and completed successfully. -

-
-
-
- -
-

Rejected

- - - Blocked rm -rf ./build - - -

- Action was denied by the user. -

-
-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/connection-demo.tsx b/apps/docs/src/components/docs/ai-elements/connection-demo.tsx deleted file mode 100644 index 629c0c58..00000000 --- a/apps/docs/src/components/docs/ai-elements/connection-demo.tsx +++ /dev/null @@ -1,70 +0,0 @@ -"use client"; - -import { type NodeTypes, ReactFlowProvider } from "@xyflow/react"; -import { - Canvas, - Connection, - Node, - NodeContent, - NodeHeader, - NodeTitle, -} from "ghost-ui"; -import { useMemo } from "react"; - -const SourceNode = () => ( - - - Source - - -

- Drag from the handle to see the custom connection line. -

-
-
-); - -const TargetNode = () => ( - - - Target - - -

Drop a connection here.

-
-
-); - -const initialNodes = [ - { id: "1", type: "source", position: { x: 0, y: 80 }, data: {} }, - { id: "2", type: "target", position: { x: 500, y: 80 }, data: {} }, -]; - -export function ConnectionDemo() { - const nodeTypes: NodeTypes = useMemo( - () => ({ - source: SourceNode, - target: TargetNode, - }), - [], - ); - - return ( -
-

- Drag from the source handle to see the animated bezier connection line - with a circular endpoint indicator. -

- -
- -
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/context-demo.tsx b/apps/docs/src/components/docs/ai-elements/context-demo.tsx deleted file mode 100644 index 6b11729b..00000000 --- a/apps/docs/src/components/docs/ai-elements/context-demo.tsx +++ /dev/null @@ -1,44 +0,0 @@ -"use client"; - -import { - Context, - ContextContent, - ContextContentBody, - ContextContentFooter, - ContextContentHeader, - ContextInputUsage, - ContextOutputUsage, - ContextTrigger, -} from "ghost-ui"; - -export function ContextDemo() { - return ( - - - - - -
- - -
-
- -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/controls-demo.tsx b/apps/docs/src/components/docs/ai-elements/controls-demo.tsx deleted file mode 100644 index 2d845c1f..00000000 --- a/apps/docs/src/components/docs/ai-elements/controls-demo.tsx +++ /dev/null @@ -1,50 +0,0 @@ -"use client"; - -import { type NodeTypes, ReactFlowProvider } from "@xyflow/react"; -import { - Canvas, - Controls, - Node, - NodeContent, - NodeHeader, - NodeTitle, -} from "ghost-ui"; -import { useMemo } from "react"; - -const SampleNode = () => ( - - - Sample Node - - -

- Use the controls in the bottom-left to zoom, fit view, and lock - interactions. -

-
-
-); - -const initialNodes = [ - { id: "1", type: "sample", position: { x: 0, y: 0 }, data: {} }, - { id: "2", type: "sample", position: { x: 400, y: 150 }, data: {} }, -]; - -export function ControlsDemo() { - const nodeTypes: NodeTypes = useMemo( - () => ({ - sample: SampleNode, - }), - [], - ); - - return ( - -
- - - -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/conversation-demo.tsx b/apps/docs/src/components/docs/ai-elements/conversation-demo.tsx deleted file mode 100644 index 32a994ac..00000000 --- a/apps/docs/src/components/docs/ai-elements/conversation-demo.tsx +++ /dev/null @@ -1,24 +0,0 @@ -"use client"; - -import { - Conversation, - ConversationContent, - ConversationEmptyState, -} from "ghost-ui"; -import { MessageSquareIcon } from "lucide-react"; - -export function ConversationDemo() { - return ( -
- - - } - /> - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/edge-demo.tsx b/apps/docs/src/components/docs/ai-elements/edge-demo.tsx deleted file mode 100644 index ec292976..00000000 --- a/apps/docs/src/components/docs/ai-elements/edge-demo.tsx +++ /dev/null @@ -1,85 +0,0 @@ -"use client"; - -import { - type EdgeTypes, - type NodeTypes, - ReactFlowProvider, -} from "@xyflow/react"; -import { Canvas, Edge, Node, NodeHeader, NodeTitle } from "ghost-ui"; -import { useMemo } from "react"; - -const SimpleNode = ({ data }: { data: { label: string } }) => ( - - - {data.label} - - -); - -const initialNodes = [ - { - id: "a1", - type: "simple", - position: { x: 0, y: 0 }, - data: { label: "Start" }, - }, - { - id: "a2", - type: "simple", - position: { x: 450, y: 0 }, - data: { label: "Animated" }, - }, - { - id: "b1", - type: "simple", - position: { x: 0, y: 150 }, - data: { label: "Draft" }, - }, - { - id: "b2", - type: "simple", - position: { x: 450, y: 150 }, - data: { label: "Temporary" }, - }, -]; - -const initialEdges = [ - { id: "e-animated", source: "a1", target: "a2", type: "animated" }, - { id: "e-temporary", source: "b1", target: "b2", type: "temporary" }, -]; - -export function EdgeDemo() { - const nodeTypes: NodeTypes = useMemo( - () => ({ - simple: SimpleNode, - }), - [], - ); - - const edgeTypes: EdgeTypes = useMemo( - () => ({ - animated: Edge.Animated, - temporary: Edge.Temporary, - }), - [], - ); - - return ( -
-

- Two edge variants: Animated (top, with a traveling dot) - and Temporary (bottom, dashed line). -

- -
- -
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/environment-variables-demo.tsx b/apps/docs/src/components/docs/ai-elements/environment-variables-demo.tsx deleted file mode 100644 index 8c0d8ce4..00000000 --- a/apps/docs/src/components/docs/ai-elements/environment-variables-demo.tsx +++ /dev/null @@ -1,74 +0,0 @@ -"use client"; - -import { - EnvironmentVariable, - EnvironmentVariableCopyButton, - EnvironmentVariableGroup, - EnvironmentVariableName, - EnvironmentVariableRequired, - EnvironmentVariables, - EnvironmentVariablesContent, - EnvironmentVariablesHeader, - EnvironmentVariablesTitle, - EnvironmentVariablesToggle, - EnvironmentVariableValue, -} from "ghost-ui"; - -export function EnvironmentVariablesDemo() { - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/file-tree-demo.tsx b/apps/docs/src/components/docs/ai-elements/file-tree-demo.tsx deleted file mode 100644 index c2ce9e49..00000000 --- a/apps/docs/src/components/docs/ai-elements/file-tree-demo.tsx +++ /dev/null @@ -1,35 +0,0 @@ -"use client"; - -import { FileTree, FileTreeFile, FileTreeFolder } from "ghost-ui"; - -export function FileTreeDemo() { - return ( -
- - - - - - - - - - - - - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/image-demo.tsx b/apps/docs/src/components/docs/ai-elements/image-demo.tsx deleted file mode 100644 index 6511c174..00000000 --- a/apps/docs/src/components/docs/ai-elements/image-demo.tsx +++ /dev/null @@ -1,47 +0,0 @@ -"use client"; - -import { Image } from "ghost-ui"; - -// A tiny 1x1 transparent PNG placeholder -const PLACEHOLDER_BASE64 = - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="; - -export function ImageDemo() { - return ( -
-

- Renders an AI-generated image from base64 data. The component - automatically constructs a data URI from the provided media type and - base64 string. -

- -
-
- AI-generated landscape placeholder - - PNG, landscape aspect ratio - -
- -
- AI-generated portrait placeholder - - PNG, square aspect ratio - -
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/index.tsx b/apps/docs/src/components/docs/ai-elements/index.tsx deleted file mode 100644 index 46e71e02..00000000 --- a/apps/docs/src/components/docs/ai-elements/index.tsx +++ /dev/null @@ -1,238 +0,0 @@ -"use client"; - -// Code -import { AgentDemo } from "@/components/docs/ai-elements/agent-demo"; -import { ArtifactDemo } from "@/components/docs/ai-elements/artifact-demo"; -// Chatbot -import { AttachmentsDemo } from "@/components/docs/ai-elements/attachments-demo"; -// Voice -import { AudioPlayerDemo } from "@/components/docs/ai-elements/audio-player-demo"; -// Workflow -import { CanvasDemo } from "@/components/docs/ai-elements/canvas-demo"; -import { ChainOfThoughtDemo } from "@/components/docs/ai-elements/chain-of-thought-demo"; -import { CheckpointDemo } from "@/components/docs/ai-elements/checkpoint-demo"; -import { CodeBlockDemo } from "@/components/docs/ai-elements/code-block-demo"; -import { CommitDemo } from "@/components/docs/ai-elements/commit-demo"; -import { ConfirmationDemo } from "@/components/docs/ai-elements/confirmation-demo"; -import { ConnectionDemo } from "@/components/docs/ai-elements/connection-demo"; -import { ContextDemo } from "@/components/docs/ai-elements/context-demo"; -import { ControlsDemo } from "@/components/docs/ai-elements/controls-demo"; -import { ConversationDemo } from "@/components/docs/ai-elements/conversation-demo"; -import { EdgeDemo } from "@/components/docs/ai-elements/edge-demo"; -import { EnvironmentVariablesDemo } from "@/components/docs/ai-elements/environment-variables-demo"; -import { FileTreeDemo } from "@/components/docs/ai-elements/file-tree-demo"; -// Utilities -import { ImageDemo } from "@/components/docs/ai-elements/image-demo"; -import { InlineCitationDemo } from "@/components/docs/ai-elements/inline-citation-demo"; -import { JsxPreviewDemo } from "@/components/docs/ai-elements/jsx-preview-demo"; -import { MessageDemo } from "@/components/docs/ai-elements/message-demo"; -import { MicSelectorDemo } from "@/components/docs/ai-elements/mic-selector-demo"; -import { ModelSelectorDemo } from "@/components/docs/ai-elements/model-selector-demo"; -import { NodeDemo } from "@/components/docs/ai-elements/node-demo"; -import { OpenInChatDemo } from "@/components/docs/ai-elements/open-in-chat-demo"; -import { PackageInfoDemo } from "@/components/docs/ai-elements/package-info-demo"; -import { PanelDemo } from "@/components/docs/ai-elements/panel-demo"; -import { PersonaDemo } from "@/components/docs/ai-elements/persona-demo"; -import { PlanDemo } from "@/components/docs/ai-elements/plan-demo"; -import { PromptInputDemo } from "@/components/docs/ai-elements/prompt-input-demo"; -import { QueueDemo } from "@/components/docs/ai-elements/queue-demo"; -import { ReasoningDemo } from "@/components/docs/ai-elements/reasoning-demo"; -import { SandboxDemo } from "@/components/docs/ai-elements/sandbox-demo"; -import { SchemaDisplayDemo } from "@/components/docs/ai-elements/schema-display-demo"; -import { ShimmerDemo } from "@/components/docs/ai-elements/shimmer-demo"; -import { SnippetDemo } from "@/components/docs/ai-elements/snippet-demo"; -import { SourcesDemo } from "@/components/docs/ai-elements/sources-demo"; -import { SpeechInputDemo } from "@/components/docs/ai-elements/speech-input-demo"; -import { StackTraceDemo } from "@/components/docs/ai-elements/stack-trace-demo"; -import { SuggestionDemo } from "@/components/docs/ai-elements/suggestion-demo"; -import { TaskDemo } from "@/components/docs/ai-elements/task-demo"; -import { TerminalDemo } from "@/components/docs/ai-elements/terminal-demo"; -import { TestResultsDemo } from "@/components/docs/ai-elements/test-results-demo"; -import { ToolDemo } from "@/components/docs/ai-elements/tool-demo"; -import { ToolbarDemo } from "@/components/docs/ai-elements/toolbar-demo"; -import { TranscriptionDemo } from "@/components/docs/ai-elements/transcription-demo"; -import { VoiceSelectorDemo } from "@/components/docs/ai-elements/voice-selector-demo"; -import { WebPreviewDemo } from "@/components/docs/ai-elements/web-preview-demo"; -import { ComponentWrapper } from "@/components/docs/primitives/component-wrapper"; - -function CategoryLabel({ children }: { children: React.ReactNode }) { - return ( -
-

- {children} -

-
- ); -} - -export function AIElementDemos() { - return ( -
- {/* Chatbot */} - Chatbot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* Code */} - Code - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* Voice */} - Voice - - - - - - - - - - - - - - - - - - - - {/* Workflow */} - Workflow - - - - - - - - - - - - - - - - - - - - - - - {/* Utilities */} - Utilities - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/inline-citation-demo.tsx b/apps/docs/src/components/docs/ai-elements/inline-citation-demo.tsx deleted file mode 100644 index 32219032..00000000 --- a/apps/docs/src/components/docs/ai-elements/inline-citation-demo.tsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client"; - -import { - InlineCitation, - InlineCitationCard, - InlineCitationCardBody, - InlineCitationCardTrigger, - InlineCitationCarousel, - InlineCitationCarouselContent, - InlineCitationCarouselHeader, - InlineCitationCarouselIndex, - InlineCitationCarouselItem, - InlineCitationCarouselNext, - InlineCitationCarouselPrev, - InlineCitationSource, - InlineCitationText, -} from "ghost-ui"; - -const sources = [ - "https://en.wikipedia.org/wiki/Large_language_model", - "https://arxiv.org/abs/2303.08774", -]; - -export function InlineCitationDemo() { - return ( -

- Large language models are neural networks trained on vast amounts of text - data.{" "} - - - They use transformer architectures to generate coherent text - - - - - - - - - - - - - - - - - - - - - - {" "} - and have become a cornerstone of modern AI applications. -

- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/jsx-preview-demo.tsx b/apps/docs/src/components/docs/ai-elements/jsx-preview-demo.tsx deleted file mode 100644 index ffa7d6f9..00000000 --- a/apps/docs/src/components/docs/ai-elements/jsx-preview-demo.tsx +++ /dev/null @@ -1,32 +0,0 @@ -"use client"; - -import { JSXPreview, JSXPreviewContent, JSXPreviewError } from "ghost-ui"; - -const validJsx = `
-

Welcome Back

-

Your dashboard is ready to explore.

-
- - -
-
`; - -const errorJsx = `
- -
`; - -export function JsxPreviewDemo() { - return ( -
- - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/message-demo.tsx b/apps/docs/src/components/docs/ai-elements/message-demo.tsx deleted file mode 100644 index 40d6673e..00000000 --- a/apps/docs/src/components/docs/ai-elements/message-demo.tsx +++ /dev/null @@ -1,49 +0,0 @@ -"use client"; - -import { - Message, - MessageAction, - MessageActions, - MessageContent, - MessageResponse, -} from "ghost-ui"; -import { - CopyIcon, - RefreshCwIcon, - ThumbsDownIcon, - ThumbsUpIcon, -} from "lucide-react"; - -export function MessageDemo() { - return ( -
- - - Can you explain how React Server Components work? - - - - - - - {`**React Server Components** (RSC) allow you to render components on the server, reducing the amount of JavaScript sent to the client.\n\n### Key Benefits\n\n- **Zero bundle size** — Server Components are not included in the client bundle\n- **Direct backend access** — You can query databases directly\n- **Automatic code splitting** — Client components are lazy-loaded\n\n\`\`\`tsx\n// This runs on the server\nasync function UserProfile({ id }: { id: string }) {\n const user = await db.user.findUnique({ where: { id } });\n return
{user.name}
;\n}\n\`\`\``} -
-
- - - - - - - - - - - - - - -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/mic-selector-demo.tsx b/apps/docs/src/components/docs/ai-elements/mic-selector-demo.tsx deleted file mode 100644 index 06786dd3..00000000 --- a/apps/docs/src/components/docs/ai-elements/mic-selector-demo.tsx +++ /dev/null @@ -1,48 +0,0 @@ -"use client"; - -import { - MicSelector, - MicSelectorContent, - MicSelectorEmpty, - MicSelectorInput, - MicSelectorItem, - MicSelectorLabel, - MicSelectorList, - MicSelectorTrigger, - MicSelectorValue, -} from "ghost-ui"; - -export function MicSelectorDemo() { - return ( -
-

- Opens a popover listing available audio input devices. Requires - microphone permission to show device names. -

- - - - - - - - {(devices) => - devices.length === 0 ? ( - - ) : ( - devices.map((device) => ( - - - - )) - ) - } - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/model-selector-demo.tsx b/apps/docs/src/components/docs/ai-elements/model-selector-demo.tsx deleted file mode 100644 index df2e74b1..00000000 --- a/apps/docs/src/components/docs/ai-elements/model-selector-demo.tsx +++ /dev/null @@ -1,68 +0,0 @@ -"use client"; - -import { - Button, - ModelSelector, - ModelSelectorContent, - ModelSelectorEmpty, - ModelSelectorGroup, - ModelSelectorInput, - ModelSelectorItem, - ModelSelectorList, - ModelSelectorLogo, - ModelSelectorLogoGroup, - ModelSelectorName, - ModelSelectorTrigger, -} from "ghost-ui"; - -export function ModelSelectorDemo() { - return ( - - - - - - - - No models found. - - - - - - GPT-4o - - - - - - GPT-4o Mini - - - - - - - - Claude Sonnet 4 - - - - - - Claude Opus 4 - - - - - - - - Gemini 2.5 Pro - - - - - - ); -} diff --git a/apps/docs/src/components/docs/ai-elements/node-demo.tsx b/apps/docs/src/components/docs/ai-elements/node-demo.tsx deleted file mode 100644 index 922f9323..00000000 --- a/apps/docs/src/components/docs/ai-elements/node-demo.tsx +++ /dev/null @@ -1,83 +0,0 @@ -"use client"; - -import { ReactFlowProvider } from "@xyflow/react"; -import { - Badge, - Button, - Node, - NodeContent, - NodeDescription, - NodeFooter, - NodeHeader, - NodeTitle, -} from "ghost-ui"; - -export function NodeDemo() { - return ( - -
-
- - - Full Node - - A node with header, content, and footer - - - -

- This node demonstrates all available sub-components arranged - together. It has both target (left) and source (right) handles. -

-
- - Ready - - -
- - - - Source Only - Starting node in a workflow - - -

- This node only has a source handle on the right side. -

-
-
- - - - Target Only - Terminal node in a workflow - - -

- This node only has a target handle on the left side. -

-
-
- - - - Standalone - No handles - - -

- A standalone card-style node with no connection handles. -

-
- - Idle - -
-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/open-in-chat-demo.tsx b/apps/docs/src/components/docs/ai-elements/open-in-chat-demo.tsx deleted file mode 100644 index f5e1c694..00000000 --- a/apps/docs/src/components/docs/ai-elements/open-in-chat-demo.tsx +++ /dev/null @@ -1,42 +0,0 @@ -"use client"; - -import { - OpenIn, - OpenInChatGPT, - OpenInClaude, - OpenInContent, - OpenInCursor, - OpenInLabel, - OpenInScira, - OpenInSeparator, - OpenInT3, - OpenInTrigger, - OpenInv0, -} from "ghost-ui"; - -export function OpenInChatDemo() { - return ( -
-

- A dropdown menu that lets users open a query in various AI chat - providers. Each item generates a provider-specific URL and opens it in a - new tab. -

- - - - - Open in a chat provider - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/package-info-demo.tsx b/apps/docs/src/components/docs/ai-elements/package-info-demo.tsx deleted file mode 100644 index d6d393dd..00000000 --- a/apps/docs/src/components/docs/ai-elements/package-info-demo.tsx +++ /dev/null @@ -1,57 +0,0 @@ -"use client"; - -import { - PackageInfo, - PackageInfoContent, - PackageInfoDependencies, - PackageInfoDependency, - PackageInfoDescription, -} from "ghost-ui"; - -export function PackageInfoDemo() { - return ( -
- - - A JavaScript library for building user interfaces - - - - - - - - - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/panel-demo.tsx b/apps/docs/src/components/docs/ai-elements/panel-demo.tsx deleted file mode 100644 index ec110916..00000000 --- a/apps/docs/src/components/docs/ai-elements/panel-demo.tsx +++ /dev/null @@ -1,61 +0,0 @@ -"use client"; - -import { type NodeTypes, ReactFlowProvider } from "@xyflow/react"; -import { - Canvas, - Node, - NodeContent, - NodeHeader, - NodeTitle, - Panel, -} from "ghost-ui"; -import { useMemo } from "react"; - -const PlaceholderNode = () => ( - - - Workflow Node - - -

- Panels float above the canvas at fixed positions. -

-
-
-); - -const initialNodes = [ - { id: "1", type: "placeholder", position: { x: 100, y: 80 }, data: {} }, -]; - -export function PanelDemo() { - const nodeTypes: NodeTypes = useMemo( - () => ({ - placeholder: PlaceholderNode, - }), - [], - ); - - return ( -
-

- Panels are floating overlays positioned at the edges of the canvas. -

- -
- - - Top Left Panel - - - Top Right Panel - - - Bottom Center Panel - - -
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/persona-demo.tsx b/apps/docs/src/components/docs/ai-elements/persona-demo.tsx deleted file mode 100644 index f5e48571..00000000 --- a/apps/docs/src/components/docs/ai-elements/persona-demo.tsx +++ /dev/null @@ -1,55 +0,0 @@ -"use client"; - -import type { PersonaState } from "ghost-ui"; -import { Button, Persona } from "ghost-ui"; -import { useState } from "react"; - -const variants = [ - "obsidian", - "glint", - "halo", - "command", - "mana", - "opal", -] as const; -const states: PersonaState[] = [ - "idle", - "listening", - "thinking", - "speaking", - "asleep", -]; - -export function PersonaDemo() { - const [currentState, setCurrentState] = useState("idle"); - - return ( -
-
- {states.map((s) => ( - - ))} -
- -
- {variants.map((variant) => ( -
- - {variant} -
- ))} -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/plan-demo.tsx b/apps/docs/src/components/docs/ai-elements/plan-demo.tsx deleted file mode 100644 index ce00bc8d..00000000 --- a/apps/docs/src/components/docs/ai-elements/plan-demo.tsx +++ /dev/null @@ -1,63 +0,0 @@ -"use client"; - -import { - Plan, - PlanAction, - PlanContent, - PlanDescription, - PlanFooter, - PlanHeader, - PlanTitle, - PlanTrigger, -} from "ghost-ui"; -import { CheckCircleIcon, CircleIcon } from "lucide-react"; - -export function PlanDemo() { - return ( -
- - -
- Build a Landing Page - - Create a responsive landing page with hero section, features, and - footer. - -
- - - -
- -
    -
  • - - - Set up project structure - -
  • -
  • - - - Design hero section - -
  • -
  • - - Build features grid -
  • -
  • - - Add footer and navigation -
  • -
-
- -

- 2 of 4 steps completed -

-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/prompt-input-demo.tsx b/apps/docs/src/components/docs/ai-elements/prompt-input-demo.tsx deleted file mode 100644 index 47132fcf..00000000 --- a/apps/docs/src/components/docs/ai-elements/prompt-input-demo.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { - PromptInput, - PromptInputButton, - PromptInputFooter, - PromptInputSubmit, - PromptInputTextarea, - PromptInputTools, -} from "ghost-ui"; -import { PaperclipIcon } from "lucide-react"; - -export function PromptInputDemo() { - return ( -
- {}}> - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/queue-demo.tsx b/apps/docs/src/components/docs/ai-elements/queue-demo.tsx deleted file mode 100644 index b6f9b370..00000000 --- a/apps/docs/src/components/docs/ai-elements/queue-demo.tsx +++ /dev/null @@ -1,86 +0,0 @@ -"use client"; - -import { - Queue, - QueueItem, - QueueItemContent, - QueueItemDescription, - QueueItemIndicator, - QueueList, - QueueSection, - QueueSectionContent, - QueueSectionLabel, - QueueSectionTrigger, -} from "ghost-ui"; -import { CheckCircleIcon, ListTodoIcon } from "lucide-react"; - -export function QueueDemo() { - return ( -
- - - - } - /> - - - - -
- - - Refactor authentication module - -
- - Extract shared logic into a reusable hook - -
- -
- - - Write unit tests for API routes - -
-
-
-
-
- - - - } - /> - - - - -
- - - Set up project scaffolding - -
-
- -
- - - Configure database schema - -
-
-
-
-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/reasoning-demo.tsx b/apps/docs/src/components/docs/ai-elements/reasoning-demo.tsx deleted file mode 100644 index 0ca165bd..00000000 --- a/apps/docs/src/components/docs/ai-elements/reasoning-demo.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { Reasoning, ReasoningContent, ReasoningTrigger } from "ghost-ui"; - -export function ReasoningDemo() { - return ( -
-
-

Completed reasoning

- - - - {`The user is asking about the performance implications of using React Server Components. Let me think through the key factors:\n\n1. **Bundle size reduction** - Since server components don't ship JavaScript to the client, the initial bundle can be significantly smaller.\n\n2. **Data fetching** - Server components can fetch data directly during rendering, eliminating client-side waterfalls.\n\n3. **Streaming** - The server can stream HTML progressively, improving Time to First Byte.`} - - -
- -
-

Streaming reasoning

- - - - {`Analyzing the query about database optimization strategies. I should consider indexing, query planning, and caching...`} - - -
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/sandbox-demo.tsx b/apps/docs/src/components/docs/ai-elements/sandbox-demo.tsx deleted file mode 100644 index 55604449..00000000 --- a/apps/docs/src/components/docs/ai-elements/sandbox-demo.tsx +++ /dev/null @@ -1,84 +0,0 @@ -"use client"; - -import { - CodeBlock, - CodeBlockActions, - CodeBlockCopyButton, - CodeBlockFilename, - CodeBlockHeader, - CodeBlockTitle, - Sandbox, - SandboxContent, - SandboxHeader, - SandboxTabContent, - SandboxTabs, - SandboxTabsBar, - SandboxTabsList, - SandboxTabsTrigger, -} from "ghost-ui"; - -const codeSnippet = `import { useState } from "react"; - -export default function Counter() { - const [count, setCount] = useState(0); - - return ( -
-

{count}

- -
- ); -}`; - -const outputText = `> next dev --turbo - Ready in 1.2s - Local: http://localhost:3000 - Network: http://192.168.1.100:3000 - - Compiled /page in 340ms`; - -export function SandboxDemo() { - return ( -
- - - - - - - Code - Output - - - - - - - counter.tsx - - - - - - - - -
{outputText}
-
-
-
-
- - - - -
- Executing test suite... -
-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/schema-display-demo.tsx b/apps/docs/src/components/docs/ai-elements/schema-display-demo.tsx deleted file mode 100644 index 12c4c54b..00000000 --- a/apps/docs/src/components/docs/ai-elements/schema-display-demo.tsx +++ /dev/null @@ -1,171 +0,0 @@ -"use client"; - -import { SchemaDisplay } from "ghost-ui"; - -export function SchemaDisplayDemo() { - return ( -
- - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/shimmer-demo.tsx b/apps/docs/src/components/docs/ai-elements/shimmer-demo.tsx deleted file mode 100644 index 2eb428f5..00000000 --- a/apps/docs/src/components/docs/ai-elements/shimmer-demo.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { Shimmer } from "ghost-ui"; - -export function ShimmerDemo() { - return ( -
- - Generating response... - - - - Analyzing your code and preparing suggestions - - - - Thinking... - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/snippet-demo.tsx b/apps/docs/src/components/docs/ai-elements/snippet-demo.tsx deleted file mode 100644 index 56d45b7b..00000000 --- a/apps/docs/src/components/docs/ai-elements/snippet-demo.tsx +++ /dev/null @@ -1,52 +0,0 @@ -"use client"; - -import { - Snippet, - SnippetAddon, - SnippetCopyButton, - SnippetInput, - SnippetText, -} from "ghost-ui"; - -export function SnippetDemo() { - return ( -
- - - $ - - - - - - - - - - $ - - - - - - - - - - - - - - - - - $ - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/sources-demo.tsx b/apps/docs/src/components/docs/ai-elements/sources-demo.tsx deleted file mode 100644 index 598afb1c..00000000 --- a/apps/docs/src/components/docs/ai-elements/sources-demo.tsx +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; - -import { Source, Sources, SourcesContent, SourcesTrigger } from "ghost-ui"; - -export function SourcesDemo() { - return ( - - - - - - - - - ); -} diff --git a/apps/docs/src/components/docs/ai-elements/speech-input-demo.tsx b/apps/docs/src/components/docs/ai-elements/speech-input-demo.tsx deleted file mode 100644 index 9d75873d..00000000 --- a/apps/docs/src/components/docs/ai-elements/speech-input-demo.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client"; - -import { SpeechInput } from "ghost-ui"; -import { useState } from "react"; - -export function SpeechInputDemo() { - const [transcript, setTranscript] = useState(""); - - return ( -
-

- Click the microphone button to begin recording. Uses the Web Speech API - when available, with a MediaRecorder fallback. -

- - - setTranscript((prev) => (prev ? `${prev} ${text}` : text)) - } - /> - -
-

Transcription output

-

- {transcript || "Transcribed text will appear here..."} -

-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/stack-trace-demo.tsx b/apps/docs/src/components/docs/ai-elements/stack-trace-demo.tsx deleted file mode 100644 index b8863d15..00000000 --- a/apps/docs/src/components/docs/ai-elements/stack-trace-demo.tsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client"; - -import { - StackTrace, - StackTraceActions, - StackTraceContent, - StackTraceCopyButton, - StackTraceError, - StackTraceErrorMessage, - StackTraceErrorType, - StackTraceExpandButton, - StackTraceFrames, - StackTraceHeader, -} from "ghost-ui"; - -const typeErrorTrace = `TypeError: Cannot read properties of undefined (reading 'map') - at UserList (/src/components/UserList.tsx:24:18) - at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:14985:18) - at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:17811:13) - at beginWork (node_modules/react-dom/cjs/react-dom.development.js:19049:16) - at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)`; - -const referenceErrorTrace = `ReferenceError: fetchData is not defined - at loadDashboard (/src/pages/dashboard.ts:15:3) - at async handleRequest (/src/server/router.ts:42:12) - at async processMiddleware (/src/server/middleware.ts:28:5) - at node:internal/process/task_queues:95:5`; - -export function StackTraceDemo() { - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/suggestion-demo.tsx b/apps/docs/src/components/docs/ai-elements/suggestion-demo.tsx deleted file mode 100644 index feea6511..00000000 --- a/apps/docs/src/components/docs/ai-elements/suggestion-demo.tsx +++ /dev/null @@ -1,18 +0,0 @@ -"use client"; - -import { Suggestion, Suggestions } from "ghost-ui"; - -export function SuggestionDemo() { - return ( -
-

Suggested prompts

- - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/task-demo.tsx b/apps/docs/src/components/docs/ai-elements/task-demo.tsx deleted file mode 100644 index fd752437..00000000 --- a/apps/docs/src/components/docs/ai-elements/task-demo.tsx +++ /dev/null @@ -1,43 +0,0 @@ -"use client"; - -import { - Task, - TaskContent, - TaskItem, - TaskItemFile, - TaskTrigger, -} from "ghost-ui"; - -export function TaskDemo() { - return ( -
- - - - - Found src/auth/login.ts — contains the - main login handler with JWT token generation. - - - Found src/middleware/auth.ts — - validates tokens on protected routes. - - - Found src/lib/session.ts — manages - session creation and expiration. - - - - - - - - - Reviewed prisma/schema.prisma for user - model relationships. - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/terminal-demo.tsx b/apps/docs/src/components/docs/ai-elements/terminal-demo.tsx deleted file mode 100644 index 6142dca7..00000000 --- a/apps/docs/src/components/docs/ai-elements/terminal-demo.tsx +++ /dev/null @@ -1,63 +0,0 @@ -"use client"; - -import { - Terminal, - TerminalActions, - TerminalContent, - TerminalCopyButton, - TerminalHeader, - TerminalTitle, -} from "ghost-ui"; - -const buildOutput = `\x1b[32m$\x1b[0m next build -\x1b[36minfo\x1b[0m - Linting and checking validity of types... -\x1b[36minfo\x1b[0m - Creating an optimized production build... -\x1b[36minfo\x1b[0m - Compiled successfully -\x1b[36minfo\x1b[0m - Collecting page data... -\x1b[36minfo\x1b[0m - Generating static pages (8/8) -\x1b[36minfo\x1b[0m - Finalizing page optimization... - -Route (app) Size First Load JS -\x1b[37m+\x1b[0m / 5.2 kB 89.3 kB -\x1b[37m+\x1b[0m /about 1.8 kB 85.9 kB -\x1b[37m+\x1b[0m /dashboard 12.4 kB 96.5 kB -\x1b[37m+\x1b[0m /api/health 0 B 0 B - -\x1b[32m\u2713\x1b[0m Build completed in 14.2s`; - -const gitOutput = `\x1b[33mOn branch main\x1b[0m -Your branch is up to date with 'origin/main'. - -Changes to be committed: - \x1b[32mnew file: src/components/avatar.tsx\x1b[0m - \x1b[32mmodified: src/lib/utils.ts\x1b[0m - \x1b[31mdeleted: src/old-component.tsx\x1b[0m - -Untracked files: - \x1b[31m.env.local\x1b[0m`; - -export function TerminalDemo() { - return ( -
- - - Build Output - - - - - - - - - - git status - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/test-results-demo.tsx b/apps/docs/src/components/docs/ai-elements/test-results-demo.tsx deleted file mode 100644 index e3811432..00000000 --- a/apps/docs/src/components/docs/ai-elements/test-results-demo.tsx +++ /dev/null @@ -1,132 +0,0 @@ -"use client"; - -import { - Test, - TestError, - TestErrorMessage, - TestErrorStack, - TestResults, - TestResultsContent, - TestResultsDuration, - TestResultsHeader, - TestResultsProgress, - TestResultsSummary, - TestSuite, - TestSuiteContent, - TestSuiteName, -} from "ghost-ui"; - -export function TestResultsDemo() { - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - Expected status 200 but received 500 - - - {`at Object. (tests/api/user.test.ts:45:10) - at processTicksAndRejections (node:internal/process/task_queues:95:5)`} - - - - - - - AssertionError: expected 'invalid' to match - /^[^@]+@[^@]+$/ - - - - - - - - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/tool-demo.tsx b/apps/docs/src/components/docs/ai-elements/tool-demo.tsx deleted file mode 100644 index db1d9e3d..00000000 --- a/apps/docs/src/components/docs/ai-elements/tool-demo.tsx +++ /dev/null @@ -1,63 +0,0 @@ -"use client"; - -import { Tool, ToolContent, ToolHeader, ToolInput, ToolOutput } from "ghost-ui"; - -export function ToolDemo() { - return ( -
- - - - - - - - - - - - - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/toolbar-demo.tsx b/apps/docs/src/components/docs/ai-elements/toolbar-demo.tsx deleted file mode 100644 index 0d6a2cf5..00000000 --- a/apps/docs/src/components/docs/ai-elements/toolbar-demo.tsx +++ /dev/null @@ -1,71 +0,0 @@ -"use client"; - -import { type NodeTypes, ReactFlowProvider } from "@xyflow/react"; -import { - Button, - Canvas, - Node, - NodeContent, - NodeHeader, - NodeTitle, - Toolbar, -} from "ghost-ui"; -import { CopyIcon, PencilIcon, Trash2Icon } from "lucide-react"; -import { useMemo } from "react"; - -const ToolbarNode = () => ( - - - Select this node - - -

- Click to select and reveal the toolbar below. -

-
- - - - - -
-); - -const initialNodes = [ - { - id: "1", - type: "toolbar", - position: { x: 100, y: 60 }, - data: {}, - selected: true, - }, -]; - -export function ToolbarDemo() { - const nodeTypes: NodeTypes = useMemo( - () => ({ - toolbar: ToolbarNode, - }), - [], - ); - - return ( -
-

- A floating toolbar that appears below a selected node, providing - contextual actions. -

- -
- -
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/transcription-demo.tsx b/apps/docs/src/components/docs/ai-elements/transcription-demo.tsx deleted file mode 100644 index 43c17faf..00000000 --- a/apps/docs/src/components/docs/ai-elements/transcription-demo.tsx +++ /dev/null @@ -1,54 +0,0 @@ -"use client"; - -import { Button, Transcription, TranscriptionSegment } from "ghost-ui"; -import { useState } from "react"; - -const mockSegments = [ - { text: "Welcome to the demo.", startSecond: 0, endSecond: 2 }, - { text: " Today we are looking at", startSecond: 2, endSecond: 4 }, - { text: " the transcription component,", startSecond: 4, endSecond: 6 }, - { text: " which highlights words", startSecond: 6, endSecond: 8 }, - { text: " as audio plays.", startSecond: 8, endSecond: 10 }, - { text: " Each segment is clickable", startSecond: 10, endSecond: 12 }, - { text: " and can seek to", startSecond: 12, endSecond: 14 }, - { text: " the corresponding position", startSecond: 14, endSecond: 16 }, - { text: " in the audio track.", startSecond: 16, endSecond: 18 }, -]; - -export function TranscriptionDemo() { - const [currentTime, setCurrentTime] = useState(0); - - return ( -
-
- - - {currentTime.toFixed(1)}s - - -
- - - {(segment, index) => ( - - )} - -
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/voice-selector-demo.tsx b/apps/docs/src/components/docs/ai-elements/voice-selector-demo.tsx deleted file mode 100644 index a5fe8b04..00000000 --- a/apps/docs/src/components/docs/ai-elements/voice-selector-demo.tsx +++ /dev/null @@ -1,137 +0,0 @@ -"use client"; - -import { - Button, - VoiceSelector, - VoiceSelectorAccent, - VoiceSelectorAge, - VoiceSelectorAttributes, - VoiceSelectorBullet, - VoiceSelectorContent, - VoiceSelectorDescription, - VoiceSelectorEmpty, - VoiceSelectorGender, - VoiceSelectorGroup, - VoiceSelectorInput, - VoiceSelectorItem, - VoiceSelectorList, - VoiceSelectorName, - VoiceSelectorPreview, - VoiceSelectorSeparator, - VoiceSelectorTrigger, -} from "ghost-ui"; -import { useState } from "react"; - -const voices = [ - { - id: "alloy", - name: "Alloy", - gender: "non-binary" as const, - accent: "american" as const, - age: "Young Adult", - description: "Versatile, balanced tone", - }, - { - id: "echo", - name: "Echo", - gender: "male" as const, - accent: "american" as const, - age: "Adult", - description: "Warm, resonant baritone", - }, - { - id: "fable", - name: "Fable", - gender: "female" as const, - accent: "british" as const, - age: "Adult", - description: "Expressive storyteller", - }, - { - id: "onyx", - name: "Onyx", - gender: "male" as const, - accent: "american" as const, - age: "Mature", - description: "Deep, authoritative", - }, - { - id: "nova", - name: "Nova", - gender: "female" as const, - accent: "australian" as const, - age: "Young Adult", - description: "Bright, energetic", - }, - { - id: "shimmer", - name: "Shimmer", - gender: "female" as const, - accent: "irish" as const, - age: "Adult", - description: "Soft, calming presence", - }, -]; - -export function VoiceSelectorDemo() { - const [selected, setSelected] = useState(undefined); - - return ( -
-

- A dialog-based voice picker with search, gender, accent, and preview - controls. -

- - - - - - - - - - No voices found. - - {voices.map((voice) => ( - setSelected(voice.id)} - > -
-
-
- {voice.name} - - - - - - {voice.age} - -
- - {voice.description} - -
- { - /* no-op in demo */ - }} - /> -
-
- ))} -
- -
-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/ai-elements/web-preview-demo.tsx b/apps/docs/src/components/docs/ai-elements/web-preview-demo.tsx deleted file mode 100644 index 76c8253b..00000000 --- a/apps/docs/src/components/docs/ai-elements/web-preview-demo.tsx +++ /dev/null @@ -1,52 +0,0 @@ -"use client"; - -import { - WebPreview, - WebPreviewBody, - WebPreviewConsole, - WebPreviewNavigation, - WebPreviewNavigationButton, - WebPreviewUrl, -} from "ghost-ui"; -import { ArrowLeftIcon, ArrowRightIcon, RefreshCwIcon } from "lucide-react"; - -export function WebPreviewDemo() { - return ( -
- - - - - - - - - - - - - - - - -
- ); -} diff --git a/apps/docs/src/components/docs/bento/activity-goal.tsx b/apps/docs/src/components/docs/bento/activity-goal.tsx deleted file mode 100644 index f7f1c2d4..00000000 --- a/apps/docs/src/components/docs/bento/activity-goal.tsx +++ /dev/null @@ -1,63 +0,0 @@ -"use client"; - -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "ghost-ui"; -import { Minus, Plus } from "lucide-react"; -import * as React from "react"; - -export function CardsActivityGoal() { - const [amount, setAmount] = React.useState(350); - - function onClick(adjustment: number) { - setAmount(Math.max(200, Math.min(400, amount + adjustment))); - } - - return ( - - - Payment Amount - Set your payment amount. - - -
- -
-
${amount}
-
- USD -
-
- -
-
- - - -
- ); -} diff --git a/apps/docs/src/components/docs/bento/calendar.tsx b/apps/docs/src/components/docs/bento/calendar.tsx deleted file mode 100644 index e1971caf..00000000 --- a/apps/docs/src/components/docs/bento/calendar.tsx +++ /dev/null @@ -1,24 +0,0 @@ -"use client"; - -import { addDays } from "date-fns"; -import { Calendar, Card, CardContent } from "ghost-ui"; - -const start = new Date(2023, 5, 5); - -export function CardsCalendar() { - return ( - - - - - - ); -} diff --git a/apps/docs/src/components/docs/bento/chat.tsx b/apps/docs/src/components/docs/bento/chat.tsx deleted file mode 100644 index 85663470..00000000 --- a/apps/docs/src/components/docs/bento/chat.tsx +++ /dev/null @@ -1,249 +0,0 @@ -"use client"; - -import { - Avatar, - AvatarFallback, - AvatarImage, - Button, - Card, - CardContent, - CardFooter, - CardHeader, - Command, - CommandEmpty, - CommandGroup, - CommandInput, - CommandItem, - CommandList, - cn, - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Input, - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "ghost-ui"; -import { Check, Plus, Send } from "lucide-react"; -import * as React from "react"; - -const users = [ - { - name: "Olivia Martin", - email: "m@example.com", - }, - { - name: "Isabella Nguyen", - email: "isabella.nguyen@email.com", - }, - { - name: "Emma Wilson", - email: "emma@example.com", - }, - { - name: "Jackson Lee", - email: "lee@example.com", - }, - { - name: "William Kim", - email: "will@email.com", - }, -] as const; - -type User = (typeof users)[number]; - -export function CardsChat() { - const [open, setOpen] = React.useState(false); - const [selectedUsers, setSelectedUsers] = React.useState([]); - - const [messages, setMessages] = React.useState([ - { - role: "agent", - content: "Hi, how can I help you today?", - }, - { - role: "user", - content: "Hey, I'm having trouble with my account.", - }, - { - role: "agent", - content: "What seems to be the problem?", - }, - { - role: "user", - content: "I can't log in.", - }, - ]); - const [input, setInput] = React.useState(""); - const inputLength = input.trim().length; - - return ( - <> - - -
- - OM - -
-

Sofia Davis

-

m@example.com

-
-
- - - - - - New message - - -
- -
- {messages.map((message, index) => ( -
- {message.content} -
- ))} -
-
- -
{ - event.preventDefault(); - if (inputLength === 0) return; - setMessages([ - ...messages, - { - role: "user", - content: input, - }, - ]); - setInput(""); - }} - className="flex w-full items-center space-x-2" - > - setInput(event.target.value)} - /> - -
-
-
- - - - New message - - Invite a user to this thread. This will create a new group - message. - - - - - - No users found. - - {users.map((user) => ( - { - if (selectedUsers.includes(user)) { - return setSelectedUsers( - selectedUsers.filter( - (selectedUser) => selectedUser !== user, - ), - ); - } - - return setSelectedUsers( - [...users].filter((u) => - [...selectedUsers, user].includes(u), - ), - ); - }} - > - - {user.name[0]} - -
-

- {user.name} -

-

- {user.email} -

-
- {selectedUsers.includes(user) ? ( - - ) : null} -
- ))} -
-
-
- - {selectedUsers.length > 0 ? ( -
- {selectedUsers.map((user) => ( - - {user.name[0]} - - ))} -
- ) : ( -

- Select users to add to this thread. -

- )} - -
-
-
- - ); -} diff --git a/apps/docs/src/components/docs/bento/cookie-settings.tsx b/apps/docs/src/components/docs/bento/cookie-settings.tsx deleted file mode 100644 index 515542a8..00000000 --- a/apps/docs/src/components/docs/bento/cookie-settings.tsx +++ /dev/null @@ -1,60 +0,0 @@ -"use client"; - -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Label, - Switch, -} from "ghost-ui"; - -export function CardsCookieSettings() { - return ( - - - Cookie Settings - Manage your cookie settings here. - - -
- - -
-
- - -
-
- - -
-
- - - -
- ); -} diff --git a/apps/docs/src/components/docs/bento/create-account.tsx b/apps/docs/src/components/docs/bento/create-account.tsx deleted file mode 100644 index 236868cd..00000000 --- a/apps/docs/src/components/docs/bento/create-account.tsx +++ /dev/null @@ -1,60 +0,0 @@ -"use client"; - -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Input, - Label, -} from "ghost-ui"; -import { Icons } from "@/components/docs/icons"; - -export function CardsCreateAccount() { - return ( - - - Create an account - - Enter your email below to create your account - - - -
- - -
-
-
- -
-
- - Or continue with - -
-
-
- - -
-
- - -
-
- - - -
- ); -} diff --git a/apps/docs/src/components/docs/bento/data-table.tsx b/apps/docs/src/components/docs/bento/data-table.tsx deleted file mode 100644 index 239bd1c7..00000000 --- a/apps/docs/src/components/docs/bento/data-table.tsx +++ /dev/null @@ -1,322 +0,0 @@ -"use client"; - -import { - ColumnDef, - ColumnFiltersState, - flexRender, - getCoreRowModel, - getFilteredRowModel, - getPaginationRowModel, - getSortedRowModel, - SortingState, - useReactTable, - VisibilityState, -} from "@tanstack/react-table"; -import { - Button, - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, - Checkbox, - DropdownMenu, - DropdownMenuCheckboxItem, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, - Input, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "ghost-ui"; -import { ArrowUpDown, ChevronDown, MoreHorizontal } from "lucide-react"; -import * as React from "react"; - -const data: Payment[] = [ - { - id: "m5gr84i9", - amount: 316, - status: "success", - email: "ken99@example.com", - }, - { - id: "3u1reuv4", - amount: 242, - status: "success", - email: "Abe45@example.com", - }, - { - id: "derv1ws0", - amount: 837, - status: "processing", - email: "Monserrat44@example.com", - }, - { - id: "bhqecj4p", - amount: 721, - status: "failed", - email: "carmella@example.com", - }, -]; - -export type Payment = { - id: string; - amount: number; - status: "pending" | "processing" | "success" | "failed"; - email: string; -}; - -export const columns: ColumnDef[] = [ - { - id: "select", - header: ({ table }) => ( - table.toggleAllPageRowsSelected(!!value)} - aria-label="Select all" - /> - ), - cell: ({ row }) => ( - row.toggleSelected(!!value)} - aria-label="Select row" - /> - ), - enableSorting: false, - enableHiding: false, - }, - { - accessorKey: "status", - header: "Status", - cell: ({ row }) => ( -
{row.getValue("status")}
- ), - }, - { - accessorKey: "email", - header: ({ column }) => { - return ( - - ); - }, - cell: ({ row }) =>
{row.getValue("email")}
, - }, - { - accessorKey: "amount", - header: () =>
Amount
, - cell: ({ row }) => { - const amount = parseFloat(row.getValue("amount")); - - // Format the amount as a dollar amount - const formatted = new Intl.NumberFormat("en-US", { - style: "currency", - currency: "USD", - }).format(amount); - - return ( -
{formatted}
- ); - }, - }, - { - id: "actions", - enableHiding: false, - cell: ({ row }) => { - const payment = row.original; - - return ( - - - - - - Actions - navigator.clipboard.writeText(payment.id)} - > - Copy payment ID - - - View customer - View payment details - - - ); - }, - }, -]; - -export function CardsDataTable() { - const [sorting, setSorting] = React.useState([]); - const [columnFilters, setColumnFilters] = React.useState( - [], - ); - const [columnVisibility, setColumnVisibility] = - React.useState({}); - const [rowSelection, setRowSelection] = React.useState({}); - - const table = useReactTable({ - data, - columns, - onSortingChange: setSorting, - onColumnFiltersChange: setColumnFilters, - getCoreRowModel: getCoreRowModel(), - getPaginationRowModel: getPaginationRowModel(), - getSortedRowModel: getSortedRowModel(), - getFilteredRowModel: getFilteredRowModel(), - onColumnVisibilityChange: setColumnVisibility, - onRowSelectionChange: setRowSelection, - state: { - sorting, - columnFilters, - columnVisibility, - rowSelection, - }, - }); - - return ( - - - Payments - Manage your payments. - - -
- - table.getColumn("email")?.setFilterValue(event.target.value) - } - className="max-w-sm" - /> - - - - - - {table - .getAllColumns() - .filter((column) => column.getCanHide()) - .map((column) => { - return ( - - column.toggleVisibility(!!value) - } - > - {column.id} - - ); - })} - - -
-
- - - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => { - return ( - - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext(), - )} - - ); - })} - - ))} - - - {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} - - ))} - - )) - ) : ( - - - No results. - - - )} - -
-
-
-
- {table.getFilteredSelectedRowModel().rows.length} of{" "} - {table.getFilteredRowModel().rows.length} row(s) selected. -
-
- - -
-
-
-
- ); -} diff --git a/apps/docs/src/components/docs/bento/index.tsx b/apps/docs/src/components/docs/bento/index.tsx deleted file mode 100644 index bf01514f..00000000 --- a/apps/docs/src/components/docs/bento/index.tsx +++ /dev/null @@ -1,100 +0,0 @@ -"use client"; - -import { useIsMobile } from "ghost-ui"; -import { lazy, Suspense } from "react"; -import { CardsChat } from "@/components/docs/bento/chat"; -import { CardsCookieSettings } from "@/components/docs/bento/cookie-settings"; -import { CardsCreateAccount } from "@/components/docs/bento/create-account"; -import { CardsPaymentMethod } from "@/components/docs/bento/payment-method"; -import { CardsReportIssue } from "@/components/docs/bento/report-issue"; -import { CardsShare } from "@/components/docs/bento/share"; -import { CardsTeamMembers } from "@/components/docs/bento/team-members"; - -const CardsStats = lazy(() => - import("@/components/docs/bento/stats").then((m) => ({ - default: m.CardsStats, - })), -); -const CardsCalendar = lazy(() => - import("@/components/docs/bento/calendar").then((m) => ({ - default: m.CardsCalendar, - })), -); -const CardsActivityGoal = lazy(() => - import("@/components/docs/bento/activity-goal").then((m) => ({ - default: m.CardsActivityGoal, - })), -); -const CardsMetric = lazy(() => - import("@/components/docs/bento/metric").then((m) => ({ - default: m.CardsMetric, - })), -); -const CardsDataTable = lazy(() => - import("@/components/docs/bento/data-table").then((m) => ({ - default: m.CardsDataTable, - })), -); - -function CalendarMetricGroup() { - return ( -
- - - -
- - - -
-
- - - -
-
- ); -} - -export function BentoDemo() { - const isMobile = useIsMobile(); - - return ( -
-
- - - - {isMobile && } -
-
- - - -
-
- - -
- -
-
-
-
-
- {!isMobile && ( - <> - - - - - - )} - -
- -
-
-
- ); -} diff --git a/apps/docs/src/components/docs/bento/metric.tsx b/apps/docs/src/components/docs/bento/metric.tsx deleted file mode 100644 index 17d3c52f..00000000 --- a/apps/docs/src/components/docs/bento/metric.tsx +++ /dev/null @@ -1,105 +0,0 @@ -"use client"; - -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, - ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from "ghost-ui"; -import { Line, LineChart } from "recharts"; - -const data = [ - { - average: 400, - today: 240, - }, - { - average: 300, - today: 139, - }, - { - average: 200, - today: 980, - }, - { - average: 278, - today: 390, - }, - { - average: 189, - today: 480, - }, - { - average: 239, - today: 380, - }, - { - average: 349, - today: 430, - }, -]; - -const chartConfig = { - today: { - label: "Current Value", - color: "hsl(var(--primary))", - }, - average: { - label: "Average Value", - color: "hsl(var(--primary))", - }, -} satisfies ChartConfig; - -export function CardsMetric() { - return ( - - - Portfolio Value - - Your portfolio is performing above its 7-day average. - - - - - - - - } /> - - - - - ); -} diff --git a/apps/docs/src/components/docs/bento/payment-amount.tsx b/apps/docs/src/components/docs/bento/payment-amount.tsx deleted file mode 100644 index d2b84774..00000000 --- a/apps/docs/src/components/docs/bento/payment-amount.tsx +++ /dev/null @@ -1,63 +0,0 @@ -"use client"; - -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "ghost-ui"; -import { Minus, Plus } from "lucide-react"; -import * as React from "react"; - -export function PaymentAmount() { - const [amount, setAmount] = React.useState(350); - - function onClick(adjustment: number) { - setAmount(Math.max(200, Math.min(400, amount + adjustment))); - } - - return ( - - - Payment Amount - Set your payment amount. - - -
- -
-
${amount}
-
- USD -
-
- -
-
- - - -
- ); -} diff --git a/apps/docs/src/components/docs/bento/payment-method.tsx b/apps/docs/src/components/docs/bento/payment-method.tsx deleted file mode 100644 index 7df3c97e..00000000 --- a/apps/docs/src/components/docs/bento/payment-method.tsx +++ /dev/null @@ -1,138 +0,0 @@ -"use client"; - -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Input, - Label, - RadioGroup, - RadioGroupItem, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "ghost-ui"; -import { Icons } from "@/components/docs/icons"; - -export function CardsPaymentMethod() { - return ( - - - Payment Method - - Add a new payment method to your account. - - - - -
- - -
-
- - -
-
-
- - -
-
- - -
-
- - -
-
-
- - -
-
- - -
-
- - -
-
-
- - - -
- ); -} diff --git a/apps/docs/src/components/docs/bento/report-issue.tsx b/apps/docs/src/components/docs/bento/report-issue.tsx deleted file mode 100644 index 4cdf6b29..00000000 --- a/apps/docs/src/components/docs/bento/report-issue.tsx +++ /dev/null @@ -1,93 +0,0 @@ -"use client"; - -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - Input, - Label, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - Textarea, -} from "ghost-ui"; -import * as React from "react"; - -export function CardsReportIssue() { - const id = React.useId(); - - return ( - - - Report an issue - - What area are you having problems with? - - - -
-
- - -
-
- - -
-
-
- - -
-
- -