@clicktap/ui 2.0.6 → 2.0.7
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{jsx as e,jsxs as d,Fragment as O}from"react/jsx-runtime";import{Children as V,isValidElement as _,Fragment as
|
|
1
|
+
"use client";import{jsx as e,jsxs as d,Fragment as O}from"react/jsx-runtime";import{Children as V,isValidElement as _,Fragment as q}from"react";import{DisclosureGroup as H,Disclosure as J,Button as L,DisclosurePanel as Q}from"react-aria-components";import{cn as r}from"../../utils/cn.js";import{DownArrow as y}from"../Icon/DownArrow.js";function E(p){return null}function C({children:p,selectionMode:N="single",defaultSelectedKeys:w,defaultExpandedKeys:k,selectedKeys:A,onSelectionChange:I,disallowEmptySelection:v=!1,hideIndicator:D=!1,showDivider:S=!0,dividerProps:K,variant:s,isCompact:i,className:F,itemClasses:n}){const c=V.toArray(p).filter(_),b=(t,l)=>String(t.key??l).replace(/^\.\$/,"").replace(/=2/g,":").replace(/=0/g,"="),j=c.map(b),h=t=>t==="all"?j:t?[...t].map(String):void 0,P=h(w??k)??[],W=h(A);return e(H,{allowsMultipleExpanded:N==="multiple",defaultExpandedKeys:P,expandedKeys:W,onExpandedChange:t=>{const l=new Set([...t].map(String));v&&l.size===0||I?.(l)},className:r("px-0",s==="bordered"&&["px-4 py-4 rounded-xl border-2 border-border-subtle"],s==="shadow"&&["px-4 py-4 rounded-xl bg-surface-subtle shadow-slate-200 border border-border-subtle"],F),children:c.map((t,l)=>{const f=b(t,l),{title:$,subtitle:m,startContent:g,indicator:u,hideIndicator:z,disableIndicatorAnimation:x,isDisabled:B,classNames:o,onPress:G,children:M}=t.props;return d(q,{children:[e(J,{id:f,isDisabled:B,className:r("w-full py-2","data-disabled:pointer-events-none data-disabled:opacity-50",s==="bordered"&&["rounded-xl py-0"],s==="splitted"&&["flex flex-col bg-surface-subtle rounded-xl border border-border-subtle"],i&&"py-0",n?.base,o?.base),children:({isExpanded:a})=>d(O,{children:[e("h2",{"data-open":a||void 0,className:r(n?.heading,o?.heading),children:d(L,{slot:"trigger","data-open":a||void 0,onPress:G,"aria-label":t.props["aria-label"],className:r("w-full h-full flex items-center gap-3 py-0 appearance-none cursor-pointer select-none","border-0 focus-visible:outline-2 focus-visible:outline focus-visible:outline-slate-100","bg-transparent text-inherit",i&&["py-2"],n?.trigger,o?.trigger),children:[g!=null&&e("span",{className:r("shrink-0",n?.startContent,o?.startContent),children:g}),d("span",{className:r("flex-1 text-left",n?.titleWrapper,o?.titleWrapper),children:[e("span",{className:r("block text-xl font-semibold",i&&"text-base",n?.title,o?.title),children:$}),m!=null&&e("span",{className:r("block text-base",i&&"text-sm",n?.subtitle,o?.subtitle),children:m})]}),z||D?null:e("span",{"aria-hidden":"true","data-open":a||void 0,className:r("shrink-0",!x&&"transition-transform duration-200",!x&&a&&"-rotate-180",n?.indicator,o?.indicator),children:typeof u=="function"?e(u,{isOpen:a}):u??e(y,{className:"w-4 h-4"})})]})}),e("div",{className:r("grid transition-[grid-template-rows] duration-200 ease-in-out",a?"grid-rows-[1fr]":"grid-rows-[0fr]"),children:e("div",{className:"overflow-hidden min-h-0",children:e(Q,{className:r(i?"py-1":"py-2",n?.content,o?.content),children:M})})})]})}),S&&l<c.length-1&&e("hr",{className:r("border-solid border-b-0 border-x-0",K?.className??["my-2 border-border-subtle",s==="shadow"&&"border-border"])})]},f)})})}function ee(){return e(y,{className:"w-4 h-4"})}export{C as Accordion,E as AccordionItem,ee as AccordionItemArrow,C as default};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Accordion controlled selection matches authored keys again
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-08-24
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
5
|
+
**Affects:** every controlled or default-expanded `Accordion` — checkout payment method selection, checkout's `defaultExpandedKeys={['cart']}`, totals/discount panel, PDP mobile overview, filter groups.
|
|
6
|
+
**Classification:** BUGFIX
|
|
7
|
+
**Breaking:** No — unless you shipped a workaround that pre-prefixes keys (see crispi note).
|
|
8
|
+
**Ticket:** CTAP-1404
|
|
9
|
+
|
|
10
|
+
## The defect (2.0.x regression from the CTAP-1383 react-aria rewrite)
|
|
11
|
+
|
|
12
|
+
The component derived internal item ids from `Children.toArray(children)`, whose
|
|
13
|
+
keys are NOT the author's keys: React prefixes them (`key="CYBERSOURCE"` arrives
|
|
14
|
+
as `".$CYBERSOURCE"`) and escapes them (`:` → `=2`, `=` → `=0`). Consumer keys
|
|
15
|
+
were only `String()`ed, so:
|
|
16
|
+
|
|
17
|
+
1. `selectedKeys` / `defaultSelectedKeys` / `defaultExpandedKeys` never matched
|
|
18
|
+
any item — nothing opened, nothing highlighted. The checkout payment step's
|
|
19
|
+
method selection "not working" was this.
|
|
20
|
+
2. `onSelectionChange` handed the PREFIXED id back out — crispi's checkout
|
|
21
|
+
dispatched `".$CYBERSOURCE"` as a payment method code to the backend.
|
|
22
|
+
|
|
23
|
+
The heroui accordion this replaced handled keys correctly. Diagnosed by the
|
|
24
|
+
crispi session against the installed 2.0.6 bundle.
|
|
25
|
+
|
|
26
|
+
## The fix
|
|
27
|
+
|
|
28
|
+
Internal ids now live in the author's key space: the `.$` prefix is stripped AND
|
|
29
|
+
React's key escaping is reversed (`=2` → `:`, `=0` → `=` — without the unescape,
|
|
30
|
+
`Module:Entity`-style keys would still mangle). The same author-space id is used
|
|
31
|
+
as the `Disclosure` id, so what react-aria reports through `onExpandedChange`
|
|
32
|
+
round-trips with no output translation. `"all"` and unkeyed children (positional
|
|
33
|
+
`".0"` ids) behave as before.
|
|
34
|
+
|
|
35
|
+
## Consumer checklist
|
|
36
|
+
|
|
37
|
+
1. Take the release; no call-site changes needed — controlled accordions start
|
|
38
|
+
working as written.
|
|
39
|
+
2. **Delete compensating shims.** crispi: `libs/crispi-ui/.../Accordion.tsx`
|
|
40
|
+
wrapper (crispi-monorepo `7a44704f0`) must be REMOVED when taking this
|
|
41
|
+
release — it translates keys into the prefixed space, which no longer
|
|
42
|
+
exists, so keeping it reintroduces the bug in the other direction. Check the
|
|
43
|
+
shim's own escape handling is not needed elsewhere (this fix also covers
|
|
44
|
+
escaped keys, which a bare `.$`-strip shim does not).
|
|
45
|
+
3. If any code path stored or transmitted a prefixed id (`.$…`) — crispi saw
|
|
46
|
+
them reach the backend as payment codes — check persisted data for the
|
|
47
|
+
`.$` prefix.
|
|
48
|
+
|
|
49
|
+
Regression tests ship with the component (`Accordion.test.tsx`), proven to fail
|
|
50
|
+
4/6 against the unfixed 2.0.6 behavior.
|
|
@@ -32,5 +32,6 @@ For migrations affecting the frontend app, see [frontend migrations](../../../..
|
|
|
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
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
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* |
|
|
35
|
+
| 2026-08-24 | [Accordion controlled selection matches authored keys again](./2026/08/ui-2026-08-24-accordion-author-key-space.md) | No | CTAP-1383 regression (CTAP-1404) |
|
|
35
36
|
|
|
36
37
|
↔ = cross-app migration (has counterpart in frontend app)
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"path": "2026/08/ui-2026-08-23-use-client-propagates-to-barrels.md",
|
|
4
|
+
"module": "libs/frontend-modules/ui",
|
|
5
|
+
"package": "@clicktap/ui",
|
|
6
|
+
"date": "2026-08-23",
|
|
7
|
+
"title": "'use client' now reaches the re-export barrels",
|
|
8
|
+
"classification": "BUGFIX (packaging)",
|
|
9
|
+
"breaking": "No.",
|
|
10
|
+
"affects": "every emitted `components/**/index.js`; `Checkbox` and `RadioGroup` sources; the build's directive verification"
|
|
11
|
+
},
|
|
2
12
|
{
|
|
3
13
|
"path": "2026/08/ui-2026-08-22-react-aria-moves-as-one-version-set.md",
|
|
4
14
|
"module": "libs/frontend-modules/ui",
|