@tribepad/themis 1.0.5 → 1.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.
Files changed (59) hide show
  1. package/dist/elements/MatrixGrid/MatrixGrid.d.ts +31 -0
  2. package/dist/elements/MatrixGrid/MatrixGrid.d.ts.map +1 -0
  3. package/dist/elements/MatrixGrid/MatrixGrid.styles.d.ts +48 -0
  4. package/dist/elements/MatrixGrid/MatrixGrid.styles.d.ts.map +1 -0
  5. package/dist/elements/MatrixGrid/MatrixGrid.types.d.ts +75 -0
  6. package/dist/elements/MatrixGrid/MatrixGrid.types.d.ts.map +1 -0
  7. package/dist/elements/MatrixGrid/index.d.ts +5 -0
  8. package/dist/elements/MatrixGrid/index.d.ts.map +1 -0
  9. package/dist/elements/MatrixGrid/index.js +3 -0
  10. package/dist/elements/MatrixGrid/index.js.map +1 -0
  11. package/dist/elements/MatrixGrid/index.mjs +3 -0
  12. package/dist/elements/MatrixGrid/index.mjs.map +1 -0
  13. package/dist/elements/RatingScale/RatingScale.d.ts +32 -0
  14. package/dist/elements/RatingScale/RatingScale.d.ts.map +1 -0
  15. package/dist/elements/RatingScale/RatingScale.styles.d.ts +52 -0
  16. package/dist/elements/RatingScale/RatingScale.styles.d.ts.map +1 -0
  17. package/dist/elements/RatingScale/RatingScale.types.d.ts +73 -0
  18. package/dist/elements/RatingScale/RatingScale.types.d.ts.map +1 -0
  19. package/dist/elements/RatingScale/index.d.ts +5 -0
  20. package/dist/elements/RatingScale/index.d.ts.map +1 -0
  21. package/dist/elements/RatingScale/index.js +3 -0
  22. package/dist/elements/RatingScale/index.js.map +1 -0
  23. package/dist/elements/RatingScale/index.mjs +3 -0
  24. package/dist/elements/RatingScale/index.mjs.map +1 -0
  25. package/dist/elements/SituationalJudgement/SituationalJudgement.d.ts +36 -0
  26. package/dist/elements/SituationalJudgement/SituationalJudgement.d.ts.map +1 -0
  27. package/dist/elements/SituationalJudgement/SituationalJudgement.styles.d.ts +19 -0
  28. package/dist/elements/SituationalJudgement/SituationalJudgement.styles.d.ts.map +1 -0
  29. package/dist/elements/SituationalJudgement/SituationalJudgement.types.d.ts +67 -0
  30. package/dist/elements/SituationalJudgement/SituationalJudgement.types.d.ts.map +1 -0
  31. package/dist/elements/SituationalJudgement/index.d.ts +5 -0
  32. package/dist/elements/SituationalJudgement/index.d.ts.map +1 -0
  33. package/dist/elements/SituationalJudgement/index.js +3 -0
  34. package/dist/elements/SituationalJudgement/index.js.map +1 -0
  35. package/dist/elements/SituationalJudgement/index.mjs +3 -0
  36. package/dist/elements/SituationalJudgement/index.mjs.map +1 -0
  37. package/dist/elements/Tabs/Tabs.d.ts +2 -2
  38. package/dist/elements/Tabs/Tabs.d.ts.map +1 -1
  39. package/dist/elements/Tabs/Tabs.types.d.ts +3 -0
  40. package/dist/elements/Tabs/Tabs.types.d.ts.map +1 -1
  41. package/dist/elements/Tabs/index.js +1 -1
  42. package/dist/elements/Tabs/index.js.map +1 -1
  43. package/dist/elements/Tabs/index.mjs +1 -1
  44. package/dist/elements/Tabs/index.mjs.map +1 -1
  45. package/dist/elements/index.d.ts +6 -0
  46. package/dist/elements/index.d.ts.map +1 -1
  47. package/dist/elements/index.js +1 -1
  48. package/dist/elements/index.js.map +1 -1
  49. package/dist/elements/index.mjs +1 -1
  50. package/dist/elements/index.mjs.map +1 -1
  51. package/dist/index.js +2 -2
  52. package/dist/index.js.map +1 -1
  53. package/dist/index.mjs +2 -2
  54. package/dist/index.mjs.map +1 -1
  55. package/package.json +15 -15
  56. package/src/elements/MatrixGrid/MatrixGrid.stories.tsx +292 -0
  57. package/src/elements/RatingScale/RatingScale.stories.tsx +379 -0
  58. package/src/elements/SituationalJudgement/SituationalJudgement.stories.tsx +305 -0
  59. package/src/elements/Tabs/Tabs.stories.tsx +231 -2
@@ -0,0 +1,31 @@
1
+ declare const MatrixGrid: import("react").ForwardRefExoticComponent<{
2
+ rows: {
3
+ id: string;
4
+ label: string;
5
+ }[];
6
+ columns: {
7
+ id: string;
8
+ label: string;
9
+ }[];
10
+ isRequired: boolean;
11
+ isDisabled: boolean;
12
+ isReadOnly: boolean;
13
+ isInvalid: boolean;
14
+ size: "default" | "sm" | "lg";
15
+ className?: string | undefined;
16
+ children?: any;
17
+ id?: string | undefined;
18
+ 'aria-label'?: string | undefined;
19
+ 'aria-labelledby'?: string | undefined;
20
+ 'aria-describedby'?: string | undefined;
21
+ 'aria-live'?: "off" | "polite" | "assertive" | undefined;
22
+ 'aria-hidden'?: boolean | undefined;
23
+ 'data-testid'?: string | undefined;
24
+ value?: Record<string, string | null> | undefined;
25
+ onChange?: ((value: Record<string, string | null>) => void) | undefined;
26
+ label?: string | undefined;
27
+ description?: string | undefined;
28
+ errorMessage?: string | undefined;
29
+ } & import("react").RefAttributes<HTMLDivElement>>;
30
+ export { MatrixGrid };
31
+ //# sourceMappingURL=MatrixGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixGrid.d.ts","sourceRoot":"","sources":["../../../src/elements/MatrixGrid/MatrixGrid.tsx"],"names":[],"mappings":"AAyCA,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDA6Rf,CAAC;AAIF,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * MatrixGrid CVA Variant Definitions
3
+ *
4
+ * 10 variant groups covering container, table, headers, cells, and radio elements.
5
+ * All interactive elements maintain 44x44px minimum touch targets (WCAG 2.2 AAA).
6
+ */
7
+ /** Root wrapper (flex col, gap, text size) */
8
+ export declare const matrixGridContainerVariants: (props?: ({
9
+ size?: "default" | "sm" | "lg" | null | undefined;
10
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
11
+ /** Horizontal scroll wrapper with padding for focus ring breathing room */
12
+ export declare const matrixGridScrollContainerVariants: (props?: ({
13
+ size?: "default" | "sm" | "lg" | null | undefined;
14
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
15
+ /** Grid element (border-collapse, density) */
16
+ export declare const matrixGridTableVariants: (props?: ({
17
+ size?: "default" | "sm" | "lg" | null | undefined;
18
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
19
+ /** Column header cells (centered, size padding) */
20
+ export declare const matrixGridColumnHeaderVariants: (props?: ({
21
+ size?: "default" | "sm" | "lg" | null | undefined;
22
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
23
+ /** Row header cells (left-aligned, min-width) */
24
+ export declare const matrixGridRowHeaderVariants: (props?: ({
25
+ size?: "default" | "sm" | "lg" | null | undefined;
26
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
27
+ /** Data cells (centered, 44px min touch target) */
28
+ export declare const matrixGridCellVariants: (props?: ({
29
+ size?: "default" | "sm" | "lg" | null | undefined;
30
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
31
+ /** Row styling with zebra striping */
32
+ export declare const matrixGridRowVariants: (props?: ({
33
+ isEven?: boolean | null | undefined;
34
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
35
+ /** Layer 1: Transparent 44x44px touch target with focus ring */
36
+ export declare const matrixGridRadioOuterVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
37
+ /** Layer 2: Radio circle (size, selected, invalid) */
38
+ export declare const matrixGridRadioVisualVariants: (props?: ({
39
+ size?: "default" | "sm" | "lg" | null | undefined;
40
+ isSelected?: boolean | null | undefined;
41
+ isInvalid?: boolean | null | undefined;
42
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
43
+ /** Layer 3: Inner dot with spring animation */
44
+ export declare const matrixGridRadioDotVariants: (props?: ({
45
+ size?: "default" | "sm" | "lg" | null | undefined;
46
+ isSelected?: boolean | null | undefined;
47
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
48
+ //# sourceMappingURL=MatrixGrid.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixGrid.styles.d.ts","sourceRoot":"","sources":["../../../src/elements/MatrixGrid/MatrixGrid.styles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAMH,8CAA8C;AAC9C,eAAO,MAAM,2BAA2B;;8EAStC,CAAC;AAEH,2EAA2E;AAC3E,eAAO,MAAM,iCAAiC;;8EAY7C,CAAC;AAMF,8CAA8C;AAC9C,eAAO,MAAM,uBAAuB;;8EAYnC,CAAC;AAMF,mDAAmD;AACnD,eAAO,MAAM,8BAA8B;;8EAe1C,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,2BAA2B;;8EAevC,CAAC;AAMF,mDAAmD;AACnD,eAAO,MAAM,sBAAsB;;8EAYlC,CAAC;AAEF,sCAAsC;AACtC,eAAO,MAAM,qBAAqB;;8EAWjC,CAAC;AAMF,gEAAgE;AAChE,eAAO,MAAM,4BAA4B,oFASxC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,6BAA6B;;;;8EAoCzC,CAAC;AAEF,+CAA+C;AAC/C,eAAO,MAAM,0BAA0B;;;8EAuBtC,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * MatrixGrid size schema
4
+ * All sizes maintain 44px minimum touch targets (WCAG 2.2 AAA)
5
+ */
6
+ export declare const MatrixGridSizeSchema: z.ZodEnum<{
7
+ default: "default";
8
+ sm: "sm";
9
+ lg: "lg";
10
+ }>;
11
+ export type MatrixGridSize = z.infer<typeof MatrixGridSizeSchema>;
12
+ /**
13
+ * Individual row schema — a statement to rate
14
+ */
15
+ export declare const MatrixGridRowSchema: z.ZodObject<{
16
+ id: z.ZodString;
17
+ label: z.ZodString;
18
+ }, z.core.$strip>;
19
+ export type MatrixGridRow = z.infer<typeof MatrixGridRowSchema>;
20
+ /**
21
+ * Individual column schema — a rating option
22
+ */
23
+ export declare const MatrixGridColumnSchema: z.ZodObject<{
24
+ id: z.ZodString;
25
+ label: z.ZodString;
26
+ }, z.core.$strip>;
27
+ export type MatrixGridColumn = z.infer<typeof MatrixGridColumnSchema>;
28
+ /**
29
+ * MatrixGrid props schema
30
+ *
31
+ * Grid-style survey question with rows (statements) and columns (rating options).
32
+ * Each row has a single radio selection.
33
+ *
34
+ * Uses .refine() to enforce unique row IDs and unique column IDs — requires
35
+ * getShape() helper from test-utils.ts in contract tests.
36
+ */
37
+ export declare const MatrixGridPropsSchema: z.ZodObject<{
38
+ className: z.ZodOptional<z.ZodString>;
39
+ children: z.ZodOptional<z.ZodAny>;
40
+ id: z.ZodOptional<z.ZodString>;
41
+ 'aria-label': z.ZodOptional<z.ZodString>;
42
+ 'aria-labelledby': z.ZodOptional<z.ZodString>;
43
+ 'aria-describedby': z.ZodOptional<z.ZodString>;
44
+ 'aria-live': z.ZodOptional<z.ZodEnum<{
45
+ off: "off";
46
+ polite: "polite";
47
+ assertive: "assertive";
48
+ }>>;
49
+ 'aria-hidden': z.ZodOptional<z.ZodBoolean>;
50
+ 'data-testid': z.ZodOptional<z.ZodString>;
51
+ rows: z.ZodArray<z.ZodObject<{
52
+ id: z.ZodString;
53
+ label: z.ZodString;
54
+ }, z.core.$strip>>;
55
+ columns: z.ZodArray<z.ZodObject<{
56
+ id: z.ZodString;
57
+ label: z.ZodString;
58
+ }, z.core.$strip>>;
59
+ value: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
60
+ onChange: z.ZodOptional<z.ZodCustom<(value: Record<string, string | null>) => void, (value: Record<string, string | null>) => void>>;
61
+ label: z.ZodOptional<z.ZodString>;
62
+ description: z.ZodOptional<z.ZodString>;
63
+ errorMessage: z.ZodOptional<z.ZodString>;
64
+ isRequired: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
65
+ isDisabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
66
+ isReadOnly: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
67
+ isInvalid: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
68
+ size: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
69
+ default: "default";
70
+ sm: "sm";
71
+ lg: "lg";
72
+ }>>>;
73
+ }, z.core.$strip>;
74
+ export type MatrixGridProps = z.infer<typeof MatrixGridPropsSchema>;
75
+ //# sourceMappingURL=MatrixGrid.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixGrid.types.d.ts","sourceRoot":"","sources":["../../../src/elements/MatrixGrid/MatrixGrid.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;EAAkC,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;iBAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;gDAOL,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,UAAtC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI;;;;;;;;;;;;;iBA2BlE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { MatrixGrid } from './MatrixGrid';
2
+ export { matrixGridContainerVariants, matrixGridScrollContainerVariants, matrixGridTableVariants, matrixGridColumnHeaderVariants, matrixGridRowHeaderVariants, matrixGridCellVariants, matrixGridRadioOuterVariants, matrixGridRadioVisualVariants, matrixGridRadioDotVariants, matrixGridRowVariants, } from './MatrixGrid.styles';
3
+ export type { MatrixGridProps, MatrixGridRow, MatrixGridColumn, MatrixGridSize, } from './MatrixGrid.types';
4
+ export { MatrixGridPropsSchema, MatrixGridRowSchema, MatrixGridColumnSchema, MatrixGridSizeSchema, } from './MatrixGrid.types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/MatrixGrid/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,uBAAuB,EACvB,8BAA8B,EAC9B,2BAA2B,EAC3B,sBAAsB,EACtB,4BAA4B,EAC5B,6BAA6B,EAC7B,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ 'use strict';var react=require('react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function ee(...p){return tailwindMerge.twMerge(clsx.clsx(p))}var H=classVarianceAuthority.cva("flex flex-col gap-1.5",{variants:{size:{sm:"text-sm",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),I=classVarianceAuthority.cva("overflow-x-auto -mx-1 px-1",{variants:{size:{sm:"py-0.5",default:"py-1",lg:"py-1.5"}},defaultVariants:{size:"default"}}),j=classVarianceAuthority.cva("w-full border-collapse",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),S=classVarianceAuthority.cva(["text-center font-medium text-[var(--content-foreground)]","whitespace-nowrap"].join(" "),{variants:{size:{sm:"px-2 py-1.5 text-xs",default:"px-3 py-2 text-sm",lg:"px-4 py-3 text-base"}},defaultVariants:{size:"default"}}),T=classVarianceAuthority.cva(["text-left font-normal text-[var(--content-foreground)]","min-w-[120px]"].join(" "),{variants:{size:{sm:"px-2 py-1.5 text-xs",default:"px-3 py-2 text-sm",lg:"px-4 py-3 text-base"}},defaultVariants:{size:"default"}}),$=classVarianceAuthority.cva("text-center min-w-[44px] min-h-[44px]",{variants:{size:{sm:"px-1 py-0.5",default:"px-2 py-1",lg:"px-3 py-1.5"}},defaultVariants:{size:"default"}}),q=classVarianceAuthority.cva("border-b border-[var(--border)]",{variants:{isEven:{true:"bg-[var(--muted)]/30",false:""}},defaultVariants:{isEven:false}}),A=classVarianceAuthority.cva(["inline-flex items-center justify-center","min-h-[44px] min-w-[44px]","cursor-pointer rounded-sm","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--themis-ring)] focus-visible:ring-offset-2","hc:focus-visible:outline hc:focus-visible:outline-4 hc:focus-visible:outline-offset-2 hc:focus-visible:outline-foreground","disabled:pointer-events-none disabled:opacity-50"].join(" ")),F=classVarianceAuthority.cva(["rounded-full border-2","transition-colors duration-200","motion-reduce:transition-none","flex items-center justify-center"].join(" "),{variants:{size:{sm:"h-4 w-4",default:"h-5 w-5",lg:"h-6 w-6"},isSelected:{true:"border-[var(--primary-action)] bg-[var(--primary-action)]",false:"border-[var(--input-border)] bg-[var(--input-background)]"},isInvalid:{true:"border-[var(--destructive-background)]",false:""}},compoundVariants:[{isSelected:true,isInvalid:true,className:"border-[var(--destructive-background)] bg-[var(--destructive-background)]"}],defaultVariants:{size:"default",isSelected:false,isInvalid:false}}),L=classVarianceAuthority.cva(["rounded-full bg-[var(--primary-action-foreground)]","transition-transform duration-200","motion-reduce:transition-none"].join(" "),{variants:{size:{sm:"h-1.5 w-1.5",default:"h-2 w-2",lg:"h-2.5 w-2.5"},isSelected:{true:"scale-100",false:"scale-0"}},defaultVariants:{size:"default",isSelected:false}});var re=react.forwardRef(function(m,b){let{rows:V,columns:g,value:B,onChange:O,label:w,description:z,errorMessage:k,isRequired:oe=false,isDisabled:v=false,isReadOnly:M=false,isInvalid:N=false,size:l="default",className:le,id:de,"aria-label":K,"aria-describedby":U,"data-testid":ue}=m,ce=react.useId(),f=de??ce,J=`${f}-label`,Q=`${f}-description`,W=`${f}-error`,h=[];U&&h.push(U),z&&h.push(Q),N&&k&&h.push(W);let D=B!==void 0,[me,pe]=react.useState({}),P=D?B??{}:me,[C,E]=react.useState([0,0]),X=react.useRef(null),R=react.useCallback((e,r)=>{if(v||M)return;let a={...P,[e]:r};D||pe(a),O?.(a);},[P,O,v,M,D]),Y=react.useCallback((e,r)=>{E([e,r]);let a=X.current;if(!a)return;let n=a.querySelectorAll("tbody tr")[e];if(!n)return;let d=n.querySelectorAll("td")[r];if(!d)return;let u=d.querySelector("button");u&&u.focus();},[]),fe=react.useCallback(e=>{let[r,a]=C,n=V.length-1,d=g.length-1,u=r,x=a,c=false;switch(e.key){case "ArrowRight":x=Math.min(a+1,d),c=true;break;case "ArrowLeft":x=Math.max(a-1,0),c=true;break;case "ArrowDown":u=Math.min(r+1,n),c=true;break;case "ArrowUp":u=Math.max(r-1,0),c=true;break;case "Home":x=0,c=true;break;case "End":x=d,c=true;break;case " ":case "Enter":{let Z=V[r],_=g[a];!v&&!M&&Z&&_&&R(Z.id,_.id),c=true;break}}c&&(e.preventDefault(),(u!==r||x!==a)&&Y(u,x));},[C,V,g,R,Y,v,M]),xe=react.useCallback((e,r,a,n)=>{E([e,r]),R(a,n);},[R]),be=react.useCallback((e,r)=>{E([e,r]);},[]);return jsxRuntime.jsxs("div",{ref:b,id:f,role:"group","aria-label":K,"aria-labelledby":w?J:void 0,"aria-describedby":h.length>0?h.join(" "):void 0,"data-testid":ue,className:ee(H({size:l}),le),children:[w&&jsxRuntime.jsxs("span",{id:J,className:"text-sm font-medium text-[var(--content-foreground)]",children:[w,oe&&jsxRuntime.jsx("span",{className:"ml-1 text-[var(--destructive-background)]","aria-hidden":"true",children:"*"})]}),z&&jsxRuntime.jsx("span",{id:Q,className:"text-sm text-[var(--menu-muted)]",children:z}),jsxRuntime.jsx("div",{className:I({size:l}),children:jsxRuntime.jsxs("table",{ref:X,role:"grid","aria-label":K??w,onKeyDown:fe,className:j({size:l}),children:[jsxRuntime.jsx("thead",{children:jsxRuntime.jsxs("tr",{role:"row",children:[jsxRuntime.jsx("td",{className:S({size:l})}),g.map(e=>jsxRuntime.jsx("th",{id:`${f}-col-${e.id}`,scope:"col",role:"columnheader",className:S({size:l}),children:e.label},e.id))]})}),jsxRuntime.jsx("tbody",{children:V.map((e,r)=>jsxRuntime.jsxs("tr",{role:"row",className:q({isEven:r%2===1}),children:[jsxRuntime.jsx("th",{scope:"row",role:"rowheader",className:T({size:l}),children:e.label}),g.map((a,n)=>{let d=P[e.id]===a.id,u=C[0]===r&&C[1]===n;return jsxRuntime.jsx("td",{role:"gridcell","aria-describedby":`${f}-col-${a.id}`,className:$({size:l}),children:jsxRuntime.jsx("button",{type:"button",role:"radio","aria-checked":d,"aria-label":`${e.label}, ${a.label}`,tabIndex:u?0:-1,disabled:v,onClick:()=>xe(r,n,e.id,a.id),onFocus:()=>be(r,n),className:A(),children:jsxRuntime.jsx("span",{className:F({size:l,isSelected:d,isInvalid:N}),"aria-hidden":"true",children:jsxRuntime.jsx("span",{className:L({size:l,isSelected:d})})})})},a.id)})]},e.id))})]})}),N&&k&&jsxRuntime.jsx("div",{id:W,role:"alert",className:"text-sm text-[var(--destructive-background)]",children:k})]})});re.displayName="MatrixGrid";var ae=zod.z.object({className:zod.z.string().optional(),children:zod.z.any().optional(),id:zod.z.string().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),"aria-describedby":zod.z.string().optional(),"aria-live":zod.z.enum(["off","polite","assertive"]).optional(),"aria-hidden":zod.z.boolean().optional(),"data-testid":zod.z.string().optional()});var ie=zod.z.enum(["sm","default","lg"]),ne=zod.z.object({id:zod.z.string(),label:zod.z.string()}),se=zod.z.object({id:zod.z.string(),label:zod.z.string()}),Ve=ae.extend({rows:zod.z.array(ne).min(2),columns:zod.z.array(se).min(2).max(10),value:zod.z.record(zod.z.string(),zod.z.string().nullable()).optional(),onChange:zod.z.custom().optional(),label:zod.z.string().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),isRequired:zod.z.boolean().optional().default(false),isDisabled:zod.z.boolean().optional().default(false),isReadOnly:zod.z.boolean().optional().default(false),isInvalid:zod.z.boolean().optional().default(false),size:ie.optional().default("default")}).refine(p=>{let m=p.rows.map(b=>b.id);return new Set(m).size===m.length},{message:"Row IDs must be unique",path:["rows"]}).refine(p=>{let m=p.columns.map(b=>b.id);return new Set(m).size===m.length},{message:"Column IDs must be unique",path:["columns"]});exports.MatrixGrid=re;exports.MatrixGridColumnSchema=se;exports.MatrixGridPropsSchema=Ve;exports.MatrixGridRowSchema=ne;exports.MatrixGridSizeSchema=ie;exports.matrixGridCellVariants=$;exports.matrixGridColumnHeaderVariants=S;exports.matrixGridContainerVariants=H;exports.matrixGridRadioDotVariants=L;exports.matrixGridRadioOuterVariants=A;exports.matrixGridRadioVisualVariants=F;exports.matrixGridRowHeaderVariants=T;exports.matrixGridRowVariants=q;exports.matrixGridScrollContainerVariants=I;exports.matrixGridTableVariants=j;//# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/MatrixGrid/MatrixGrid.styles.ts","../../../src/elements/MatrixGrid/MatrixGrid.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/MatrixGrid/MatrixGrid.types.ts"],"names":["cn","inputs","twMerge","clsx","matrixGridContainerVariants","cva","matrixGridScrollContainerVariants","matrixGridTableVariants","matrixGridColumnHeaderVariants","matrixGridRowHeaderVariants","matrixGridCellVariants","matrixGridRowVariants","matrixGridRadioOuterVariants","matrixGridRadioVisualVariants","matrixGridRadioDotVariants","MatrixGrid","forwardRef","props","ref","rows","columns","value","onChange","label","description","errorMessage","isRequired","isDisabled","isReadOnly","isInvalid","size","className","id","ariaLabel","ariaDescribedby","dataTestId","generatedId","useId","groupId","labelId","descriptionId","errorId","describedByParts","isControlled","internalValue","setInternalValue","useState","currentValue","focusedCell","setFocusedCell","gridRef","useRef","handleSelect","useCallback","rowId","colId","newValue","focusCell","rowIdx","colIdx","table","row","cell","button","handleKeyDown","maxRow","maxCol","nextRow","nextCol","handled","targetRow","targetCol","handleCellClick","handleCellFocus","jsxs","jsx","col","isSelected","isFocused","BaseComponentPropsSchema","z","MatrixGridSizeSchema","MatrixGridRowSchema","MatrixGridColumnSchema","MatrixGridPropsSchema","data","ids","r","c"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { cva } from 'class-variance-authority';\n\n/**\n * MatrixGrid CVA Variant Definitions\n *\n * 10 variant groups covering container, table, headers, cells, and radio elements.\n * All interactive elements maintain 44x44px minimum touch targets (WCAG 2.2 AAA).\n */\n\n// =============================================================================\n// Container\n// =============================================================================\n\n/** Root wrapper (flex col, gap, text size) */\nexport const matrixGridContainerVariants = cva(\"flex flex-col gap-1.5\", {\n variants: {\n size: {\n sm: \"text-sm\",\n default: \"text-sm\",\n lg: \"text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n});\n\n/** Horizontal scroll wrapper with padding for focus ring breathing room */\nexport const matrixGridScrollContainerVariants = cva(\n \"overflow-x-auto -mx-1 px-1\",\n {\n variants: {\n size: {\n sm: \"py-0.5\",\n default: \"py-1\",\n lg: \"py-1.5\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n// =============================================================================\n// Table / Grid\n// =============================================================================\n\n/** Grid element (border-collapse, density) */\nexport const matrixGridTableVariants = cva(\n \"w-full border-collapse\",\n {\n variants: {\n size: {\n sm: \"\",\n default: \"\",\n lg: \"\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n// =============================================================================\n// Headers\n// =============================================================================\n\n/** Column header cells (centered, size padding) */\nexport const matrixGridColumnHeaderVariants = cva(\n [\n \"text-center font-medium text-[var(--content-foreground)]\",\n \"whitespace-nowrap\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"px-2 py-1.5 text-xs\",\n default: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-3 text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n/** Row header cells (left-aligned, min-width) */\nexport const matrixGridRowHeaderVariants = cva(\n [\n \"text-left font-normal text-[var(--content-foreground)]\",\n \"min-w-[120px]\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"px-2 py-1.5 text-xs\",\n default: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-3 text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n// =============================================================================\n// Cells & Rows\n// =============================================================================\n\n/** Data cells (centered, 44px min touch target) */\nexport const matrixGridCellVariants = cva(\n \"text-center min-w-[44px] min-h-[44px]\",\n {\n variants: {\n size: {\n sm: \"px-1 py-0.5\",\n default: \"px-2 py-1\",\n lg: \"px-3 py-1.5\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n/** Row styling with zebra striping */\nexport const matrixGridRowVariants = cva(\n \"border-b border-[var(--border)]\",\n {\n variants: {\n isEven: {\n true: \"bg-[var(--muted)]/30\",\n false: \"\",\n },\n },\n defaultVariants: { isEven: false },\n }\n);\n\n// =============================================================================\n// Radio (Three-Layer Architecture)\n// =============================================================================\n\n/** Layer 1: Transparent 44x44px touch target with focus ring */\nexport const matrixGridRadioOuterVariants = cva(\n [\n \"inline-flex items-center justify-center\",\n \"min-h-[44px] min-w-[44px]\",\n \"cursor-pointer rounded-sm\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--themis-ring)] focus-visible:ring-offset-2\",\n \"hc:focus-visible:outline hc:focus-visible:outline-4 hc:focus-visible:outline-offset-2 hc:focus-visible:outline-foreground\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n ].join(\" \"),\n);\n\n/** Layer 2: Radio circle (size, selected, invalid) */\nexport const matrixGridRadioVisualVariants = cva(\n [\n \"rounded-full border-2\",\n \"transition-colors duration-200\",\n \"motion-reduce:transition-none\",\n \"flex items-center justify-center\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"h-4 w-4\",\n default: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n },\n isSelected: {\n true: \"border-[var(--primary-action)] bg-[var(--primary-action)]\",\n false: \"border-[var(--input-border)] bg-[var(--input-background)]\",\n },\n isInvalid: {\n true: \"border-[var(--destructive-background)]\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n isSelected: true,\n isInvalid: true,\n className: \"border-[var(--destructive-background)] bg-[var(--destructive-background)]\",\n },\n ],\n defaultVariants: {\n size: \"default\",\n isSelected: false,\n isInvalid: false,\n },\n }\n);\n\n/** Layer 3: Inner dot with spring animation */\nexport const matrixGridRadioDotVariants = cva(\n [\n \"rounded-full bg-[var(--primary-action-foreground)]\",\n \"transition-transform duration-200\",\n \"motion-reduce:transition-none\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"h-1.5 w-1.5\",\n default: \"h-2 w-2\",\n lg: \"h-2.5 w-2.5\",\n },\n isSelected: {\n true: \"scale-100\",\n false: \"scale-0\",\n },\n },\n defaultVariants: {\n size: \"default\",\n isSelected: false,\n },\n }\n);\n","'use client';\n\n/**\n * MatrixGrid Component\n * Grid-style survey question with rows (statements) and columns (rating options).\n * Each row has a single radio selection.\n *\n * Uses role=\"grid\" ARIA pattern with roving tabindex for keyboard navigation.\n * Built from React Aria primitives directly for cell-based selection.\n *\n * @see WCAG 2.2 AAA — 44x44px touch targets, 7:1 contrast, keyboard navigation\n */\n\nimport {\n forwardRef,\n useState,\n useId,\n useCallback,\n useRef,\n type ForwardedRef,\n type KeyboardEvent,\n} from 'react';\nimport { cn } from '../../utils/cn';\nimport type { MatrixGridProps } from './MatrixGrid.types';\nimport {\n matrixGridContainerVariants,\n matrixGridScrollContainerVariants,\n matrixGridTableVariants,\n matrixGridColumnHeaderVariants,\n matrixGridRowHeaderVariants,\n matrixGridCellVariants,\n matrixGridRadioOuterVariants,\n matrixGridRadioVisualVariants,\n matrixGridRadioDotVariants,\n matrixGridRowVariants,\n} from './MatrixGrid.styles';\n\n// =============================================================================\n// MatrixGrid Component\n// =============================================================================\n\nconst MatrixGrid = forwardRef<HTMLDivElement, MatrixGridProps>(\n function MatrixGrid(props: MatrixGridProps, ref: ForwardedRef<HTMLDivElement>) {\n const {\n // Data\n rows,\n columns,\n // Value\n value,\n onChange,\n // Labels\n label,\n description,\n errorMessage,\n // State\n isRequired = false,\n isDisabled = false,\n isReadOnly = false,\n isInvalid = false,\n // Sizing\n size = 'default',\n // Standard\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedby,\n 'data-testid': dataTestId,\n } = props;\n\n const generatedId = useId();\n const groupId = id ?? generatedId;\n const labelId = `${groupId}-label`;\n const descriptionId = `${groupId}-description`;\n const errorId = `${groupId}-error`;\n\n const describedByParts: string[] = [];\n if (ariaDescribedby) describedByParts.push(ariaDescribedby);\n if (description) describedByParts.push(descriptionId);\n if (isInvalid && errorMessage) describedByParts.push(errorId);\n\n // Controlled vs uncontrolled state\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<Record<string, string | null>>({});\n const currentValue = isControlled ? (value ?? {}) : internalValue;\n\n // Roving tabindex: track focused cell [rowIndex, colIndex]\n // rowIndex is 0-based into data rows, colIndex is 0-based into columns\n const [focusedCell, setFocusedCell] = useState<[number, number]>([0, 0]);\n const gridRef = useRef<HTMLTableElement>(null);\n\n const handleSelect = useCallback(\n (rowId: string, colId: string) => {\n if (isDisabled || isReadOnly) return;\n const newValue = { ...currentValue, [rowId]: colId };\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onChange?.(newValue);\n },\n [currentValue, onChange, isDisabled, isReadOnly, isControlled],\n );\n\n const focusCell = useCallback(\n (rowIdx: number, colIdx: number) => {\n setFocusedCell([rowIdx, colIdx]);\n // Focus the button in the target cell\n const table = gridRef.current;\n if (!table) return;\n const row = table.querySelectorAll('tbody tr')[rowIdx];\n if (!row) return;\n // +1 to skip the row header cell\n const cell = row.querySelectorAll('td')[colIdx];\n if (!cell) return;\n const button = cell.querySelector('button');\n if (button) button.focus();\n },\n [],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTableElement>) => {\n const [rowIdx, colIdx] = focusedCell;\n const maxRow = rows.length - 1;\n const maxCol = columns.length - 1;\n\n let nextRow = rowIdx;\n let nextCol = colIdx;\n let handled = false;\n\n switch (e.key) {\n case 'ArrowRight':\n nextCol = Math.min(colIdx + 1, maxCol);\n handled = true;\n break;\n case 'ArrowLeft':\n nextCol = Math.max(colIdx - 1, 0);\n handled = true;\n break;\n case 'ArrowDown':\n nextRow = Math.min(rowIdx + 1, maxRow);\n handled = true;\n break;\n case 'ArrowUp':\n nextRow = Math.max(rowIdx - 1, 0);\n handled = true;\n break;\n case 'Home':\n nextCol = 0;\n handled = true;\n break;\n case 'End':\n nextCol = maxCol;\n handled = true;\n break;\n case ' ':\n case 'Enter': {\n const targetRow = rows[rowIdx];\n const targetCol = columns[colIdx];\n if (!isDisabled && !isReadOnly && targetRow && targetCol) {\n handleSelect(targetRow.id, targetCol.id);\n }\n handled = true;\n break;\n }\n default:\n break;\n }\n\n if (handled) {\n e.preventDefault();\n if (nextRow !== rowIdx || nextCol !== colIdx) {\n focusCell(nextRow, nextCol);\n }\n }\n },\n [focusedCell, rows, columns, handleSelect, focusCell, isDisabled, isReadOnly],\n );\n\n const handleCellClick = useCallback(\n (rowIdx: number, colIdx: number, rowId: string, colId: string) => {\n setFocusedCell([rowIdx, colIdx]);\n handleSelect(rowId, colId);\n },\n [handleSelect],\n );\n\n const handleCellFocus = useCallback(\n (rowIdx: number, colIdx: number) => {\n setFocusedCell([rowIdx, colIdx]);\n },\n [],\n );\n\n return (\n <div\n ref={ref}\n id={groupId}\n role=\"group\"\n aria-label={ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={describedByParts.length > 0 ? describedByParts.join(' ') : undefined}\n data-testid={dataTestId}\n className={cn(matrixGridContainerVariants({ size }), className)}\n >\n {/* Label */}\n {label && (\n <span id={labelId} className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n {isRequired && (\n <span className=\"ml-1 text-[var(--destructive-background)]\" aria-hidden=\"true\">\n *\n </span>\n )}\n </span>\n )}\n\n {/* Description */}\n {description && (\n <span\n id={descriptionId}\n className=\"text-sm text-[var(--menu-muted)]\"\n >\n {description}\n </span>\n )}\n\n {/* Scroll container */}\n <div className={matrixGridScrollContainerVariants({ size })}>\n <table\n ref={gridRef}\n role=\"grid\"\n aria-label={ariaLabel ?? label}\n onKeyDown={handleKeyDown}\n className={matrixGridTableVariants({ size })}\n >\n <thead>\n <tr role=\"row\">\n {/* Corner cell — visually empty but accessible */}\n <td className={matrixGridColumnHeaderVariants({ size })} />\n {columns.map((col) => (\n <th\n key={col.id}\n id={`${groupId}-col-${col.id}`}\n scope=\"col\"\n role=\"columnheader\"\n className={matrixGridColumnHeaderVariants({ size })}\n >\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, rowIdx) => (\n <tr\n key={row.id}\n role=\"row\"\n className={matrixGridRowVariants({ isEven: rowIdx % 2 === 1 })}\n >\n <th\n scope=\"row\"\n role=\"rowheader\"\n className={matrixGridRowHeaderVariants({ size })}\n >\n {row.label}\n </th>\n {columns.map((col, colIdx) => {\n const isSelected = currentValue[row.id] === col.id;\n const isFocused = focusedCell[0] === rowIdx && focusedCell[1] === colIdx;\n\n return (\n <td\n key={col.id}\n role=\"gridcell\"\n aria-describedby={`${groupId}-col-${col.id}`}\n className={matrixGridCellVariants({ size })}\n >\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n aria-label={`${row.label}, ${col.label}`}\n tabIndex={isFocused ? 0 : -1}\n disabled={isDisabled}\n onClick={() => handleCellClick(rowIdx, colIdx, row.id, col.id)}\n onFocus={() => handleCellFocus(rowIdx, colIdx)}\n className={matrixGridRadioOuterVariants()}\n >\n <span\n className={matrixGridRadioVisualVariants({\n size,\n isSelected,\n isInvalid,\n })}\n aria-hidden=\"true\"\n >\n <span\n className={matrixGridRadioDotVariants({\n size,\n isSelected,\n })}\n />\n </span>\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Error message */}\n {isInvalid && errorMessage && (\n <div\n id={errorId}\n role=\"alert\"\n className=\"text-sm text-[var(--destructive-background)]\"\n >\n {errorMessage}\n </div>\n )}\n </div>\n );\n },\n);\n\nMatrixGrid.displayName = \"MatrixGrid\";\n\nexport { MatrixGrid };\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\n\n/**\n * MatrixGrid size schema\n * All sizes maintain 44px minimum touch targets (WCAG 2.2 AAA)\n */\nexport const MatrixGridSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type MatrixGridSize = z.infer<typeof MatrixGridSizeSchema>;\n\n/**\n * Individual row schema — a statement to rate\n */\nexport const MatrixGridRowSchema = z.object({\n id: z.string(),\n label: z.string(),\n});\n\nexport type MatrixGridRow = z.infer<typeof MatrixGridRowSchema>;\n\n/**\n * Individual column schema — a rating option\n */\nexport const MatrixGridColumnSchema = z.object({\n id: z.string(),\n label: z.string(),\n});\n\nexport type MatrixGridColumn = z.infer<typeof MatrixGridColumnSchema>;\n\n/**\n * MatrixGrid props schema\n *\n * Grid-style survey question with rows (statements) and columns (rating options).\n * Each row has a single radio selection.\n *\n * Uses .refine() to enforce unique row IDs and unique column IDs — requires\n * getShape() helper from test-utils.ts in contract tests.\n */\nexport const MatrixGridPropsSchema = BaseComponentPropsSchema.extend({\n // Data\n rows: z.array(MatrixGridRowSchema).min(2),\n columns: z.array(MatrixGridColumnSchema).min(2).max(10),\n\n // Value — Record<rowId, columnId | null>\n value: z.record(z.string(), z.string().nullable()).optional(),\n onChange: z.custom<(value: Record<string, string | null>) => void>().optional(),\n\n // Labels\n label: z.string().optional(),\n description: z.string().optional(),\n errorMessage: z.string().optional(),\n\n // State\n isRequired: z.boolean().optional().default(false),\n isDisabled: z.boolean().optional().default(false),\n isReadOnly: z.boolean().optional().default(false),\n isInvalid: z.boolean().optional().default(false),\n\n // Sizing\n size: MatrixGridSizeSchema.optional().default('default'),\n}).refine(\n (data) => {\n const ids = data.rows.map((r) => r.id);\n return new Set(ids).size === ids.length;\n },\n { message: 'Row IDs must be unique', path: ['rows'] },\n).refine(\n (data) => {\n const ids = data.columns.map((c) => c.id);\n return new Set(ids).size === ids.length;\n },\n { message: 'Column IDs must be unique', path: ['columns'] },\n);\n\nexport type MatrixGridProps = z.infer<typeof MatrixGridPropsSchema>;\n"]}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import {forwardRef,useId,useState,useRef,useCallback}from'react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsxs,jsx}from'react/jsx-runtime';import {z}from'zod';function ee(...p){return twMerge(clsx(p))}var H=cva("flex flex-col gap-1.5",{variants:{size:{sm:"text-sm",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),I=cva("overflow-x-auto -mx-1 px-1",{variants:{size:{sm:"py-0.5",default:"py-1",lg:"py-1.5"}},defaultVariants:{size:"default"}}),j=cva("w-full border-collapse",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),S=cva(["text-center font-medium text-[var(--content-foreground)]","whitespace-nowrap"].join(" "),{variants:{size:{sm:"px-2 py-1.5 text-xs",default:"px-3 py-2 text-sm",lg:"px-4 py-3 text-base"}},defaultVariants:{size:"default"}}),T=cva(["text-left font-normal text-[var(--content-foreground)]","min-w-[120px]"].join(" "),{variants:{size:{sm:"px-2 py-1.5 text-xs",default:"px-3 py-2 text-sm",lg:"px-4 py-3 text-base"}},defaultVariants:{size:"default"}}),$=cva("text-center min-w-[44px] min-h-[44px]",{variants:{size:{sm:"px-1 py-0.5",default:"px-2 py-1",lg:"px-3 py-1.5"}},defaultVariants:{size:"default"}}),q=cva("border-b border-[var(--border)]",{variants:{isEven:{true:"bg-[var(--muted)]/30",false:""}},defaultVariants:{isEven:false}}),A=cva(["inline-flex items-center justify-center","min-h-[44px] min-w-[44px]","cursor-pointer rounded-sm","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--themis-ring)] focus-visible:ring-offset-2","hc:focus-visible:outline hc:focus-visible:outline-4 hc:focus-visible:outline-offset-2 hc:focus-visible:outline-foreground","disabled:pointer-events-none disabled:opacity-50"].join(" ")),F=cva(["rounded-full border-2","transition-colors duration-200","motion-reduce:transition-none","flex items-center justify-center"].join(" "),{variants:{size:{sm:"h-4 w-4",default:"h-5 w-5",lg:"h-6 w-6"},isSelected:{true:"border-[var(--primary-action)] bg-[var(--primary-action)]",false:"border-[var(--input-border)] bg-[var(--input-background)]"},isInvalid:{true:"border-[var(--destructive-background)]",false:""}},compoundVariants:[{isSelected:true,isInvalid:true,className:"border-[var(--destructive-background)] bg-[var(--destructive-background)]"}],defaultVariants:{size:"default",isSelected:false,isInvalid:false}}),L=cva(["rounded-full bg-[var(--primary-action-foreground)]","transition-transform duration-200","motion-reduce:transition-none"].join(" "),{variants:{size:{sm:"h-1.5 w-1.5",default:"h-2 w-2",lg:"h-2.5 w-2.5"},isSelected:{true:"scale-100",false:"scale-0"}},defaultVariants:{size:"default",isSelected:false}});var re=forwardRef(function(m,b){let{rows:V,columns:g,value:B,onChange:O,label:w,description:z,errorMessage:k,isRequired:oe=false,isDisabled:v=false,isReadOnly:M=false,isInvalid:N=false,size:l="default",className:le,id:de,"aria-label":K,"aria-describedby":U,"data-testid":ue}=m,ce=useId(),f=de??ce,J=`${f}-label`,Q=`${f}-description`,W=`${f}-error`,h=[];U&&h.push(U),z&&h.push(Q),N&&k&&h.push(W);let D=B!==void 0,[me,pe]=useState({}),P=D?B??{}:me,[C,E]=useState([0,0]),X=useRef(null),R=useCallback((e,r)=>{if(v||M)return;let a={...P,[e]:r};D||pe(a),O?.(a);},[P,O,v,M,D]),Y=useCallback((e,r)=>{E([e,r]);let a=X.current;if(!a)return;let n=a.querySelectorAll("tbody tr")[e];if(!n)return;let d=n.querySelectorAll("td")[r];if(!d)return;let u=d.querySelector("button");u&&u.focus();},[]),fe=useCallback(e=>{let[r,a]=C,n=V.length-1,d=g.length-1,u=r,x=a,c=false;switch(e.key){case "ArrowRight":x=Math.min(a+1,d),c=true;break;case "ArrowLeft":x=Math.max(a-1,0),c=true;break;case "ArrowDown":u=Math.min(r+1,n),c=true;break;case "ArrowUp":u=Math.max(r-1,0),c=true;break;case "Home":x=0,c=true;break;case "End":x=d,c=true;break;case " ":case "Enter":{let Z=V[r],_=g[a];!v&&!M&&Z&&_&&R(Z.id,_.id),c=true;break}}c&&(e.preventDefault(),(u!==r||x!==a)&&Y(u,x));},[C,V,g,R,Y,v,M]),xe=useCallback((e,r,a,n)=>{E([e,r]),R(a,n);},[R]),be=useCallback((e,r)=>{E([e,r]);},[]);return jsxs("div",{ref:b,id:f,role:"group","aria-label":K,"aria-labelledby":w?J:void 0,"aria-describedby":h.length>0?h.join(" "):void 0,"data-testid":ue,className:ee(H({size:l}),le),children:[w&&jsxs("span",{id:J,className:"text-sm font-medium text-[var(--content-foreground)]",children:[w,oe&&jsx("span",{className:"ml-1 text-[var(--destructive-background)]","aria-hidden":"true",children:"*"})]}),z&&jsx("span",{id:Q,className:"text-sm text-[var(--menu-muted)]",children:z}),jsx("div",{className:I({size:l}),children:jsxs("table",{ref:X,role:"grid","aria-label":K??w,onKeyDown:fe,className:j({size:l}),children:[jsx("thead",{children:jsxs("tr",{role:"row",children:[jsx("td",{className:S({size:l})}),g.map(e=>jsx("th",{id:`${f}-col-${e.id}`,scope:"col",role:"columnheader",className:S({size:l}),children:e.label},e.id))]})}),jsx("tbody",{children:V.map((e,r)=>jsxs("tr",{role:"row",className:q({isEven:r%2===1}),children:[jsx("th",{scope:"row",role:"rowheader",className:T({size:l}),children:e.label}),g.map((a,n)=>{let d=P[e.id]===a.id,u=C[0]===r&&C[1]===n;return jsx("td",{role:"gridcell","aria-describedby":`${f}-col-${a.id}`,className:$({size:l}),children:jsx("button",{type:"button",role:"radio","aria-checked":d,"aria-label":`${e.label}, ${a.label}`,tabIndex:u?0:-1,disabled:v,onClick:()=>xe(r,n,e.id,a.id),onFocus:()=>be(r,n),className:A(),children:jsx("span",{className:F({size:l,isSelected:d,isInvalid:N}),"aria-hidden":"true",children:jsx("span",{className:L({size:l,isSelected:d})})})})},a.id)})]},e.id))})]})}),N&&k&&jsx("div",{id:W,role:"alert",className:"text-sm text-[var(--destructive-background)]",children:k})]})});re.displayName="MatrixGrid";var ae=z.object({className:z.string().optional(),children:z.any().optional(),id:z.string().optional(),"aria-label":z.string().optional(),"aria-labelledby":z.string().optional(),"aria-describedby":z.string().optional(),"aria-live":z.enum(["off","polite","assertive"]).optional(),"aria-hidden":z.boolean().optional(),"data-testid":z.string().optional()});var ie=z.enum(["sm","default","lg"]),ne=z.object({id:z.string(),label:z.string()}),se=z.object({id:z.string(),label:z.string()}),Ve=ae.extend({rows:z.array(ne).min(2),columns:z.array(se).min(2).max(10),value:z.record(z.string(),z.string().nullable()).optional(),onChange:z.custom().optional(),label:z.string().optional(),description:z.string().optional(),errorMessage:z.string().optional(),isRequired:z.boolean().optional().default(false),isDisabled:z.boolean().optional().default(false),isReadOnly:z.boolean().optional().default(false),isInvalid:z.boolean().optional().default(false),size:ie.optional().default("default")}).refine(p=>{let m=p.rows.map(b=>b.id);return new Set(m).size===m.length},{message:"Row IDs must be unique",path:["rows"]}).refine(p=>{let m=p.columns.map(b=>b.id);return new Set(m).size===m.length},{message:"Column IDs must be unique",path:["columns"]});export{re as MatrixGrid,se as MatrixGridColumnSchema,Ve as MatrixGridPropsSchema,ne as MatrixGridRowSchema,ie as MatrixGridSizeSchema,$ as matrixGridCellVariants,S as matrixGridColumnHeaderVariants,H as matrixGridContainerVariants,L as matrixGridRadioDotVariants,A as matrixGridRadioOuterVariants,F as matrixGridRadioVisualVariants,T as matrixGridRowHeaderVariants,q as matrixGridRowVariants,I as matrixGridScrollContainerVariants,j as matrixGridTableVariants};//# sourceMappingURL=index.mjs.map
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/MatrixGrid/MatrixGrid.styles.ts","../../../src/elements/MatrixGrid/MatrixGrid.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/MatrixGrid/MatrixGrid.types.ts"],"names":["cn","inputs","twMerge","clsx","matrixGridContainerVariants","cva","matrixGridScrollContainerVariants","matrixGridTableVariants","matrixGridColumnHeaderVariants","matrixGridRowHeaderVariants","matrixGridCellVariants","matrixGridRowVariants","matrixGridRadioOuterVariants","matrixGridRadioVisualVariants","matrixGridRadioDotVariants","MatrixGrid","forwardRef","props","ref","rows","columns","value","onChange","label","description","errorMessage","isRequired","isDisabled","isReadOnly","isInvalid","size","className","id","ariaLabel","ariaDescribedby","dataTestId","generatedId","useId","groupId","labelId","descriptionId","errorId","describedByParts","isControlled","internalValue","setInternalValue","useState","currentValue","focusedCell","setFocusedCell","gridRef","useRef","handleSelect","useCallback","rowId","colId","newValue","focusCell","rowIdx","colIdx","table","row","cell","button","handleKeyDown","maxRow","maxCol","nextRow","nextCol","handled","targetRow","targetCol","handleCellClick","handleCellFocus","jsxs","jsx","col","isSelected","isFocused","BaseComponentPropsSchema","z","MatrixGridSizeSchema","MatrixGridRowSchema","MatrixGridColumnSchema","MatrixGridPropsSchema","data","ids","r","c"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { cva } from 'class-variance-authority';\n\n/**\n * MatrixGrid CVA Variant Definitions\n *\n * 10 variant groups covering container, table, headers, cells, and radio elements.\n * All interactive elements maintain 44x44px minimum touch targets (WCAG 2.2 AAA).\n */\n\n// =============================================================================\n// Container\n// =============================================================================\n\n/** Root wrapper (flex col, gap, text size) */\nexport const matrixGridContainerVariants = cva(\"flex flex-col gap-1.5\", {\n variants: {\n size: {\n sm: \"text-sm\",\n default: \"text-sm\",\n lg: \"text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n});\n\n/** Horizontal scroll wrapper with padding for focus ring breathing room */\nexport const matrixGridScrollContainerVariants = cva(\n \"overflow-x-auto -mx-1 px-1\",\n {\n variants: {\n size: {\n sm: \"py-0.5\",\n default: \"py-1\",\n lg: \"py-1.5\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n// =============================================================================\n// Table / Grid\n// =============================================================================\n\n/** Grid element (border-collapse, density) */\nexport const matrixGridTableVariants = cva(\n \"w-full border-collapse\",\n {\n variants: {\n size: {\n sm: \"\",\n default: \"\",\n lg: \"\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n// =============================================================================\n// Headers\n// =============================================================================\n\n/** Column header cells (centered, size padding) */\nexport const matrixGridColumnHeaderVariants = cva(\n [\n \"text-center font-medium text-[var(--content-foreground)]\",\n \"whitespace-nowrap\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"px-2 py-1.5 text-xs\",\n default: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-3 text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n/** Row header cells (left-aligned, min-width) */\nexport const matrixGridRowHeaderVariants = cva(\n [\n \"text-left font-normal text-[var(--content-foreground)]\",\n \"min-w-[120px]\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"px-2 py-1.5 text-xs\",\n default: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-3 text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n// =============================================================================\n// Cells & Rows\n// =============================================================================\n\n/** Data cells (centered, 44px min touch target) */\nexport const matrixGridCellVariants = cva(\n \"text-center min-w-[44px] min-h-[44px]\",\n {\n variants: {\n size: {\n sm: \"px-1 py-0.5\",\n default: \"px-2 py-1\",\n lg: \"px-3 py-1.5\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n/** Row styling with zebra striping */\nexport const matrixGridRowVariants = cva(\n \"border-b border-[var(--border)]\",\n {\n variants: {\n isEven: {\n true: \"bg-[var(--muted)]/30\",\n false: \"\",\n },\n },\n defaultVariants: { isEven: false },\n }\n);\n\n// =============================================================================\n// Radio (Three-Layer Architecture)\n// =============================================================================\n\n/** Layer 1: Transparent 44x44px touch target with focus ring */\nexport const matrixGridRadioOuterVariants = cva(\n [\n \"inline-flex items-center justify-center\",\n \"min-h-[44px] min-w-[44px]\",\n \"cursor-pointer rounded-sm\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--themis-ring)] focus-visible:ring-offset-2\",\n \"hc:focus-visible:outline hc:focus-visible:outline-4 hc:focus-visible:outline-offset-2 hc:focus-visible:outline-foreground\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n ].join(\" \"),\n);\n\n/** Layer 2: Radio circle (size, selected, invalid) */\nexport const matrixGridRadioVisualVariants = cva(\n [\n \"rounded-full border-2\",\n \"transition-colors duration-200\",\n \"motion-reduce:transition-none\",\n \"flex items-center justify-center\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"h-4 w-4\",\n default: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n },\n isSelected: {\n true: \"border-[var(--primary-action)] bg-[var(--primary-action)]\",\n false: \"border-[var(--input-border)] bg-[var(--input-background)]\",\n },\n isInvalid: {\n true: \"border-[var(--destructive-background)]\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n isSelected: true,\n isInvalid: true,\n className: \"border-[var(--destructive-background)] bg-[var(--destructive-background)]\",\n },\n ],\n defaultVariants: {\n size: \"default\",\n isSelected: false,\n isInvalid: false,\n },\n }\n);\n\n/** Layer 3: Inner dot with spring animation */\nexport const matrixGridRadioDotVariants = cva(\n [\n \"rounded-full bg-[var(--primary-action-foreground)]\",\n \"transition-transform duration-200\",\n \"motion-reduce:transition-none\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"h-1.5 w-1.5\",\n default: \"h-2 w-2\",\n lg: \"h-2.5 w-2.5\",\n },\n isSelected: {\n true: \"scale-100\",\n false: \"scale-0\",\n },\n },\n defaultVariants: {\n size: \"default\",\n isSelected: false,\n },\n }\n);\n","'use client';\n\n/**\n * MatrixGrid Component\n * Grid-style survey question with rows (statements) and columns (rating options).\n * Each row has a single radio selection.\n *\n * Uses role=\"grid\" ARIA pattern with roving tabindex for keyboard navigation.\n * Built from React Aria primitives directly for cell-based selection.\n *\n * @see WCAG 2.2 AAA — 44x44px touch targets, 7:1 contrast, keyboard navigation\n */\n\nimport {\n forwardRef,\n useState,\n useId,\n useCallback,\n useRef,\n type ForwardedRef,\n type KeyboardEvent,\n} from 'react';\nimport { cn } from '../../utils/cn';\nimport type { MatrixGridProps } from './MatrixGrid.types';\nimport {\n matrixGridContainerVariants,\n matrixGridScrollContainerVariants,\n matrixGridTableVariants,\n matrixGridColumnHeaderVariants,\n matrixGridRowHeaderVariants,\n matrixGridCellVariants,\n matrixGridRadioOuterVariants,\n matrixGridRadioVisualVariants,\n matrixGridRadioDotVariants,\n matrixGridRowVariants,\n} from './MatrixGrid.styles';\n\n// =============================================================================\n// MatrixGrid Component\n// =============================================================================\n\nconst MatrixGrid = forwardRef<HTMLDivElement, MatrixGridProps>(\n function MatrixGrid(props: MatrixGridProps, ref: ForwardedRef<HTMLDivElement>) {\n const {\n // Data\n rows,\n columns,\n // Value\n value,\n onChange,\n // Labels\n label,\n description,\n errorMessage,\n // State\n isRequired = false,\n isDisabled = false,\n isReadOnly = false,\n isInvalid = false,\n // Sizing\n size = 'default',\n // Standard\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedby,\n 'data-testid': dataTestId,\n } = props;\n\n const generatedId = useId();\n const groupId = id ?? generatedId;\n const labelId = `${groupId}-label`;\n const descriptionId = `${groupId}-description`;\n const errorId = `${groupId}-error`;\n\n const describedByParts: string[] = [];\n if (ariaDescribedby) describedByParts.push(ariaDescribedby);\n if (description) describedByParts.push(descriptionId);\n if (isInvalid && errorMessage) describedByParts.push(errorId);\n\n // Controlled vs uncontrolled state\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<Record<string, string | null>>({});\n const currentValue = isControlled ? (value ?? {}) : internalValue;\n\n // Roving tabindex: track focused cell [rowIndex, colIndex]\n // rowIndex is 0-based into data rows, colIndex is 0-based into columns\n const [focusedCell, setFocusedCell] = useState<[number, number]>([0, 0]);\n const gridRef = useRef<HTMLTableElement>(null);\n\n const handleSelect = useCallback(\n (rowId: string, colId: string) => {\n if (isDisabled || isReadOnly) return;\n const newValue = { ...currentValue, [rowId]: colId };\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onChange?.(newValue);\n },\n [currentValue, onChange, isDisabled, isReadOnly, isControlled],\n );\n\n const focusCell = useCallback(\n (rowIdx: number, colIdx: number) => {\n setFocusedCell([rowIdx, colIdx]);\n // Focus the button in the target cell\n const table = gridRef.current;\n if (!table) return;\n const row = table.querySelectorAll('tbody tr')[rowIdx];\n if (!row) return;\n // +1 to skip the row header cell\n const cell = row.querySelectorAll('td')[colIdx];\n if (!cell) return;\n const button = cell.querySelector('button');\n if (button) button.focus();\n },\n [],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTableElement>) => {\n const [rowIdx, colIdx] = focusedCell;\n const maxRow = rows.length - 1;\n const maxCol = columns.length - 1;\n\n let nextRow = rowIdx;\n let nextCol = colIdx;\n let handled = false;\n\n switch (e.key) {\n case 'ArrowRight':\n nextCol = Math.min(colIdx + 1, maxCol);\n handled = true;\n break;\n case 'ArrowLeft':\n nextCol = Math.max(colIdx - 1, 0);\n handled = true;\n break;\n case 'ArrowDown':\n nextRow = Math.min(rowIdx + 1, maxRow);\n handled = true;\n break;\n case 'ArrowUp':\n nextRow = Math.max(rowIdx - 1, 0);\n handled = true;\n break;\n case 'Home':\n nextCol = 0;\n handled = true;\n break;\n case 'End':\n nextCol = maxCol;\n handled = true;\n break;\n case ' ':\n case 'Enter': {\n const targetRow = rows[rowIdx];\n const targetCol = columns[colIdx];\n if (!isDisabled && !isReadOnly && targetRow && targetCol) {\n handleSelect(targetRow.id, targetCol.id);\n }\n handled = true;\n break;\n }\n default:\n break;\n }\n\n if (handled) {\n e.preventDefault();\n if (nextRow !== rowIdx || nextCol !== colIdx) {\n focusCell(nextRow, nextCol);\n }\n }\n },\n [focusedCell, rows, columns, handleSelect, focusCell, isDisabled, isReadOnly],\n );\n\n const handleCellClick = useCallback(\n (rowIdx: number, colIdx: number, rowId: string, colId: string) => {\n setFocusedCell([rowIdx, colIdx]);\n handleSelect(rowId, colId);\n },\n [handleSelect],\n );\n\n const handleCellFocus = useCallback(\n (rowIdx: number, colIdx: number) => {\n setFocusedCell([rowIdx, colIdx]);\n },\n [],\n );\n\n return (\n <div\n ref={ref}\n id={groupId}\n role=\"group\"\n aria-label={ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={describedByParts.length > 0 ? describedByParts.join(' ') : undefined}\n data-testid={dataTestId}\n className={cn(matrixGridContainerVariants({ size }), className)}\n >\n {/* Label */}\n {label && (\n <span id={labelId} className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n {isRequired && (\n <span className=\"ml-1 text-[var(--destructive-background)]\" aria-hidden=\"true\">\n *\n </span>\n )}\n </span>\n )}\n\n {/* Description */}\n {description && (\n <span\n id={descriptionId}\n className=\"text-sm text-[var(--menu-muted)]\"\n >\n {description}\n </span>\n )}\n\n {/* Scroll container */}\n <div className={matrixGridScrollContainerVariants({ size })}>\n <table\n ref={gridRef}\n role=\"grid\"\n aria-label={ariaLabel ?? label}\n onKeyDown={handleKeyDown}\n className={matrixGridTableVariants({ size })}\n >\n <thead>\n <tr role=\"row\">\n {/* Corner cell — visually empty but accessible */}\n <td className={matrixGridColumnHeaderVariants({ size })} />\n {columns.map((col) => (\n <th\n key={col.id}\n id={`${groupId}-col-${col.id}`}\n scope=\"col\"\n role=\"columnheader\"\n className={matrixGridColumnHeaderVariants({ size })}\n >\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, rowIdx) => (\n <tr\n key={row.id}\n role=\"row\"\n className={matrixGridRowVariants({ isEven: rowIdx % 2 === 1 })}\n >\n <th\n scope=\"row\"\n role=\"rowheader\"\n className={matrixGridRowHeaderVariants({ size })}\n >\n {row.label}\n </th>\n {columns.map((col, colIdx) => {\n const isSelected = currentValue[row.id] === col.id;\n const isFocused = focusedCell[0] === rowIdx && focusedCell[1] === colIdx;\n\n return (\n <td\n key={col.id}\n role=\"gridcell\"\n aria-describedby={`${groupId}-col-${col.id}`}\n className={matrixGridCellVariants({ size })}\n >\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n aria-label={`${row.label}, ${col.label}`}\n tabIndex={isFocused ? 0 : -1}\n disabled={isDisabled}\n onClick={() => handleCellClick(rowIdx, colIdx, row.id, col.id)}\n onFocus={() => handleCellFocus(rowIdx, colIdx)}\n className={matrixGridRadioOuterVariants()}\n >\n <span\n className={matrixGridRadioVisualVariants({\n size,\n isSelected,\n isInvalid,\n })}\n aria-hidden=\"true\"\n >\n <span\n className={matrixGridRadioDotVariants({\n size,\n isSelected,\n })}\n />\n </span>\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Error message */}\n {isInvalid && errorMessage && (\n <div\n id={errorId}\n role=\"alert\"\n className=\"text-sm text-[var(--destructive-background)]\"\n >\n {errorMessage}\n </div>\n )}\n </div>\n );\n },\n);\n\nMatrixGrid.displayName = \"MatrixGrid\";\n\nexport { MatrixGrid };\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\n\n/**\n * MatrixGrid size schema\n * All sizes maintain 44px minimum touch targets (WCAG 2.2 AAA)\n */\nexport const MatrixGridSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type MatrixGridSize = z.infer<typeof MatrixGridSizeSchema>;\n\n/**\n * Individual row schema — a statement to rate\n */\nexport const MatrixGridRowSchema = z.object({\n id: z.string(),\n label: z.string(),\n});\n\nexport type MatrixGridRow = z.infer<typeof MatrixGridRowSchema>;\n\n/**\n * Individual column schema — a rating option\n */\nexport const MatrixGridColumnSchema = z.object({\n id: z.string(),\n label: z.string(),\n});\n\nexport type MatrixGridColumn = z.infer<typeof MatrixGridColumnSchema>;\n\n/**\n * MatrixGrid props schema\n *\n * Grid-style survey question with rows (statements) and columns (rating options).\n * Each row has a single radio selection.\n *\n * Uses .refine() to enforce unique row IDs and unique column IDs — requires\n * getShape() helper from test-utils.ts in contract tests.\n */\nexport const MatrixGridPropsSchema = BaseComponentPropsSchema.extend({\n // Data\n rows: z.array(MatrixGridRowSchema).min(2),\n columns: z.array(MatrixGridColumnSchema).min(2).max(10),\n\n // Value — Record<rowId, columnId | null>\n value: z.record(z.string(), z.string().nullable()).optional(),\n onChange: z.custom<(value: Record<string, string | null>) => void>().optional(),\n\n // Labels\n label: z.string().optional(),\n description: z.string().optional(),\n errorMessage: z.string().optional(),\n\n // State\n isRequired: z.boolean().optional().default(false),\n isDisabled: z.boolean().optional().default(false),\n isReadOnly: z.boolean().optional().default(false),\n isInvalid: z.boolean().optional().default(false),\n\n // Sizing\n size: MatrixGridSizeSchema.optional().default('default'),\n}).refine(\n (data) => {\n const ids = data.rows.map((r) => r.id);\n return new Set(ids).size === ids.length;\n },\n { message: 'Row IDs must be unique', path: ['rows'] },\n).refine(\n (data) => {\n const ids = data.columns.map((c) => c.id);\n return new Set(ids).size === ids.length;\n },\n { message: 'Column IDs must be unique', path: ['columns'] },\n);\n\nexport type MatrixGridProps = z.infer<typeof MatrixGridPropsSchema>;\n"]}
@@ -0,0 +1,32 @@
1
+ declare const RatingScale: import("react").ForwardRefExoticComponent<{
2
+ min: number;
3
+ max: number;
4
+ step: number;
5
+ displayStyle: "slider" | "buttons" | "stars";
6
+ showNA: boolean;
7
+ isRequired: boolean;
8
+ isDisabled: boolean;
9
+ isReadOnly: boolean;
10
+ isInvalid: boolean;
11
+ size: "default" | "sm" | "lg";
12
+ className?: string | undefined;
13
+ children?: any;
14
+ id?: string | undefined;
15
+ 'aria-label'?: string | undefined;
16
+ 'aria-labelledby'?: string | undefined;
17
+ 'aria-describedby'?: string | undefined;
18
+ 'aria-live'?: "off" | "polite" | "assertive" | undefined;
19
+ 'aria-hidden'?: boolean | undefined;
20
+ 'data-testid'?: string | undefined;
21
+ value?: number | null | undefined;
22
+ onChange?: ((value: number | null) => void) | undefined;
23
+ label?: string | undefined;
24
+ description?: string | undefined;
25
+ errorMessage?: string | undefined;
26
+ lowLabel?: string | undefined;
27
+ highLabel?: string | undefined;
28
+ valueLabels?: Record<string, string> | undefined;
29
+ name?: string | undefined;
30
+ } & import("react").RefAttributes<HTMLDivElement>>;
31
+ export { RatingScale };
32
+ //# sourceMappingURL=RatingScale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RatingScale.d.ts","sourceRoot":"","sources":["../../../src/elements/RatingScale/RatingScale.tsx"],"names":[],"mappings":"AA0PA,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDAqMhB,CAAC;AAIF,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * RatingScale CVA Variant Definitions
3
+ *
4
+ * Organised by display style (buttons, stars, slider) and shared elements.
5
+ * All interactive elements maintain 44x44px minimum touch targets (WCAG 2.2 AAA).
6
+ */
7
+ /** Root wrapper */
8
+ export declare const ratingScaleContainerVariants: (props?: ({
9
+ size?: "default" | "sm" | "lg" | null | undefined;
10
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
11
+ /** Horizontal row containing scale items + endpoint labels */
12
+ export declare const ratingScaleRowVariants: (props?: ({
13
+ size?: "default" | "sm" | "lg" | null | undefined;
14
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
15
+ /** Layer 1: Touch target for each button (44x44px minimum, transparent) */
16
+ export declare const ratingScaleButtonOuterVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
17
+ /** Layer 2: Visual button */
18
+ export declare const ratingScaleButtonVisualVariants: (props?: ({
19
+ size?: "default" | "sm" | "lg" | null | undefined;
20
+ isSelected?: boolean | null | undefined;
21
+ isInvalid?: boolean | null | undefined;
22
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
23
+ /** Layer 1: Touch target for each star (44x44px minimum, transparent) */
24
+ export declare const ratingScaleStarOuterVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
25
+ /** Layer 2: Star icon visual */
26
+ export declare const ratingScaleStarVisualVariants: (props?: ({
27
+ size?: "default" | "sm" | "lg" | null | undefined;
28
+ isFilled?: boolean | null | undefined;
29
+ isInvalid?: boolean | null | undefined;
30
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
31
+ /** Slider track — overflow-visible so thumb + ticks render outside the thin bar */
32
+ export declare const ratingScaleSliderTrackVariants: (props?: ({
33
+ size?: "default" | "sm" | "lg" | null | undefined;
34
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
35
+ /** Slider filled portion of track */
36
+ export declare const ratingScaleSliderFillVariants: (props?: ({
37
+ isInvalid?: boolean | null | undefined;
38
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
39
+ /** Slider thumb — Layer 1 is handled by React Aria's SliderThumb (44px touch target) */
40
+ export declare const ratingScaleSliderThumbVariants: (props?: ({
41
+ size?: "default" | "sm" | "lg" | null | undefined;
42
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
43
+ /** Slider tick mark at each step — vertical lines below the track */
44
+ export declare const ratingScaleSliderTickVariants: (props?: ({
45
+ size?: "default" | "sm" | "lg" | null | undefined;
46
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
47
+ /** N/A toggle button */
48
+ export declare const ratingScaleNAButtonVariants: (props?: ({
49
+ size?: "default" | "sm" | "lg" | null | undefined;
50
+ isSelected?: boolean | null | undefined;
51
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
52
+ //# sourceMappingURL=RatingScale.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RatingScale.styles.d.ts","sourceRoot":"","sources":["../../../src/elements/RatingScale/RatingScale.styles.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAMH,mBAAmB;AACnB,eAAO,MAAM,4BAA4B;;8EASvC,CAAC;AAEH,8DAA8D;AAC9D,eAAO,MAAM,sBAAsB;;8EASjC,CAAC;AAMH,2EAA2E;AAC3E,eAAO,MAAM,8BAA8B,oFAS1C,CAAC;AAEF,6BAA6B;AAC7B,eAAO,MAAM,+BAA+B;;;;8EA6B3C,CAAC;AAMF,yEAAyE;AACzE,eAAO,MAAM,4BAA4B,oFASxC,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,6BAA6B;;;;8EA2BzC,CAAC;AAMF,mFAAmF;AACnF,eAAO,MAAM,8BAA8B;;8EAiB1C,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,6BAA6B;;8EAWzC,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,8BAA8B;;8EAoB1C,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,6BAA6B;;8EAYzC,CAAC;AAMF,wBAAwB;AACxB,eAAO,MAAM,2BAA2B;;;8EA6BvC,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * RatingScale display style schema
4
+ * Determines the visual rendering of the scale
5
+ */
6
+ export declare const RatingScaleDisplayStyleSchema: z.ZodEnum<{
7
+ slider: "slider";
8
+ buttons: "buttons";
9
+ stars: "stars";
10
+ }>;
11
+ export type RatingScaleDisplayStyle = z.infer<typeof RatingScaleDisplayStyleSchema>;
12
+ /**
13
+ * RatingScale size schema
14
+ * All sizes maintain 44px minimum touch targets (WCAG 2.2 AAA)
15
+ */
16
+ export declare const RatingScaleSizeSchema: z.ZodEnum<{
17
+ default: "default";
18
+ sm: "sm";
19
+ lg: "lg";
20
+ }>;
21
+ export type RatingScaleSize = z.infer<typeof RatingScaleSizeSchema>;
22
+ /**
23
+ * RatingScale props schema
24
+ *
25
+ * Configurable rating scale with 3 display styles:
26
+ * - buttons: RadioGroup with numbered buttons
27
+ * - stars: RadioGroup with star icons (fill up to selected)
28
+ * - slider: Slider with discrete steps and tick marks
29
+ */
30
+ export declare const RatingScalePropsSchema: z.ZodObject<{
31
+ className: z.ZodOptional<z.ZodString>;
32
+ children: z.ZodOptional<z.ZodAny>;
33
+ id: z.ZodOptional<z.ZodString>;
34
+ 'aria-label': z.ZodOptional<z.ZodString>;
35
+ 'aria-labelledby': z.ZodOptional<z.ZodString>;
36
+ 'aria-describedby': z.ZodOptional<z.ZodString>;
37
+ 'aria-live': z.ZodOptional<z.ZodEnum<{
38
+ off: "off";
39
+ polite: "polite";
40
+ assertive: "assertive";
41
+ }>>;
42
+ 'aria-hidden': z.ZodOptional<z.ZodBoolean>;
43
+ 'data-testid': z.ZodOptional<z.ZodString>;
44
+ value: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
45
+ onChange: z.ZodOptional<z.ZodCustom<(value: number | null) => void, (value: number | null) => void>>;
46
+ min: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
47
+ max: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
48
+ step: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
49
+ displayStyle: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
50
+ slider: "slider";
51
+ buttons: "buttons";
52
+ stars: "stars";
53
+ }>>>;
54
+ label: z.ZodOptional<z.ZodString>;
55
+ description: z.ZodOptional<z.ZodString>;
56
+ errorMessage: z.ZodOptional<z.ZodString>;
57
+ lowLabel: z.ZodOptional<z.ZodString>;
58
+ highLabel: z.ZodOptional<z.ZodString>;
59
+ valueLabels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
60
+ showNA: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
61
+ isRequired: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
62
+ isDisabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
63
+ isReadOnly: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
64
+ isInvalid: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
65
+ size: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
66
+ default: "default";
67
+ sm: "sm";
68
+ lg: "lg";
69
+ }>>>;
70
+ name: z.ZodOptional<z.ZodString>;
71
+ }, z.core.$strip>;
72
+ export type RatingScaleProps = z.infer<typeof RatingScalePropsSchema>;
73
+ //# sourceMappingURL=RatingScale.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RatingScale.types.d.ts","sourceRoot":"","sources":["../../../src/elements/RatingScale/RatingScale.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,eAAO,MAAM,6BAA6B;;;;EAAyC,CAAC;AACpF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;gDAGN,MAAM,GAAG,IAAI,KAAK,IAAI,UAAtB,MAAM,GAAG,IAAI,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCjD,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { RatingScale } from './RatingScale';
2
+ export { ratingScaleContainerVariants, ratingScaleRowVariants, ratingScaleButtonOuterVariants, ratingScaleButtonVisualVariants, ratingScaleStarOuterVariants, ratingScaleStarVisualVariants, ratingScaleSliderTrackVariants, ratingScaleSliderFillVariants, ratingScaleSliderThumbVariants, ratingScaleSliderTickVariants, ratingScaleNAButtonVariants, } from './RatingScale.styles';
3
+ export type { RatingScaleProps, RatingScaleDisplayStyle, RatingScaleSize, } from './RatingScale.types';
4
+ export { RatingScalePropsSchema, RatingScaleDisplayStyleSchema, RatingScaleSizeSchema, } from './RatingScale.types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/RatingScale/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,8BAA8B,EAC9B,+BAA+B,EAC/B,4BAA4B,EAC5B,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,qBAAqB,CAAC"}