@ai-matrx/design-system 0.12.1 → 0.14.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,104 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.0 — 2026-09-10
4
+
5
+ ### `ArchivedDisclosure` — the card-list half of the ONE archive control
6
+
7
+ 0.13.0 shipped `ArchiveFilter` and the platform still had two archive controls,
8
+ because the frontend kept the other one: `components/official/ArchivedDisclosure`,
9
+ the "Archived (N)" one-click reveal proven in Transcript Studio, invented the
10
+ same day in a different repo. Arman's ruling is that the control is the same
11
+ primitive EVERYWHERE (`common-docs/policies/archived-items.md`), so a second
12
+ home for half of it is the defect, not a convenience.
13
+
14
+ `ArchivedDisclosure` now lives here, ported VERBATIM from that file (including
15
+ its `countLabel` and `keepWhileOpen` additions): a one-click "Archived (N)"
16
+ disclosure, closed by default, rendering archived rows in place underneath —
17
+ or, with `children` omitted, the toggle alone for a host that merges archived
18
+ rows into its own table. `count` is always the true number of archived rows:
19
+ at zero the control renders NOTHING rather than an empty promise, unless
20
+ `keepWhileOpen` marks a surface whose open state IS the archive view (a server
21
+ request), where the way back must never vanish. `countLabel` covers the two
22
+ cases a bare integer cannot tell the truth about: a capped server count
23
+ (`"50+"`) and a count that has not landed (`null` prints no parenthetical).
24
+
25
+ **Two shapes, one vocabulary.** `ArchiveFilter` for table/browse surfaces whose
26
+ reader takes an archive parameter; `ArchivedDisclosure` for card lists, panels
27
+ and pickers that are not table shaped. Never a third. Both speak the single set
28
+ of words, now exported from one module: `ArchiveFilterValue`,
29
+ `ARCHIVE_FILTER_VALUES`, `DEFAULT_ARCHIVE_FILTER` (`active`),
30
+ `ARCHIVE_FILTER_LABELS`, plus two new exports — `ARCHIVE_LABEL`, the ONE noun
31
+ both controls print (`ARCHIVE_FILTER_LABELS.archived` is derived from it, so
32
+ renaming it renames both by construction), and
33
+ `archiveFilterFromDisclosure(open)`, which says a disclosure's state in the
34
+ tri-state words (`open` → `all`, because a disclosure reveals archived rows
35
+ BESIDE the live ones) for hosts whose toggle is a server request.
36
+
37
+ Icons stay inlined (C19): lucide `chevron-down` and `archive` joined
38
+ `src/icons.tsx`, so the port renders the same glyphs with no icon dependency.
39
+
40
+ ### Consumer action
41
+
42
+ **matrx-frontend must delete `components/official/ArchivedDisclosure.tsx`** and
43
+ repoint every importer to `@ai-matrx/design-system` — at the time of writing:
44
+ `features/organizations/components/OrgResourceList.tsx`,
45
+ `features/whatsapp-clone/conversation-list/ConversationListPane.tsx`,
46
+ `features/pdf/scanner/components/desktop/ScannerDesktop.tsx`,
47
+ `features/agents/agent-creators/templates/TemplatesGrid.tsx`,
48
+ `features/canvas/core/SavedCanvasItems.tsx`,
49
+ `features/page-extraction/components/SavedJobsList.tsx`,
50
+ `features/transcript-studio/components/scribe/RecordingCardList.tsx`,
51
+ `features/masterwork/browse/components/MasterworkBrowseCards.tsx`,
52
+ `features/masterwork/home/MasterworkHomePage.tsx`,
53
+ `features/masterwork/components/masterworks/MasterworksPage.tsx`,
54
+ `features/masterwork/components/detail/RulebookDetailPage.tsx`,
55
+ `features/hr/settings/fields/HrFieldsPanel.tsx`,
56
+ `features/pdf-extractor/studio/PdfStudioSidebar.tsx`,
57
+ `features/pdf-extractor/components/PdfExtractorWorkspace.tsx`.
58
+ `lib/entity-list`'s Archived radio renders `<ArchiveFilter>` (its URL and
59
+ preference plumbing is unchanged — only the control component is the package's),
60
+ and `lib/entity-list`'s `ArchivedFilter` type is now an alias of
61
+ `ArchiveFilterValue`. Every other host: a local "Archived (N)" toggle or a
62
+ local tri-state archive segmented control is a twin — delete it and import
63
+ these.
64
+
65
+ ## 0.13.0 — 2026-09-09
66
+
67
+ ### `ArchiveFilter` — THE ARCHIVED-ITEMS LAW made a control
68
+
69
+ Arman ruled on 2026-09-09 that archived rows of every entity are treated
70
+ identically everywhere: every list carries an archive filter, the default hides
71
+ archived, and revealing them is one or two clicks
72
+ (`common-docs/policies/archived-items.md`). Before this release each host
73
+ invented its own answer — a boolean `includeArchived` that nothing ever passed,
74
+ a badge that showed archived rows mixed in, or nothing at all — so the reveal
75
+ the platform intended was unreachable in most clients.
76
+
77
+ `ArchiveFilter` is that control, once: a three-state segmented toggle over
78
+ `active` (default) / `archived` / `all`, speaking the same words the Next.js
79
+ app already uses (`lib/entity-list`'s "Active only" / "Archived only" /
80
+ "Active + archived"). Shipped alongside it: `ARCHIVE_FILTER_VALUES`,
81
+ `DEFAULT_ARCHIVE_FILTER`, `ARCHIVE_FILTER_LABELS`, the `ArchiveFilterValue`
82
+ type, and `toArchiveFilter()` — which narrows an untrusted value (URL param,
83
+ stored preference, API echo) to the tri-state and falls back to `active`, so a
84
+ bad value can never silently widen a list to archived rows.
85
+
86
+ Optional `counts` render a per-state number beside each label. Pass a count
87
+ only when it describes what the list would actually render: a screen never
88
+ lies.
89
+
90
+ The control is a REQUEST, not a client-side sieve. Hand its value to the reader
91
+ (an RPC's `p_archived`, an endpoint's `archived=`) so counts, badges and
92
+ pagination agree with the rows on screen.
93
+
94
+ ### Consumer action
95
+
96
+ Any list over an entity with `is_archived` / `archived_at` / an archived status
97
+ must render `<ArchiveFilter>` and pass its value through to the server-side
98
+ reader. Delete local `showArchived` booleans and hardcoded archive predicates —
99
+ a boolean cannot express "archived only", which is why the law names three
100
+ states.
101
+
3
102
  ## 0.12.1 — 2026-09-09
4
103
 
5
104
  Dialog, AlertDialog, Drawer, Sheet, and BottomSheet footer actions now carry a
package/README.md CHANGED
@@ -5,7 +5,7 @@ The small, semantic UI foundation shared by AI Matrx React applications — prim
5
5
  **Controls:** Button, Badge, Label, Separator, the Input family, the Textarea family, Checkbox, Switch, RadioGroup, Slider, Toggle + ToggleGroup, Avatar, Progress.
6
6
  **Surfaces:** Card, Table, Tabs, Accordion, Collapsible, ScrollArea, Popover, Tooltip, HoverCard, Sheet, Dialog, AlertDialog, Drawer, BottomSheet + TabbedBottomSheet, Alert, Resizable, Skeleton.
7
7
  **Menus:** DropdownMenu, ContextMenu, Command / CommandDialog, Select, CreatablePicker.
8
- **Composed:** EditableLabel, SegmentedControl, ScoreRing, OverflowToolbar, ConfirmDialog + ConfirmDialogHost.
8
+ **Composed:** EditableLabel, SegmentedControl, ArchiveFilter, ScoreRing, OverflowToolbar, ConfirmDialog + ConfirmDialogHost.
9
9
  **Hooks + utilities:** `useScrollFade`, `useIsMobile`, `usePortalContainer`, `useDialogContainer`, `useDrawerDirection`, `cn`.
10
10
 
11
11
  **The confirm dialog lives here; the imperative `confirm()` lives in `@ai-matrx/kit`.** Since 0.11.0 / kit 0.9.0 the surface is one implementation, in the package that owns AlertDialog, the motion layer and the overlay scrim token. Mount the host once near your provider root and call `confirm()` from anywhere — they share one registry through a `globalThis` slot:
@@ -29,6 +29,19 @@ Use the declarative `<ConfirmDialog open … busy />` inline instead when the di
29
29
 
30
30
  **Footer actions stay touch-sized through portals.** Dialog, AlertDialog, Drawer, Sheet, and BottomSheet footers apply a 44px action floor on coarse pointers or below 1024px. Import the package stylesheet; no host subtree class is required. Fine-pointer desktop keeps its declared density. State controls and prose links retain their sizing; exceptional compact actions can use `data-touch-exempt` with a call-site reason.
31
31
 
32
+ **Every list over an archivable entity uses `ArchiveFilter`.** THE ARCHIVED-ITEMS LAW (Arman, 2026-09-09 — `common-docs/policies/archived-items.md`): an archive filter on every list, the default hides archived rows, and seeing them is one click. `ArchiveFilter` is the one control — `active` (default) / `archived` / `all`, in the same words the Next.js app uses.
33
+
34
+ ```tsx
35
+ import { ArchiveFilter, DEFAULT_ARCHIVE_FILTER, type ArchiveFilterValue } from "@ai-matrx/design-system";
36
+
37
+ const [archived, setArchived] = React.useState<ArchiveFilterValue>(DEFAULT_ARCHIVE_FILTER);
38
+ const rows = useRows({ archived }); // the SERVER applies the predicate
39
+
40
+ <ArchiveFilter value={archived} onValueChange={setArchived} counts={{ active: rows.activeCount }} />
41
+ ```
42
+
43
+ Pass the value to the reader, never filter the already-fetched page: counts, badges and pagination must describe what the list renders. `toArchiveFilter()` narrows an untrusted value (URL param, stored preference) back to the tri-state, defaulting to `active` so nothing silently widens.
44
+
32
45
  **The Tooltip lives here, and only here.** `@ai-matrx/tap-target` used to ship its own copy; since design-system 0.7.0 / tap-target 0.2.0 it consumes this one and re-exports nothing.
33
46
 
34
47
  Where hosts had forked a primitive over DENSITY, density is a prop, not a fork: `Card size="sm|md|lg"`, `Table size="sm|md"`, `Accordion size="sm|md"`, `Switch`/`Avatar`/`Checkbox`/`Slider`/`RadioGroup`/`Toggle` `size`, `ResizableHandle size="xs".."4xl"`. It is declared once on the root and every item reads it from context, so a card cannot mix paddings and a radio group cannot mix control sizes.