@clicktap/ui 0.42.3 → 0.43.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/components/ResendCode/ResendCode.d.ts +5 -1
- package/components/ResendCode/ResendCode.js +1 -1
- package/components/ResendCode/ResendCode.types.d.ts +5 -0
- package/docs/migrations/2026/01/2026-01-14-external-link-detection.md +1 -0
- package/docs/migrations/2026/01/2026-01-14-use-route-hook.md +1 -0
- package/docs/migrations/2026/01/2026-01-15-input-disable-skeleton.md +1 -0
- package/docs/migrations/2026/02/2026-02-17-select-popover-portal-container-restored.md +1 -0
- package/docs/migrations/2026/02/{2026-02-16-env-utils-from-clicktap-ui.md → ui-2026-02-16-env-utils-from-clicktap-ui.md} +2 -0
- package/docs/migrations/2026/03/2026-03-24-image-dimmed-hidden-onready.md +1 -0
- package/docs/migrations/2026/03/2026-03-24-modal-overlay-backdrop-dismiss.md +1 -0
- package/docs/migrations/2026/04/2026-04-17-select-address-input-onchange-key-or-item.md +1 -0
- package/docs/migrations/2026/04/{2026-04-24-image-placeholder-frontend-fallback.md → ui-2026-04-24-image-placeholder-frontend-fallback.md} +5 -3
- package/docs/migrations/2026/04/{2026-04-30-prune-invalid-pdp-selections.md → ui-2026-04-30-prune-invalid-pdp-selections.md} +6 -4
- package/docs/migrations/2026/04/{2026-04-30-top-down-pdp-option-dependency.md → ui-2026-04-30-top-down-pdp-option-dependency.md} +4 -2
- package/docs/migrations/2026/05/2026-05-01-build-pdp-url-util.md +1 -0
- package/docs/migrations/2026/05/2026-05-03-auth-aware-graphql-client.md +1 -0
- package/docs/migrations/2026/05/2026-05-20-framer-motion-11-idioms.md +1 -0
- package/docs/migrations/2026/05/2026-05-21-button-loading-content.md +1 -0
- package/docs/migrations/2026/05/2026-05-21-password-check-hide-on-empty.md +1 -0
- package/docs/migrations/2026/05/2026-05-29-password-check-requirements-variant.md +1 -0
- package/docs/migrations/2026/06/2026-06-17-select-standardization.md +1 -0
- package/docs/migrations/2026/06/2026-06-18-select-hiddenselect-setvalue-crash.md +1 -0
- package/docs/migrations/2026/08/2026-08-02-nextui-to-heroui.md +1 -0
- package/docs/migrations/2026/08/2026-08-04-password-reveal-press-and-hold.md +1 -0
- package/docs/migrations/2026/08/2026-08-04-resend-code-control.md +1 -0
- package/docs/migrations/2026/08/2026-08-06-clicktap-ui-image-next-subpath.md +1 -0
- package/docs/migrations/2026/08/2026-08-06-clicktap-ui-loaders-drop-framer-motion.md +1 -0
- package/docs/migrations/2026/08/2026-08-06-clicktap-ui-semantic-tokens.md +1 -0
- package/docs/migrations/README.md +4 -4
- package/docs/migrations/index.json +272 -0
- package/hooks/useCooldown.d.ts +10 -3
- package/hooks/useCooldown.js +1 -1
- package/package.json +1 -1
|
@@ -4,6 +4,10 @@ import { ResendCodeProps } from './ResendCode.types';
|
|
|
4
4
|
* request and cooldown state (e.g. via a resend hook composing `useCooldown`). Renders one of three
|
|
5
5
|
* labels: the cooldown countdown, the in-flight label, or the idle action label; the button is
|
|
6
6
|
* disabled unless `canResend`.
|
|
7
|
+
*
|
|
8
|
+
* A visually-hidden polite live region announces when resend becomes available (CTAP-1167). The
|
|
9
|
+
* announcement is a separate region — not `aria-live` on the button — so screen-reader users hear
|
|
10
|
+
* the cooldown END without having every one-second countdown label change read out.
|
|
7
11
|
*/
|
|
8
|
-
export declare function ResendCode({ cooldownSeconds, isResending, canResend, onResend, prompt, label, resendingLabel, className, buttonClassName, }: ResendCodeProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function ResendCode({ cooldownSeconds, isResending, canResend, onResend, prompt, label, resendingLabel, availableAnnouncement, className, buttonClassName, }: ResendCodeProps): import("react/jsx-runtime").JSX.Element;
|
|
9
13
|
export default ResendCode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as
|
|
1
|
+
"use client";import{jsxs as m,jsx as t}from"react/jsx-runtime";import{cn as a}from"../../utils/cn.js";function x({cooldownSeconds:e,isResending:n,canResend:s,onResend:d,prompt:i="Didn't get a code?",label:l="Resend code",resendingLabel:r="Sending…",availableAnnouncement:o="You can request a new code now.",className:c,buttonClassName:u}){const b=e>0?`Resend in ${e}s`:n?r:l;return m("p",{className:a("text-sm",c),children:[i," ",t("button",{type:"button",onClick:d,disabled:!s,className:a("underline disabled:no-underline disabled:opacity-50 disabled:cursor-not-allowed",u),children:b}),t("span",{"aria-live":"polite",className:"sr-only",children:e===0&&!n?o:""})]})}export{x as ResendCode,x as default};
|
|
@@ -13,6 +13,11 @@ export type ResendCodeProps = {
|
|
|
13
13
|
label?: string;
|
|
14
14
|
/** Label shown while a resend is in flight. Defaults to "Sending…". */
|
|
15
15
|
resendingLabel?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Screen-reader announcement made (via a polite live region) when the cooldown ends and resend
|
|
18
|
+
* becomes available. Defaults to "You can request a new code now.".
|
|
19
|
+
*/
|
|
20
|
+
availableAnnouncement?: string;
|
|
16
21
|
/** className for the wrapping paragraph. */
|
|
17
22
|
className?: string;
|
|
18
23
|
/** className for the action button. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Environment Utilities from @clicktap/ui
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-02-16
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** All files importing `isDevelopment` / `isProduction` from local `utils/env`
|
|
5
6
|
**Classification:** IMPROVEMENT
|
|
6
7
|
**Breaking:** No
|
|
@@ -55,6 +56,7 @@ import { isDevelopment } from '../../../../../utils/env';
|
|
|
55
56
|
```
|
|
56
57
|
|
|
57
58
|
**After:**
|
|
59
|
+
**Formerly named:** `ui-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.**
|
|
58
60
|
```ts
|
|
59
61
|
import { isDevelopment } from '@clicktap/ui/utils/env';
|
|
60
62
|
```
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Select / AddressInput: `onSelectionChange` / `onChange` callback widened to `Key | T`
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-04-17 *(documentation date; underlying react-aria upgrade landed 2026-01-19 via commit `7c27599b2a`)*
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** Frontend apps consuming `@clicktap/ui`'s `Select` and components that re-export its types (`AddressInput`, etc.). Any handler typed as `(value: Key) => void` breaks after the update.
|
|
5
6
|
**Classification:** COMPATIBILITY
|
|
6
7
|
**Breaking:** Yes — TypeScript-only. No runtime change; existing handlers still receive the same value at runtime, but strict TS setups fail to compile.
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# `PLACEHOLDER_IMAGE` Export from `@clicktap/ui/utils/placeholder`
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-04-24
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui` consumers that render product/category images
|
|
5
6
|
**Classification:** IMPROVEMENT
|
|
6
7
|
**Breaking:** No
|
|
8
|
+
**Formerly named:** `ui-2026-04-24-image-placeholder-frontend-fallback.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.**
|
|
7
9
|
|
|
8
10
|
## Dependencies
|
|
9
11
|
|
|
10
|
-
- See [frontend counterpart](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-24-image-placeholder-frontend-fallback.md) ↔ for the consuming-app changes.
|
|
12
|
+
- See [frontend counterpart](../../../../../../apps/frontend/docs/migrations/2026/04/ui-2026-04-24-image-placeholder-frontend-fallback.md) ↔ for the consuming-app changes.
|
|
11
13
|
|
|
12
14
|
## Summary
|
|
13
15
|
|
|
@@ -60,7 +62,7 @@ Works equally well with raw `<img>`:
|
|
|
60
62
|
<img src={product.image ?? PLACEHOLDER_IMAGE} alt="" />
|
|
61
63
|
```
|
|
62
64
|
|
|
63
|
-
For the PDP/PLP migration, see the [frontend counterpart guide](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-24-image-placeholder-frontend-fallback.md) — it covers the full cascade decision (variant → placeholder, no parent fallback) and the dead `no_selection` checks to remove.
|
|
65
|
+
For the PDP/PLP migration, see the [frontend counterpart guide](../../../../../../apps/frontend/docs/migrations/2026/04/ui-2026-04-24-image-placeholder-frontend-fallback.md) — it covers the full cascade decision (variant → placeholder, no parent fallback) and the dead `no_selection` checks to remove.
|
|
64
66
|
|
|
65
67
|
## Files Changed
|
|
66
68
|
|
|
@@ -74,7 +76,7 @@ For the PDP/PLP migration, see the [frontend counterpart guide](../../../../../.
|
|
|
74
76
|
|
|
75
77
|
- [ ] `@clicktap/ui >= 0.27.0` installed in consumers.
|
|
76
78
|
- [ ] No need to copy any SVG into the consuming app's `public/` folder.
|
|
77
|
-
- [ ] Apply the [frontend counterpart guide](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-24-image-placeholder-frontend-fallback.md) for the consuming-app changes.
|
|
79
|
+
- [ ] Apply the [frontend counterpart guide](../../../../../../apps/frontend/docs/migrations/2026/04/ui-2026-04-24-image-placeholder-frontend-fallback.md) for the consuming-app changes.
|
|
78
80
|
|
|
79
81
|
## Why a data URL and not a bundled file?
|
|
80
82
|
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# PDP Option Selection — Conservative Prune Helper (`pruneInvalidSelections`)
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-04-30
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui/utils/variantOptions` — adds `pruneInvalidSelections`
|
|
5
6
|
**Classification:** IMPROVEMENT
|
|
6
7
|
**Breaking:** No (additive)
|
|
8
|
+
**Formerly named:** `ui-2026-04-30-prune-invalid-pdp-selections.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.**
|
|
7
9
|
|
|
8
10
|
## Dependencies
|
|
9
11
|
|
|
10
|
-
- Builds on [`2026-04-30-top-down-pdp-option-dependency.md`](./2026-04-30-top-down-pdp-option-dependency.md). That migration introduced top-down option filtering with a blanket "clear every downstream selection on any upstream change". This migration replaces the recommended consumer pattern with a more conservative prune that preserves still-valid downstream picks.
|
|
11
|
-
- Frontend counterpart: [`apps/frontend/.../2026-04-30-prune-invalid-pdp-selections.md`](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-30-prune-invalid-pdp-selections.md) ↔.
|
|
12
|
+
- Builds on [`2026-04-30-top-down-pdp-option-dependency.md`](./ui-2026-04-30-top-down-pdp-option-dependency.md). That migration introduced top-down option filtering with a blanket "clear every downstream selection on any upstream change". This migration replaces the recommended consumer pattern with a more conservative prune that preserves still-valid downstream picks.
|
|
13
|
+
- Frontend counterpart: [`apps/frontend/.../ui-2026-04-30-prune-invalid-pdp-selections.md`](../../../../../../apps/frontend/docs/migrations/2026/04/ui-2026-04-30-prune-invalid-pdp-selections.md) ↔.
|
|
12
14
|
|
|
13
15
|
## Summary
|
|
14
16
|
|
|
@@ -162,5 +164,5 @@ Replace the manual delete loop with a single `pruneInvalidSelections` call (see
|
|
|
162
164
|
|
|
163
165
|
## References
|
|
164
166
|
|
|
165
|
-
- Frontend counterpart migration: [`apps/frontend/.../2026-04-30-prune-invalid-pdp-selections.md`](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-30-prune-invalid-pdp-selections.md) ↔
|
|
166
|
-
- Previous top-down migration this builds on: [`2026-04-30-top-down-pdp-option-dependency.md`](./2026-04-30-top-down-pdp-option-dependency.md)
|
|
167
|
+
- Frontend counterpart migration: [`apps/frontend/.../ui-2026-04-30-prune-invalid-pdp-selections.md`](../../../../../../apps/frontend/docs/migrations/2026/04/ui-2026-04-30-prune-invalid-pdp-selections.md) ↔
|
|
168
|
+
- Previous top-down migration this builds on: [`2026-04-30-top-down-pdp-option-dependency.md`](./ui-2026-04-30-top-down-pdp-option-dependency.md)
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Top-Down PDP Option Dependency — `@clicktap/ui/utils/variantOptions`
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-04-30
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** New utility module `@clicktap/ui/utils/variantOptions` (ships generic `filterAvailableOptions`, `findVariant`, `getDownstreamAxisCodes`)
|
|
5
6
|
**Classification:** IMPROVEMENT
|
|
6
7
|
**Breaking:** No (additive)
|
|
7
8
|
|
|
8
9
|
## Dependencies
|
|
9
10
|
|
|
10
|
-
- Builds on the per-axis selection model used in [`apps/frontend/.../2026-04-24-pdp-configurable-selector-ux.md`](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-24-pdp-configurable-selector-ux.md). The previous symmetric filter lived in the frontend app; that logic now lives here in generic, reusable form. See [`apps/frontend/.../2026-04-30-top-down-pdp-option-dependency.md`](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-30-top-down-pdp-option-dependency.md) ↔ for the frontend-side migration steps that adopt the new utilities and switch to top-down semantics.
|
|
11
|
+
- Builds on the per-axis selection model used in [`apps/frontend/.../2026-04-24-pdp-configurable-selector-ux.md`](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-24-pdp-configurable-selector-ux.md). The previous symmetric filter lived in the frontend app; that logic now lives here in generic, reusable form. See [`apps/frontend/.../ui-2026-04-30-top-down-pdp-option-dependency.md`](../../../../../../apps/frontend/docs/migrations/2026/04/ui-2026-04-30-top-down-pdp-option-dependency.md) ↔ for the frontend-side migration steps that adopt the new utilities and switch to top-down semantics.
|
|
11
12
|
|
|
12
13
|
## Summary
|
|
13
14
|
|
|
@@ -32,6 +33,7 @@ This module ships the filter logic only. The selection-state mechanics (clearing
|
|
|
32
33
|
### New module
|
|
33
34
|
|
|
34
35
|
**Source:** `libs/ui/src/utils/variantOptions/`
|
|
36
|
+
**Formerly named:** `ui-2026-04-30-top-down-pdp-option-dependency.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.**
|
|
35
37
|
|
|
36
38
|
```
|
|
37
39
|
libs/ui/src/utils/variantOptions/
|
|
@@ -282,5 +284,5 @@ Skip this and you'll occasionally see the matched variant query against an impos
|
|
|
282
284
|
|
|
283
285
|
## References
|
|
284
286
|
|
|
285
|
-
- Frontend counterpart migration: [`apps/frontend/.../2026-04-30-top-down-pdp-option-dependency.md`](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-30-top-down-pdp-option-dependency.md) ↔
|
|
287
|
+
- Frontend counterpart migration: [`apps/frontend/.../ui-2026-04-30-top-down-pdp-option-dependency.md`](../../../../../../apps/frontend/docs/migrations/2026/04/ui-2026-04-30-top-down-pdp-option-dependency.md) ↔
|
|
286
288
|
- Prior symmetric-filter implementation it replaces: [`apps/frontend/.../2026-04-24-pdp-configurable-selector-ux.md`](../../../../../../apps/frontend/docs/migrations/2026/04/2026-04-24-pdp-configurable-selector-ux.md)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Auth-aware GraphQL client — `@clicktap/ui/utils/createAuthAwareGraphqlClient`
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-05-03
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui/utils/createAuthAwareGraphqlClient` — new export
|
|
5
6
|
**Classification:** IMPROVEMENT
|
|
6
7
|
**Breaking:** No (additive)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# framer-motion 11.x idioms — opacity-only for modal entry/exit, primitives over transform strings, matched keyframe shapes
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-05-20
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui/components/Dialog`, `@clicktap/ui/components/ModalOverlay`, `@clicktap/ui/components/Badge`, `@clicktap/ui/components/Loader/CircularEasing`, `@clicktap/ui/components/Loader/Pulse`, and any consumer-side `motion.*` usage on framer-motion 11.x.
|
|
5
6
|
**Classification:** COMPATIBILITY
|
|
6
7
|
**Breaking:** Yes (for consumers passing custom `animationVariants` containing multi-function `transform` strings, transform/scale primitives in modal variants, calc-with-mixed-units in animate targets, or who copy-paste the affected motion patterns into their own components — see Consumer Impact)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `ButtonLoadingContent` helper — standardized right-side spinner for all submit buttons
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-05-21
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui/components/Button` (new `ButtonLoadingContent` export) and every submit-style button in the frontend app.
|
|
5
6
|
**Classification:** IMPROVEMENT
|
|
6
7
|
**Breaking:** No
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `PasswordCheck` — the `requirements` variant (adoption guide for forks)
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-05-29 (retroactive — the variant already ships in `@clicktap/ui`)
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `libs/ui/src/components/PasswordCheck/PasswordCheck.tsx`, `libs/ui/src/components/PasswordCheck/PasswordCheck.types.ts`
|
|
5
6
|
**Classification:** IMPROVEMENT
|
|
6
7
|
**Breaking:** No (the variant is additive; `default` is unchanged)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Select standardization — one `<Select searchable>`, `DropdownSelect` removed
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-06-17
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** Any app consuming `@clicktap/ui`'s `Select` / `DropdownSelect` (Crispi, FFL, and any fork that renders pickers, sort controls, country/region selects, or configurable-product options).
|
|
5
6
|
**Classification:** FEATURE + BREAKING
|
|
6
7
|
**Breaking:** Yes — (1) `DropdownSelect` removed, (2) the bare `<Select>` is now a **button picker**, not a combobox, (3) `DropdownSelect`'s `classNames.trigger` is now `classNames.input`, (4) the root is `w-full` by default, (5) `<Option>` is react-stately's `Item` — keyed by `key` (no `id`) and **cannot be wrapped**.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `Select` (searchable): fix "setValue is not a function" crash on browser autofill
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-06-18
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui` `Select` — the **searchable** (ComboBox) variant (`ComboBoxSelect`)
|
|
5
6
|
**Classification:** BUGFIX
|
|
6
7
|
**Breaking:** No
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# NextUI → HeroUI for `Accordion`, `Badge`, `Pagination`, `Tooltip`
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-08-02
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui` peer dependencies — `Accordion`, `Badge`, `Pagination`, `Tooltip`
|
|
5
6
|
**Classification:** DEPENDENCY
|
|
6
7
|
**Breaking:** Yes (peer dependencies change; requires Tailwind 4 — see below)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Password reveal is press-and-hold, not a toggle
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-08-04
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui` — `Input` with `type="password"`.
|
|
5
6
|
**Classification:** IMPROVEMENT (security / UX)
|
|
6
7
|
**Breaking:** Behavioural only — the reveal changed from a click-toggle to press-and-hold. No API/prop
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `ResendCode` control + `useCooldown` hook
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-08-04
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui` — new `components/ResendCode` and `hooks/useCooldown` exports.
|
|
5
6
|
**Classification:** IMPROVEMENT (new capability)
|
|
6
7
|
**Breaking:** No — additive exports.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `Image` is framework-free; Next's optimizer moves to `@clicktap/ui/next`
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-08-06
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Ticket:** CTAP-1125 (epic CTAP-1122)
|
|
5
6
|
**Affects:** Any consumer importing `@clicktap/ui/components/Image` or `@clicktap/ui/components/UploadImage`. Consumer counterpart: [`apps/frontend/docs/migrations/2026/08/2026-08-06-image-from-clicktap-ui-next.md`](../../../../../../apps/frontend/docs/migrations/2026/08/2026-08-06-image-from-clicktap-ui-next.md)
|
|
6
7
|
**Requires:** `@clicktap/ui` at the release bundling CTAP-1125. Next consumers additionally need `next >= 14` installed — it is now an **optional peer**, so your package manager will not add it for you.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `Button` and the loaders no longer need `framer-motion` (CTAP-1156)
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-08-06
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui` — `Button`, `ButtonLoadingContent`, `Loader/CircularEasing`, `Loader/Pulse`
|
|
5
6
|
**Breaking:** No API change. **One requirement to be aware of** — see below.
|
|
6
7
|
**Requires:** `@import '@clicktap/ui/theme.css'` in your CSS entry
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `@clicktap/ui` semantic design tokens — add one CSS import (CTAP-1123)
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-08-06
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
4
5
|
**Affects:** `@clicktap/ui`, every app that renders its components
|
|
5
6
|
**Breaking:** **Yes — one required import.** Components render *unstyled* without it.
|
|
6
7
|
**Requires:** Tailwind v4 (`@import 'tailwindcss'` in your CSS entry). See
|
|
@@ -11,14 +11,14 @@ For migrations affecting the frontend app, see [frontend migrations](../../../..
|
|
|
11
11
|
| 2026-01-14 | [External link detection + `LinkProvider`](./2026/01/2026-01-14-external-link-detection.md) | No | *None* |
|
|
12
12
|
| 2026-01-14 | [`useRoute` hook + `RouteProvider`](./2026/01/2026-01-14-use-route-hook.md) | No | *None* |
|
|
13
13
|
| 2026-01-15 | [`Input` `disableSkeleton` prop](./2026/01/2026-01-15-input-disable-skeleton.md) | No | *None* |
|
|
14
|
-
| 2026-02-16 | [Environment utilities — `@clicktap/ui/utils/env`](./2026/02/2026-02-16-env-utils-from-clicktap-ui.md) | No | *None* |
|
|
14
|
+
| 2026-02-16 | [Environment utilities — `@clicktap/ui/utils/env`](./2026/02/ui-2026-02-16-env-utils-from-clicktap-ui.md) | No | *None* |
|
|
15
15
|
| 2026-02-17 | [`Select` `popoverPortalContainer` restored](./2026/02/2026-02-17-select-popover-portal-container-restored.md) | No | *None* |
|
|
16
16
|
| 2026-03-24 | [Image: dimmed, hidden, and onReady Props](./2026/03/2026-03-24-image-dimmed-hidden-onready.md) ↔ | No | *None* |
|
|
17
17
|
| 2026-03-24 | [ModalOverlay: fix dismiss on backdrop click](./2026/03/2026-03-24-modal-overlay-backdrop-dismiss.md) | No | *None* |
|
|
18
18
|
| 2026-04-17 | [`Select`/`AddressInput` `onChange` widened to `Key \| T`](./2026/04/2026-04-17-select-address-input-onchange-key-or-item.md) | Yes | *None* |
|
|
19
|
-
| 2026-04-24 | [`PLACEHOLDER_IMAGE` Export from `@clicktap/ui/utils/placeholder`](./2026/04/2026-04-24-image-placeholder-frontend-fallback.md) ↔ | No | *None* |
|
|
20
|
-
| 2026-04-30 | [Top-Down PDP Option Dependency — `@clicktap/ui/utils/variantOptions`](./2026/04/2026-04-30-top-down-pdp-option-dependency.md) ↔ | No | *None* |
|
|
21
|
-
| 2026-04-30 | [PDP Option Selection — Conservative Prune Helper (`pruneInvalidSelections`)](./2026/04/2026-04-30-prune-invalid-pdp-selections.md) ↔ | No | Top-Down PDP Option Dependency |
|
|
19
|
+
| 2026-04-24 | [`PLACEHOLDER_IMAGE` Export from `@clicktap/ui/utils/placeholder`](./2026/04/ui-2026-04-24-image-placeholder-frontend-fallback.md) ↔ | No | *None* |
|
|
20
|
+
| 2026-04-30 | [Top-Down PDP Option Dependency — `@clicktap/ui/utils/variantOptions`](./2026/04/ui-2026-04-30-top-down-pdp-option-dependency.md) ↔ | No | *None* |
|
|
21
|
+
| 2026-04-30 | [PDP Option Selection — Conservative Prune Helper (`pruneInvalidSelections`)](./2026/04/ui-2026-04-30-prune-invalid-pdp-selections.md) ↔ | No | Top-Down PDP Option Dependency |
|
|
22
22
|
| 2026-05-01 | [`buildPdpUrl` Utility — `@clicktap/ui/utils/buildPdpUrl`](./2026/05/2026-05-01-build-pdp-url-util.md) | No | *None* |
|
|
23
23
|
| 2026-05-03 | [Auth-aware GraphQL client — `@clicktap/ui/utils/createAuthAwareGraphqlClient`](./2026/05/2026-05-03-auth-aware-graphql-client.md) | No | *None* |
|
|
24
24
|
| 2026-05-20 | [framer-motion 11.x idioms — opacity-only for modals, primitives elsewhere, matched keyframe shapes](./2026/05/2026-05-20-framer-motion-11-idioms.md) ↔ | Yes (custom `animationVariants` only) | *None* |
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"path": "2026/08/2026-08-07-ui-peer-contract-form-graphql-optional-peers.md",
|
|
4
|
+
"module": "libs/ui",
|
|
5
|
+
"package": "@clicktap/ui",
|
|
6
|
+
"date": "2026-08-07",
|
|
7
|
+
"title": "`@clicktap/ui` peer contract: three new optional peers; `clsx` corrected (CTAP-1158)",
|
|
8
|
+
"classification": "COMPATIBILITY",
|
|
9
|
+
"breaking": "No for minimal consumers; action needed only if you use the form or GraphQL-aware components",
|
|
10
|
+
"affects": ""
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"path": "2026/08/2026-08-06-clicktap-ui-semantic-tokens.md",
|
|
14
|
+
"module": "libs/ui",
|
|
15
|
+
"package": "@clicktap/ui",
|
|
16
|
+
"date": "2026-08-06",
|
|
17
|
+
"title": "`@clicktap/ui` semantic design tokens — add one CSS import (CTAP-1123)",
|
|
18
|
+
"classification": "COMPATIBILITY",
|
|
19
|
+
"breaking": "**Yes — one required import.** Components render *unstyled* without it.",
|
|
20
|
+
"affects": "`@clicktap/ui`, every app that renders its components"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"path": "2026/08/2026-08-06-clicktap-ui-loaders-drop-framer-motion.md",
|
|
24
|
+
"module": "libs/ui",
|
|
25
|
+
"package": "@clicktap/ui",
|
|
26
|
+
"date": "2026-08-06",
|
|
27
|
+
"title": "`Button` and the loaders no longer need `framer-motion` (CTAP-1156)",
|
|
28
|
+
"classification": "IMPROVEMENT",
|
|
29
|
+
"breaking": "No API change. **One requirement to be aware of** — see below.",
|
|
30
|
+
"affects": "`@clicktap/ui` — `Button`, `ButtonLoadingContent`, `Loader/CircularEasing`, `Loader/Pulse`"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"path": "2026/08/2026-08-06-clicktap-ui-image-next-subpath.md",
|
|
34
|
+
"module": "libs/ui",
|
|
35
|
+
"package": "@clicktap/ui",
|
|
36
|
+
"date": "2026-08-06",
|
|
37
|
+
"title": "`Image` is framework-free; Next's optimizer moves to `@clicktap/ui/next`",
|
|
38
|
+
"classification": "IMPROVEMENT",
|
|
39
|
+
"breaking": "Yes, for Next consumers — one import path per call site. See \"If you are a Next app\" below.",
|
|
40
|
+
"affects": "Any consumer importing `@clicktap/ui/components/Image` or `@clicktap/ui/components/UploadImage`. Consumer counterpart: [`apps/frontend/docs/migrations/2026/08/2026-08-06-image-from-clicktap-ui-next.md`](../../../../../../apps/frontend/docs/migrations/2026/08/2026-08-06-image-from-clicktap-ui-next.md)"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"path": "2026/08/2026-08-04-resend-code-control.md",
|
|
44
|
+
"module": "libs/ui",
|
|
45
|
+
"package": "@clicktap/ui",
|
|
46
|
+
"date": "2026-08-04",
|
|
47
|
+
"title": "`ResendCode` control + `useCooldown` hook",
|
|
48
|
+
"classification": "IMPROVEMENT (new capability)",
|
|
49
|
+
"breaking": "No — additive exports.",
|
|
50
|
+
"affects": "`@clicktap/ui` — new `components/ResendCode` and `hooks/useCooldown` exports."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"path": "2026/08/2026-08-04-password-reveal-press-and-hold.md",
|
|
54
|
+
"module": "libs/ui",
|
|
55
|
+
"package": "@clicktap/ui",
|
|
56
|
+
"date": "2026-08-04",
|
|
57
|
+
"title": "Password reveal is press-and-hold, not a toggle",
|
|
58
|
+
"classification": "IMPROVEMENT (security / UX)",
|
|
59
|
+
"breaking": "Behavioural only — the reveal changed from a click-toggle to press-and-hold. No API/prop",
|
|
60
|
+
"affects": "`@clicktap/ui` — `Input` with `type=\"password\"`."
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"path": "2026/08/2026-08-02-nextui-to-heroui.md",
|
|
64
|
+
"module": "libs/ui",
|
|
65
|
+
"package": "@clicktap/ui",
|
|
66
|
+
"date": "2026-08-02",
|
|
67
|
+
"title": "NextUI → HeroUI for `Accordion`, `Badge`, `Pagination`, `Tooltip`",
|
|
68
|
+
"classification": "DEPENDENCY",
|
|
69
|
+
"breaking": "Yes (peer dependencies change; requires Tailwind 4 — see below)",
|
|
70
|
+
"affects": "`@clicktap/ui` peer dependencies — `Accordion`, `Badge`, `Pagination`, `Tooltip`"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"path": "2026/07/2026-07-31-ui-exports-bundler-resolution.md",
|
|
74
|
+
"module": "libs/ui",
|
|
75
|
+
"package": "@clicktap/ui",
|
|
76
|
+
"date": "2026-07-31",
|
|
77
|
+
"title": "`@clicktap/ui` resolves its deep subpaths under `moduleResolution: bundler` (CTAP-1060)",
|
|
78
|
+
"classification": "BUGFIX (packaging) — unblocks `moduleResolution: bundler`, and with it TypeScript 7",
|
|
79
|
+
"breaking": "No — additive to the `exports` map. Existing `moduleResolution: node` / `node10`",
|
|
80
|
+
"affects": ""
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"path": "2026/06/2026-06-18-select-hiddenselect-setvalue-crash.md",
|
|
84
|
+
"module": "libs/ui",
|
|
85
|
+
"package": "@clicktap/ui",
|
|
86
|
+
"date": "2026-06-18",
|
|
87
|
+
"title": "`Select` (searchable): fix \"setValue is not a function\" crash on browser autofill",
|
|
88
|
+
"classification": "BUGFIX",
|
|
89
|
+
"breaking": "No",
|
|
90
|
+
"affects": "`@clicktap/ui` `Select` — the **searchable** (ComboBox) variant (`ComboBoxSelect`)"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"path": "2026/06/2026-06-17-select-standardization.md",
|
|
94
|
+
"module": "libs/ui",
|
|
95
|
+
"package": "@clicktap/ui",
|
|
96
|
+
"date": "2026-06-17",
|
|
97
|
+
"title": "Select standardization — one `<Select searchable>`, `DropdownSelect` removed",
|
|
98
|
+
"classification": "FEATURE + BREAKING",
|
|
99
|
+
"breaking": "Yes — (1) `DropdownSelect` removed, (2) the bare `<Select>` is now a **button picker**, not a combobox, (3) `DropdownSelect`'s `classNames.trigger` is now `classNames.input`, (4) the root is `w-full` by default, (5) `<Option>` is react-stately's `Item` — keyed by `key` (no `id`) and **cannot be wrapped**.",
|
|
100
|
+
"affects": "Any app consuming `@clicktap/ui`'s `Select` / `DropdownSelect` (Crispi, FFL, and any fork that renders pickers, sort controls, country/region selects, or configurable-product options)."
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"path": "2026/05/2026-05-29-password-check-requirements-variant.md",
|
|
104
|
+
"module": "libs/ui",
|
|
105
|
+
"package": "@clicktap/ui",
|
|
106
|
+
"date": "2026-05-29",
|
|
107
|
+
"title": "`PasswordCheck` — the `requirements` variant (adoption guide for forks)",
|
|
108
|
+
"classification": "IMPROVEMENT",
|
|
109
|
+
"breaking": "No (the variant is additive; `default` is unchanged)",
|
|
110
|
+
"affects": "`libs/ui/src/components/PasswordCheck/PasswordCheck.tsx`, `libs/ui/src/components/PasswordCheck/PasswordCheck.types.ts`"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"path": "2026/05/2026-05-21-password-check-hide-on-empty.md",
|
|
114
|
+
"module": "libs/ui",
|
|
115
|
+
"package": "@clicktap/ui",
|
|
116
|
+
"date": "2026-05-21",
|
|
117
|
+
"title": "`PasswordCheck` `requirements` variant hides until the visitor types",
|
|
118
|
+
"classification": "IMPROVEMENT",
|
|
119
|
+
"breaking": "No",
|
|
120
|
+
"affects": "`libs/ui/src/components/PasswordCheck/PasswordCheck.tsx`"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"path": "2026/05/2026-05-21-button-loading-content.md",
|
|
124
|
+
"module": "libs/ui",
|
|
125
|
+
"package": "@clicktap/ui",
|
|
126
|
+
"date": "2026-05-21",
|
|
127
|
+
"title": "`ButtonLoadingContent` helper — standardized right-side spinner for all submit buttons",
|
|
128
|
+
"classification": "IMPROVEMENT",
|
|
129
|
+
"breaking": "No",
|
|
130
|
+
"affects": "`@clicktap/ui/components/Button` (new `ButtonLoadingContent` export) and every submit-style button in the frontend app."
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"path": "2026/05/2026-05-20-framer-motion-11-idioms.md",
|
|
134
|
+
"module": "libs/ui",
|
|
135
|
+
"package": "@clicktap/ui",
|
|
136
|
+
"date": "2026-05-20",
|
|
137
|
+
"title": "framer-motion 11.x idioms — opacity-only for modal entry/exit, primitives over transform strings, matched keyframe shapes",
|
|
138
|
+
"classification": "COMPATIBILITY",
|
|
139
|
+
"breaking": "Yes (for consumers passing custom `animationVariants` containing multi-function `transform` strings, transform/scale primitives in modal variants, calc-with-mixed-units in animate targets, or who copy-paste the affected motion patterns into their own components — see Consumer Impact)",
|
|
140
|
+
"affects": "`@clicktap/ui/components/Dialog`, `@clicktap/ui/components/ModalOverlay`, `@clicktap/ui/components/Badge`, `@clicktap/ui/components/Loader/CircularEasing`, `@clicktap/ui/components/Loader/Pulse`, and any consumer-side `motion.*` usage on framer-motion 11.x."
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"path": "2026/05/2026-05-03-auth-aware-graphql-client.md",
|
|
144
|
+
"module": "libs/ui",
|
|
145
|
+
"package": "@clicktap/ui",
|
|
146
|
+
"date": "2026-05-03",
|
|
147
|
+
"title": "Auth-aware GraphQL client — `@clicktap/ui/utils/createAuthAwareGraphqlClient`",
|
|
148
|
+
"classification": "IMPROVEMENT",
|
|
149
|
+
"breaking": "No (additive)",
|
|
150
|
+
"affects": "`@clicktap/ui/utils/createAuthAwareGraphqlClient` — new export"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"path": "2026/05/2026-05-01-build-pdp-url-util.md",
|
|
154
|
+
"module": "libs/ui",
|
|
155
|
+
"package": "@clicktap/ui",
|
|
156
|
+
"date": "2026-05-01",
|
|
157
|
+
"title": "`buildPdpUrl` Utility — `@clicktap/ui/utils/buildPdpUrl`",
|
|
158
|
+
"classification": "IMPROVEMENT",
|
|
159
|
+
"breaking": "No (additive)",
|
|
160
|
+
"affects": "`@clicktap/ui/utils/buildPdpUrl` — new export"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"path": "2026/04/ui-2026-04-30-top-down-pdp-option-dependency.md",
|
|
164
|
+
"module": "libs/ui",
|
|
165
|
+
"package": "@clicktap/ui",
|
|
166
|
+
"date": "2026-04-30",
|
|
167
|
+
"title": "Top-Down PDP Option Dependency — `@clicktap/ui/utils/variantOptions`",
|
|
168
|
+
"classification": "IMPROVEMENT",
|
|
169
|
+
"breaking": "No (additive)",
|
|
170
|
+
"affects": "New utility module `@clicktap/ui/utils/variantOptions` (ships generic `filterAvailableOptions`, `findVariant`, `getDownstreamAxisCodes`)"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"path": "2026/04/ui-2026-04-30-prune-invalid-pdp-selections.md",
|
|
174
|
+
"module": "libs/ui",
|
|
175
|
+
"package": "@clicktap/ui",
|
|
176
|
+
"date": "2026-04-30",
|
|
177
|
+
"title": "PDP Option Selection — Conservative Prune Helper (`pruneInvalidSelections`)",
|
|
178
|
+
"classification": "IMPROVEMENT",
|
|
179
|
+
"breaking": "No (additive)",
|
|
180
|
+
"affects": "`@clicktap/ui/utils/variantOptions` — adds `pruneInvalidSelections`"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"path": "2026/04/ui-2026-04-24-image-placeholder-frontend-fallback.md",
|
|
184
|
+
"module": "libs/ui",
|
|
185
|
+
"package": "@clicktap/ui",
|
|
186
|
+
"date": "2026-04-24",
|
|
187
|
+
"title": "`PLACEHOLDER_IMAGE` Export from `@clicktap/ui/utils/placeholder`",
|
|
188
|
+
"classification": "IMPROVEMENT",
|
|
189
|
+
"breaking": "No",
|
|
190
|
+
"affects": "`@clicktap/ui` consumers that render product/category images"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"path": "2026/04/2026-04-17-select-address-input-onchange-key-or-item.md",
|
|
194
|
+
"module": "libs/ui",
|
|
195
|
+
"package": "@clicktap/ui",
|
|
196
|
+
"date": "2026-04-17",
|
|
197
|
+
"title": "Select / AddressInput: `onSelectionChange` / `onChange` callback widened to `Key | T`",
|
|
198
|
+
"classification": "COMPATIBILITY",
|
|
199
|
+
"breaking": "Yes — TypeScript-only. No runtime change; existing handlers still receive the same value at runtime, but strict TS setups fail to compile.",
|
|
200
|
+
"affects": "Frontend apps consuming `@clicktap/ui`'s `Select` and components that re-export its types (`AddressInput`, etc.). Any handler typed as `(value: Key) => void` breaks after the update."
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"path": "2026/03/2026-03-24-modal-overlay-backdrop-dismiss.md",
|
|
204
|
+
"module": "libs/ui",
|
|
205
|
+
"package": "@clicktap/ui",
|
|
206
|
+
"date": "2026-03-24",
|
|
207
|
+
"title": "ModalOverlay: Fix Dismiss on Backdrop Click",
|
|
208
|
+
"classification": "BUGFIX",
|
|
209
|
+
"breaking": "No",
|
|
210
|
+
"affects": "`@clicktap/ui` — `ModalOverlay` component"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"path": "2026/03/2026-03-24-image-dimmed-hidden-onready.md",
|
|
214
|
+
"module": "libs/ui",
|
|
215
|
+
"package": "@clicktap/ui",
|
|
216
|
+
"date": "2026-03-24",
|
|
217
|
+
"title": "Image: dimmed, hidden, and onReady Props",
|
|
218
|
+
"classification": "IMPROVEMENT",
|
|
219
|
+
"breaking": "No",
|
|
220
|
+
"affects": "`@clicktap/ui` — `Image` component"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"path": "2026/02/2026-02-17-select-popover-portal-container-restored.md",
|
|
224
|
+
"module": "libs/ui",
|
|
225
|
+
"package": "@clicktap/ui",
|
|
226
|
+
"date": "2026-02-17",
|
|
227
|
+
"title": "Select popoverPortalContainer Restored",
|
|
228
|
+
"classification": "BUGFIX",
|
|
229
|
+
"breaking": "No",
|
|
230
|
+
"affects": "`@clicktap/ui` Select component, any consumer using Select inside Dialog or Modal"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"path": "2026/02/ui-2026-02-16-env-utils-from-clicktap-ui.md",
|
|
234
|
+
"module": "libs/ui",
|
|
235
|
+
"package": "@clicktap/ui",
|
|
236
|
+
"date": "2026-02-16",
|
|
237
|
+
"title": "Environment Utilities from @clicktap/ui",
|
|
238
|
+
"classification": "IMPROVEMENT",
|
|
239
|
+
"breaking": "No",
|
|
240
|
+
"affects": "All files importing `isDevelopment` / `isProduction` from local `utils/env`"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"path": "2026/01/2026-01-15-input-disable-skeleton.md",
|
|
244
|
+
"module": "libs/ui",
|
|
245
|
+
"package": "@clicktap/ui",
|
|
246
|
+
"date": "2026-01-15",
|
|
247
|
+
"title": "Input disableSkeleton Prop",
|
|
248
|
+
"classification": "IMPROVEMENT",
|
|
249
|
+
"breaking": "No",
|
|
250
|
+
"affects": "`@clicktap/ui`, `apps/frontend`"
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"path": "2026/01/2026-01-14-use-route-hook.md",
|
|
254
|
+
"module": "libs/ui",
|
|
255
|
+
"package": "@clicktap/ui",
|
|
256
|
+
"date": "2026-01-14",
|
|
257
|
+
"title": "useRoute Hook Migration",
|
|
258
|
+
"classification": "IMPROVEMENT",
|
|
259
|
+
"breaking": "No (additive, but recommended migration)",
|
|
260
|
+
"affects": "`@clicktap/ui`, `apps/frontend`"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"path": "2026/01/2026-01-14-external-link-detection.md",
|
|
264
|
+
"module": "libs/ui",
|
|
265
|
+
"package": "@clicktap/ui",
|
|
266
|
+
"date": "2026-01-14",
|
|
267
|
+
"title": "External Link Detection Migration",
|
|
268
|
+
"classification": "IMPROVEMENT",
|
|
269
|
+
"breaking": "No (additive, but requires provider setup for SSR)",
|
|
270
|
+
"affects": "`@clicktap/ui`, `apps/frontend`"
|
|
271
|
+
}
|
|
272
|
+
]
|
package/hooks/useCooldown.d.ts
CHANGED
|
@@ -16,9 +16,16 @@ export interface UseCooldownResult {
|
|
|
16
16
|
/**
|
|
17
17
|
* A headless one-second countdown. `start(n)` sets the remaining seconds and it ticks down to zero.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* Deadline-based (CTAP-1167): `start(n)` stores an absolute deadline and every tick recomputes the
|
|
20
|
+
* remaining time from the clock instead of decrementing. Browsers and WebViews throttle timers in
|
|
21
|
+
* backgrounded tabs (Capacitor apps aggressively), so a decrementing counter falls behind real
|
|
22
|
+
* time — a 60s cooldown resumed after backgrounding would still show tens of seconds long after
|
|
23
|
+
* the real deadline passed. Recomputing makes the first tick after a throttled gap snap to the
|
|
24
|
+
* true remaining time, and `isActiveNow()` compares against the deadline itself so re-entry
|
|
25
|
+
* guards are immune to a stale count.
|
|
26
|
+
*
|
|
27
|
+
* StrictMode-safe: the tick lives in an effect (not a state updater), and the deadline is a ref so
|
|
28
|
+
* the timer chain reads the latest value without re-subscribing each second.
|
|
22
29
|
*/
|
|
23
30
|
export declare function useCooldown(): UseCooldownResult;
|
|
24
31
|
export default useCooldown;
|
package/hooks/useCooldown.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useState as
|
|
1
|
+
"use client";import{useState as f,useRef as d,useCallback as r,useEffect as w}from"react";function M(){const[u,o]=f(0),e=d(0),i=r(n=>{const t=Math.max(0,Math.ceil(n));e.current=t>0?Date.now()+t*1e3:0,o(t)},[]),l=r(()=>{e.current=0,o(0)},[]),m=r(()=>e.current>Date.now(),[]),c=u>0;return w(()=>{if(!c)return;let n;const t=()=>{const s=e.current-Date.now();return s>0?s%1e3||1e3:0},a=()=>{const s=Math.max(0,Math.ceil((e.current-Date.now())/1e3));o(s),s>0&&(n=setTimeout(a,t()))};return n=setTimeout(a,t()),()=>clearTimeout(n)},[c]),{seconds:u,isActive:c,start:i,reset:l,isActiveNow:m}}export{M as default,M as useCooldown};
|