daedalus-ui
v0.1.0
Published
Daedalus UI — decorative letter library
Readme
daedalus-ui
Daedalus UI — decorative SVG letter library. Glyphs ship as TypeScript vector
data (per-letter modules); there are no shipped .svg asset files.
Install
bun add daedalus-uiDev setup
bun installUsage
TypeScript
import { families, listFamilies, listGlyphs, getGlyph, findGlyphs, renderSvg } from "daedalus-ui";
console.log(listFamilies()); // ['slinky', 'elegant', 'fast-furious', 'sports-sliced']
console.log(families); // [{ id, name, glyphCount }, ...] (counts from the registries)
// Exact char match; no variant -> first in reading order.
const a = getGlyph("slinky", "a"); // { family, char, bbox, body, defs }
const sTagline = getGlyph("fast-furious", "s", "line03-1"); // explicit variant
// All variants of a char, in reading order.
const sAll = findGlyphs("fast-furious", "s"); // 4 entries: line02, line03-1, line03-2, line06
// Distinct chars of a family, in reading order.
console.log(listGlyphs("elegant").length); // 62
// Standalone SVG artwork for a word.
const svg = renderSvg("elegant", "Hello 123", { padding: 4 });JavaScript (ESM)
import { getGlyph, findGlyphs, listGlyphs, renderSvg } from "daedalus-ui";
console.log(getGlyph("slinky", "a").bbox);
console.log(findGlyphs("fast-furious", "a").map((g) => g.variant)); // ['line04-1', 'line04-2', 'line05']
console.log(listGlyphs("sports-sliced").join("")); // 'abc...z'
console.log(renderSvg("slinky", "slinky").slice(0, 38)); // '<?xml version="1.0" ...'Errors
Matching is exact and case-sensitive. Unknown families throw Unknown family;
unknown chars, variants, or text characters throw Unknown glyph:
getGlyph("nope", "a"); // throws Unknown family: nope
getGlyph("slinky", "A"); // throws Unknown glyph (slinky ships lowercase only)
getGlyph("fast-furious", "s", "nope"); // throws Unknown glyph (no such variant)
renderSvg("elegant", "hi!"); // throws Unknown glyph ('!' is not covered; nothing is silently skipped)renderSvg layout
renderSvg(family, text, opts?: { tracking?: number; padding?: number; className?: string })
lays text out left-to-right with a cursor that advances by each glyph's bbox
width plus tracking:
- Default
tracking= 8% of the per-render median glyph width (computed from the bbox widths of the glyphs in that render; family-wide median fallback when the text holds no letters). - The space character advances without artwork at 40% of that median.
- Output is a standalone SVG string: XML declaration first, then
<svg viewBox="0 0 W H" ...>sized to the content pluspadding, one<defs>block uniting the used glyph defs exactly once, and each glyph body nested in<g transform="translate(x y)">at its x-offset. - Limitation: no kerning pairs — advances are purely bbox-width + tracking.
- Companion CSS:
styles/fonts.cssexposes per-family--dl-trackingcustom props (same 8%-of-median rule, em-scaled) for wrapping elements.
Example output shape (abridged):
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1458.63 251.97" width="1458.63" height="251.97">
<defs>
...family defs used by these glyphs, exactly once...
</defs>
<g transform="translate(-218.75 -223.47)">
...glyph body paths...
</g>
...
</svg>CSS
Link the tracking-utility stylesheet:
<link rel="stylesheet" href="node_modules/daedalus-ui/styles/fonts.css" /><div class="dl-elegant">wrapped renderSvg artwork</div>See styles/fonts.css for all four family classes. These are spacing
utilities only — they carry no artwork and reference no asset files.
Coverage
| family | id | chars covered | glyph modules | variants | notes |
| -------------- | --------------- | ---------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Slinky | slinky | a–z (lowercase, 26) | 26 | none | bare single-case alphabet |
| Fast & Furious | fast-furious | 0–9 + a–z (lowercase, 36 distinct) | 57 | variant = line id (line01, line02, line03-1, line03-2, line04-1, line04-2, line05, line06, …) | digits on line01; tagline words lines 02–04 (multi-size dupes, e.g. s × 4); full specimen a–z lines 05–06 |
| Sports Sliced | sports-sliced | a–z (lowercase, 26) | 26 | line02 (a–o), line03 (p–z) | one size per letter |
| Elegant | elegant | 0–9 + a–z + A–Z (62) | 62 | line01 (digits), line04 (lowercase), line05 (UPPERCASE) | only family with both cases; match is exact |
Extras (slinky coils, ff/sliced/elegant backgrounds, headers, titles,
diagonals) exist as code modules but are EXCLUDED from the letter APIs: the
family registries list only single alphanumeric chars, so decoration art can
never come back from getGlyph/findGlyphs/listGlyphs/renderSvg.
No shipped assets
No .svg files ship with this package — and since T15 none remain in the
repo either. The artwork lives only as inline vector data in src/glyphs/
(per-letter TypeScript modules); package.json files covers dist/ +
styles/ only, and the packed tarball contains zero .svg files.
Consumers get vector data via the API above, never files.
Source history (removed in T15, user decision 2026-09-24): the Vecteezy
originals at the repo root and their assets/*.svg extraction copies were
deleted once the glyph modules were frozen — re-extraction is no longer
possible from this repo. (scripts/extract-glyphs.ts was kept as a historical
record until T16, then removed too — recoverable via git history. The repo
is private and src/ is the source of truth.)
Build
bun run buildThis runs the prebuild clean (rm -rf dist, so stale pre-rename modules can
never linger) then tsc (TypeScript 7), emitting dist/ (compiled from
src/ with strict mode). prepack rebuilds dist/ automatically before
packing or publishing.
bun pm pack --dry-runChangelog
0.1.0(pre-publish, T18): migrated to ESM ("type": "module",tscmodule: NodeNext,.jsextensions on all 521 relative imports) +exportsmap +"sideEffects": falsefor tree-shaking. Drops CJSrequire()support (breaking-for-0.x before first publish). (Version stays0.1.0, never published.)0.1.0(pre-publish, T15): deleted ALL.svgfiles from the repo (5 root Vecteezy originals + 5assets/extraction copies + 20smoke/*.svgQA sheets) and then removedsmoke/entirely (validator + labels.json — repo is private,src/is the source of truth). Artwork lives only as inline vector data insrc/glyphs/. (T16:scripts/extract-glyphs.tsremoved as well — recoverable via git history. Version stays0.1.0, never published.)0.1.0(pre-publish, T12): public glyph API replaces asset paths.resolveAsset(andlistIds) removed — usegetGlyph/findGlyphs/listGlyphs/listFamilies/renderSvginstead.assets/no longer ships (extraction source only);styles/fonts.cssno longer references asset files (tracking utilities now). Positional glyph ids are gone —variant(line id) disambiguates dupes. (Version stays0.1.0, never published.)0.1.0(pre-publish): removed thesports-minimalfamily from the library (user decision T11c: hard to read, not worth it). The package ships 4 families. The rootvecteezy_sports-minimal-tech-…svgsource file stays in the repo as source material. (Version stays0.1.0, never published.)0.1.0(pre-publish): dropped thekawaiifamily from the library. This is noted as a breaking-for-0.x change before the first publish (version stays0.1.0, never published).
License
MIT — see LICENSE.
