Give NumberInput a `unit` prop that renders inside the input (left of the
steppers), plus `dense` sizing, a `disabled` state, a numeric/commit
`onchange` mode, and an `onclear` hook for nullable fields. Fix a
min-content overflow so the flex control shrinks inside grid/flex cells.
Apply the unit input to:
- add-spool form (density, diameter, temps, weights)
- label designer, element inspector, print layout panel (mm)
- library adjust-weight field, and the filament/vendor/spool inspector
detail grids (diameter, density, temps, price, empty-spool-weight)
Move the units out of the English label strings into the inputs; locale
keys are kept so Weblate translations aren't orphaned.
Adds a color-theme preference (system/light/dark) in Settings, persisted
to localStorage and defaulting to the OS preference. An inline script in
app.html resolves the saved theme before first paint to avoid a flash of
the wrong theme; the theme store keeps <html data-theme> and the
theme-color meta in sync reactively (including live OS changes).
The light palette is applied purely by overriding the design tokens under
:root[data-theme='light']. Hardcoded neutral/accent colors scattered
across components were converted to tokens (adding --surface-sunken,
--accent-muted[-2], --track, --swatch-border[-hover]) so both themes stay
in sync.
In the Group: Filament view, used SpoolRows shed their filament identity
(the sticky header already carries it), leaving a bare column grid. The
collapsed UnusedRow, still shaped like a filament-led row, clashed with
them. Under the filament group it now renders as a quiet collapsible
divider ("N unused · Xg each" + hairline rule) that introduces the unused
pile; expanding lists the spools as ordinary rows aligned with the used
siblings. Other group axes keep the filament-name-led summary, where the
name distinguishes different filaments' unused piles.
Implements the search feature for client_v2: a new backend search endpoint
plus a results-panel UI, replacing the old query box that only filtered the
library list by filament name.
Backend (additive, API v1 backward compatibility preserved):
- New GET /api/v1/search returning categorized spool/filament/vendor results,
each annotated with the field that matched, plus an is_color_query flag.
- Case-insensitive text search over native text fields and text/choice extra
fields; exact spool-id match for numeric queries; color-similarity search
(CSS color name or hex) via find_by_color, ordered closest first.
- spoolman/colors.py resolves the CSS4 color names / hex codes to hex.
- Integration tests (run across SQLite/PostgreSQL/MySQL/CockroachDB in CI).
Frontend (client_v2):
- SearchBox overlay with Spools/Filaments/Manufacturers sections, per-result
match badges, keyboard navigation, a color-similarity threshold slider
(persisted to localStorage), and an English-only color-name hint.
- Clicking a result opens the matching inspector on the Library page.
- Removes the old q -> filament.name inline list filtering.
Claude-Session: https://claude.ai/code/session_01Ne7RsfHejKZX97uAq3aVMn
Introduce full i18n for the Svelte client_v2 using svelte-i18n (ICU/formatjs),
mirroring the old client's language support.
- i18n setup in src/lib/i18n/ (lazy per-language loaders, init + waitLocale boot
guard, setLocale persisted to localStorage, Intl locale helper); 26-language
registry ported from the old client.
- Language picker on the Settings page.
- scripts/convert-locales.mjs seeds static/locales/<lang>/common.json from the
old client's Weblate files: {{var}} -> {var}, escapes literal braces, merges
i18next plural suffixes into ICU plurals. Existing translations are reused via
the same keys; new v2-only strings are added to en/common.json only and fall
back to English until Weblate fills them.
- Extracted all hardcoded UI strings across routes and components to $_ lookups;
DateTimeField derives month/weekday names from Intl in the active locale.
- static/locales is prettier-ignored (mirrors the old client's public/locales).
Follow-up (maintainer): add a Weblate component pointing at
client_v2/static/locales (nested JSON, ICU MessageFormat, English source).
Claude-Session: https://claude.ai/code/session_01Ne7RsfHejKZX97uAq3aVMn
Adds a label design/print subsystem (canvas editor, QR/logo/paper
helpers, print layout panel) backed by a new label_designs setting,
plus a footer, datetime field component, and assorted fixes across
the library and settings views.
Introduces client_v2, a new SvelteKit-based client, alongside the
backend it depends on: a /spool/group endpoint that returns
per-group aggregates (count, in-use count, remaining weight,
last-used) grouped by filament, vendor, material or location, so the
client can paginate whole groups instead of fetching every spool.
Not yet complete/wired up for release.