v0.1.35 - Ingredient categories: created categories now available across all rows

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 12:28:23 +12:00
co-authored by Claude Opus 4.8
parent c9f233dc0e
commit dc50e0538e
6 changed files with 39 additions and 11 deletions
+8
View File
@@ -17,6 +17,14 @@ export type ChangelogEntry = {
export const APP_VERSION: string = packageInfo.version;
export const changelog: ChangelogEntry[] = [
{
version: '0.1.35',
date: '2026-06-21',
highlights: [
'App: Bug fixes & improvements.',
'App: General improvements.'
]
},
{
version: '0.1.34',
date: '2026-06-21',
@@ -14,7 +14,8 @@
placeholder = 'Category',
inputId,
disabled = false,
ariaLabel = 'Category'
ariaLabel = 'Category',
oncreate
}: {
value?: string;
options?: string[];
@@ -22,6 +23,9 @@
inputId?: string;
disabled?: boolean;
ariaLabel?: string;
/** Fired when the user deliberately creates a brand-new category, so the
* parent can keep it available to every other row. */
oncreate?: (category: string) => void;
} = $props();
// `query` is the ephemeral search text; `value` is the committed category.
@@ -80,7 +84,9 @@
}
function createNew() {
value = trimmed;
const created = trimmed;
value = created;
oncreate?.(created);
closeMenu();
}
+19 -5
View File
@@ -174,14 +174,28 @@
})
);
// Categories the user has explicitly created via the combobox this session.
// Tracked separately from row values so a freshly-created category stays
// available to every row even before it's been saved to (or assigned on) any
// ingredient — otherwise it would vanish as soon as you moved off the row.
let createdCategories = $state<string[]>([]);
function registerCategory(category: string) {
const name = category.trim();
if (!name) return;
if (createdCategories.some((existing) => existing.toLowerCase() === name.toLowerCase())) return;
createdCategories = [...createdCategories, name];
}
// Existing categories, offered as autocomplete suggestions so spelling stays
// consistent across ingredients.
const knownCategories = $derived(
Array.from(
new Set(
rows
.map((row) => (row.draft_category || row.category || '').trim())
.filter((value) => value.length > 0)
[
...rows.map((row) => (row.draft_category || row.category || '').trim()),
...createdCategories.map((value) => value.trim())
].filter((value) => value.length > 0)
)
).sort((a, b) => a.localeCompare(b))
);
@@ -298,7 +312,7 @@
</label>
<label>
<span>Category</span>
<CategoryCombobox bind:value={newIngredient.category} options={knownCategories} placeholder="e.g. Grains" inputId="new-ingredient-category" />
<CategoryCombobox bind:value={newIngredient.category} options={knownCategories} placeholder="e.g. Grains" inputId="new-ingredient-category" oncreate={registerCategory} />
</label>
<label>
<span>Rounding</span>
@@ -368,7 +382,7 @@
<div class="cell">
<span class="cell-label">Category</span>
<CategoryCombobox bind:value={row.draft_category} options={knownCategories} placeholder="—" ariaLabel={`Category for ${row.name}`} />
<CategoryCombobox bind:value={row.draft_category} options={knownCategories} placeholder="—" ariaLabel={`Category for ${row.name}`} oncreate={registerCategory} />
</div>
<div class="cell">