@clicktap/ui 0.43.5 → 1.0.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.
@@ -1 +1 @@
1
- "use client";import{jsxs as s,jsx as e}from"react/jsx-runtime";import{Label as p,TextField as v,Input as k,Text as L,FieldError as C}from"react-aria-components";import{forwardRef as I,useState as N}from"react";import{cn as r}from"../../utils/cn.js";import{Skeleton as P}from"../Skeleton/Skeleton.js";import M from"../../hooks/useIsClient.js";function S({className:t}){return s("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:t,children:[e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.64 0 8.577 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.64 0-8.577-3.007-9.963-7.178Z"}),e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"})]})}function j({className:t}){return e("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:t,children:e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"})})}function y({className:t}){return e(P,{className:r("w-full h-10 rounded-md z-20 relative",t)})}const W=I(({inputProps:t,label:l,description:d,errorMessage:x,placeholder:m,className:u,classNames:o,disableSkeleton:h,type:c,...b},w)=>{const g=M(),i=c==="password",[f,n]=N(!1);return!g&&!h?s("div",{className:r("flex flex-col w-full text-fg",u),children:[l?e(p,{className:r("flex text-fg-muted text-xs",o?.label),children:l}):null,e(y,{className:o?.skeleton})]}):s(v,{className:r("flex flex-col w-full text-fg",u),type:i?f?"text":"password":c,...b,children:[e(p,{className:r("flex text-fg-muted text-xs",o?.label),children:l}),s("div",{className:"relative",children:[e(k,{ref:w,placeholder:m,className:r("border-solid border border-border rounded-md","text-sm text-fg placeholder-fg-subtle","h-10 px-2 py-0 m-0 w-full","bg-white","transition-all duration-200 ease-in-out","hover:border-border-emphasis","focus:outline-2 focus:outline focus:outline-border-subtle focus:border-border-emphasis","disabled:border-border-subtle disabled:bg-surface-subtle","invalid:border-danger-soft invalid:bg-danger-surface invalid:text-danger","invalid:hover:border-danger invalid:focus:border-danger invalid:focus:outline-danger-ring",i&&"pr-10",o?.input),...t}),i&&e("button",{type:"button",className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-fg-subtle hover:text-slate-600 bg-transparent border-none cursor-pointer select-none",onPointerDown:a=>{a.preventDefault(),n(!0)},onPointerUp:()=>n(!1),onPointerLeave:()=>n(!1),onPointerCancel:()=>n(!1),onContextMenu:a=>a.preventDefault(),"aria-label":"Show password while pressed",tabIndex:-1,children:f?e(j,{className:"w-5 h-5"}):e(S,{className:"w-5 h-5"})})]}),d&&e(L,{className:r("flex text-fg-muted text-sm",o?.description),slot:"description",children:d}),e(C,{className:r("flex text-danger-soft text-sm",o?.error),children:x})]})});export{W as Input,W as default};
1
+ "use client";import{jsxs as s,jsx as e}from"react/jsx-runtime";import{Label as f,TextField as v,Input as k,Text as L,FieldError as C}from"react-aria-components";import{forwardRef as I,useState as N}from"react";import{cn as r}from"../../utils/cn.js";import{Skeleton as M}from"../Skeleton/Skeleton.js";import S from"../../hooks/useIsClient.js";function j({className:t}){return s("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:t,children:[e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.64 0 8.577 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.64 0-8.577-3.007-9.963-7.178Z"}),e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"})]})}function y({className:t}){return e("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:t,children:e("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"})})}function E({className:t}){return e(M,{className:r("w-full h-10 rounded-md z-20 relative",t)})}const W=I(({inputProps:t,label:l,description:a,errorMessage:p,placeholder:m,className:u,classNames:o,disableSkeleton:x,type:c,...h},b)=>{const w=S(),i=c==="password",[n,g]=N(!1);return!w&&!x?s("div",{className:r("flex flex-col w-full text-fg",u),children:[l?e(f,{className:r("flex text-fg-muted text-xs",o?.label),children:l}):null,e(E,{className:o?.skeleton})]}):s(v,{className:r("flex flex-col w-full text-fg",u),type:i?n?"text":"password":c,...h,children:[e(f,{className:r("flex text-fg-muted text-xs",o?.label),children:l}),s("div",{className:"relative",children:[e(k,{ref:b,placeholder:m,className:r("border-solid border border-border rounded-md","text-sm text-fg placeholder-fg-subtle","h-10 px-2 py-0 m-0 w-full","bg-white","transition-all duration-200 ease-in-out","hover:border-border-emphasis","focus:outline-2 focus:outline focus:outline-border-subtle focus:border-border-emphasis","disabled:border-border-subtle disabled:bg-surface-subtle","invalid:border-danger-soft invalid:bg-danger-surface invalid:text-danger","invalid:hover:border-danger invalid:focus:border-danger invalid:focus:outline-danger-ring",i&&"pr-10",o?.input),...t}),i&&e("button",{type:"button",className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-fg-subtle hover:text-slate-600 bg-transparent border-none cursor-pointer select-none",onMouseDown:d=>d.preventDefault(),onClick:()=>g(d=>!d),"aria-label":n?"Hide password":"Show password","aria-pressed":n,children:n?e(y,{className:"w-5 h-5"}):e(j,{className:"w-5 h-5"})})]}),a&&e(L,{className:r("flex text-fg-muted text-sm",o?.description),slot:"description",children:a}),e(C,{className:r("flex text-danger-soft text-sm",o?.error),children:p})]})});export{W as Input,W as default};
@@ -56,10 +56,10 @@ import { isDevelopment } from '../../../../../utils/env';
56
56
  ```
57
57
 
58
58
  **After:**
59
- **Formerly named:** `2026-02-16-env-utils-from-clicktap-ui.md` — renamed 2026-08-07 (CTAP-1143) for global filename uniqueness; an identically-named guide exists in another tree and mirrored folders overwrote each other. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
60
59
  ```ts
61
60
  import { isDevelopment } from '@clicktap/ui/utils/env';
62
61
  ```
62
+ **Formerly named:** `2026-02-16-env-utils-from-clicktap-ui.md` — renamed 2026-08-07 (CTAP-1143) for global filename uniqueness; an identically-named guide exists in another tree and mirrored folders overwrote each other. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
63
63
 
64
64
  ### Files changed
65
65
 
@@ -4,10 +4,10 @@
4
4
  **Revised:** 2026-08-08 — the test-runner half (CTAP-1195): every runtime subpath entry gains a `default` condition, so CJS resolvers (Jest) stop falling through to the `.d.ts`. See "Test runners (Jest)" below; reported by noco.
5
5
  **Package:** `@clicktap/ui`
6
6
  **Breaking:** No — additive to the `exports` map. Existing `moduleResolution: node` / `node10`
7
- **Formerly named:** `2026-07-31-ui-exports-bundler-resolution.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
8
7
  consumers are unaffected (that resolver ignores `exports`); this only *adds* working resolution under
9
8
  `bundler` / `node16` / `nodenext`.
10
9
  **Classification:** BUGFIX (packaging) — unblocks `moduleResolution: bundler`, and with it TypeScript 7
10
+ **Formerly named:** `2026-07-31-ui-exports-bundler-resolution.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
11
11
 
12
12
  ## What was wrong
13
13
 
@@ -5,9 +5,11 @@
5
5
  **Affects:** `@clicktap/ui` — `Input` with `type="password"`.
6
6
  **Classification:** IMPROVEMENT (security / UX)
7
7
  **Breaking:** Behavioural only — the reveal changed from a click-toggle to press-and-hold. No API/prop
8
- **Formerly named:** `2026-08-04-password-reveal-press-and-hold.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
9
8
  change; adoption is automatic.
10
9
  **Ticket:** CTAP-1128
10
+ **Status:** ⚠️ **Superseded — do not adopt.** (CTAP-1240)
11
+ **Superseded by:** [`ui-2026-08-11-password-reveal-toggle.md`](./ui-2026-08-11-password-reveal-toggle.md) — press-and-hold made a revealed password impossible to copy into a password manager, so the reveal went back to a click toggle. If you have not applied this guide yet, skip it and apply that one. If you have, that guide tells you how to reverse it.
12
+ **Formerly named:** `2026-08-04-password-reveal-press-and-hold.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
11
13
 
12
14
  ## Summary
13
15
 
@@ -6,8 +6,8 @@
6
6
  **Classification:** IMPROVEMENT (new capability)
7
7
  **Breaking:** No — additive exports.
8
8
  **Consumers:** the OTP resend timer — [wire it everywhere](../../../../../../apps/frontend/docs/migrations/2026/08/2026-08-04-otp-resend-timer.md) ·
9
- **Formerly named:** `2026-08-04-resend-code-control.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
10
9
  GraphQL contract — [resend mutations](../../../../../../libs/mezzio-modules/user/docs/migrations/2026/08/2026-08-04-otp-resend-mutations.md)
10
+ **Formerly named:** `2026-08-04-resend-code-control.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
11
11
 
12
12
  ## Summary
13
13
 
@@ -5,9 +5,9 @@
5
5
  **Affects:** `@clicktap/ui` — `Button`, `ButtonLoadingContent`, `Loader/CircularEasing`, `Loader/Pulse`
6
6
  **Breaking:** No API change. **One requirement to be aware of** — see below.
7
7
  **Requires:** `@import '@clicktap/ui/theme.css'` in your CSS entry
8
- **Formerly named:** `2026-08-06-clicktap-ui-loaders-drop-framer-motion.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
9
8
  ([tokens guide](./ui-2026-08-06-clicktap-ui-semantic-tokens.md))
10
9
  **Classification:** IMPROVEMENT
10
+ **Formerly named:** `2026-08-06-clicktap-ui-loaders-drop-framer-motion.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
11
11
 
12
12
  ## What changed
13
13
 
@@ -5,9 +5,9 @@
5
5
  **Affects:** `@clicktap/ui`, every app that renders its components
6
6
  **Breaking:** **Yes — one required import.** Components render *unstyled* without it.
7
7
  **Requires:** Tailwind v4 (`@import 'tailwindcss'` in your CSS entry). See
8
- **Formerly named:** `2026-08-06-clicktap-ui-semantic-tokens.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
9
8
  [the v4 upgrade guide](../../../../../../apps/frontend/docs/migrations/2026/07/2026-07-31-tailwind-3-to-4.md).
10
9
  **Classification:** COMPATIBILITY
10
+ **Formerly named:** `2026-08-06-clicktap-ui-semantic-tokens.md` — renamed 2026-08-10 (CTAP-1214) for global filename uniqueness; library guides carry their package slug so they can never collide with an app-level guide in a consumer's aggregated working set. **If you carry a `-applied` sibling under the old name, rename it to match — do NOT re-apply.**
11
11
 
12
12
  ## Do this
13
13
 
@@ -0,0 +1,75 @@
1
+ # Password reveal is a toggle again, not press-and-hold
2
+
3
+ **Date:** 2026-08-11
4
+ **Package:** `@clicktap/ui`
5
+ **Affects:** `@clicktap/ui` — `Input` with `type="password"`.
6
+ **Classification:** IMPROVEMENT (UX / accessibility)
7
+ **Breaking:** Behavioural only — the reveal changed from press-and-hold back to a click toggle, and the
8
+ control entered the tab order. No API/prop change; adoption is automatic.
9
+ **Ticket:** CTAP-1240
10
+ **Supersedes:** [`ui-2026-08-04-password-reveal-press-and-hold.md`](./ui-2026-08-04-password-reveal-press-and-hold.md) (CTAP-1128).
11
+ If you have not applied that guide yet, **skip it** and apply this one instead — the end state is the
12
+ same either way.
13
+
14
+ ## Summary
15
+
16
+ The password-field reveal (the eye button in `Input`) is a **toggle** again: one click shows the value
17
+ and it stays shown until you click again. CTAP-1128 had made it press-and-hold — visible only while the
18
+ control was physically held — to shrink the shoulder-surfing window. That traded away more than it
19
+ bought:
20
+
21
+ - **You cannot copy a password you cannot release.** Revealing a password so you can select it and
22
+ paste it into a password manager is a routine thing to do, and press-and-hold makes it impossible.
23
+ - **You cannot watch yourself type.** Holding the button with one hand while typing a long password
24
+ with the other is not a real workflow.
25
+ - **A toggle is the control users already know.** Edge's own built-in password reveal is a toggle, as
26
+ are the Chrome and Safari password managers and effectively every major sign-in form.
27
+
28
+ The reveal is still user-initiated and still resets to hidden on every mount, so a revealed password
29
+ never survives a page load.
30
+
31
+ ## What changed
32
+
33
+ The reveal button swapped its pointer press-and-hold handlers back for a click toggle, and picked up
34
+ proper toggle-button semantics:
35
+
36
+ ```tsx
37
+ // before (CTAP-1128) // after (CTAP-1240)
38
+ onPointerDown={(e) => { onMouseDown={(e) => e.preventDefault()}
39
+ e.preventDefault(); onClick={() => setShowPassword((shown) => !shown)}
40
+ setShowPassword(true); aria-label={showPassword ? 'Hide password' : 'Show password'}
41
+ }} aria-pressed={showPassword}
42
+ onPointerUp={() => setShowPassword(false)}
43
+ onPointerLeave={() => setShowPassword(false)}
44
+ onPointerCancel={() => setShowPassword(false)}
45
+ onContextMenu={(e) => e.preventDefault()}
46
+ aria-label="Show password while pressed"
47
+ tabIndex={-1}
48
+ ```
49
+
50
+ - **`preventDefault()` on mousedown** keeps the caret in the input when you click the eye, so you can
51
+ toggle visibility mid-typing without losing your place.
52
+ - **`tabIndex={-1}` is gone** — the button is now in the tab order and operable with Enter/Space. This
53
+ is the one behavioural change a consumer might notice beyond the reveal itself: **a password field
54
+ now has one extra tab stop between it and the next control.** If you have a test that tabs through a
55
+ sign-in form by counting stops, update it.
56
+ - **`aria-pressed`** exposes the on/off state to assistive tech, and the label swaps between
57
+ `Show password` and `Hide password` instead of the static "Show password while pressed".
58
+ - Press-and-hold was **not** kept as an opt-in mode — there is one reveal behaviour, no new prop.
59
+
60
+ Shipped in `@clicktap/ui` **0.43.6**.
61
+
62
+ ## Action required (consumer)
63
+
64
+ - **Using `@clicktap/ui` `Input`:** nothing — the behaviour ships with the component. Re-check any
65
+ keyboard-navigation test that asserts an exact tab order around a password field.
66
+ - **Rolled your own password reveal:** swap the pointer handlers back for the `onClick` toggle above,
67
+ and add `aria-pressed` + the state-dependent `aria-label` while you are in there. The reference
68
+ frontend also updated its one bespoke reveal (`UpdateEmailForm`) to match.
69
+ - **Applied the CTAP-1128 guide:** this reverses it. Nothing to un-install beyond the handler swap.
70
+
71
+ ## Verify
72
+
73
+ Click the eye control → the characters show and **stay** shown. Select the revealed text and copy it —
74
+ it lands on the clipboard. Click again → hidden. Tab to the control and press Enter → it toggles.
75
+ Reload the page → the field is hidden again.
@@ -0,0 +1,61 @@
1
+ # `next` and `@heroui/*` peer ranges are capped; `react-stately` pinned
2
+
3
+ **Date:** 2026-08-11
4
+ **Package:** `@clicktap/ui`
5
+ **Affects:** every consumer — the peer ranges are the declaration your package manager installs against.
6
+ **Classification:** COMPATIBILITY
7
+ **Breaking:** Yes for a consumer already past a ceiling. No code change; the contract narrowed.
8
+ **Ticket:** CTAP-1241
9
+
10
+ ## Summary
11
+
12
+ Three peer ranges were open-ended and are now bounded:
13
+
14
+ | Peer | Before | After |
15
+ |---|---|---|
16
+ | `next` | `>=14` | `^14.0.0` |
17
+ | `@heroui/system` | `>=2.4.18` | `^2.4.18` |
18
+ | `@heroui/theme` | `>=2.4.24` | `^2.4.24` |
19
+
20
+ A caret already carries its ceiling — `^14.0.0` *is* `>=14.0.0 <15.0.0` — so the ranges are written that
21
+ way rather than as explicit bounds. For a `0.x` dependency the equivalent is a tilde (`~0.8.0` is
22
+ `>=0.8.0 <0.9.0`), because a `0.x` minor bump is a breaking change.
23
+
24
+ An open-ended peer with `auto-install-peers=true` means **"newest major, forever"** — a standing licence
25
+ for the next `pnpm update` to move you onto a major this package has never been built against, silently.
26
+ The ceilings are the highest major this repo builds and tests against, not the next major above the
27
+ floor.
28
+
29
+ ## Also: `react-stately` is pinned to the version the app owns
30
+
31
+ `react-stately` was a `devDependency` at `^3.46.0` while `apps/frontend` pins `3.44.0`, so the family
32
+ split across workspace members — the lib resolved 3.46.0, the app 3.44.0. `react`, `react-aria` and
33
+ `react-aria-components` were all clean singletons at the same time, which is what makes this shape easy
34
+ to miss: a `grep` for duplicate `react@` in the lockfile finds nothing, and only the resolved symlinks
35
+ show the split one family member over.
36
+
37
+ It is now pinned to `3.44.0`. **Not breaking** — `react-stately` remains a peer at `^3.36.0`, and the
38
+ build already externalizes `react-stately` and `@react-stately/*`, so nothing about what you install
39
+ changes. The pin only stops the lib's own dev tree from resolving a different copy than the app's.
40
+
41
+ ## Action required (consumer)
42
+
43
+ **On Next 14 and HeroUI 2.x:** nothing.
44
+
45
+ **Past a ceiling** (Next 15/16, HeroUI 3): your install now reports an unmet peer, and fails under
46
+ `strict-peer-dependencies`. That is the intended signal — it means you are on a major nobody has
47
+ verified this package against. Either move back onto a supported major, or ask for the ceiling to be
48
+ raised deliberately once the package has been built and tested there. Raising it is a one-line change;
49
+ what is missing is the verification, not the willingness.
50
+
51
+ **Worth checking while you are here:** if you have a `react-stately` (or any `@react-*`) version pinned
52
+ in your own app, confirm it matches what `@clicktap/ui` resolves. The split above existed for a while
53
+ without symptoms, and duplicate react-aria/stately instances surface as subtle focus and overlay bugs
54
+ rather than as an error.
55
+
56
+ ## Verify
57
+
58
+ ```bash
59
+ pnpm install # no unmet-peer warning for next or @heroui/*
60
+ pnpm why react-stately # one version across every member
61
+ ```
@@ -28,7 +28,9 @@ For migrations affecting the frontend app, see [frontend migrations](../../../..
28
28
  | 2026-06-17 | [Select standardization — one `<Select searchable>`, `DropdownSelect` removed](./2026/06/ui-2026-06-17-select-standardization.md) ↔ | Yes | *None* |
29
29
  | 2026-06-18 | [Select (searchable): fix "setValue is not a function" crash on browser autofill](./2026/06/ui-2026-06-18-select-hiddenselect-setvalue-crash.md) | No | Select standardization |
30
30
  | 2026-08-04 | [`ResendCode` control + `useCooldown` hook](./2026/08/ui-2026-08-04-resend-code-control.md) ↔ | No | OTP resend timer (CTAP-1114) |
31
- | 2026-08-04 | [Password reveal is press-and-hold, not a toggle](./2026/08/ui-2026-08-04-password-reveal-press-and-hold.md) | Behavioural | *None* (CTAP-1128) |
31
+ | 2026-08-04 | [Password reveal is press-and-hold, not a toggle](./2026/08/ui-2026-08-04-password-reveal-press-and-hold.md) ⚠️ superseded | Behavioural | *None* (CTAP-1128) |
32
32
  | 2026-08-06 | [`Image` is framework-free; Next's optimizer moves to `@clicktap/ui/next`](./2026/08/ui-2026-08-06-clicktap-ui-image-next-subpath.md) ↔ | Yes (Next consumers) | *None* |
33
+ | 2026-08-11 | [Password reveal is a toggle again, not press-and-hold](./2026/08/ui-2026-08-11-password-reveal-toggle.md) | Behavioural | Supersedes CTAP-1128 |
34
+ | 2026-08-11 | [`next` / `@heroui/*` peers capped; `react-stately` pinned](./2026/08/ui-2026-08-11-peer-ranges-capped.md) | Yes (consumers past a ceiling) | *None* |
33
35
 
34
36
  ↔ = cross-app migration (has counterpart in frontend app)
@@ -1,4 +1,24 @@
1
1
  [
2
+ {
3
+ "path": "2026/08/ui-2026-08-11-peer-ranges-capped.md",
4
+ "module": "libs/frontend-modules/ui",
5
+ "package": "@clicktap/ui",
6
+ "date": "2026-08-11",
7
+ "title": "`next` and `@heroui/*` peer ranges are capped; `react-stately` pinned",
8
+ "classification": "COMPATIBILITY",
9
+ "breaking": "Yes for a consumer already past a ceiling. No code change; the contract narrowed.",
10
+ "affects": "every consumer — the peer ranges are the declaration your package manager installs against."
11
+ },
12
+ {
13
+ "path": "2026/08/ui-2026-08-11-password-reveal-toggle.md",
14
+ "module": "libs/frontend-modules/ui",
15
+ "package": "@clicktap/ui",
16
+ "date": "2026-08-11",
17
+ "title": "Password reveal is a toggle again, not press-and-hold",
18
+ "classification": "IMPROVEMENT (UX / accessibility)",
19
+ "breaking": "Behavioural only — the reveal changed from press-and-hold back to a click toggle, and the",
20
+ "affects": "`@clicktap/ui` — `Input` with `type=\"password\"`."
21
+ },
2
22
  {
3
23
  "path": "2026/08/ui-2026-08-07-ui-peer-contract-form-graphql-optional-peers.md",
4
24
  "module": "libs/frontend-modules/ui",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clicktap/ui",
3
- "version": "0.43.5",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "author": "Clicktap",
6
6
  "description": "A library of React UI components and low-level hooks.",
@@ -124,7 +124,7 @@
124
124
  "react-aria-components": "^1.15.0",
125
125
  "react-hook-form": "^7.71.1",
126
126
  "react-international-phone": "^4.7.0",
127
- "react-stately": "^3.46.0",
127
+ "react-stately": "3.44.0",
128
128
  "rollup-preserve-directives": "^1.1.3",
129
129
  "tailwindcss": "^4.3.3",
130
130
  "vite": "^7.3.1",
@@ -138,13 +138,13 @@
138
138
  "@heroui/accordion": "^2.2.0",
139
139
  "@heroui/badge": "^2.2.0",
140
140
  "@heroui/pagination": "^2.2.0",
141
- "@heroui/system": ">=2.4.18",
142
- "@heroui/theme": ">=2.4.24",
141
+ "@heroui/system": "^2.4.18",
142
+ "@heroui/theme": "^2.4.24",
143
143
  "@heroui/tooltip": "^2.2.0",
144
144
  "@types/react": "^18.0.0",
145
145
  "framer-motion": "^11.18.0",
146
146
  "graphql-request": "^6.1.0",
147
- "next": ">=14",
147
+ "next": "^14.0.0",
148
148
  "react": "^18.0.0",
149
149
  "react-aria": "^3.46.0",
150
150
  "react-aria-components": "^1.15.0",