Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 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
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
6c798f8
B5: Close the image dialog at the end of the thaana test
n4ff4h Nov 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/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/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/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/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.
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
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ See [`REQUIREMENTS.md`](REQUIREMENTS.md) for the full specification and [`docs/`
## Install

```bash
npm install @javaabu/onu
# optional font pack (Inter, JetBrains Mono, Noto Sans Thaana; Faruma and MV Faseyha are bundled)
npm install @javaabu/onu react-hook-form @tanstack/react-query
# optional font pack (Inter, JetBrains Mono, Noto Sans Thaana; Faruma and MV Faseyha come with tailwind.css and styles.css)
npm install @fontsource-variable/inter @fontsource-variable/jetbrains-mono @fontsource-variable/noto-sans-thaana
```

Expand Down
4 changes: 2 additions & 2 deletions REQUIREMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ This document captures the requirements, constraints and full build list for Onu
- `@javaabu/onu/styles.css` — theme tokens + base styles
- `@javaabu/onu/tailwind.css` — Tailwind `@theme` / `@source` entry for consumers
- **R2.6** Heavy or licensed third-party dependencies (map SDKs, chart libs, editors, scanners, FontAwesome, fonts) are **optional peer dependencies**, required only when the matching subpath is imported.
- **R2.7** Peer dependencies: `react` and `react-dom` `^18.3 || ^19`, `tailwindcss` `^4`.
- **R2.7** Peer dependencies: `react` and `react-dom` `^19`, `tailwindcss` `^4`.
- **R2.8** Ship TypeScript declarations; source written in TypeScript `strict` mode. No `any` in public APIs.
- **R2.9** Every client component file carries a `"use client"` directive so it works in React Server Component environments (Next.js App Router).
- **R2.10** Semantic versioning. Releases managed with [Changesets](https://github.com/changesets/changesets); `CHANGELOG.md` generated from them.
Expand Down Expand Up @@ -181,7 +181,7 @@ A dependency must meet **all** of these criteria:
- **Maintained**: a release or meaningful commit within the last 12 months, a responsive issue tracker, and not archived or deprecated.
- **Reputable**: widely adopted, and backed by an organisation or established maintainers.
- **Typed**: first-party TypeScript types.
- **Compatible**: React 18 and 19, SSR-safe, tree-shakable.
- **Compatible**: React 19, SSR-safe, tree-shakable.
- **Accessible and RTL-capable**, or can be made so by wrapping.
- **Reasonable bundle size** for what it provides.

Expand Down
4 changes: 2 additions & 2 deletions docs/choice-inputs/api-select.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { ApiSelect } from '@javaabu/onu';
- **Paging**: when the response says there is a next page (`meta.last_page`, `last_page`, `next_page_url`, `links.next`, `next_cursor`), the next page loads as the list scrolls to the end.
- **Preloading**: options load when the list opens, or immediately with `preload`.
- **States**: loading, empty ("No results for …"), and an error with a **Retry** button. All are announced in a polite live region.
- **Caching**: per endpoint + params + query, for `staleTime` (5 minutes). After creating a record elsewhere, call `invalidateApiOptions(url)` (or `queryClient.invalidateQueries({ queryKey: apiOptionsQueryKey(url) })` with your own client). Quick-create (`onCreate`) invalidates automatically.
- **Caching**: per endpoint + params + query, for `staleTime` (5 minutes). After creating a record elsewhere, call `invalidateApiOptions(client, url)` with the client from `useOnuQueryClient()` (or `queryClient.invalidateQueries({ queryKey: apiOptionsQueryKey(url) })` with your own). Quick-create (`onCreate`) invalidates automatically.
- **No requests without a URL or fetcher** you supply; CSRF and auth headers are yours to add (`headers`, `credentials`).

## Props
Expand Down Expand Up @@ -70,7 +70,7 @@ Values are strings (`id: 12` becomes `"12"`), so they round-trip through forms u

## Data layer

The helpers behind it are exported for Autocomplete and your own components: `fetchApiOptions`, `parseApiResponse`, `parseApiItem`, `mapApiItem`, `detectHasMore`, `buildUrl`, `requestJson`, `useOnuQueryClient`, `getOnuQueryClient`, `invalidateApiOptions`, `apiOptionsQueryKey`.
The helpers behind it are exported for Autocomplete and your own components: `fetchApiOptions`, `parseApiResponse`, `parseApiItem`, `mapApiItem`, `detectHasMore`, `buildUrl`, `requestJson`, `useOnuQueryClient`, `invalidateApiOptions`, `apiOptionsQueryKey`.

## Accessibility

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/dhivehi-and-locales.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,4 @@ Charts have their own `useChartFormat` in `@javaabu/onu/charts`, with axis and p

# Fonts

Dhivehi text uses Faruma, with MV Faseyha for headings and bold, both bundled with `fonts.css`. See [Fonts](./fonts).
Dhivehi text uses Faruma, with MV Faseyha for headings and bold, both loaded by `tailwind.css`. See [Fonts](./fonts).
6 changes: 2 additions & 4 deletions docs/guides/fonts.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@ All of these are self-hosted from npm, so no requests go to a font CDN.

# Thaana fonts

Onu ships Faruma and MV Faseyha with `fonts.css`, as `woff2` files subset to Thaana and its punctuation (about 12 kB each). Their `unicode-range` means a browser only downloads them when a page shows Thaana text, and Latin text in a mixed sentence stays in Inter.
`tailwind.css` and `styles.css` load Faruma and MV Faseyha, so they work without `fonts.css` and its packages. They ship as `woff2` files subset to Thaana and its punctuation (about 12 kB each). Their `unicode-range` means a browser only downloads them when a page shows Thaana text, and Latin text in a mixed sentence stays in Inter.

- **Faruma** is used for Dhivehi body text (`--onu-font-thaana`).
- **MV Faseyha** is used for Dhivehi headings and `<b>`/`<strong>` (`--onu-font-thaana-bold`). Both fonts have a single weight and Onu turns off faux bold for Dhivehi, so emphasis uses the second face instead.
- Characters neither font covers fall back to Noto Sans Thaana.

If you don't import `fonts.css`, the same names still apply to copies installed on the device.
- Characters neither font covers fall back to Noto Sans Thaana when you import `fonts.css`.

# Mixed Dhivehi and English

Expand Down
Loading
Loading