@poodle64/ui 2026.10.3 → 2026.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -911,9 +911,11 @@ Settled here, the same in every module, and not props:
911
911
  above its card; figures in the body face with tabular numerals, money out
912
912
  bracketed and money in green (`formatCurrency(v, { negative: 'brackets' })`).
913
913
  - **Sorting and the groups' one control.** Click a column head to sort by it,
914
- largest or newest first; click again to reverse. A sorted list is one flat
915
- run with no group heads and shows the Date column even by day. Until the
916
- viewer sorts, rows sit newest first in their groups. A chevron in the head's
914
+ largest or newest first; click again to reverse; a third click returns to the
915
+ default order. A sort orders rows inside the grouping the viewer chose (the
916
+ groups stay newest first); grouped by none, the list is one flat run. The
917
+ head shows its state: a down chevron descending, an up chevron ascending,
918
+ none at rest. Until the viewer sorts, rows sit newest first. A chevron in the head's
917
919
  gutter opens or closes every group at once; where rows tick, the gutter
918
920
  widens to hold it beside the select-all checkbox.
919
921
  - **The Columns menu** holds every column as a tick, the three fixed ones
@@ -220,9 +220,9 @@
220
220
  /** What a column sorts by; the running balance depends on the order, so never it. */
221
221
  const sorter = (c: { key: string; sort?: LedgerColumn<R>['sort']; text?: LedgerColumn<R>['text'] }) =>
222
222
  c.key === 'balance' ? undefined : (c.sort ?? c.text);
223
- /** Click a head to sort by it, largest or newest first; again to reverse. */
223
+ /** Click a head to sort by it, largest or newest first; again to reverse; a third time back to the default order. */
224
224
  function sortBy(key: string) {
225
- sort = sort?.key === key ? { key, dir: sort.dir === 1 ? -1 : 1 } : { key, dir: -1 };
225
+ sort = sort?.key !== key ? { key, dir: -1 } : sort.dir === -1 ? { key, dir: 1 } : null;
226
226
  }
227
227
  /** The sort in force: a column the viewer has since unticked no longer sorts. */
228
228
  const activeSort = $derived.by(() => {
@@ -231,8 +231,8 @@
231
231
  ? sort
232
232
  : null;
233
233
  });
234
- /** Until the viewer sorts, rows sit newest first in their period's groups. */
235
- const grouped = $derived(prefs.period !== 'none' && !activeSort);
234
+ /** A sort orders rows inside their period's groups; only `none` is the flat list. */
235
+ const grouped = $derived(prefs.period !== 'none');
236
236
  const BY_DAY = $derived(grouped && prefs.period === 'day');
237
237
 
238
238
  const shown = $derived(
@@ -262,8 +262,9 @@
262
262
  });
263
263
  const groups = $derived.by(() => {
264
264
  const by = activeSort && sorter(resolved.find((c) => c.key === activeSort.key)!);
265
- if (activeSort && by) return [{ key: '', rows: sortRows(rows, by, activeSort.dir) }];
266
- return groupRows(rows, prefs.period, fy);
265
+ const base = groupRows(rows, prefs.period, fy);
266
+ if (!activeSort || !by) return base;
267
+ return base.map((g) => ({ key: g.key, rows: sortRows(g.rows, by, activeSort.dir) }));
267
268
  });
268
269
  /** Closed groups, keyed with their period so a new period starts open. */
269
270
  const closed = new SvelteSet<string>();
@@ -923,7 +924,7 @@
923
924
  mine && 'text-foreground'
924
925
  )}
925
926
  aria-label={mine
926
- ? `Sorted by ${c.label}, ${mine.dir === -1 ? 'descending' : 'ascending'}. Click to reverse`
927
+ ? `Sorted by ${c.label}, ${mine.dir === -1 ? 'descending' : 'ascending'}. Click ${mine.dir === -1 ? 'to reverse' : 'for the default order'}`
927
928
  : `Sort by ${c.label}`}
928
929
  onclick={() => sortBy(c.key)}
929
930
  data-slot="ledger-sort"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poodle64/ui",
3
- "version": "2026.10.3",
3
+ "version": "2026.10.4",
4
4
  "description": "Household shared component layer: shadcn-svelte primitives (bits-ui) plus the composed page chrome every app builds its routes from, restyled by each app's @poodle64/design-tokens alias layer. One fix reaches every app.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "meta": {
3
3
  "package": "@poodle64/ui",
4
- "version": "2026.10.3",
4
+ "version": "2026.10.4",
5
5
  "generatedBy": "scripts/generate-registry.mjs",
6
6
  "source": "scripts/situations.json + package source (DO NOT EDIT the outputs by hand)",
7
7
  "componentCount": 62,
@@ -1,7 +1,7 @@
1
1
  # @poodle64/ui — situation → component map
2
2
 
3
3
  <!-- GENERATED by scripts/generate-registry.mjs from scripts/situations.json + package source. DO NOT EDIT. -->
4
- Generated from `@poodle64/ui@2026.10.3`. 62 components, 18 situations.
4
+ Generated from `@poodle64/ui@2026.10.4`. 62 components, 18 situations.
5
5
 
6
6
  **Read this before writing a `<div>`.** Find the SITUATION you are in below, then compose the component named for it — do not hand-build it from raw `Card` or utility classes. Import is `import { Name } from '<import path>'`. Props marked `?` are optional. This map is the retrieval step the [`frontend-design` skill] makes mandatory; the [CHI 2026 study] measured composing-from-a-registry at 95% design-system compliance against 71% for writing the CSS from a prose style guide.
7
7