Author SHA1 Message Date
hanzo-dev 70382d4f10 ci: canonical pair — hanzo.yml + forge caller
Hanzo CI/CD / cicd (push) Successful in 36s
CI/CD / cicd (push) Successful in 37s
github.com has no runner for hanzo-build-linux-amd64, so a caller under
.github/workflows is a gate that can never be scheduled. This is the ~7-line
caller on the plane that can (git.hanzo.ai git-runner fleet), pinned @v1.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-08-06 02:34:31 -07:00
zeekayandClaude Fable 5 be8468add4 publish through the shared sitedeploy action
deploy / site (push) Successful in 11s
The enqueue -> upload -> complete calls were transcribed into this file and
twelve others before hanzoai/ci carried them. Four steps collapse to one
`uses:`, so the plane's contract is written once and a fix lands everywhere
rather than in whichever repo someone remembered to edit.

It also self-provisions. sitedeploy POSTs /v1/projects idempotently before the
enqueue, so a slug that has never deployed no longer 404s on its first run --
which is every site in this fleet except hanzo-ai, hips and hanzo-app.

Build steps are untouched, verified byte-identical against the previous
revision; only the Sites-plane plumbing moved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 19:46:34 -07:00
zeekayandClaude Fable 5 915403d9fa Track the reference: upload under a grant, not with bucket keys
deploy / site (push) Failing after 9s
The canonical flow in hanzoai/hips moved while this was being written. It no
longer syncs with SITES_S3_*: the 202 carries a presigned POST policy confined
to this site's prefix and expiring in 30 minutes, CI POSTs one object at a time
under it, and completion reports the file manifest as `keys` so cloud prunes
the prefix -- a write-only grant cannot delete, so `--delete` had to move
server-side.

Worth stating why, not just what. Those bucket keys were the hanzo-sites
bucket's own long-lived credentials, and that bucket holds EVERY org's site
separated only by key prefix. A copy in this repo was write access to everyone's
site, forever, in as many places as there were repos. Now this repo holds no
storage credential at all; the only secret is HANZO_DEPLOY_TOKEN, which
identifies us rather than granting anything, and it lives on the FORGE because
.hanzo/workflows is what the forge reads.

Verified by diffing the generated plane steps against the reference: every
executable line is byte-identical, including the ::add-mask:: of the policy and
signature. The deltas are comment wrapping, the dead `bucket` output dropped
(nothing consumes it once the grant carries the URL), and the enqueue error
naming the slug -- these projects are unverifiable from here, so a 4xx should
say which one it could not find.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 18:56:10 -07:00
zeekayandClaude Fable 5 84586e4ee9 Record that hz.js cannot authenticate yet
Measured, not assumed: POST /v1/event with an unattributed batch answers
401 ingest_key_required, and hz.js through 0.3.11 sends neither an
Authorization header nor ?ingest_key= — the npm client has ingestKey on both
the fetch and the beacon, the script form was never given the same. So this
page is wired to the right door and is being turned away at it.

Written down rather than worked around. The fix is one attribute in
hanzoai/ui pkgs/event/hz.js; an inline script here that happened to send the
key would be a second telemetry client, which is the thing hz.js exists to
prevent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 18:42:48 -07:00
zeekayandClaude Fable 5 5dd8fb3ddd Correct which side of the mirror is writable
LLM.md said "git.hanzo.ai is canonical; GitHub is a mirror". The forge refuses
`git push` with `Mirror Repository hanzoai/logo is read-only` — it is a PULL
mirror of GitHub, so the arrow points the other way. Code lands on GitHub; the
forge pulls it and runs the workflows GitHub cannot see.

Written down because acting on the old sentence means pushing at a remote that
rejects you, and because the real consequence is easy to miss: a push is not a
deploy, and the lag until one is the mirror's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 18:40:54 -07:00
zeekayandClaude Fable 5 4aba18574d Ship logo.hanzo.ai on the Sites plane
deploy / site (push) Failing after 9s
publish / publish (push) Successful in 9s
index.html is one self-contained page. Nothing here executes, so an image, a
CR, a tag and a pod are four moving parts standing between a static file and a
browser. deploy.yml now enqueues, syncs, and flips live -- the same three steps
every other Hanzo site uses.

out/ is ASSEMBLED rather than built: index.html plus hz.js, the script-tag form
of @hanzo/event, copied out of node_modules. That is why @hanzo/event is a
devDependency here. It is not vendored and not loaded from a public CDN: the
lockfile decides which version of the telemetry client ships, and the only
script this page loads stays same-origin. hz.js posts to the same
api.hanzo.ai/v1/event as every bundled surface, so this page counts on the one
stream instead of being the one surface nobody measures.

The Dockerfile stays until hanzoai/universe retires the App CR and DNS moves --
deleting the recipe for the thing currently serving would be a half-migration.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04 18:29:29 -07:00
Claude 33b5ef2b2e ci: name a pool the fleet actually advertises
deploy / image (push) Successful in 9s
The deploy job asked for `ubuntu-latest`. This file lives in .hanzo/workflows,
which GitHub never reads -- git.hanzo.ai is the only thing that can run it, and
the fleet advertises no generic ubuntu-* label. That is deliberate and recorded
in the runner ConfigMap: ~1400 mirrored upstream forks all ask for ubuntu-latest,
and the forge errors rather than skipping a job it cannot place, so one bad job
was retried ~520 times across 10 runners.

An unmatched label is not a failure here, it is silence -- the job queues until
the 24h timeout. So this deploy has never produced an image, and nothing ever
said so. Same class as the playground regression, found by checking every
.hanzo/workflows file against the labels the runner ConfigMap actually declares
rather than against the ones I assumed.

hanzo-build-linux-amd64 is registered (verified against cm/git-runner-config).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 16:55:28 -07:00
hanzo-dev 8cf57626fc ci: drop the pull job — this repo is a mirror, Gitea already syncs it
Added it on the theory that the forge was drifting. It is not: the forge copy
matched GitHub at every check, because this repo is a pull-mirror and Gitea's
own scheduler keeps it current. The job would have been a second mechanism
doing what the first already does, pushing refs into a repo the server owns.

sync-from-github belongs to the NATIVE forge repos — cloud, ci, mirrors — which
have no mirror behind them. The real reason nothing ran here was the Actions
unit, off since migrate; hanzoai/mirrors reconcile.py now switches it on for any
repo carrying .hanzo/workflows.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 21:57:26 -07:00
hanzo-dev d106e4395a ci: one publish trigger, one pull transport; drop the Zoo Makefile
publish fires on a version change in package.json, the same as every sibling —
the v* tag was a second place the version lived. Its test step no longer carries
continue-on-error, and it installs with pnpm, which the repo moved to.

sync-from-github pulls the mirror into the forge every 10m, fast-forward only.
Nothing carried refs here before, and the repo drifted 3 ahead and 8 behind.

The Makefile was Zoo's, verbatim: Zoo help text, @zooai/logo, docker targets
tagging zooai/logo from a Hanzo repo. It wrapped npm around what are now pnpm
scripts and offered a second way to publish. Deleted, with the stray zoo names
in .gitignore and the menu-bar preview.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 21:50:59 -07:00
hanzo-dev 5520e7208c fix: lockfile must agree that sharp is a devDependency
The reconcile merge took sharp -> devDependencies from the published line and
the lockfile from main, which still listed it under dependencies. CI installs
with --frozen-lockfile by default, so the two disagreeing meant every publish
would have failed at install.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 21:47:23 -07:00
hanzo-dev 2aa71b0610 merge: reconcile the published 1.0.13 line with the pnpm/TS7 main
npm shipped @hanzo/logo@1.0.13 with the motion layer, but main sat at 1.0.10
and never had src/motion.ts — the registry was ahead of the branch, so a
checkout of main could not rebuild what users were installing.

Both sides survive: the motion layer and the ./motion export from the published
line, the pnpm migration, TS7 tsconfig and .hanzo/workflows from main. pnpm wins
the lockfile, so package-lock.json goes.

1.0.14 — the next patch after what is actually on the registry.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 21:37:19 -07:00
zeekayandhanzo-dev 1a38d4e6e9 build: migrate tsconfig to TypeScript 7 (native compiler)
TypeScript 7 is the native Go compiler and removes `baseUrl` and
`moduleResolution: node|node10`. Both appear here, so `tsc` from TS7
refuses the config outright (TS5102 / TS5108) and cannot typecheck.

`paths` targets resolve relative to `baseUrl` when it is set and relative
to the tsconfig file otherwise. Every `baseUrl` folded here already
pointed at the config's own directory, so dropping it moves nothing and
the targets are left byte-identical. Where a baseUrl pointed elsewhere,
each affected target was rewritten as join(baseUrl, target).

`moduleResolution` was chosen from the declared `module`: commonjs ->
node16, esnext/preserve -> bundler. Configs whose `module` is unset or
exotic were left alone rather than guessed at.

The result is accepted by BOTH toolchains, so nothing has to upgrade
TypeScript in lockstep. Verified on hanzo/chat packages/api: tsc 5.9
779 -> 778 errors (no regression), and tsc 7.0.2 now runs the project
in 2s where it previously refused the config.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 14:18:20 -07:00
hanzo-dev 33d2945d8e ci: drop the Gitea mirror-sync nudge
Superseded: the Hanzo GitHub App pushes a webhook, so the forge tracks GitHub
without a per-repo workflow. This file called git.hanzo.ai/api/v1/.../mirror-sync
— a Gitea API for a system we no longer drive — and would sit inert in every repo.

One mechanism, in one place, instead of ~350 copies of a cron.
2026-07-27 10:36:47 -07:00
zeekay 1972f6f7bb Merge remote-tracking branch 'origin/main' into HEAD
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 09:00:56 -07:00
zeekayandhanzo-dev 24def2ea2a build: move to pnpm
One package manager, one lockfile. pnpm-lock.yaml is tracked, package-lock.json is
deleted and every other manager's is ignored, and `packageManager` pins the version
corepack installs so a laptop and CI resolve the same tree.

Where a pnpm-workspace.yaml appears, it names the packages allowed to run install
scripts — pnpm denies them by default, so anything not listed cannot execute code
at install time just by being pulled in.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 09:00:55 -07:00
zeekayandhanzo-dev 9243dc2f96 ci: restore the @hanzo/logo publisher under .hanzo/workflows
The tag publisher was deleted this morning without a replacement, so @hanzo/logo
had no producer anywhere: no workflow, no failing run, just a package that would
stop moving. It is back at .hanzo/workflows/publish.yml where the forge reads it,
with two changes and no others.

It reads NPM_TOKEN, the one secret name every other Hanzo repo uses, instead of a
second name for the same credential. And it no longer writes a GitHub Release: the
forge does not serve that API, and the step ran after a successful publish, so it
would have turned a shipped package red.

.github/workflows now holds the canonical sync.yml alone — refs to git.hanzo.ai
and nothing else.

The site follows the same shape as every other Hanzo surface: index.html is
self-contained, so the Dockerfile copies it into ghcr.io/hanzoai/static with no
build stage, and deploy.yml publishes ghcr.io/hanzoai/logo:<sha> without deploying
it. hanzoai/universe crs/logo.yaml names the tag that serves and is inert until a
human pins one. Replaces a gh-pages push for a Pages site that was never
configured — logo.hanzo.ai has answered 404 from our own ingress the whole time.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-27 08:45:54 -07:00
hanzo-dev be91e9d5af ci: nudge git.hanzo.ai to pull on push
git.hanzo.ai mirrors this repo by PULL on a ~10-minute interval, and arcd runs
CI/CD there — so every push waited out that interval before anything built.
This asks Gitea to pull HEAD immediately.

Latency only: the repo already mirrors via the App webhook, so a missing
HANZO_GIT_TOKEN or a failed curl is non-fatal and never fails the push.
Idempotent (mirror-sync just pulls HEAD) and concurrency-coalesced.
2026-07-27 08:23:09 -07:00
hanzo-dev 13f3ac48ca ci: remove GitHub CI — native git.hanzo.ai + cd.hanzo.ai only
This workflow ran on a self-hosted actions-runner-controller pool. ARC is
decommissioned: CI executes inside git.hanzo.ai (Gitea Actions, .hanzo/workflows)
and delivery is cd.hanzo.ai reconciling the reviewed image pin in
hanzoai/universe. GitHub is a mirror and runs nothing.

Removed rather than repointed — there is no GitHub-side pool to move to, and
leaving it would keep ARC load-bearing.
2026-07-27 08:17:46 -07:00
hanzo-dev ed8c4680d9 ci: remove GitHub CI — native git.hanzo.ai + cd.hanzo.ai only
This workflow ran on a self-hosted actions-runner-controller pool. ARC is
decommissioned: CI executes inside git.hanzo.ai (Gitea Actions, .hanzo/workflows)
and delivery is cd.hanzo.ai reconciling the reviewed image pin in
hanzoai/universe. GitHub is a mirror and runs nothing.

Removed rather than repointed — there is no GitHub-side pool to move to, and
leaving it would keep ARC load-bearing.
2026-07-27 08:17:44 -07:00
Hanzo AI 4a73203aaf deps: sharp is the asset-CLI's tool, not a consumer runtime dep — devDependencies; publish 1.0.13 2026-07-20 13:00:40 -07:00
Hanzo AI b5ae14a3fb brand motion: canonical 7-path shaded H everywhere + pure-CSS motion layer (flip + breathe + wordmark collapse); publish 1.0.12 2026-07-20 10:43:28 -07:00
22 changed files with 814 additions and 930 deletions
-26
View File
@@ -1,26 +0,0 @@
name: Deploy to GitHub Pages
on:
push:
branches: [main, master]
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
jobs:
deploy:
runs-on: hanzo-deploy-linux-amd64
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./
publish_branch: gh-pages
exclude_assets: '.github,README.md,LICENSE,.gitignore'
-106
View File
@@ -1,106 +0,0 @@
name: Publish on Tag
on:
push:
tags:
- 'v*' # Match version tags (e.g., v1.0.4)
jobs:
test:
name: Run Tests
runs-on: hanzo-build-linux-amd64
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build package
run: npm run build
- name: Run tests
run: npm test
continue-on-error: true # Don't fail if no tests configured yet
publish:
name: Publish to NPM
needs: test
runs-on: hanzo-build-linux-amd64
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Build package
run: npm run build
- name: Configure npm authentication
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
run: |
npm config set //registry.npmjs.org/:_authToken $NODE_AUTH_TOKEN
npm whoami
- name: Check and publish package
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
run: |
CURRENT_VERSION=$(node -p "require('./package.json').version")
PACKAGE_NAME=$(node -p "require('./package.json').name")
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📦 Checking $PACKAGE_NAME@$CURRENT_VERSION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# Check if this version already exists on npm
if npm view "$PACKAGE_NAME@$CURRENT_VERSION" version 2>/dev/null; then
echo "⏭️ Already published - skipping"
echo "ALREADY_PUBLISHED=true" >> $GITHUB_ENV
else
echo "🚀 Publishing to npm..."
npm publish --access public
echo "✅ Successfully published $PACKAGE_NAME@$CURRENT_VERSION"
echo "PUBLISHED=true" >> $GITHUB_ENV
echo "PACKAGE_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV
fi
- name: Create GitHub Release
if: env.PUBLISHED == 'true'
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
body: |
## 📦 NPM Package Published
- @hanzo/logo@${{ env.PACKAGE_VERSION }}
### Installation
```bash
npm install @hanzo/logo@${{ env.PACKAGE_VERSION }}
```
### Changes
See [CHANGELOG.md](https://github.com/hanzoai/logo/blob/main/CHANGELOG.md) for details.
files: |
CHANGELOG.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+7 -3
View File
@@ -6,6 +6,8 @@ node_modules/
# Build output
dist/
build/
# The site directory CI assembles (index.html + hz.js out of node_modules).
out/
*.tsbuildinfo
generated/
@@ -57,9 +59,6 @@ tmp/
# But keep important files for GitHub display
!menu-bar-preview.html
!dist/zoo-logo.svg
!dist/zoo-logo-mono.svg
!dist/zoo-logo-menubar.svg
# Keep showcase images for README
!docs/assets/*.png
@@ -89,3 +88,8 @@ dist/**/*.map
dist/*.js
dist/*.d.ts
.npmrc
# pnpm only — pnpm-lock.yaml is the tracked lockfile.
package-lock.json
yarn.lock
bun.lockb
+15
View File
@@ -0,0 +1,15 @@
# Canonical caller — every knob lives in /hanzo.yml, none here.
# Runs on the git-runner fleet at git.hanzo.ai, the only pool serving these
# labels. github.com resolves only .github/workflows and has no runner for
# them, so a caller placed there is a gate that cannot be scheduled.
name: CI/CD
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
jobs:
cicd:
uses: hanzoai/ci/.hanzo/workflows/build.yml@v1
secrets: inherit
+75
View File
@@ -0,0 +1,75 @@
name: deploy
# logo.hanzo.ai is a SITE, not an App: a static export with no compute. It ships on the
# Sites plane. Not GitHub Pages, not Cloudflare Pages, and not an image — baking
# files that never execute into a container so a Go binary can serve them means an
# image, a push, a tag pinned in a CR and running pods, all to hand back bytes.
#
# build -> out
# -> sitedeploy
#
# The publish mechanics are NOT here. They are bin/sitedeploy in hanzoai/ci,
# reached through its action, and every static surface in the fleet calls that one
# script — ensure-project, enqueue, presigned per-file upload, complete. A
# contract transcribed per repo is a contract that drifts, and this file used to
# carry its own copy of every call. It also SELF-PROVISIONS: the project is
# created idempotently before the enqueue, so committing this file is enough to
# stand the site up.
#
# The one secret is HANZO_DEPLOY_TOKEN, which identifies us rather than granting
# storage. It is set ON THE FORGE: this file lives under .hanzo/workflows/, which
# only git.hanzo.ai reads, so GitHub's secret store is not in this path at all.
on:
push:
branches: [main]
paths: ['index.html', 'package.json', 'pnpm-lock.yaml', '.hanzo/workflows/deploy.yml']
workflow_dispatch:
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false
jobs:
site:
# NOT ubuntu-latest. This file lives in .hanzo/workflows, which GitHub never
# reads — git.hanzo.ai is the only thing that can run it, and its fleet
# advertises hanzo-build-linux-amd64. An unmatched label is not an error here,
# it is silence: the job queues until the 24h timeout and nothing says so.
runs-on: hanzo-build-linux-amd64
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
# index.html is the whole page — one self-contained file, inline CSS, no
# local subresources — so there is nothing to compile. What IS assembled is
# the site directory: the page plus hz.js, the script-tag form of
# @hanzo/event. hz.js is COPIED OUT OF node_modules, never vendored and
# never loaded from a public CDN: the lockfile pins which version ships and
# the page keeps its only script same-origin.
- name: assemble the site
run: |
set -euo pipefail
corepack enable
pnpm install --frozen-lockfile
rm -rf out && mkdir -p out
cp index.html out/index.html
cp node_modules/@hanzo/event/hz.js out/hz.js
test -s out/hz.js || { echo "::error::@hanzo/event/hz.js missing from the install"; exit 1; }
echo "assembled $(find out -type f | wc -l) files"
# ONE credential. The 202 carries a prefix-scoped, 30-minute presigned POST
# grant, so nothing here holds a bucket key. Do NOT add SITES_S3_* — that is
# the standing shared-bucket credential the grant replaced, and it could
# overwrite every other org's site.
- name: Publish to the Sites plane
uses: hanzoai/ci/.github/actions/sitedeploy@v1
with:
slug: logo
dir: out
env:
HANZO_DEPLOY_TOKEN: ${{ secrets.HANZO_DEPLOY_TOKEN }}
+51
View File
@@ -0,0 +1,51 @@
name: publish
# Publishes @hanzo/logo when the version in package.json changes on main.
# A version already on the registry is skipped, so re-runs are safe.
on:
push:
branches: [main]
paths: ['package.json']
workflow_dispatch:
permissions:
contents: read
jobs:
publish:
runs-on: hanzo-build-linux-amd64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
registry-url: https://registry.npmjs.org/
- name: Skip if already published
id: check
run: |
NAME=$(jq -r .name package.json)
VER=$(jq -r .version package.json)
if curl -fsSL "https://registry.npmjs.org/$NAME/$VER" > /dev/null 2>&1; then
echo "$NAME@$VER already on registry; skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
# `test` typechecks and then builds — one command for both. The rendered
# images under dist/ are tracked but the compiled dist/*.js and dist/*.d.ts
# are gitignored, so publishing without this ships every icon and no entry
# point. corepack takes the pnpm version from packageManager.
- name: Test
if: steps.check.outputs.skip != 'true'
run: |
corepack enable
pnpm install --frozen-lockfile
pnpm test
- name: Publish
if: steps.check.outputs.skip != 'true'
# npm, not pnpm: pnpm publish adds git checks a CI checkout fails.
# --no-provenance: a token publish 422s without it.
run: npm publish --access public --no-provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+9
View File
@@ -0,0 +1,9 @@
# logo.hanzo.ai — the logo page, served by hanzoai/static (a Go binary on
# scratch) behind hanzoai/ingress. No nginx, no GitHub Pages, no CF Pages: the
# site is an image the operator runs like every other Hanzo surface.
#
# index.html is the whole site: one self-contained page, inline CSS, no scripts
# and no local subresources. There is nothing to build, so there is no build
# stage — a compile step here would exist only to look like the others.
FROM ghcr.io/hanzoai/static:v0.5.1
COPY index.html /public/index.html
+96 -31
View File
@@ -1,56 +1,121 @@
# @hanzo/logo
Official Hanzo logo package. Provides SVG logos as inline strings, React components, and a build pipeline for generating favicons, Apple touch icons, dock icons, and menu bar assets. Published as `@hanzo/logo` (v1.0.5) on npm.
Official Hanzo logo package. Provides SVG logos as inline strings, React components, a pure-CSS brand motion layer, and a build pipeline for generating favicons, Apple touch icons, dock icons, and menu bar assets. Published as `@hanzo/logo` on npm (bump `version` on `main` → CI publishes).
## Canon
The Hanzo mark is the **7-path shaded H** (67x67 viewBox): five body blocks + two
`class="shade"` accent slivers (#DDDDDD). `MARK_PATHS` in `src/logos.ts` is the one
source of the geometry — every variant (color/mono/white/menubar/animated/motion)
renders it. The flat 5-path H is only for tiny favicons (`getFaviconSVG`).
## How this ships
One way, and it runs on our own stack:
push -> github.com/hanzoai/logo where code lands
-> git.hanzo.ai/hanzoai/logo pull mirror; runs the CI
.hanzo/workflows/publish.yml publishes @hanzo/logo to npm
.hanzo/workflows/deploy.yml ships logo.hanzo.ai (Sites plane)
**Push to GitHub. The forge is a READ-ONLY pull mirror**`git push` to it is
refused with `Mirror Repository hanzoai/logo is read-only`, so the `native`
remote is for reading the mirror's state, never for writing. GitHub holds the
code; the forge holds the CI, because `.github/workflows/` is empty and every
build, check and publish lives under `.hanzo/workflows/`, which only the forge
reads. Both use GitHub Actions syntax, so a workflow moves between them by
changing directory and nothing else.
The consequence worth remembering: a push is not a deploy. Nothing runs until
the mirror pulls, and that lag is the forge's, not yours.
`publish.yml` is the SOLE publisher of `@hanzo/logo`. It fires when `version` in
`package.json` changes on `main`, skips a version already on the registry, and
runs `pnpm test` first — typecheck, then build. The rendered images under `dist/`
are tracked but the compiled `dist/*.js` and `dist/*.d.ts` are gitignored, so
publishing without that build ships every icon and no entry point. Needs
`NPM_TOKEN` as a forge secret.
### The site
`index.html` is the whole page: one self-contained file, inline CSS, no local
subresources. It is a SITE, not an App — nothing here executes — so it ships on
the Sites plane and there is no image, no CR and no pod:
assemble out/ -> POST /v1/projects/logo/deploy 202 + an upload grant
-> POST each file under the grant bytes skip the API
-> POST …/deployments/<id>/complete {status, keys}
This repo holds NO S3 credential. The grant is confined to this site's prefix and
expires in 30 minutes; deletion rides the `keys` manifest, because a write-only
grant cannot remove a file. The one secret is `HANZO_DEPLOY_TOKEN`, set ON THE
FORGE — GitHub's secret store is not in this path at all.
No GitHub Pages and no Cloudflare Pages: the repo used to push this page to a
`gh-pages` branch, Pages was never configured for it, and `logo.hanzo.ai` has
answered 404 from our own ingress ever since.
`out/` is ASSEMBLED, not built — `index.html` plus `hz.js`, the script-tag form of
`@hanzo/event`, copied out of `node_modules` at build time. That is the whole
reason `@hanzo/event` is a devDependency here: the lockfile decides which version
of the telemetry client ships, and the only script this page loads stays
same-origin instead of coming off a public CDN. `hz.js` posts to the same
`api.hanzo.ai/v1/event` as every bundled Hanzo surface.
**Known gap, upstream:** `hz.js` (through 0.3.11) cannot authenticate. It sends
no `Authorization` header and no `?ingest_key=` query, while `/v1/event` answers
`401 ingest_key_required` to an unattributed batch — so every event this page
sends is currently refused. The npm client supports `ingestKey` on both the fetch
and the beacon; the script form was never given the same. The fix belongs in
`hanzoai/ui` `pkgs/event/hz.js` (read `data-ingest-key`, ride it the way
`core.ts` already does), NOT in a bespoke script here — a second telemetry client
is exactly what `hz.js` exists to prevent.
## Stack
- TypeScript 5, ESM-only output
- React (optional peer dep >= 16.8)
- sharp (image generation for favicons/icons)
- Exports: `.` (main), `./logos` (raw SVG getters), `./react` (React components)
- Exports: `.` (main), `./logos` (raw SVG getters), `./motion` (CSS motion layer), `./react` (React components)
## Structure
```
src/
index.ts # Re-exports logos, types, react
logos.ts # SVG string generators: getColorSVG, getMonoSVG, getWhiteSVG, getFaviconSVG
types.ts # LogoVariant (color|mono|white|favicon), LogoFormat, LogoOptions
react.tsx # HanzoLogo and HanzoFavicon React components
generator.ts # Image generation pipeline (PNG/ICO from SVG via sharp)
build.ts # CLI build script for generating all icon variants
generate-showcase.ts # Generates menu-bar-preview.html showcase
dist/
*.svg # Pre-built SVG files (hanzo-logo.svg, hanzo-favicon.svg, etc.)
apple/ # Apple touch icons
dock/ # macOS dock icons
favicon/ # Multi-size favicons
icons/ # General icon set
index.ts # Re-exports logos, motion, types, react
logos.ts # MARK_PATHS + SVG generators: getColorSVG, getMonoSVG, getWhiteSVG,
# getMenuBarSVG (currentColor), getFaviconSVG, getAnimatedSVG
motion.ts # MOTION_CSS + getMotionHTML/getMotionMarkup — intro flip + idle
# breathing + wordmark collapse, pure CSS, reduced-motion-safe.
# Framework-free strings for Svelte/Tamagui/plain HTML.
animated.ts # ANIMATED_SVG — self-contained interactive mark (fold-in → hover
# turn → press squash)
types.ts # LogoVariant (color|mono|white|favicon|animated), LogoFormat, LogoOptions
react.tsx # HanzoLogo (variant + `animated` motion-shell prop), HanzoFavicon
build.ts # CLI build script for generating all icon variants (brand-neutral,
# reads package.json `brand`)
dist/ # Rendered assets (tracked): svg/, favicon/, apple/, dock/, icons/,
# menubar/, slack/, showcase.html
```
## Commands
```bash
make install # npm install
make build # Clean + compile TS + build CLI
make dev # tsc --watch
make generate # Build then run icon generator (outputs to dist/)
make preview # Generate + open menu-bar-preview.html
make test # typecheck + build
make publish # clean, install, build, test, npm publish
make clean # rm -rf dist node_modules package-lock.json
pnpm install # install dev deps
pnpm typecheck # tsc --noEmit
pnpm build # clean + compile + build CLI + generate assets
pnpm test # typecheck + build (the release gate)
```
## Usage
```tsx
import { HanzoLogo } from '@hanzo/logo/react'
<HanzoLogo variant="color" size={64} />
<HanzoLogo variant="mono" size="2rem" />
<HanzoLogo size={64} />
<HanzoLogo animated /> // motion shell: flip + breathe + wordmark
<HanzoLogo animated wordmark="Lux" /> // white-label
import { getColorSVG, getFaviconSVG } from '@hanzo/logo/logos'
const svgString = getColorSVG()
import { getColorSVG, getAnimatedSVG } from '@hanzo/logo/logos'
import { MOTION_CSS, getMotionHTML } from '@hanzo/logo/motion' // Svelte/Tamagui
```
## Notes
- Logo is the geometric H mark (white on transparent, 67x67 viewBox)
- Variants: color (white fill), mono (stroke), white (solid white), favicon (simplified)
- `ZooLogo` and `ZooFavicon` are exported as backwards-compatible aliases
- Makefile still has "Zoo Logo Generator" branding in help text -- needs updating
- Variants: color (white fill + shade), mono (black fill + shade), white, menubar
(currentColor), favicon (simplified 5-path for 16-64px), animated (interactive)
- Release: bump the patch in `package.json`, merge to `main`. There is no tag.
- `CLAUDE.md`, `AGENTS.md`, `QWEN.md`, `GEMINI.md` are all symlinks to this file
-109
View File
@@ -1,109 +0,0 @@
# Zoo Logo Generator Makefile
# @zooai/logo - TypeScript logo generator for the Zoo ecosystem
.PHONY: help install build clean dev test publish generate-icons preview lint format typecheck all
# Default target
all: install build
# Help target - displays available commands
help:
@echo "Zoo Logo Generator - Make targets:"
@echo ""
@echo " make install - Install dependencies"
@echo " make build - Build TypeScript files"
@echo " make clean - Remove build artifacts and dependencies"
@echo " make dev - Run in development mode with watch"
@echo " make test - Run tests"
@echo " make lint - Run ESLint"
@echo " make format - Format code with Prettier"
@echo " make typecheck - Run TypeScript type checking"
@echo " make generate - Generate all logo variations and icons"
@echo " make preview - Open preview of generated logos"
@echo " make publish - Publish package to npm"
@echo " make all - Install and build (default)"
@echo ""
# Install dependencies
install:
npm install
# Build TypeScript files
build:
npm run build
# Clean build artifacts and dependencies
clean:
rm -rf dist node_modules package-lock.json
@echo "✓ Cleaned build artifacts and dependencies"
# Development mode with watch
dev:
npm run dev
# Run tests
test:
npm test
# Run linter
lint:
npm run lint
# Format code
format:
npm run format
# Type checking
typecheck:
npm run typecheck
# Generate all logo variations and icons
generate: build
npm run generate
# Preview generated logos (opens in default browser)
preview: generate
@if [ -f "menu-bar-preview.html" ]; then \
open menu-bar-preview.html; \
else \
echo "Generating preview..."; \
npm run preview; \
open menu-bar-preview.html; \
fi
# Publish to npm
publish: clean install build test
npm publish
# Watch for changes and rebuild
watch:
npm run watch
# Install global CLI
install-cli:
npm link
# Uninstall global CLI
uninstall-cli:
npm unlink
# Check for updates
check-updates:
npx npm-check-updates
# Update dependencies
update-deps:
npx npm-check-updates -u
npm install
# Generate documentation
docs:
npx typedoc src/index.ts
# Docker build (for CI/CD)
docker-build:
docker build -t zooai/logo .
# Run in Docker
docker-run:
docker run --rm -v $(PWD)/dist:/app/dist zooai/logo
+19
View File
@@ -0,0 +1,19 @@
# Canonical CI/CD config for hanzoai/logo — the one file both the hanzoai/ci
# reusable (.hanzo/workflows/cicd.yml) and platform.hanzo.ai read.
#
# GATE ONLY: @hanzo/logo is an npm package, and the logo site has its own lanes
# already (.hanzo/workflows/publish.yml, deploy.yml). A second image build for
# the same Dockerfile on the same push buys nothing.
#
# `pnpm test` here is `pnpm typecheck && pnpm build` — and the build half is the
# real gate, because this package's output is GENERATED: `pnpm generate` runs
# the compiled dist/build.js, which bakes the tuner's animation states into the
# svg + animated.ts that every consumer imports. A break in the generator is a
# break in the artifact, and it only shows when the generator is actually run.
test:
- name: build
run: |
set -e
corepack enable
pnpm install --frozen-lockfile
pnpm test
+8
View File
@@ -121,5 +121,13 @@
</div>
</div>
<div class="footer">&copy; 2025 Hanzo AI. All rights reserved.</div>
<!-- hz.js is the script-tag form of @hanzo/event — the SAME client and the
SAME wire as every bundled Hanzo surface, POSTing to api.hanzo.ai/v1/event.
This page has no bundler, so it gets the script rather than the module.
It is served from /hz.js, not a public CDN: CI copies it out of
node_modules at build time, so the lockfile decides which version ships and
the only script this page loads is same-origin. -->
<script async src="/hz.js" data-product="logo" data-host="https://api.hanzo.ai"></script>
</body>
</html>
+5 -5
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zoo Logo Menu Bar Preview</title>
<title>Hanzo Logo Menu Bar Preview</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
@@ -127,7 +127,7 @@
</style>
</head>
<body>
<h1>Zoo Logo Menu Bar Preview</h1>
<h1>Hanzo Logo Menu Bar Preview</h1>
<h2>See how the monochrome logo looks in the Mac menu bar</h2>
<div class="preview-section">
@@ -141,7 +141,7 @@
<svg class="menu-icon" viewBox="0 0 16 16" fill="currentColor">
<path d="M3 7h10v2H3z M6 3h4v10H6z"/>
</svg>
<!-- Our Zoo icon -->
<!-- Our Hanzo icon -->
<svg id="menuIconDark" class="menu-icon" viewBox="98 102 812 820"></svg>
<!-- More system icons -->
<svg class="menu-icon" viewBox="0 0 16 16" fill="currentColor">
@@ -161,7 +161,7 @@
<svg class="menu-icon" viewBox="0 0 16 16" fill="currentColor">
<path d="M3 7h10v2H3z M6 3h4v10H6z"/>
</svg>
<!-- Our Zoo icon -->
<!-- Our Hanzo icon -->
<svg id="menuIconLight" class="menu-icon" viewBox="98 102 812 820"></svg>
<!-- More system icons -->
<svg class="menu-icon" viewBox="0 0 16 16" fill="currentColor">
@@ -290,7 +290,7 @@
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'zoo-logo-mono.svg';
a.download = 'hanzo-logo-mono.svg';
a.click();
}
-634
View File
@@ -1,634 +0,0 @@
{
"name": "@hanzo/logo",
"version": "1.0.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@hanzo/logo",
"version": "1.0.11",
"license": "MIT",
"dependencies": {
"sharp": "^0.34.4"
},
"devDependencies": {
"@types/minimatch": "^5.1.2",
"@types/node": "^20.19.17",
"@types/react": "^18.3.24",
"react": "^18.3.1",
"typescript": "^5.9.2"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
}
},
"node_modules/@emnapi/runtime": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
"integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@img/colour": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
"integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@img/sharp-darwin-arm64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz",
"integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-arm64": "1.2.3"
}
},
"node_modules/@img/sharp-darwin-x64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz",
"integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-x64": "1.2.3"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz",
"integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz",
"integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz",
"integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==",
"cpu": [
"arm"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz",
"integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-ppc64": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz",
"integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==",
"cpu": [
"ppc64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-s390x": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz",
"integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==",
"cpu": [
"s390x"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz",
"integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz",
"integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz",
"integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-linux-arm": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz",
"integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.2.3"
}
},
"node_modules/@img/sharp-linux-arm64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz",
"integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm64": "1.2.3"
}
},
"node_modules/@img/sharp-linux-ppc64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz",
"integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-ppc64": "1.2.3"
}
},
"node_modules/@img/sharp-linux-s390x": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz",
"integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==",
"cpu": [
"s390x"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-s390x": "1.2.3"
}
},
"node_modules/@img/sharp-linux-x64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz",
"integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.2.3"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz",
"integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-arm64": "1.2.3"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz",
"integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-x64": "1.2.3"
}
},
"node_modules/@img/sharp-wasm32": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz",
"integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==",
"cpu": [
"wasm32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
"@emnapi/runtime": "^1.5.0"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-arm64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz",
"integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-ia32": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz",
"integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==",
"cpu": [
"ia32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-x64": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz",
"integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@types/minimatch": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
"integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.19.17",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.17.tgz",
"integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.15",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.3.24",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.24.tgz",
"integrity": "sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true,
"license": "MIT"
},
"node_modules/detect-libc": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz",
"integrity": "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==",
"license": "Apache-2.0",
"engines": {
"node": ">=8"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sharp": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz",
"integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@img/colour": "^1.0.0",
"detect-libc": "^2.1.0",
"semver": "^7.7.2"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "0.34.4",
"@img/sharp-darwin-x64": "0.34.4",
"@img/sharp-libvips-darwin-arm64": "1.2.3",
"@img/sharp-libvips-darwin-x64": "1.2.3",
"@img/sharp-libvips-linux-arm": "1.2.3",
"@img/sharp-libvips-linux-arm64": "1.2.3",
"@img/sharp-libvips-linux-ppc64": "1.2.3",
"@img/sharp-libvips-linux-s390x": "1.2.3",
"@img/sharp-libvips-linux-x64": "1.2.3",
"@img/sharp-libvips-linuxmusl-arm64": "1.2.3",
"@img/sharp-libvips-linuxmusl-x64": "1.2.3",
"@img/sharp-linux-arm": "0.34.4",
"@img/sharp-linux-arm64": "0.34.4",
"@img/sharp-linux-ppc64": "0.34.4",
"@img/sharp-linux-s390x": "0.34.4",
"@img/sharp-linux-x64": "0.34.4",
"@img/sharp-linuxmusl-arm64": "0.34.4",
"@img/sharp-linuxmusl-x64": "0.34.4",
"@img/sharp-wasm32": "0.34.4",
"@img/sharp-win32-arm64": "0.34.4",
"@img/sharp-win32-ia32": "0.34.4",
"@img/sharp-win32-x64": "0.34.4"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD",
"optional": true
},
"node_modules/typescript": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true,
"license": "MIT"
}
}
}
+13 -8
View File
@@ -1,6 +1,7 @@
{
"name": "@hanzo/logo",
"version": "1.0.11",
"version": "1.0.14",
"packageManager": "pnpm@11.17.0",
"description": "Official Hanzo logo package with React components and utilities",
"type": "module",
"main": "dist/index.js",
@@ -22,6 +23,11 @@
"import": "./dist/logos.js",
"require": "./dist/logos.js"
},
"./motion": {
"types": "./dist/motion.d.ts",
"import": "./dist/motion.js",
"require": "./dist/motion.js"
},
"./react": {
"types": "./dist/react.d.ts",
"import": "./dist/react.js",
@@ -29,19 +35,19 @@
}
},
"scripts": {
"build": "npm run clean && npm run compile && npm run build:cli && npm run generate",
"build": "pnpm clean && pnpm compile && pnpm build:cli && pnpm generate",
"build:cli": "tsc src/build.ts --outDir dist --module esnext --target es2020 --moduleResolution node --esModuleInterop --skipLibCheck",
"compile": "tsc",
"clean": "rm -rf dist",
"dev": "tsc --watch",
"generate": "node dist/build.js",
"preview": "npm run generate && open menu-bar-preview.html",
"preview": "pnpm generate && open menu-bar-preview.html",
"lint": "eslint src --ext .ts,.tsx",
"format": "prettier --write 'src/**/*.{ts,tsx,json}'",
"typecheck": "tsc --noEmit",
"test": "npm run typecheck && npm run build",
"test": "pnpm typecheck && pnpm build",
"watch": "tsc --watch",
"prepublishOnly": "npm run build"
"prepublishOnly": "pnpm build"
},
"keywords": [
"hanzo",
@@ -53,14 +59,13 @@
],
"author": "Hanzo AI",
"license": "MIT",
"dependencies": {
"sharp": "^0.34.4"
},
"devDependencies": {
"@hanzo/event": "^0.3.11",
"@types/minimatch": "^5.1.2",
"@types/node": "^20.19.17",
"@types/react": "^18.3.24",
"react": "^18.3.1",
"sharp": "^0.34.4",
"typescript": "^5.9.2"
},
"peerDependencies": {
+421
View File
@@ -0,0 +1,421 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
devDependencies:
'@hanzo/event':
specifier: ^0.3.11
version: 0.3.11(react@18.3.1)
'@types/minimatch':
specifier: ^5.1.2
version: 5.1.2
'@types/node':
specifier: ^20.19.17
version: 20.19.43
'@types/react':
specifier: ^18.3.24
version: 18.3.31
react:
specifier: ^18.3.1
version: 18.3.1
sharp:
specifier: ^0.34.4
version: 0.34.5
typescript:
specifier: ^5.9.2
version: 5.9.3
packages:
'@emnapi/runtime@1.11.3':
resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
'@hanzo/event@0.3.11':
resolution: {integrity: sha512-HLdDWZPPonel3HPgmDOQ+LqXPV8hPEMZFGnXlFT2gPQq+MxcHgAY482Y9jHCCKwLFo8v805FZ81ylTlBAl5RVQ==}
peerDependencies:
react: ^18.0.0 || ^19.0.0
peerDependenciesMeta:
react:
optional: true
'@img/colour@1.1.0':
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'}
'@img/sharp-darwin-arm64@0.34.5':
resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [darwin]
'@img/sharp-darwin-x64@0.34.5':
resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [darwin]
'@img/sharp-libvips-darwin-arm64@1.2.4':
resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
cpu: [arm64]
os: [darwin]
'@img/sharp-libvips-darwin-x64@1.2.4':
resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
cpu: [x64]
os: [darwin]
'@img/sharp-libvips-linux-arm64@1.2.4':
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-arm@1.2.4':
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-ppc64@1.2.4':
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-riscv64@1.2.4':
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.2.4':
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-x64@1.2.4':
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-linux-arm64@0.34.5':
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-arm@0.34.5':
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-linux-ppc64@0.34.5':
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-riscv64@0.34.5':
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-s390x@0.34.5':
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-linux-x64@0.34.5':
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.34.5':
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-linuxmusl-x64@0.34.5':
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-wasm32@0.34.5':
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [wasm32]
'@img/sharp-win32-arm64@0.34.5':
resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [win32]
'@img/sharp-win32-ia32@0.34.5':
resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ia32]
os: [win32]
'@img/sharp-win32-x64@0.34.5':
resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [win32]
'@types/minimatch@5.1.2':
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
'@types/node@20.19.43':
resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==}
'@types/prop-types@15.7.15':
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
'@types/react@18.3.31':
resolution: {integrity: sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==}
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
react@18.3.1:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
semver@7.8.5:
resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
engines: {node: '>=10'}
hasBin: true
sharp@0.34.5:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
hasBin: true
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
snapshots:
'@emnapi/runtime@1.11.3':
dependencies:
tslib: 2.8.1
optional: true
'@hanzo/event@0.3.11(react@18.3.1)':
optionalDependencies:
react: 18.3.1
'@img/colour@1.1.0': {}
'@img/sharp-darwin-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.2.4
optional: true
'@img/sharp-darwin-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.2.4
optional: true
'@img/sharp-libvips-darwin-arm64@1.2.4':
optional: true
'@img/sharp-libvips-darwin-x64@1.2.4':
optional: true
'@img/sharp-libvips-linux-arm64@1.2.4':
optional: true
'@img/sharp-libvips-linux-arm@1.2.4':
optional: true
'@img/sharp-libvips-linux-ppc64@1.2.4':
optional: true
'@img/sharp-libvips-linux-riscv64@1.2.4':
optional: true
'@img/sharp-libvips-linux-s390x@1.2.4':
optional: true
'@img/sharp-libvips-linux-x64@1.2.4':
optional: true
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
optional: true
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
optional: true
'@img/sharp-linux-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.2.4
optional: true
'@img/sharp-linux-arm@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.2.4
optional: true
'@img/sharp-linux-ppc64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-ppc64': 1.2.4
optional: true
'@img/sharp-linux-riscv64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-riscv64': 1.2.4
optional: true
'@img/sharp-linux-s390x@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-s390x': 1.2.4
optional: true
'@img/sharp-linux-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.2.4
optional: true
'@img/sharp-linuxmusl-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
optional: true
'@img/sharp-linuxmusl-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
optional: true
'@img/sharp-wasm32@0.34.5':
dependencies:
'@emnapi/runtime': 1.11.3
optional: true
'@img/sharp-win32-arm64@0.34.5':
optional: true
'@img/sharp-win32-ia32@0.34.5':
optional: true
'@img/sharp-win32-x64@0.34.5':
optional: true
'@types/minimatch@5.1.2': {}
'@types/node@20.19.43':
dependencies:
undici-types: 6.21.0
'@types/prop-types@15.7.15': {}
'@types/react@18.3.31':
dependencies:
'@types/prop-types': 15.7.15
csstype: 3.2.3
csstype@3.2.3: {}
detect-libc@2.1.2: {}
js-tokens@4.0.0: {}
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
react@18.3.1:
dependencies:
loose-envify: 1.4.0
semver@7.8.5: {}
sharp@0.34.5:
dependencies:
'@img/colour': 1.1.0
detect-libc: 2.1.2
semver: 7.8.5
optionalDependencies:
'@img/sharp-darwin-arm64': 0.34.5
'@img/sharp-darwin-x64': 0.34.5
'@img/sharp-libvips-darwin-arm64': 1.2.4
'@img/sharp-libvips-darwin-x64': 1.2.4
'@img/sharp-libvips-linux-arm': 1.2.4
'@img/sharp-libvips-linux-arm64': 1.2.4
'@img/sharp-libvips-linux-ppc64': 1.2.4
'@img/sharp-libvips-linux-riscv64': 1.2.4
'@img/sharp-libvips-linux-s390x': 1.2.4
'@img/sharp-libvips-linux-x64': 1.2.4
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
'@img/sharp-linux-arm': 0.34.5
'@img/sharp-linux-arm64': 0.34.5
'@img/sharp-linux-ppc64': 0.34.5
'@img/sharp-linux-riscv64': 0.34.5
'@img/sharp-linux-s390x': 0.34.5
'@img/sharp-linux-x64': 0.34.5
'@img/sharp-linuxmusl-arm64': 0.34.5
'@img/sharp-linuxmusl-x64': 0.34.5
'@img/sharp-wasm32': 0.34.5
'@img/sharp-win32-arm64': 0.34.5
'@img/sharp-win32-ia32': 0.34.5
'@img/sharp-win32-x64': 0.34.5
tslib@2.8.1:
optional: true
typescript@5.9.3: {}
undici-types@6.21.0: {}
+9
View File
@@ -0,0 +1,9 @@
# Install scripts run only for packages listed here.
allowBuilds:
sharp: true
# Our own scopes skip pnpm's new-release quarantine. Scope glob, not a version
# pin: pnpm rewrites version entries on every bump and breaks --frozen-lockfile.
minimumReleaseAgeExclude:
- '@hanzo/*'
- '@hanzogui/*'
+4 -3
View File
@@ -1,4 +1,5 @@
// GENERATED by the @hanzo logo tuner bake — do not edit by hand.
// Source of truth: the tuner's GEN.hanzo() + the shared interaction layer.
// GENERATED from the @hanzo logo tuner bake, upgraded to the canonical
// 7-path shaded H (5 body blocks + 2 shade slivers). Source of truth for the
// interaction layer: the tuner's GEN.hanzo() + the shared interaction layer.
// Origami fold-in → hover: one 3-D turn → press: squash. Pure CSS, no JS.
export const ANIMATED_SVG = "<svg role=\"img\" aria-label=\"Hanzo\" viewBox=\"0 0 67 67\" xmlns=\"http://www.w3.org/2000/svg\">\n<!-- Origami fold-in → hover: one 3-D turn → press: squash. Pure CSS, no JS. Generated from the @hanzo logo tuner — edit there, not here. -->\n\n<style>.o{fill:#fff;opacity:0;transform-box:fill-box;transform-origin:left center;animation:fold 0.42s cubic-bezier(.16,1,.3,1) forwards}\n@keyframes fold{from{opacity:0;transform:perspective(320px) rotateY(90deg)}to{opacity:1;transform:none}}\n.o0{animation-delay:0.00s}.o1{animation-delay:0.06s}.o2{animation-delay:0.12s}.o3{animation-delay:0.18s}.o4{animation-delay:0.24s}\n/* interaction — pure CSS, no JS: hover = one graceful turn (returns to rest), press = squash */\n.hanzo-hov{transform-box:view-box;transform-origin:33.5px 33.5px}\n.hanzo-prs{transform-box:view-box;transform-origin:33.5px 33.5px;transition:transform .22s cubic-bezier(.22,1,.36,1)}\nsvg:hover .hanzo-hov{animation:hanzoTurn 0.85s cubic-bezier(.45,0,.2,1)}\nsvg:active .hanzo-prs{transform:scale(.92)}\n@keyframes hanzoTurn{0%{transform:perspective(300px) rotateY(0)}100%{transform:perspective(300px) rotateY(360deg)}}\n@media (prefers-reduced-motion:reduce){.hanzo-hov,.hanzo-prs{animation:none!important;transform:none!important}.o{opacity:1;animation:none;transform:none}}\n</style>\n<g class=\"hanzo-hov\"><g class=\"hanzo-prs\">\n<path class=\"o o0\" d=\"M22.21 0H0V22.3184H22.21V0Z\"/>\n<path class=\"o o1\" d=\"M66.7198 0H44.5098V22.3184H66.7198V0Z\"/>\n<path class=\"o o2\" d=\"M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z\"/>\n<path class=\"o o3\" d=\"M22.21 67V44.6369H0V67H22.21Z\"/>\n<path class=\"o o4\" d=\"M66.7198 67V44.6369H44.5098V67H66.7198Z\"/>\n</g></g>\n</svg>";
export const ANIMATED_SVG = "<svg role=\"img\" aria-label=\"Hanzo\" viewBox=\"0 0 67 67\" xmlns=\"http://www.w3.org/2000/svg\">\n<!-- Origami fold-in → hover: one 3-D turn → press: squash. Pure CSS, no JS. Canonical 7-path shaded H. -->\n\n<style>.o{fill:#fff;opacity:0;transform-box:fill-box;transform-origin:left center;animation:fold 0.42s cubic-bezier(.16,1,.3,1) forwards}\n.s{fill:#ddd}\n@keyframes fold{from{opacity:0;transform:perspective(320px) rotateY(90deg)}to{opacity:1;transform:none}}\n.o0{animation-delay:0.00s}.o1{animation-delay:0.06s}.o2{animation-delay:0.12s}.o3{animation-delay:0.18s}.o4{animation-delay:0.24s}\n/* interaction — pure CSS, no JS: hover = one graceful turn (returns to rest), press = squash */\n.hanzo-hov{transform-box:view-box;transform-origin:33.5px 33.5px}\n.hanzo-prs{transform-box:view-box;transform-origin:33.5px 33.5px;transition:transform .22s cubic-bezier(.22,1,.36,1)}\nsvg:hover .hanzo-hov{animation:hanzoTurn 0.85s cubic-bezier(.45,0,.2,1)}\nsvg:active .hanzo-prs{transform:scale(.92)}\n@keyframes hanzoTurn{0%{transform:perspective(300px) rotateY(0)}100%{transform:perspective(300px) rotateY(360deg)}}\n@media (prefers-reduced-motion:reduce){.hanzo-hov,.hanzo-prs{animation:none!important;transform:none!important}.o{opacity:1;animation:none;transform:none}}\n</style>\n<g class=\"hanzo-hov\"><g class=\"hanzo-prs\">\n<path class=\"o o0\" d=\"M22.21 0H0V22.3184H22.21V0Z\"/>\n<path class=\"o o1\" d=\"M66.7198 0H44.5098V22.3184H66.7198V0Z\"/>\n<path class=\"o o1 s\" d=\"M66.6753 22.3185L44.5098 20.0822V22.3185H66.6753Z\"/>\n<path class=\"o o2\" d=\"M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z\"/>\n<path class=\"o o3\" d=\"M22.21 67V44.6369H0V67H22.21Z\"/>\n<path class=\"o o3 s\" d=\"M0 44.6369L22.21 46.8285V44.6369H0Z\"/>\n<path class=\"o o4\" d=\"M66.7198 67V44.6369H44.5098V67H66.7198Z\"/>\n</g></g>\n</svg>";
+1
View File
@@ -5,5 +5,6 @@
*/
export * from './logos.js';
export * from './motion.js';
export * from './types.js';
export * from './react.js';
+7 -2
View File
@@ -17,15 +17,20 @@ export const LOGO_SETTINGS: LogoSettings = {
export const MARK_VIEWBOX = '0 0 67 67';
/**
* Raw, fill-less block-H path geometry — the single source of the Hanzo mark.
* Callers set their own `fill` (e.g. `@hanzo/brand` card generators, og images).
* Raw block-H path geometry — the single source of the Hanzo mark.
* The canonical mark is SEVEN paths: five fill-less body blocks (callers set
* their own `fill` — e.g. `@hanzo/brand` card generators, og images) plus the
* two `class="shade"` accent slivers that give the H its shaded depth
* (#DDDDDD in every shipped variant; restyle via `.shade` if needed).
* Use this instead of re-typing the path data anywhere.
*/
export const MARK_PATHS =
'<path d="M22.21 67V44.6369H0V67H22.21Z"/>' +
'<path class="shade" fill="#DDDDDD" d="M0 44.6369L22.21 46.8285V44.6369H0Z"/>' +
'<path d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z"/>' +
'<path d="M22.21 0H0V22.3184H22.21V0Z"/>' +
'<path d="M66.7198 0H44.5098V22.3184H66.7198V0Z"/>' +
'<path class="shade" fill="#DDDDDD" d="M66.6753 22.3185L44.5098 20.0822V22.3185H66.6753Z"/>' +
'<path d="M66.7198 67V44.6369H44.5098V67H66.7198Z"/>';
/**
+42
View File
@@ -0,0 +1,42 @@
import { getMenuBarSVG } from './logos.js';
/**
* Brand motion — the shared shell animation for the Hanzo mark, pure CSS:
*
* 1. intro flip — mark flips in (rotateY 180° → 0, scale .6 → 1, fade)
* 2. idle breathe — a slow, subtle scale pulse once at rest
* 3. wordmark — slides in after the flip, holds, then collapses;
* returns on :hover of the shell
*
* All reduced-motion-safe. Framework-free: pair `MOTION_CSS` with
* `getMotionHTML()` from React, Svelte, Tamagui, or plain HTML — the mark
* and wordmark inherit `currentColor`, so theming is one `color` away.
*/
export const MOTION_CSS = `.hanzo-motion{display:inline-flex;align-items:center;color:inherit}
.hanzo-motion .hanzo-mark{display:block;line-height:0;width:1.25em;height:1.25em;animation:hanzo-flip .5s cubic-bezier(.16,1,.3,1) .2s backwards,hanzo-breathe 6s ease-in-out 3.2s infinite}
.hanzo-motion .hanzo-mark svg{display:block;width:100%;height:100%}
.hanzo-motion .hanzo-word{overflow:hidden;display:inline-block;margin-left:.5em}
.hanzo-motion .hanzo-word>span{display:inline-block;white-space:nowrap;font-weight:600;transform:translateX(-102%);transition:transform .3s ease-out;animation:hanzo-word 2.8s ease-out}
.hanzo-motion:hover .hanzo-word>span{transform:translateX(0)}
@keyframes hanzo-flip{from{opacity:0;transform:perspective(320px) rotateY(180deg) scale(.6)}to{opacity:1;transform:none}}
@keyframes hanzo-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.04)}}
@keyframes hanzo-word{0%,40%{transform:translateX(-102%)}55%,82%{transform:translateX(0)}100%{transform:translateX(-102%)}}
@media (prefers-reduced-motion:reduce){.hanzo-motion .hanzo-mark,.hanzo-motion .hanzo-word>span{animation:none!important}.hanzo-motion .hanzo-word>span{transition:none}}`;
/**
* The motion shell markup — mark + collapsing wordmark. Inline it (with
* `MOTION_CSS` in a <style>) anywhere HTML renders; not for <img>.
*/
export function getMotionHTML(wordmark = 'Hanzo'): string {
return (
`<span class="hanzo-motion">` +
`<span class="hanzo-mark">${getMenuBarSVG()}</span>` +
`<span class="hanzo-word"><span>${wordmark}</span></span>` +
`</span>`
);
}
/** The shell + its CSS as one self-contained HTML fragment. */
export function getMotionMarkup(wordmark = 'Hanzo'): string {
return `<style>${MOTION_CSS}</style>${getMotionHTML(wordmark)}`;
}
+31 -2
View File
@@ -1,5 +1,6 @@
import React from 'react';
import { getColorSVG, getMonoSVG, getWhiteSVG, getFaviconSVG, getAnimatedSVG } from './logos.js';
import { getColorSVG, getMonoSVG, getWhiteSVG, getFaviconSVG, getAnimatedSVG, getMenuBarSVG } from './logos.js';
import { MOTION_CSS } from './motion.js';
import type { LogoVariant } from './types.js';
export interface HanzoLogoProps {
@@ -7,6 +8,14 @@ export interface HanzoLogoProps {
size?: number | string;
className?: string;
style?: React.CSSProperties;
/**
* Render the brand motion shell: intro flip + idle breathing + a wordmark
* that slides in, holds, then collapses (returns on hover). Pure CSS,
* reduced-motion-safe. The mark inherits `currentColor`.
*/
animated?: boolean;
/** Wordmark text for the animated shell (white-label). Default "Hanzo". */
wordmark?: string;
}
/**
@@ -25,8 +34,28 @@ export const HanzoLogo: React.FC<HanzoLogoProps> = ({
variant = 'color',
size = 64,
className,
style
style,
animated = false,
wordmark = 'Hanzo'
}) => {
if (animated) {
return (
<span className={className} style={style}>
<style dangerouslySetInnerHTML={{ __html: MOTION_CSS }} />
<span className="hanzo-motion">
<span
className="hanzo-mark"
style={{ width: size, height: size }}
dangerouslySetInnerHTML={{ __html: getMenuBarSVG() }}
/>
<span className="hanzo-word">
<span>{wordmark}</span>
</span>
</span>
</span>
);
}
let svg = '';
switch (variant) {
+1 -1
View File
@@ -12,7 +12,7 @@
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"types": ["node"]