@clicktap/ui 2.4.4 → 2.4.6
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/Accordion/Accordion.d.ts +7 -16
- package/components/Accordion/Accordion.js +1 -1
- package/components/Checkbox/Checkbox.js +1 -1
- package/components/CreditCardExpirationInput/CreditCardExpirationInput.js +1 -1
- package/components/CreditCardInput/CreditCardInput.js +1 -1
- package/components/DateInput/DateInput.js +1 -1
- package/components/DobInput/DobInput.js +1 -1
- package/components/Input/Input.js +1 -1
- package/components/NumberInput/NumberInput.js +1 -1
- package/components/Radio/Radio.js +1 -1
- package/components/TimeInput/TimeInput.js +1 -1
- package/docs/migrations/2026/10/ui-2026-10-06-accordion-mounts-collapsed-content-on-expand.md +93 -0
- package/docs/migrations/2026/10/ui-2026-10-06-invalid-styling-keys-on-data-invalid.md +34 -0
- package/docs/migrations/index.json +20 -0
- package/package.json +1 -1
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
import { ComponentType, ReactNode } from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* Native accordion on react-aria-components Disclosure (CTAP-1383).
|
|
4
|
-
*
|
|
5
|
-
* Previously a styled wrapper around @heroui/accordion — the ONLY
|
|
6
|
-
* initially-rendered @heroui consumer (the PLP filter sidebar), which pulled
|
|
7
|
-
* the whole @heroui system + theme (~25 KiB gz) into every page's initial JS.
|
|
8
|
-
* react-aria-components is already this library's base, so the rewrite costs
|
|
9
|
-
* nothing new. API-compatible with the call sites this repo uses:
|
|
10
|
-
* selectionMode / defaultSelectedKeys ("all" included), per-item title,
|
|
11
|
-
* subtitle, startContent, indicator (component, receives nothing, rotates on
|
|
12
|
-
* open), classNames slots, showDivider (an <hr> between items — consumers
|
|
13
|
-
* hide it with [&_hr]:hidden), onPress, and the `data-open` attribute on
|
|
14
|
-
* heading/trigger/indicator that consumers style with data-[open=true]:.
|
|
15
|
-
* Height animates with the CSS grid-rows trick — no animation runtime.
|
|
16
|
-
*/
|
|
17
2
|
type ItemSlotClassNames = {
|
|
18
3
|
base?: string;
|
|
19
4
|
heading?: string;
|
|
@@ -38,6 +23,8 @@ export type AccordionItemProps = {
|
|
|
38
23
|
hideIndicator?: boolean;
|
|
39
24
|
disableIndicatorAnimation?: boolean;
|
|
40
25
|
isDisabled?: boolean;
|
|
26
|
+
/** Overrides the Accordion's keepContentMounted for this item. */
|
|
27
|
+
keepContentMounted?: boolean;
|
|
41
28
|
textValue?: string;
|
|
42
29
|
'aria-label'?: string;
|
|
43
30
|
classNames?: ItemSlotClassNames;
|
|
@@ -53,6 +40,10 @@ export type AccordionProps = {
|
|
|
53
40
|
selectedKeys?: 'all' | Iterable<string>;
|
|
54
41
|
onSelectionChange?: (keys: Set<string>) => void;
|
|
55
42
|
disallowEmptySelection?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Keep every collapsed item's content mounted (and server-rendered). Off by
|
|
45
|
+
* default: a collapsed item renders its content only while expanded.
|
|
46
|
+
*/
|
|
56
47
|
keepContentMounted?: boolean;
|
|
57
48
|
/** Hide every item's indicator (heroui group-level prop). */
|
|
58
49
|
hideIndicator?: boolean;
|
|
@@ -73,6 +64,6 @@ export type AccordionProps = {
|
|
|
73
64
|
* did not change.
|
|
74
65
|
*/
|
|
75
66
|
export declare function AccordionItem(_props: AccordionItemProps): null;
|
|
76
|
-
export declare function Accordion({ children, selectionMode, defaultSelectedKeys, defaultExpandedKeys, selectedKeys, onSelectionChange, disallowEmptySelection, hideIndicator: groupHideIndicator, showDivider, dividerProps, variant, isCompact, className, itemClasses, }: AccordionProps): import("react/jsx-runtime").JSX.Element;
|
|
67
|
+
export declare function Accordion({ children, selectionMode, defaultSelectedKeys, defaultExpandedKeys, selectedKeys, onSelectionChange, disallowEmptySelection, keepContentMounted: groupKeepContentMounted, hideIndicator: groupHideIndicator, showDivider, dividerProps, variant, isCompact, className, itemClasses, }: AccordionProps): import("react/jsx-runtime").JSX.Element;
|
|
77
68
|
export default Accordion;
|
|
78
69
|
export declare function AccordionItemArrow(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as
|
|
1
|
+
"use client";import{jsx as e,jsxs as b,Fragment as G}from"react/jsx-runtime";import{Children as V,isValidElement as q,Fragment as H,useState as D,useEffect as J}from"react";import{DisclosureGroup as Q,Disclosure as R,Button as U,DisclosurePanel as X}from"react-aria-components";import{cn as r}from"../../utils/cn.js";import{DownArrow as M}from"../Icon/DownArrow.js";const Y=200;function oe(n){return null}function le({children:n,selectionMode:f="single",defaultSelectedKeys:m,defaultExpandedKeys:h,selectedKeys:d,onSelectionChange:c,disallowEmptySelection:g=!1,keepContentMounted:y=!1,hideIndicator:s=!1,showDivider:K=!0,dividerProps:P,variant:u,isCompact:p,className:T,itemClasses:o}){const x=V.toArray(n).filter(q),w=(t,a)=>String(t.key??a).replace(/^\.\$/,"").replace(/=2/g,":").replace(/=0/g,"="),F=x.map(w),k=t=>t==="all"?F:t?[...t].map(String):void 0,W=k(m??h)??[],j=k(d);return e(Q,{allowsMultipleExpanded:f==="multiple",defaultExpandedKeys:W,expandedKeys:j,onExpandedChange:t=>{const a=new Set([...t].map(String));g&&a.size===0||c?.(a)},className:r("px-0",u==="bordered"&&["px-4 py-4 rounded-xl border-2 border-border-subtle"],u==="shadow"&&["px-4 py-4 rounded-xl bg-surface-subtle border border-border-subtle"],T),children:x.map((t,a)=>{const A=w(t,a),{title:L,subtitle:S,startContent:I,indicator:N,hideIndicator:O,disableIndicatorAnimation:v,isDisabled:_,keepContentMounted:$,classNames:l,onPress:z,children:B}=t.props;return b(H,{children:[e(R,{id:A,isDisabled:_,className:r("w-full py-2","data-disabled:pointer-events-none data-disabled:opacity-50",u==="bordered"&&["rounded-xl py-0"],u==="splitted"&&["flex flex-col bg-surface-subtle rounded-xl border border-border-subtle"],p&&"py-0",o?.base,l?.base),children:({isExpanded:i})=>b(G,{children:[e("h2",{"data-open":i||void 0,className:r(o?.heading,l?.heading),children:b(U,{slot:"trigger","data-open":i||void 0,onPress:z,"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-border-subtle","bg-transparent text-inherit",p&&["py-2"],o?.trigger,l?.trigger),children:[I!=null&&e("span",{className:r("shrink-0",o?.startContent,l?.startContent),children:I}),b("span",{className:r("flex-1 text-left",o?.titleWrapper,l?.titleWrapper),children:[e("span",{className:r("block text-xl font-semibold",p&&"text-base",o?.title,l?.title),children:L}),S!=null&&e("span",{className:r("block text-base",p&&"text-sm",o?.subtitle,l?.subtitle),children:S})]}),O||s?null:e("span",{"aria-hidden":"true","data-open":i||void 0,className:r("shrink-0",!v&&"transition-transform duration-200",!v&&i&&"-rotate-180",o?.indicator,l?.indicator),children:typeof N=="function"?e(N,{isOpen:i}):N??e(M,{className:"w-4 h-4"})})]})}),e(Z,{isExpanded:i,keepContentMounted:$??y,className:r(p?"py-1":"py-2",o?.content,l?.content),children:B})]})}),K&&a<x.length-1&&e("hr",{className:r("border-solid border-b-0 border-x-0",P?.className??["my-2 border-border-subtle",u==="shadow"&&"border-border"])})]},A)})})}function Z({isExpanded:n,keepContentMounted:f,className:m,children:h}){const[d,c]=D(!1),[g,y]=D(n);return g!==n&&(y(n),c(!n)),J(()=>{if(!d)return;const s=setTimeout(()=>c(!1),Y+50);return()=>clearTimeout(s)},[d]),e("div",{className:r("grid transition-[grid-template-rows] duration-200 ease-in-out",n?"grid-rows-[1fr]":"grid-rows-[0fr]"),onTransitionEnd:s=>{s.target===s.currentTarget&&!n&&c(!1)},children:e("div",{className:"overflow-hidden min-h-0",children:e(X,{className:m,children:f||n||d?h:null})})})}function ae(){return e(M,{className:"w-4 h-4"})}export{le as Accordion,oe as AccordionItem,ae as AccordionItemArrow,le as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as n,jsxs as c,Fragment as h}from"react/jsx-runtime";import{Checkbox as s}from"react-aria-components";import{cn as l}from"../../utils/cn.js";function x({control:e,isHovered:
|
|
1
|
+
"use client";import{jsx as n,jsxs as c,Fragment as h}from"react/jsx-runtime";import{Checkbox as s}from"react-aria-components";import{cn as l}from"../../utils/cn.js";function x({control:e,isHovered:a,isFocused:u,isDisabled:t,isIndeterminate:r,isInvalid:o,isSelected:b,isPressed:f,classNames:d,...g}){return e?typeof e=="function"?e({isHovered:a,isFocused:u,isDisabled:t,isIndeterminate:r,isInvalid:o,isSelected:b,isPressed:f,...g}):e:n("div",{className:l("flex items-center justify-center","w-6 h-6","border border-solid border-border rounded","transition-all duration-200 ease-in-out","checkbox-control",a&&["border-border-emphasis"],u&&["border-border-emphasis outline-2 outline outline-border-subtle"],(t||t&&r)&&["border-border-subtle bg-surface-subtle"],o&&["bg-surface-subtle text-danger border-danger-soft"],o&&a&&["border-danger"],o&&u&&["border-danger outline-danger-ring"],o&&b&&r&&["bg-danger-soft border-danger-soft"],o&&b&&r&&f&&["bg-danger border-danger"],(b||r)&&["border-border bg-border"],(b||r)&&f&&["border-border-emphasis bg-border-emphasis"],d?.control),children:n("svg",{viewBox:"0 0 18 18","aria-hidden":"true",style:{strokeDasharray:"22px",strokeDashoffset:b||r?44:66},className:l("w-4 h-4 fill-none","stroke-white stroke-[3px]","transition-all duration-200 ease-in-out",t&&r&&["stroke-none fill-border"],r&&["stroke-none fill-white"]),children:r?n("rect",{x:1,y:7.5,width:15,height:3}):n("polyline",{points:"1 9 7 14 15 4"})})})}function w({children:e,slots:a,className:u,classNames:t,...r}){return n(s,{className:l("flex items-center gap-2 cursor-pointer","text-xs text-fg-muted forced-color-adjust-none disabled:text-fg-subtle disabled:cursor-not-allowed group","data-[invalid]:text-danger-soft",u),...r,children:o=>c(h,{children:[n(x,{control:a?.control,classNames:t,...o}),typeof e=="function"?e(o):e]})})}export{w as Checkbox,w as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as N,jsx as
|
|
1
|
+
"use client";import{jsxs as N,jsx as a}from"react/jsx-runtime";import{N as V}from"../../assets/react-number-format.es-Bf_lGveD.js";import{TextField as v,Label as I,Text as C,FieldError as F,Input as $}from"react-aria-components";import{useState as j}from"react";import{cn as t}from"../../utils/cn.js";function w({className:l,...o}){return a($,{className:t("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-surface","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","data-[invalid]:border-danger-soft data-[invalid]:bg-danger-surface data-[invalid]:text-danger","data-[invalid]:hover:border-danger data-[invalid]:focus:border-danger data-[invalid]:focus:outline-danger-ring",l),...o})}function L({label:l,description:o,errorMessage:d,placeholder:i,value:s,className:u,classNames:n,onChange:f,...m}){const[b,c]=j(""),x=s??b,g=r=>{if(r==="")return"";let e=r.substring(0,2);const h=r.substring(2,4);return e.length===1&&Number(e[0])>1?e=`0${e[0]}`:e.length===2&&(Number(e)===0?e="01":Number(e)>12&&(e="12")),`${e}/${h}`},p=r=>{c(r.formattedValue),f?.(r.formattedValue)};return N(v,{className:t("flex flex-col w-full text-fg",u),...m,children:[a(I,{className:t("flex text-fg-muted text-xs",n?.label),children:l}),a(V,{format:g,customInput:w,className:t(n?.input),placeholder:i,value:x,onValueChange:p}),o&&a(C,{className:t("flex text-fg-muted text-sm",n?.description),slot:"description",children:o}),a(F,{className:t("flex text-danger-soft text-sm",n?.error),children:d})]})}export{L as CreditCardExpirationInput,L as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as I,jsx as l}from"react/jsx-runtime";import{useState as N}from"react";import{N as P}from"../../assets/react-number-format.es-Bf_lGveD.js";import{TextField as j,Label as w,Text as L,FieldError as T,Input as k}from"react-aria-components";import{cn as
|
|
1
|
+
"use client";import{jsxs as I,jsx as l}from"react/jsx-runtime";import{useState as N}from"react";import{N as P}from"../../assets/react-number-format.es-Bf_lGveD.js";import{TextField as j,Label as w,Text as L,FieldError as T,Input as k}from"react-aria-components";import{cn as r}from"../../utils/cn.js";const m=a=>{const d=[{regex:/^4[0-9]{0,15}/,format:"#### #### #### ####"},{regex:/^5[1-5][0-9]{0,14}/,format:"#### #### #### ####"},{regex:/^3[47][0-9]{0,13}/,format:"#### ###### #####"},{regex:/^6(?:011|5[0-9]{2})[0-9]{0,12}/,format:"#### #### #### ####"},{regex:/^3(?:0[0-5]|[68][0-9])[0-9]{0,11}/,format:"#### ###### ####"},{regex:/^(?:2131|1800|35\d{3})\d{0,11}/,format:"#### #### #### ####"}].find(f=>f.regex.test(a));return d?d.format:"#### #### #### #### ###"};function y({className:a,...o}){return l(k,{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-surface","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","data-[invalid]:border-danger-soft data-[invalid]:bg-danger-surface data-[invalid]:text-danger","data-[invalid]:hover:border-danger data-[invalid]:focus:border-danger data-[invalid]:focus:outline-danger-ring",a),...o})}function z({label:a,description:o,errorMessage:d,placeholder:f,value:g,onChange:x,className:b,classNames:s,...p}){const[h,v]=N(""),V=g??h,F=i=>{if(i==="")return"";const e=i.replace(/\s+/g,""),u=m(e);let n="",t=0;for(let c=0;c<u.length;c+=1)if(u[c]==="#")if(t<e.length)n+=e[t],t+=1;else break;else n+=u[c];return n},C=i=>{const e=i.value.replace(/\s+/g,""),n=m(e).replace(/[^#]/g,"").length,t=e.slice(0,n);v(t),x?.(t)};return I(j,{className:r("flex flex-col w-full text-fg",b),...p,children:[l(w,{className:r("flex text-fg-muted text-sm",s?.label),children:a}),l(P,{value:V,format:F,customInput:y,className:r(s?.input),placeholder:f,onValueChange:C}),o&&l(L,{className:r("flex text-fg-muted text-sm",s?.description),slot:"description",children:o}),l(T,{className:r("flex text-danger-soft text-sm",s?.error),children:d})]})}export{z as CreditCardInput,z as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as s,jsx as
|
|
1
|
+
"use client";import{jsxs as s,jsx as a}from"react/jsx-runtime";import{DateField as u,Label as f,DateInput as c,DateSegment as b,Text as g,FieldError as x}from"react-aria-components";import{cn as e}from"../../utils/cn.js";function v({label:d,description:r,errorMessage:i,className:o,classNames:t,...n}){return s(u,{className:e("text-fg",o),...n,children:[a(f,{className:e("flex text-fg-muted text-xs",t?.label),children:d}),a(c,{className:e("flex items-center","border-solid border border-border rounded-md","text-sm text-fg","h-10 px-1 py-0 m-0 w-full","bg-surface","transition-all duration-200 ease-in-out","hover:border-border-emphasis","focus-within:outline-2 focus-within:outline focus-within:outline-border-subtle focus-within:border-border-emphasis","disabled:border-border-subtle disabled:bg-surface-subtle","data-[invalid]:border-danger-soft data-[invalid]:bg-danger-surface data-[invalid]:text-danger","data-[invalid]:hover:border-danger data-[invalid]:focus-within:border-danger data-[invalid]:focus-within:outline-danger-ring",t?.input),children:l=>a(b,{segment:l,className:e("p-1 tabular-nums text-end text-fg","data-[invalid]:text-danger-soft","disabled:cursor-default disabled:select-none disabled:text-fg-subtle","focus:text-fg focus:bg-border-subtle focus:outline-0 focus:rounded-md focus:caret-transparent focus:data-[invalid]:bg-danger-soft focus:data-[invalid]:text-fg-inverse","type-literal:p-0","data-[placeholder]:text-fg-subtle data-[placeholder]:data-[invalid]:text-danger-soft data-[placeholder]:data-[invalid]:focus:text-fg-inverse","aria-[readonly]:focus-visible:outline aria-[readonly]:focus-visible:outline-fg-muted aria-[readonly]:focus-visible:outline-1","aria-[readonly]:focus:outline aria-[readonly]:focus:outline-fg-muted aria-[readonly]:focus:bg-transparent aria-[readonly]:focus:outline-2",t?.segment)})}),r&&a(g,{className:e("flex text-fg-muted text-sm",t?.description),slot:"description",children:r}),a(x,{className:e("flex text-danger-soft text-sm",t?.error),children:i})]})}export{v as DateInput,v as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as j,jsx as
|
|
1
|
+
"use client";import{jsxs as j,jsx as a}from"react/jsx-runtime";import{useId as w,useState as C}from"react";import{TextField as k,Label as y,FieldError as A,Input as B}from"react-aria-components";import{N as D}from"../../assets/react-number-format.es-Bf_lGveD.js";import{cn as r}from"../../utils/cn.js";function E({className:o,...s}){return a(B,{className:r("peer h-11",o),...s})}function z({label:o,description:s,errorMessage:u,type:m,className:p,classNames:l,id:f,value:g,onChange:h,...x}){const c=w(),[V,v]=C(""),I=g??V,F=e=>{if(e==="")return"";const b=e.replace(/\s+/g,""),n="##-##-####";let d="",i=0;for(let t=0;t<n.length;t+=1)if(n[t]==="#")if(i<b.length)d+=b[i],i+=1;else break;else d+=n[t];return d},N=e=>{v(e.formattedValue),h?.(e.formattedValue)};return j(k,{className:r("flex flex-col w-full text-fg",p),type:m,...x,children:[a(y,{className:r("flex text-fg-muted text-xs",l?.label),htmlFor:f||c,children:o}),a(D,{id:f||c,value:I,format:F,customInput:E,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-surface","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","data-[invalid]:border-danger-soft data-[invalid]:bg-danger-surface data-[invalid]:text-danger","data-[invalid]:hover:border-danger data-[invalid]:focus:border-danger data-[invalid]:focus:outline-danger-ring",l?.input),onValueChange:N}),u&&a(A,{className:r(l?.error),children:u})]})}export{z as DobInput,z as default};
|
|
@@ -1 +1 @@
|
|
|
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:
|
|
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:a,description:i,errorMessage:m,placeholder:p,className:u,classNames:o,disableSkeleton:x,type:c,...h},b)=>{const g=S(),l=c==="password",[n,w]=N(!1);return!g&&!x?s("div",{className:r("flex flex-col w-full text-fg",u),children:[a?e(f,{className:r("flex text-fg-muted text-xs",o?.label),children:a}):null,e(E,{className:o?.skeleton})]}):s(v,{className:r("flex flex-col w-full text-fg",u),type:l?n?"text":"password":c,...h,children:[e(f,{className:r("flex text-fg-muted text-xs",o?.label),children:a}),s("div",{className:"relative",children:[e(k,{ref:b,placeholder:p,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-surface","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","data-[invalid]:border-danger-soft data-[invalid]:bg-danger-surface data-[invalid]:text-danger","data-[invalid]:hover:border-danger data-[invalid]:focus:border-danger data-[invalid]:focus:outline-danger-ring",l&&"pr-10",o?.input),...t}),l&&e("button",{type:"button",className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-fg-subtle hover:text-fg-muted bg-transparent border-none cursor-pointer select-none",onMouseDown:d=>d.preventDefault(),onClick:()=>w(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"})})]}),i&&e(L,{className:r("flex text-fg-muted text-sm",o?.description),slot:"description",children:i}),e(C,{className:r("flex text-danger-soft text-sm",o?.error),children:m})]})});export{W as Input,W as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as
|
|
1
|
+
"use client";import{jsxs as l,jsx as e}from"react/jsx-runtime";import{NumberField as p,Label as h,Group as m,Button as u,Input as x,Text as v,FieldError as w}from"react-aria-components";import{cn as r}from"../../utils/cn.js";const k=e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:e("path",{d:"M5 12H19",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})}),y=e("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:e("path",{d:"M12 5V19M5 12H19",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})});function L({label:b,description:d,errorMessage:c,isInvalid:n,isReadOnly:a,slots:i,className:g,classNames:o,...f}){const t=["group-hover:border-border-emphasis","group-disabled:border-border-subtle","group-data-[invalid]:border-danger-soft group-data-[invalid]:bg-danger-surface group-data-[invalid]:text-danger","group-data-[invalid]:group-hover:border-danger","group-data-[invalid]:group-focus:border-danger"],s=["flex items-center justify-center shrink-0","rounded-md border-solid border","font-semibold text-sm","w-10 h-10 py-0 px-0 cursor-pointer disabled:cursor-default","transition-all duration-200 ease-in-out","focus:outline-2 focus:outline focus:outline-border-subtle pressed:scale-95","bg-transparent hover:bg-transparent focus:bg-transparent disabled:bg-transparent","border-border hover:border-border-emphasis focus:border-border-emphasis disabled:border-border-subtle","text-fg disabled:text-fg-muted","group-aria-readonly:bg-surface-subtle group-aria-readonly:text-fg-muted group-aria-readonly:border-border-subtle group-aria-readonly:cursor-default"];return l(p,{isInvalid:n,isReadOnly:a,className:r("flex flex-col w-full",g),...f,children:[e(h,{className:r("flex text-fg-muted text-sm",o?.label),children:b}),l(m,{isInvalid:n,"aria-readonly":a,className:r("flex rounded-md group","focus-within:outline-2 focus-within:outline focus-within:outline-border-subtle","focus-within:data-[invalid]:outline-2 focus-within:data-[invalid]:outline focus-within:data-[invalid]:outline-border-subtle","disabled:bg-surface-subtle",o?.group),children:[e(u,{slot:"decrement",className:r(s,t,"border-r-0 rounded-r-none",o?.decrementBtn),children:i?.decrementIcon||k}),e(x,{className:r("border-solid border border-border text-center","text-sm text-fg placeholder-fg-subtle","h-10 px-2 py-0 m-0 w-full","bg-surface","transition-all duration-200 ease-in-out","hover:border-border-emphasis","focus:outline-0 focus:border-border-emphasis","disabled:border-border-subtle disabled:bg-surface-subtle","data-[invalid]:border-danger-soft data-[invalid]:bg-danger-surface data-[invalid]:text-danger","data-[invalid]:hover:border-danger data-[invalid]:focus:border-danger",t,o?.input)}),e(u,{slot:"increment",className:r(s,t,"border-l-0 rounded-l-none",o?.incrementBtn),children:i?.incrementIcon||y})]}),d&&e(v,{className:r("flex text-fg-muted text-sm",o?.description),slot:"description",children:d}),e(w,{className:r("flex text-danger-soft text-sm",o?.error),children:c})]})}export{L as NumberInput,L as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as r,jsxs as g,Fragment as v}from"react/jsx-runtime";import{Radio as p}from"react-aria-components";import{cn as s}from"../../utils/cn.js";function m({control:a,classNames:i,isHovered:d,isFocused:t,isFocusVisible:n,isDisabled:e,isInvalid:u,isSelected:o,isPressed:l,isReadOnly:b,isRequired:f,defaultChildren:h,...x}){const c={isHovered:d,isFocused:t,isFocusVisible:n,isDisabled:e,isInvalid:u,isSelected:o,isPressed:l,isReadOnly:b,isRequired:f};return a?typeof a=="function"?a(c):a:r("div",{"data-hovered":d,"data-focused":t,"data-disabled":e,"data-invalid":u,"data-selected":o,"data-pressed":l,className:s("flex items-center justify-center w-6 h-6 border-solid border border-border ransition-all duration-300 ease rounded-full",'data-[hovered="true"]:border-border-emphasis','data-[focused="true"]:border-border-emphasis data-[focused="true"]:outline-2 data-[focused="true"]:outline data-[focused="true"]:outline-border-subtle','data-[disabled="true"]:border-border-subtle data-[disabled="true"]:bg-surface-subtle','data-[invalid="true"]:bg-danger-surface data-[invalid="true"]:text-danger data-[invalid="true"]:border-danger-soft','data-[invalid="true"]:data-[disabled="true"]:border-danger-ring data-[invalid="true"]:data-[disabled="true"]:bg-danger-surface','data-[invalid="true"]:data-[hovered="true"]:border-danger','data-[invalid="true"]:data-[focused="true"]:border-danger data-[invalid="true"]:data-[focused="true"]:outline-danger-ring','data-[invalid="true"]:data-[selected="true"]:bg-danger-surface data-[invalid="true"]:data-[selected="true"]:border-danger-soft','data-[invalid="true"]:data-[pressed="true"]:bg-danger data-[invalid="true"]:data-[pressed="true"]:border-danger',i?.control),children:r("div",{"data-invalid":u,className:s('w-3 h-3 rounded-full bg-surface-inverse opacity-0 transition-all duration-300 ease data-[invalid="true"]:bg-danger-soft',{"opacity-100":o})})})}function N({children:a,slots:i,className:d,classNames:t,...n}){return r(p,{className:s("flex items-center gap-2 group","data-[invalid]:text-danger-soft data-[invalid]:disabled:text-red-300","disabled:text-fg-subtle",d),...n,children:e=>g(v,{children:[r(m,{control:i?.control,classNames:t,...e}),typeof a=="function"?a(e):a]})})}export{N as Radio,N as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsxs as s,jsx as
|
|
1
|
+
"use client";import{jsxs as s,jsx as a}from"react/jsx-runtime";import{TimeField as u,Label as f,DateInput as c,DateSegment as b,Text as g,FieldError as x}from"react-aria-components";import{cn as e}from"../../utils/cn.js";function v({label:d,description:r,errorMessage:i,className:o,classNames:t,...n}){return s(u,{className:e("text-fg",o),...n,children:[a(f,{className:e("flex text-fg-muted text-sm",t?.label),children:d}),a(c,{className:e("flex items-center","border-solid border border-border rounded-md","text-sm text-fg","h-10 px-1 py-0 m-0 w-full","bg-surface","transition-all duration-200 ease-in-out","hover:border-border-emphasis","focus-within:outline-2 focus-within:outline focus-within:outline-border-subtle focus-within:border-border-emphasis","disabled:border-border-subtle disabled:bg-surface-subtle","data-[invalid]:border-danger-soft data-[invalid]:bg-danger-surface data-[invalid]:text-danger","data-[invalid]:hover:border-danger data-[invalid]:focus-within:border-danger data-[invalid]:focus-within:outline-danger-ring",t?.input),children:l=>a(b,{segment:l,className:e("p-1 tabular-nums text-end text-fg","data-[invalid]:text-danger-soft","disabled:cursor-default disabled:select-none disabled:text-fg-subtle","focus:text-fg focus:bg-border-subtle focus:outline-0 focus:rounded-md focus:caret-transparent focus:data-[invalid]:bg-danger-soft focus:data-[invalid]:text-fg-inverse","type-literal:p-0.5","data-[placeholder]:text-fg-subtle data-[placeholder]:data-[invalid]:text-danger-soft data-[placeholder]:data-[invalid]:focus:text-fg-inverse","aria-[readonly]:focus-visible:outline aria-[readonly]:focus-visible:outline-fg-muted aria-[readonly]:focus-visible:outline-1","aria-[readonly]:focus:outline aria-[readonly]:focus:outline-fg-muted aria-[readonly]:focus:bg-transparent aria-[readonly]:focus:outline-2",t?.segment)})}),r&&a(g,{className:e("flex text-fg-muted text-sm",t?.description),slot:"description",children:r}),a(x,{className:e("flex text-danger-soft text-sm",t?.error),children:i})]})}export{v as TimeInput,v as default};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# `Accordion` mounts a collapsed item's content only when it expands
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-10-06
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
5
|
+
**Affects:** `components/Accordion` (`Accordion`, `AccordionItem`)
|
|
6
|
+
**Classification:** BUGFIX
|
|
7
|
+
**Breaking:** No API change. ⚠️ Behavior change for any consumer that relies on collapsed content being in the server-rendered HTML, findable with the browser's find-in-page, or keeping its state across a collapse. Pass `keepContentMounted` there.
|
|
8
|
+
**Ticket:** CTAP-2217
|
|
9
|
+
|
|
10
|
+
## Dependencies
|
|
11
|
+
|
|
12
|
+
*None*
|
|
13
|
+
|
|
14
|
+
## Summary
|
|
15
|
+
|
|
16
|
+
The react-aria `Accordion` that replaced heroui's in `@clicktap/ui` 2.0 rendered every item's content,
|
|
17
|
+
expanded or not, and hid collapsed items with CSS only. Collapsed content mounted, ran its effects and
|
|
18
|
+
queries, and filled the DOM. One consumer's page, with a data-fetching panel per group and nested
|
|
19
|
+
accordions, sent 520 GraphQL requests and rendered about 72,000 hidden DOM nodes on load. heroui never
|
|
20
|
+
mounted a collapsed item unless `keepContentMounted` was set, and `AccordionProps` kept declaring that
|
|
21
|
+
prop, but the component ignored it.
|
|
22
|
+
|
|
23
|
+
The default is now heroui's: a collapsed item's content is not rendered. It mounts when the item expands,
|
|
24
|
+
stays mounted while the collapse transition runs, then unmounts. `keepContentMounted` works again.
|
|
25
|
+
|
|
26
|
+
## Changes
|
|
27
|
+
|
|
28
|
+
| | Before | After |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| Collapsed item, default | Content mounted, hidden by CSS | Content not rendered |
|
|
31
|
+
| Expanding | Already mounted | Content mounts |
|
|
32
|
+
| Collapsing | Stays mounted | Unmounts once the height transition ends (or after 250 ms) |
|
|
33
|
+
| `keepContentMounted` on `Accordion` | Accepted, ignored | Every item's content always mounted, as before this fix |
|
|
34
|
+
| `keepContentMounted` on `AccordionItem` | Not a prop | Overrides the `Accordion`'s value for that item, in either direction |
|
|
35
|
+
|
|
36
|
+
The panel element itself (`DisclosurePanel`, the target of the trigger's `aria-controls`) is still always
|
|
37
|
+
rendered; only its children are conditional.
|
|
38
|
+
|
|
39
|
+
**Source**: `libs/frontend-modules/ui/src/components/Accordion/Accordion.tsx` (`AccordionPanel`)
|
|
40
|
+
|
|
41
|
+
## Migrate
|
|
42
|
+
|
|
43
|
+
Most accordions need nothing: menus, filters, cookie categories and checkout sections are interactive
|
|
44
|
+
content that nobody needs before it is opened. Pass `keepContentMounted` where one of these holds.
|
|
45
|
+
|
|
46
|
+
1. **The content must be in the initial HTML**, typically for search engines: FAQ answers, product
|
|
47
|
+
details, specifications.
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<Accordion keepContentMounted>
|
|
51
|
+
{faqs.map((faq) => (
|
|
52
|
+
<AccordionItem key={faq.id} title={faq.question}>
|
|
53
|
+
{faq.answer}
|
|
54
|
+
</AccordionItem>
|
|
55
|
+
))}
|
|
56
|
+
</Accordion>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The platform's reference storefront does this in `apps/frontend/components/FAQ/FAQ.tsx`.
|
|
60
|
+
|
|
61
|
+
2. **State inside the panel must survive a collapse**: a half-filled form, a payment widget that
|
|
62
|
+
initializes once, a nested accordion's open item. Set it on the whole accordion or on just that
|
|
63
|
+
item:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
<Accordion>
|
|
67
|
+
<AccordionItem key="card" title="Card" keepContentMounted>
|
|
68
|
+
<CardForm />
|
|
69
|
+
</AccordionItem>
|
|
70
|
+
<AccordionItem key="paypal" title="PayPal">
|
|
71
|
+
<PayPalButton />
|
|
72
|
+
</AccordionItem>
|
|
73
|
+
</Accordion>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
An item can also opt out of a group-level `keepContentMounted` with `keepContentMounted={false}`.
|
|
77
|
+
|
|
78
|
+
3. **Code that reads collapsed content from the DOM** (a test that queries a collapsed item's text, a
|
|
79
|
+
script that measures it) must expand the item first, or the accordion must keep its content mounted.
|
|
80
|
+
|
|
81
|
+
Find your call sites:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
grep -rn '<Accordion\b' apps/ libs/ --include=*.tsx
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Verify
|
|
88
|
+
|
|
89
|
+
- With the default, open a page with an accordion and search the page source (view-source, not the
|
|
90
|
+
inspector) for text from a collapsed item: it is absent. Expanding the item renders it.
|
|
91
|
+
- With `keepContentMounted`, the same text is present in the page source.
|
|
92
|
+
- On a page whose panels fetch data, the network panel shows no requests for collapsed items until they
|
|
93
|
+
are opened.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Required fields are no longer red before anyone types
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-10-06
|
|
4
|
+
**Package:** `@clicktap/ui`
|
|
5
|
+
**Affects:** `Input`, `CreditCardInput`, `CreditCardExpirationInput`, `DobInput`, `NumberInput`, `DateInput`, `TimeInput`, `Radio`, `Checkbox`
|
|
6
|
+
**Classification:** BUGFIX
|
|
7
|
+
**Breaking:** No. A field shows its danger styling only when react-aria reports it invalid.
|
|
8
|
+
**Ticket:** CTAP-2225
|
|
9
|
+
|
|
10
|
+
## What changed
|
|
11
|
+
|
|
12
|
+
These components styled their invalid state with Tailwind's `invalid:` and `group-invalid:`
|
|
13
|
+
variants, which compile to the CSS `:invalid` pseudo-class. That had two effects:
|
|
14
|
+
|
|
15
|
+
- A required `<input>` that is empty matches `:invalid` as soon as it renders, so every
|
|
16
|
+
`isRequired` field (sign-in, password reset, checkout) showed the danger border, background and
|
|
17
|
+
text before the user had typed or submitted anything.
|
|
18
|
+
- The date, time, radio and checkbox components put those classes on react-aria `div` and `label`
|
|
19
|
+
elements, which never match `:invalid`, so their invalid styling never showed at all.
|
|
20
|
+
|
|
21
|
+
They now key on react-aria's `data-invalid` attribute (`data-[invalid]:` and
|
|
22
|
+
`group-data-[invalid]:`), which react-aria sets when the field's invalid state is displayed: after a
|
|
23
|
+
submit or commit fails validation, or when `isInvalid` / `validate` says so.
|
|
24
|
+
|
|
25
|
+
## Migrate
|
|
26
|
+
|
|
27
|
+
Nothing for an app that uses the components as they are. An app that passed its own `invalid:`
|
|
28
|
+
classes through `className` / `classNames` has the same on-load problem; switch them to
|
|
29
|
+
`data-[invalid]:` too.
|
|
30
|
+
|
|
31
|
+
## Verify
|
|
32
|
+
|
|
33
|
+
Open a form with a required field: it renders with the normal border. Submit it empty, or pass
|
|
34
|
+
`isInvalid`, and the danger styling appears.
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"path": "2026/10/ui-2026-10-06-invalid-styling-keys-on-data-invalid.md",
|
|
4
|
+
"module": "libs/frontend-modules/ui",
|
|
5
|
+
"package": "@clicktap/ui",
|
|
6
|
+
"date": "2026-10-06",
|
|
7
|
+
"title": "Required fields are no longer red before anyone types",
|
|
8
|
+
"classification": "BUGFIX",
|
|
9
|
+
"breaking": "No. A field shows its danger styling only when react-aria reports it invalid.",
|
|
10
|
+
"affects": "`Input`, `CreditCardInput`, `CreditCardExpirationInput`, `DobInput`, `NumberInput`, `DateInput`, `TimeInput`, `Radio`, `Checkbox`"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"path": "2026/10/ui-2026-10-06-accordion-mounts-collapsed-content-on-expand.md",
|
|
14
|
+
"module": "libs/frontend-modules/ui",
|
|
15
|
+
"package": "@clicktap/ui",
|
|
16
|
+
"date": "2026-10-06",
|
|
17
|
+
"title": "`Accordion` mounts a collapsed item's content only when it expands",
|
|
18
|
+
"classification": "BUGFIX",
|
|
19
|
+
"breaking": "No API change. ⚠️ Behavior change for any consumer that relies on collapsed content being in the server-rendered HTML, findable with the browser's find-in-page, or keeping its state across a collapse. Pass `keepContentMounted` there.",
|
|
20
|
+
"affects": "`components/Accordion` (`Accordion`, `AccordionItem`)"
|
|
21
|
+
},
|
|
2
22
|
{
|
|
3
23
|
"path": "2026/10/ui-2026-10-02-user-icon-drops-project-color-class.md",
|
|
4
24
|
"module": "libs/frontend-modules/ui",
|