Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
324d0e8
A1: Require React 19
n4ff4h Nov 1, 2026
d05c72d
A2: Release every package at one version
n4ff4h Nov 1, 2026
85509ba
A3: Load the Thaana fonts without the optional font pack
n4ff4h Nov 1, 2026
c4de3d5
A4: Make react-hook-form and TanStack Query peers
n4ff4h Nov 1, 2026
f78af77
A5: Remove the unused base-ui Combobox primitive
n4ff4h Nov 1, 2026
ca42386
A6: Drop optional peers nothing imports
n4ff4h Nov 1, 2026
7b30030
B1: Stop the calendar's month arrows flipping twice in RTL
n4ff4h Nov 1, 2026
c105788
B2: Keep touch targets when a Button sets its own slot
n4ff4h Nov 1, 2026
c0b9a84
B3: Translate three hard-coded English strings
n4ff4h Nov 1, 2026
bf91ce2
B4: Give the toast close button a usable size, and test toasts
n4ff4h Nov 1, 2026
e7503ac
B5: Use the editor's thaana prop on the image alt text field
n4ff4h Nov 1, 2026
f96bcc7
B6: Use placeholders instead of gluing translated labels together
n4ff4h Nov 1, 2026
b03561d
B7: Stop the vertical carousel arrows mirroring in RTL
n4ff4h Nov 1, 2026
46ec8a5
B8: Give the kanban count screen reader text instead of an aria-label…
n4ff4h Nov 1, 2026
1a13337
B9: Don't read the clock or Math.random during the first render
n4ff4h Nov 1, 2026
f9ebac5
B10: Guard useLayoutEffect for server rendering
n4ff4h Nov 1, 2026
8302a59
B11: Use tokens for overlays and the app shell
n4ff4h Nov 1, 2026
178e966
B12: Type SegmentedControl's name prop
n4ff4h Nov 1, 2026
18ad3c8
B13: Take logical sides on Tip, PopoverPanel and ActionMenu
n4ff4h Nov 1, 2026
0213d57
C1: Share one useControllableState
n4ff4h Nov 1, 2026
a2d7f1e
C2: Use onValueChange for every callback that reports a value
n4ff4h Nov 1, 2026
2d504ab
C3: Use one severity scale, tone
n4ff4h Nov 1, 2026
d3399b3
C4: Use one size scale
n4ff4h Nov 1, 2026
56ae1f7
C5: Accept rest props, ref and classNames consistently
n4ff4h Nov 1, 2026
ebb8254
C6: Share one copy of each duplicated helper
n4ff4h Nov 1, 2026
4d2b26b
C7: Give every controlled prop an uncontrolled partner
n4ff4h Nov 1, 2026
b76ac6f
C8: Use label and minChars everywhere
n4ff4h Nov 1, 2026
9d44964
C9: Remove unused locale keys and announce filter and selection changes
n4ff4h Nov 1, 2026
361bddb
C10: Split the auth forms into one file per form
n4ff4h Nov 1, 2026
5f2a4f1
Record the pinned pnpm in the lockfile
n4ff4h Nov 1, 2026
f3f853c
Update dependencies with known vulnerabilities
n4ff4h Nov 1, 2026
ac8de2f
Merge the CI lockfile and security updates into Part A
n4ff4h Nov 1, 2026
9c3a3ff
Merge the CI lockfile and security updates
n4ff4h Nov 1, 2026
ab0c1e6
Merge the CI lockfile and security updates
n4ff4h Nov 1, 2026
6c798f8
B5: Close the image dialog at the end of the thaana test
n4ff4h Nov 1, 2026
ff8af40
Merge the Part B test fix
n4ff4h Nov 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .changeset/class-names-and-rest-props.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

More components accept rest props and `ref` on their root and a `classNames` slot map, and `BackToTop`, `ConditionalLink` and `LinkButton` gain `asChild`.
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"fixed": [["@javaabu/onu", "@javaabu/onu-mcp"]],
"linked": [],
"access": "public",
"baseBranch": "main",
Expand Down
5 changes: 5 additions & 0 deletions .changeset/drop-unused-peers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

Removed four optional peers nothing imports: `@tiptap/extension-link`, `@tiptap/extension-drag-handle-react`, `@tiptap/extension-code-block-lowlight` and `lowlight`.
5 changes: 5 additions & 0 deletions .changeset/editor-dialog-thaana.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

The editors' image alt text field now follows the editor's `thaana` prop.
5 changes: 5 additions & 0 deletions .changeset/hard-coded-english.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

`DialogFooter`'s close button, the `useConfirm` `window.confirm` fallback and a `ValidationError` without a message no longer show hard-coded English.
5 changes: 5 additions & 0 deletions .changeset/labels-with-placeholders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

The move, switch account and inline edit labels are now whole translated sentences with a placeholder, instead of two strings joined together.
5 changes: 5 additions & 0 deletions .changeset/locale-cleanup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

Remove unused locale keys, give Dhivehi separate words for clear and delete, and announce applied filters and cleared selections to screen readers.
5 changes: 5 additions & 0 deletions .changeset/logical-sides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

`Tip`, `PopoverPanel` and `ActionMenu` take `side="top" | "bottom" | "start" | "end"`; `left` and `right` are gone.
5 changes: 5 additions & 0 deletions .changeset/on-value-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

Every component that reports a value now uses `onValueChange(value)`; `onChange` only ever means the native event. `FileInput` loses `onChange(files)` (use `onValueChange(entries)`), and `onReject` always takes an array.
5 changes: 5 additions & 0 deletions .changeset/overlay-token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

New `--onu-overlay` token for the dim behind dialogs, sheets and drawers (`bg-overlay`). The app shell classes use the shell token utilities instead of hex fallbacks.
5 changes: 5 additions & 0 deletions .changeset/peer-form-and-query.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

`react-hook-form` and `@tanstack/react-query` are now peer dependencies. `getOnuQueryClient` is gone: the fallback client belongs to each `OnuProvider`, and `invalidateApiOptions` takes the client first.
5 changes: 5 additions & 0 deletions .changeset/prop-names.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

The accessible name of a root region is `label` everywhere (`CommandPalette` and `OverlayMenu` `title`, `TopNav` `navLabel`, `Tabs` `listLabel`), and the minimum query length is `minChars` everywhere (`CommandPalette` `minQueryLength`, `PlaceSearchBox` `minLength`).
5 changes: 5 additions & 0 deletions .changeset/react-19-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

Onu now requires React 19; React 18 is no longer in the peer range.
5 changes: 5 additions & 0 deletions .changeset/remove-base-ui-combobox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

Removed the unused `Combobox` primitive from `@javaabu/onu/primitives`, and with it the `@base-ui/react` dependency.
5 changes: 5 additions & 0 deletions .changeset/segmented-control-name.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

`SegmentedControl`'s `name` prop is now part of its type.
5 changes: 5 additions & 0 deletions .changeset/shared-helpers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

Shared helpers move to `src/lib` and `src/hooks` with one behaviour each: `toArray` and the `initials` media export are gone, `normalizeUrl` returns `string | null`, the editor's `Callout` node is now `CalloutNode`, `CommandPalette` debounces by 300 ms, and the auth forms use `PasswordInput`.
5 changes: 5 additions & 0 deletions .changeset/size-scale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

`Tag`, `SkeletonText`, `Modal` and `UserAvatar` rename size `md` to `default`. `NumberInput` is now `h-8` like every other field, and `TextInput` gains the same `size` prop.
5 changes: 5 additions & 0 deletions .changeset/stable-first-render.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

`Countdown`, `RelativeDate`, `Timeline`, `PublishBox` and `SidebarMenuSkeleton` render the same markup on the server and the client's first render. `SidebarMenuSkeleton` takes an `index` to vary its width.
5 changes: 5 additions & 0 deletions .changeset/stable-labels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

The vertical `Carousel` arrows point the right way in RTL, and `KanbanBoard`'s column count is real screen reader text instead of an `aria-label` on a `span`.
5 changes: 5 additions & 0 deletions .changeset/thaana-fonts-always.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

Faruma and MV Faseyha now load from `tailwind.css` and `styles.css`, so Thaana text works without the optional font pack.
5 changes: 5 additions & 0 deletions .changeset/toast-close-size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": patch
---

The toast close button is now 24 px, and 44 px on touch screens.
5 changes: 5 additions & 0 deletions .changeset/tone-scale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

One severity scale, `tone`: `neutral`, `info`, `success`, `warning`, `danger`. `Callout`, `AnnouncementBar` and `NotificationCenter` items rename `variant` to `tone`, `destructive` and `error` become `danger`, and `default` becomes `neutral` (also on `IconText`). `AnnouncementBar` gains `success` and `danger`. `Button` keeps `variant="destructive"`.
5 changes: 5 additions & 0 deletions .changeset/uncontrolled-partners.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@javaabu/onu": minor
---

`LanguageSwitcher` and `RepeatingGroup` gain `defaultValue`, `Callout`, `FilterPanel` and `Lightbox` gain `defaultOpen`, and `Lightbox` `open` and `onOpenChange` become optional with `index` controlled only when it is passed.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
exit 1
fi
done
node scripts/sync-plugin-version.mjs --check
- name: Check the npm token
run: |
if [ -z "$NPM_TOKEN" ]; then
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pnpm e2e:chromium # Playwright (a11y with axe, visual)

## Rules

- A component is done only with: light/dark, LTR/RTL, `dv` strings, `thaana` on free-text fields, tokens-only colours, `className`/`classNames`/`asChild`, axe-clean, unit tests, a demo, a docs page and a changeset (`.changeset/*.md`).
- A component is done only with: light/dark, LTR/RTL, `dv` strings, `thaana` on free-text fields, tokens-only colours, `className`/`classNames`, `asChild` where the component renders one element an app may need to replace (links, buttons, triggers), axe-clean, unit tests, a demo, a docs page and a changeset (`.changeset/*.md`).
- Logical Tailwind utilities only (`ms-`, `pe-`, `start-`, `text-start`); ESLint rejects `left`/`right` ones. Theme tokens only, never raw colours.
- Icons through `<Icon name="…">` with semantic names; never render Lucide components or import `src/icons/lucide-map` in a component.
- No hard-coded English: strings live in `src/locales/{en,dv}/<namespace>.ts`, and a module registers the English namespaces it uses with `registerEnglish(...)`.
Expand Down
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Maps in the web app use Google Maps when `VITE_GOOGLE_MAPS_API_KEY` (and optiona

## Definition of done

A component is done only when it meets REQUIREMENTS §21: light/dark, LTR/RTL, `dv` locale, `thaana` prop for free text, tokens-only colours, responsive and touch-friendly, `className`/`classNames`/`asChild` overrides, WCAG 2.2 AA with axe tests, unit tests, a showcase demo in `web/src/showcase`, a docs page in `docs/`, and a changeset.
A component is done only when it meets REQUIREMENTS §21: light/dark, LTR/RTL, `dv` locale, `thaana` prop for free text, tokens-only colours, responsive and touch-friendly, `className`/`classNames` overrides, `asChild` where the component renders one element an app may need to replace (links, buttons, triggers), WCAG 2.2 AA with axe tests, unit tests, a showcase demo in `web/src/showcase`, a docs page in `docs/`, and a changeset.

## Where things go

Expand All @@ -33,6 +33,7 @@ A component is done only when it meets REQUIREMENTS §21: light/dark, LTR/RTL, `
## Rules of thumb

- Use logical Tailwind utilities (`ms-`, `pe-`, `start-`, `text-start`, …). ESLint rejects physical `left`/`right` ones.
- Report a value with `onValueChange(value)`; `onChange` is only for the native event.
- Use theme tokens (`bg-primary`, `text-muted-foreground`), never raw colours.
- Use `<Icon name="…">` (from `src/icons/icon`) with semantic names, so `OnuProvider icons` overrides apply. Never render a Lucide component directly. When a component always shows the same glyph (a spinner, a close button, a chevron), also pass that Lucide icon as `fallback`, e.g. `<Icon name="loading" fallback={Loader2Icon} />`: overrides still win, and the component keeps its glyph outside `OnuProvider`.
- Never import `src/icons/lucide-map` in a component. `OnuProvider` loads the default set on demand, so neither a single component nor the provider ships ~250 icons. ESLint and `src/icons/icon-imports.test.ts` enforce this, and `pnpm --filter @javaabu/onu size` checks the bundle budgets.
Expand Down Expand Up @@ -85,10 +86,10 @@ Every change that affects a published package adds a changeset (`pnpm changeset`

To release:

1. On `dev`, run `pnpm changeset version`. It bumps every package with pending changesets, writes their `CHANGELOG.md` and deletes the changesets. All packages share one version, so check that `packages/onu` and `packages/onu-mcp` match.
1. On `dev`, run `pnpm changeset version && node scripts/sync-plugin-version.mjs`. `@javaabu/onu` and `@javaabu/onu-mcp` are a fixed group in `.changeset/config.json`, so they always move to the same version; the script copies that version into `plugins/onu/.claude-plugin/plugin.json`, which changesets can't see. `changeset version` also writes their `CHANGELOG.md` and deletes the changesets.
2. Commit (`Release v0.1.0`) and merge `dev` into `main`. Wait for CI to pass on `main`.
3. Tag that commit on `main` and push the tag: `git tag v0.1.0 && git push origin v0.1.0`.

The **Release** workflow runs only for `v*` tags. It checks that the tagged commit is on `main` and that every package's version matches the tag, then builds and publishes to npm (versions already on npm are skipped). Tags with a pre-release suffix (`v1.0.0-beta.1`) publish under the `next` dist-tag.
The **Release** workflow runs only for `v*` tags. It checks that the tagged commit is on `main` and that every package's version and the plugin's match the tag, then builds and publishes to npm (versions already on npm are skipped). Tags with a pre-release suffix (`v1.0.0-beta.1`) publish under the `next` dist-tag.

Publishing needs an `NPM_TOKEN` repository secret: an npm granular access token with read and write access to the `@javaabu` scope and "bypass 2FA" allowed, from an account that can publish to `@javaabu`. Write tokens expire after about 90 days. Provenance is signed only once the repository is public. After the first release, you can switch to npm trusted publishing (each package's settings on npmjs.com, pointing at `release.yml`) and remove the token.
13 changes: 7 additions & 6 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Selection order: shadcn/ui component → reputable library (shadcn ecosystem fir
| Package | Purpose | Licence | Notes |
| -------------------------------------------------- | -------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------ |
| `radix-ui` | Accessible primitives behind the shadcn components | MIT | shadcn default base |
| `@base-ui/react` | Combobox primitive (shadcn's combobox) | MIT | From the Radix / MUI team |
| `class-variance-authority` | Variants (`buttonVariants`, …) | Apache-2.0 | Stable and feature-complete; last release 2024 (exception to the 12-month rule, used by shadcn) |
| `clsx`, `tailwind-merge` | `cn()` class merging so consumer classes win | MIT | |
| `tw-animate-css` | Enter/exit animations | MIT | shadcn default |
Expand All @@ -19,25 +18,27 @@ Selection order: shadcn/ui component → reputable library (shadcn ecosystem fir
| `vaul` | Drawer / bottom sheet | MIT | shadcn `drawer`. **Watch-list**: reduced maintenance (R4.3); kept behind Onu's API |
| `input-otp` | OTP input | MIT | shadcn `input-otp` |
| `react-day-picker`, `date-fns` | Calendar and date maths | MIT | shadcn `calendar`; Dhivehi locale maintained in Onu |
| `@internationalized/date` | Hijri (Umm al-Qura) calendar maths, date/time fields | Apache-2.0 | Adobe |
| `react-aria-components` | Tree, colour picker, date/time segment fields | Apache-2.0 | Adobe; fills Radix gaps (§4 step 3) |
| `@internationalized/date` | Hijri (Umm al-Qura) calendar maths, date/time segment fields | Apache-2.0 | Adobe |
| `react-aria-components` | Tree, colour picker | Apache-2.0 | Adobe; fills Radix gaps (§4 step 3) |
| `embla-carousel-react` | Carousel | MIT | shadcn `carousel` |
| `react-hook-form` | Form state | MIT | |
| `@tanstack/react-table`, `@tanstack/react-virtual` | Tables, data grid, virtualised lists | MIT | |
| `@tanstack/react-query` | API select caching and de-duplication | MIT | R16.5 |
| `@dnd-kit/react`, `@dnd-kit/helpers` | Drag and drop (kanban, sortable lists, row reordering) with touch sensors | MIT | The maintained successor of `@dnd-kit/core` |
| `@dnd-kit/dom` | dnd-kit's `Accessibility` plugin, configured with translated announcements | MIT | Already installed by `@dnd-kit/react`; imported directly so drag announcements follow the locale |
| `react-phone-number-input` | Phone input (libphonenumber) | MIT | Default region MV |
| `@sindresorhus/slugify` | Slug generator | MIT | |
| `uqr` | QR code encoding for `QrCode` (media entry); Onu renders the SVG | MIT | unjs; zero-dep, typed. Picked over `qrcode` (Node deps), `qrcode-generator` (stale) |

## Peers (core)

`react-hook-form` (form state, MIT) and `@tanstack/react-query` (API select caching and de-duplication, R16.5, MIT) are required peers, alongside `react` and `react-dom`. Onu reads their React context, so the app and Onu must resolve the same copy. They stay required because the core entry imports them statically.

## Optional peers (entry points)

| Entry | Packages | Licence |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- |
| `@javaabu/onu/charts` | `recharts` | MIT |
| `@javaabu/onu/maps` | `@vis.gl/react-google-maps`, `terra-draw`, `terra-draw-google-maps-adapter`, `@googlemaps/markerclusterer`, `@deck.gl/core`, `@deck.gl/layers`, `@deck.gl/aggregation-layers`, `@deck.gl/google-maps`, `@turf/turf` | MIT / Apache-2.0 |
| `@javaabu/onu/editor` | `@tiptap/core`, `@tiptap/react`, `@tiptap/pm`, `@tiptap/starter-kit`, `@tiptap/static-renderer`, `@tiptap/suggestion` (slash menu), `@tiptap/extension-*` (MIT packages only), `lowlight`, `shiki` | MIT |
| `@javaabu/onu/editor` | `@tiptap/core`, `@tiptap/react`, `@tiptap/pm`, `@tiptap/starter-kit`, `@tiptap/static-renderer`, `@tiptap/suggestion` (slash menu), `@tiptap/extension-*` (MIT packages only), `shiki` | MIT |
| `@javaabu/onu/calendar` | `@fullcalendar/core`, `@fullcalendar/react`, `@fullcalendar/daygrid`, `@fullcalendar/timegrid`, `@fullcalendar/list`, `@fullcalendar/interaction` (standard plugins only, v6) | MIT |
| `@javaabu/onu/media` | `react-easy-crop`, `signature_pad`, `barcode-detector`, `yet-another-react-lightbox`, `media-chrome` | MIT |
| `@javaabu/onu/export` | `write-excel-file` (Excel `.xlsx` only; CSV and PDF need nothing). Loaded with `import()` on the first Excel export. Chosen over the npm `xlsx` (SheetJS) package, whose npm release is outdated; supports right-to-left sheets and keeps Thaana text intact | MIT |
Expand Down
Loading
Loading