react-awesome-stars-rating 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![CI](https://github.com/fedoryakubovich/react-awesome-stars-rating/actions/workflows/ci.yml/badge.svg)](https://github.com/fedoryakubovich/react-awesome-stars-rating/actions/workflows/ci.yml)
5
5
  [![license](https://img.shields.io/npm/l/react-awesome-stars-rating)](https://github.com/fedoryakubovich/react-awesome-stars-rating/blob/main/LICENSE)
6
6
 
7
- An accessible star rating component for React. Half stars from pointer position, full keyboard control, any scale or palette — in under 2 kB gzipped with no runtime dependencies.
7
+ An accessible star rating component for React. Half stars from pointer position, full keyboard control, any scale or palette — in under 3 kB gzipped with no runtime dependencies.
8
8
 
9
9
  **[Live demo](https://react-awesome-stars-rating.vercel.app)** · **[Storybook](https://react-awesome-stars-rating.vercel.app/storybook)**
10
10
 
@@ -12,7 +12,7 @@ An accessible star rating component for React. Half stars from pointer position,
12
12
 
13
13
  ## Highlights
14
14
 
15
- - Under 2 kB gzipped, no runtime dependencies
15
+ - Under 3 kB gzipped, no runtime dependencies
16
16
  - Half-star precision from pointer position, plus arrow-key stepping
17
17
  - `role="slider"` with live `aria-valuenow` / `aria-valuetext`, verified with axe-core
18
18
  - ESM + CJS with correct types for each, and a UMD bundle for CDN use
@@ -69,23 +69,27 @@ export default function Example() {
69
69
 
70
70
  ## Props
71
71
 
72
- | Name | Description | Type | Default |
73
- | :------------- | :---------------------------------------- | :------------------------ | :-------------- |
74
- | id | Identifier | `string` | auto-generated |
75
- | value | Current value | `number` | `0` |
76
- | onChange | Called when value changes | `(value: number) => void` | `() => {}` |
77
- | isEdit | Editing mode | `boolean` | `true` |
78
- | isHalf | Allow half stars | `boolean` | `true` |
79
- | count | Number of stars | `number` | `5` |
80
- | size | Star size (px) | `number` | `25` |
81
- | starGap | Gap between stars | `number` | `0` |
82
- | className | Container class | `string` | `''` |
83
- | primaryColor | Active star color | `string` | `'orange'` |
84
- | secondaryColor | Inactive star color | `string` | `'grey'` |
85
- | hoverColor | Optional pointer-preview color | `string` | `undefined` |
86
- | isArrowSubmit | Arrow keys trigger `onChange` immediately | `boolean` | `false` |
87
- | ariaLabel | Accessible label (if no `ariaLabelledBy`) | `string` | `'Star rating'` |
88
- | ariaLabelledBy | ID of element that labels the control | `string` | `undefined` |
72
+ | Name | Description | Type | Default |
73
+ | :------------- | :---------------------------------------- | :------------------------- | :-------------- |
74
+ | id | Identifier | `string` | auto-generated |
75
+ | value | Controlled current value | `number` | `undefined` |
76
+ | defaultValue | Initial uncontrolled value | `number` | `0` |
77
+ | onChange | Called when value changes | `(value: number) => void` | `() => {}` |
78
+ | name | Hidden native form input name | `string` | `undefined` |
79
+ | disabled | Disable interaction and form submission | `boolean` | `false` |
80
+ | isEdit | Editing mode | `boolean` | `true` |
81
+ | isHalf | Allow half stars | `boolean` | `true` |
82
+ | count | Number of stars | `number` | `5` |
83
+ | size | Star size (px) | `number` | `25` |
84
+ | starGap | Gap between stars | `number` | `0` |
85
+ | className | Container class | `string` | `''` |
86
+ | primaryColor | Active star color | `string` | `'orange'` |
87
+ | secondaryColor | Inactive star color | `string` | `'grey'` |
88
+ | hoverColor | Optional pointer-preview color | `string` | `undefined` |
89
+ | isArrowSubmit | Arrow keys trigger `onChange` immediately | `boolean` | `false` |
90
+ | ariaLabel | Accessible label (if no `ariaLabelledBy`) | `string` | `'Star rating'` |
91
+ | ariaLabelledBy | ID of element that labels the control | `string` | `undefined` |
92
+ | getValueText | Formats accessible value text | `(value, count) => string` | English text |
89
93
 
90
94
  ## Keyboard and accessibility
91
95
 
@@ -103,6 +107,16 @@ With `isArrowSubmit`, each arrow step reports through `onChange` immediately rat
103
107
 
104
108
  When `isEdit` is `false` the control is inert regardless of `isArrowSubmit`: no hover preview, no keyboard, `tabIndex={-1}`, and `aria-readonly="true"`.
105
109
 
110
+ The slider explicitly reports `aria-orientation="horizontal"`. Use
111
+ `getValueText` to localize its spoken value:
112
+
113
+ ```tsx
114
+ <ReactStarsRating
115
+ value={2.5}
116
+ getValueText={(value, count) => `${value} von ${count} Sternen`}
117
+ />
118
+ ```
119
+
106
120
  ### Hover preview color
107
121
 
108
122
  Set `hoverColor` to distinguish the pointer preview from both the saved value
@@ -129,6 +143,22 @@ The package carries the `'use client'` directive, so it can be imported directly
129
143
 
130
144
  ## Form Integrations
131
145
 
146
+ ### Native HTML forms
147
+
148
+ Pass `name` to contribute a hidden value to `FormData`. `defaultValue` enables
149
+ uncontrolled usage and native form reset behavior.
150
+
151
+ ```tsx
152
+ <form action="/reviews" method="post">
153
+ <ReactStarsRating name="rating" defaultValue={3} />
154
+ <button type="submit">Submit</button>
155
+ <button type="reset">Reset</button>
156
+ </form>
157
+ ```
158
+
159
+ Use `value` with `onChange` for controlled state. Supplying `value` always
160
+ takes precedence over `defaultValue`.
161
+
132
162
  ### React Hook Form
133
163
 
134
164
  ```tsx
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require("react"),t=require("react/jsx-runtime");var n=(e,t)=>Math.min(100,Math.max(0,Math.round((e-(t-1))*1e4)/100)),r=({primaryColor:e,secondaryColor:r,offset:i=50,index:a,value:o,fullId:s,halfId:c,noneId:l,hoverColor:u,hoverValue:d=null,committedValue:f=o,hoverGradientId:p})=>{if(u&&d!==null&&p){let i=Math.min(f,d),o=Math.max(f,d),s=n(i,a),c=n(o,a),l=[{start:0,end:s,color:d<=f?u:e},{start:s,end:c,color:d<=f?e:u},{start:c,end:100,color:r}].filter(({start:e,end:t})=>t>e);return(0,t.jsx)(`defs`,{children:(0,t.jsx)(`linearGradient`,{id:p,children:l.flatMap(({start:e,end:n,color:r},i)=>[(0,t.jsx)(`stop`,{offset:`${e}%`,stopColor:r},`${i}-start`),(0,t.jsx)(`stop`,{offset:`${n}%`,stopColor:r},`${i}-end`)])})})}let m=i;return a===1&&(m=Math.round(o%1*1e4)/100),a===1?(0,t.jsxs)(`defs`,{children:[(0,t.jsx)(`linearGradient`,{id:s,children:(0,t.jsx)(`stop`,{offset:`100%`,stopColor:e})}),(0,t.jsx)(`linearGradient`,{id:l,children:(0,t.jsx)(`stop`,{offset:`100%`,stopColor:r})}),(0,t.jsxs)(`linearGradient`,{id:c,children:[(0,t.jsx)(`stop`,{offset:`${m}%`,stopColor:e}),(0,t.jsx)(`stop`,{offset:`${m}%`,stopColor:r})]})]}):null},i=({viewBox:e=`0 0 306 306`,size:n,onMouseMove:i,onMouseLeave:a,onChange:o,index:s,value:c,isHalf:l,primaryColor:u,secondaryColor:d,hoverColor:f,hoverValue:p=null,committedValue:m=c,fill:h,offset:g=50,fullId:_,halfId:v,noneId:y})=>{let b=h,x=`${_}-hover-${s}`;return b=f&&p!==null?`url(#${x})`:s<=c?`url(#${_})`:l&&Math.ceil(c)===s?`url(#${v})`:`url(#${y})`,(0,t.jsxs)(`svg`,{width:n,viewBox:e,xmlns:`http://www.w3.org/2000/svg`,xmlnsXlink:`http://www.w3.org/1999/xlink`,onMouseLeave:a,onClick:o,onMouseMove:i,children:[(0,t.jsx)(r,{primaryColor:u,secondaryColor:d,offset:g,index:s,value:c,fullId:_,halfId:v,noneId:y,hoverColor:f,hoverValue:p,committedValue:m,hoverGradientId:x}),(0,t.jsx)(`polygon`,{fill:b,points:`153,230.775 247.35,299.625 211.65,187.425 306,121.125 191.25,121.125 153,6.375 114.75,121.125 0,121.125 94.35,187.425 58.65,299.625`,pointerEvents:`none`})]})},a={activeContainer:{border:`none`,display:`inline-flex`},inActiveContainer:{border:`none`,outline:0,display:`inline-flex`}},o=({id:n,value:r=0,onChange:o=()=>{},isEdit:s=!0,isHalf:c=!0,count:l=5,size:u=25,starGap:d=0,className:f=``,primaryColor:p=`orange`,secondaryColor:m=`grey`,hoverColor:h,isArrowSubmit:g=!1,ariaLabel:_=`Star rating`,ariaLabelledBy:v})=>{let y=(0,e.useId)().replace(/:/g,``),b=n??`react-stars-rating-${y}`,[x,S]=(0,e.useState)(()=>({sourceValue:r,displayValue:r})),C=(0,e.useRef)(null),[w,T]=(0,e.useState)(null),E=x.sourceValue===r?x.displayValue:r,D=e=>{S({sourceValue:r,displayValue:e})},O=(0,e.useMemo)(()=>`fullId-${b}`,[b]),k=(0,e.useMemo)(()=>`halfId-${b}`,[b]),A=(0,e.useMemo)(()=>`noneId-${b}`,[b]);(0,e.useEffect)(()=>{C.current=null},[r]);let j=e=>{let t=e.currentTarget.getBoundingClientRect();return e.clientX-t.left>t.width/2},M=(e,t)=>c?j(e)?t:t-.5:t,N=(e,t)=>{if(!s)return;let n=M(e,t);T(n),D(n)},P=()=>{s&&(T(null),D(r||0))},F=()=>{let e=C.current;e!==null&&(C.current=null,o(e))},I=(e,t)=>{if(!s)return;let n=M(e,t);D(n),C.current=null,o(n)},L=e=>{let t=Math.min(Math.max(e,0),l);t!==E&&(D(t),g?(C.current=null,o(t)):C.current=t)},R=e=>{let t=E%1==.5?E:Math.round(E);L(t+e)},z=e=>{switch(e.key){case`ArrowLeft`:case`ArrowDown`:e.preventDefault(),R(c?-.5:-1);break;case`ArrowRight`:case`ArrowUp`:e.preventDefault(),R(c?.5:1);break;case`Home`:e.preventDefault(),L(0);break;case`End`:e.preventDefault(),L(l);break;case`Enter`:e.preventDefault(),C.current=null,o(E)}},B=()=>Array.from({length:l},(e,n)=>{let a=n+1,o=a===l?void 0:{paddingRight:d};return(0,t.jsx)(`span`,{className:`star star-${a}`,style:o,children:(0,t.jsx)(i,{index:a,value:E,size:u,isHalf:c,fullId:O,halfId:k,noneId:A,primaryColor:p,secondaryColor:m,hoverColor:h,hoverValue:w,committedValue:r,onMouseMove:e=>N(e,a),onMouseLeave:P,onChange:e=>I(e,a)})},`react-stars-rating-char${a}`)}),V=s,H=Math.min(Math.max(E,0),l);return(0,t.jsx)(`span`,{id:b,role:`slider`,"aria-label":v?void 0:_,"aria-labelledby":v,"aria-valuemin":0,"aria-valuemax":l,"aria-valuenow":H,"aria-valuetext":`${H} of ${l}`,"aria-readonly":!s,tabIndex:V?0:-1,onKeyDown:V?z:void 0,onBlur:V?F:void 0,style:s?a.activeContainer:a.inActiveContainer,className:f,children:B()})};exports.ReactStarsRating=o,exports.default=o;
1
+ "use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require("react"),t=require("react/jsx-runtime");var n=(e,t)=>Math.min(100,Math.max(0,Math.round((e-(t-1))*1e4)/100)),r=({primaryColor:e,secondaryColor:r,offset:i=50,index:a,value:o,fullId:s,halfId:c,noneId:l,hoverColor:u,hoverValue:d=null,committedValue:f=o,hoverGradientId:p})=>{if(u&&d!==null&&p){let i=Math.min(f,d),o=Math.max(f,d),s=n(i,a),c=n(o,a),l=[{start:0,end:s,color:d<=f?u:e},{start:s,end:c,color:d<=f?e:u},{start:c,end:100,color:r}].filter(({start:e,end:t})=>t>e);return(0,t.jsx)(`defs`,{children:(0,t.jsx)(`linearGradient`,{id:p,children:l.flatMap(({start:e,end:n,color:r},i)=>[(0,t.jsx)(`stop`,{offset:`${e}%`,stopColor:r},`${i}-start`),(0,t.jsx)(`stop`,{offset:`${n}%`,stopColor:r},`${i}-end`)])})})}let m=i;return a===1&&(m=Math.round(o%1*1e4)/100),a===1?(0,t.jsxs)(`defs`,{children:[(0,t.jsx)(`linearGradient`,{id:s,children:(0,t.jsx)(`stop`,{offset:`100%`,stopColor:e})}),(0,t.jsx)(`linearGradient`,{id:l,children:(0,t.jsx)(`stop`,{offset:`100%`,stopColor:r})}),(0,t.jsxs)(`linearGradient`,{id:c,children:[(0,t.jsx)(`stop`,{offset:`${m}%`,stopColor:e}),(0,t.jsx)(`stop`,{offset:`${m}%`,stopColor:r})]})]}):null},i=({viewBox:e=`0 0 306 306`,size:n,onPointerMove:i,onPointerLeave:a,onPointerDown:o,onPointerUp:s,onPointerCancel:c,index:l,value:u,isHalf:d,primaryColor:f,secondaryColor:p,hoverColor:m,hoverValue:h=null,committedValue:g=u,fill:_,offset:v=50,fullId:y,halfId:b,noneId:x})=>{let S=_,C=`${y}-hover-${l}`;return S=m&&h!==null?`url(#${C})`:l<=u?`url(#${y})`:d&&Math.ceil(u)===l?`url(#${b})`:`url(#${x})`,(0,t.jsxs)(`svg`,{width:n,viewBox:e,xmlns:`http://www.w3.org/2000/svg`,xmlnsXlink:`http://www.w3.org/1999/xlink`,onPointerLeave:a,onPointerMove:i,onPointerDown:o,onPointerUp:s,onPointerCancel:c,children:[(0,t.jsx)(r,{primaryColor:f,secondaryColor:p,offset:v,index:l,value:u,fullId:y,halfId:b,noneId:x,hoverColor:m,hoverValue:h,committedValue:g,hoverGradientId:C}),(0,t.jsx)(`polygon`,{fill:S,points:`153,230.775 247.35,299.625 211.65,187.425 306,121.125 191.25,121.125 153,6.375 114.75,121.125 0,121.125 94.35,187.425 58.65,299.625`,pointerEvents:`none`})]})},a={activeContainer:{border:`none`,display:`inline-flex`},inActiveContainer:{border:`none`,outline:0,display:`inline-flex`}},o=e=>Number.isFinite(e)&&e>=1?Math.floor(e):5,s=(e,t,n=0)=>Number.isFinite(e)&&e>=n?e:t,c=(e,t,n)=>{let r=Math.min(Math.max(Number.isFinite(e)?e:0,0),t);return n?r:Math.round(r)},l=({id:n,value:r,defaultValue:l=0,onChange:u=()=>{},name:d,disabled:f=!1,isEdit:p=!0,isHalf:m=!0,count:h=5,size:g=25,starGap:_=0,className:v=``,primaryColor:y=`orange`,secondaryColor:b=`grey`,hoverColor:x,isArrowSubmit:S=!1,ariaLabel:C=`Star rating`,ariaLabelledBy:w,getValueText:ee=(e,t)=>`${e} of ${t}`})=>{let T=o(h),te=s(g,25,2**-52),E=s(_,0),D=r!==void 0,[ne,O]=(0,e.useState)(()=>c(l,T,m)),k=c(r??ne,T,m),A=(0,e.useId)().replace(/:/g,``),j=n??`react-stars-rating-${A}`,[M,N]=(0,e.useState)(()=>({sourceValue:k,displayValue:k})),P=(0,e.useRef)(null),[F,I]=(0,e.useState)(null),L=(0,e.useRef)(null),R=M.sourceValue===k?M.displayValue:k,z=e=>{N({sourceValue:k,displayValue:c(e,T,m)})},re=(0,e.useMemo)(()=>`fullId-${j}`,[j]),B=(0,e.useMemo)(()=>`halfId-${j}`,[j]),V=(0,e.useMemo)(()=>`noneId-${j}`,[j]);(0,e.useEffect)(()=>{P.current=null},[k]),(0,e.useEffect)(()=>{if(D)return;let e=L.current?.closest(`form`),t=()=>{let e=c(l,T,m);P.current=null,I(null),O(e),N({sourceValue:e,displayValue:e})};return e?.addEventListener(`reset`,t),()=>e?.removeEventListener(`reset`,t)},[l,D,m,T]);let H=(e,t)=>{let n=Array.from(L.current?.querySelectorAll(`svg`)??[]),r=n.find(t=>{let n=t.getBoundingClientRect();return n.width>0&&e.clientX<=n.right})??n[n.length-1]??e.currentTarget,i=n.indexOf(r)+1||t;if(!m)return i;let a=r.getBoundingClientRect();return e.clientX-a.left>a.width/2?i:i-.5},U=(e,t)=>{if(!p||f)return;let n=typeof e.currentTarget.hasPointerCapture==`function`&&e.currentTarget.hasPointerCapture(e.pointerId);if(e.pointerType===`touch`&&!n)return;let r=H(e,t);P.current=null,I(r),z(r)},W=e=>{!p||f||e.buttons!==0||(I(null),z(k))},G=()=>{let e=P.current;e!==null&&(P.current=null,K(e))},K=e=>{let t=c(e,T,m);z(t),D||O(t),u(t)},q=(e,t)=>{if(!p||f)return;L.current?.focus(),e.currentTarget.setPointerCapture?.(e.pointerId),P.current=null;let n=H(e,t);I(n),z(n)},J=(e,t)=>{!p||f||(K(H(e,t)),e.currentTarget.releasePointerCapture?.(e.pointerId),e.pointerType===`touch`&&I(null))},Y=e=>{e.currentTarget.releasePointerCapture?.(e.pointerId),P.current=null,I(null),z(k)},X=e=>{let t=c(e,T,m);t!==R&&(z(t),S?(P.current=null,K(t)):P.current=t)},Z=e=>{let t=R%1==.5?R:Math.round(R);X(t+e)},ie=e=>{switch(e.key){case`ArrowLeft`:case`ArrowDown`:e.preventDefault(),Z(m?-.5:-1);break;case`ArrowRight`:case`ArrowUp`:e.preventDefault(),Z(m?.5:1);break;case`Home`:e.preventDefault(),X(0);break;case`End`:e.preventDefault(),X(T);break;case`Enter`:e.preventDefault(),P.current=null,K(R)}},ae=()=>Array.from({length:T},(e,n)=>{let r=n+1,a=r===T?void 0:{paddingRight:E};return(0,t.jsx)(`span`,{className:`star star-${r}`,style:a,children:(0,t.jsx)(i,{index:r,value:R,size:te,isHalf:m,fullId:re,halfId:B,noneId:V,primaryColor:y,secondaryColor:b,hoverColor:x,hoverValue:F,committedValue:k,onPointerMove:e=>U(e,r),onPointerLeave:W,onPointerDown:e=>q(e,r),onPointerUp:e=>J(e,r),onPointerCancel:Y})},`react-stars-rating-char${r}`)}),Q=p&&!f,$=c(R,T,m);return(0,t.jsxs)(`span`,{ref:L,id:j,role:`slider`,"aria-label":w?void 0:C,"aria-labelledby":w,"aria-valuemin":0,"aria-valuemax":T,"aria-valuenow":$,"aria-valuetext":ee($,T),"aria-orientation":`horizontal`,"aria-readonly":!p,"aria-disabled":f||void 0,tabIndex:Q?0:-1,onKeyDown:Q?ie:void 0,onBlur:Q?G:void 0,style:p?a.activeContainer:a.inActiveContainer,className:v,children:[ae(),d?(0,t.jsx)(`input`,{type:`hidden`,name:d,value:k,disabled:f}):null]})};exports.ReactStarsRating=l,exports.default=l;
package/dist/index.d.cts CHANGED
@@ -5,18 +5,28 @@ export type ReactStarsRatingProps = {
5
5
  */
6
6
  id?: string;
7
7
  /**
8
- * Current rating. Values outside `0` to {@link ReactStarsRatingProps.count}
9
- * are clamped before they are reported to assistive technology.
8
+ * Controlled current rating. Values outside `0` to
9
+ * {@link ReactStarsRatingProps.count} are clamped. When omitted, the
10
+ * component manages its own value.
11
+ */
12
+ value?: number;
13
+ /**
14
+ * Initial value when the component is uncontrolled. Ignored when
15
+ * {@link ReactStarsRatingProps.value} is provided.
10
16
  *
11
17
  * @defaultValue 0
12
18
  */
13
- value?: number;
19
+ defaultValue?: number;
14
20
  /**
15
21
  * Called with the new rating on click, on `Enter`, and on blur — and on
16
22
  * every arrow key when {@link ReactStarsRatingProps.isArrowSubmit} is set.
17
23
  * Hovering never calls it.
18
24
  */
19
25
  onChange?: (value: number) => void;
26
+ /** Name of the hidden input contributed to the nearest HTML form. */
27
+ name?: string;
28
+ /** Disable interaction and native form submission. */
29
+ disabled?: boolean;
20
30
  /**
21
31
  * Whether the rating can be changed. When `false` the control has no hover
22
32
  * preview, no keyboard handling, and is removed from the tab order.
@@ -98,6 +108,12 @@ export type ReactStarsRatingProps = {
98
108
  * {@link ReactStarsRatingProps.ariaLabel}.
99
109
  */
100
110
  ariaLabelledBy?: string;
111
+ /**
112
+ * Formats the accessible value description.
113
+ *
114
+ * @defaultValue `(value, count) => `${value} of ${count}``
115
+ */
116
+ getValueText?: (value: number, count: number) => string;
101
117
  };
102
118
  /**
103
119
  * A star rating control. Renders as a single `role="slider"` element that
@@ -110,6 +126,6 @@ export type ReactStarsRatingProps = {
110
126
  * <ReactStarsRating value={value} onChange={setValue} isHalf size={32} />
111
127
  * ```
112
128
  */
113
- declare const ReactStarsRating: ({ id, value, onChange, isEdit, isHalf, count, size, starGap, className, primaryColor, secondaryColor, hoverColor, isArrowSubmit, ariaLabel, ariaLabelledBy, }: ReactStarsRatingProps) => import("react").JSX.Element;
129
+ declare const ReactStarsRating: ({ id, value, defaultValue, onChange, name, disabled, isEdit, isHalf, count, size, starGap, className, primaryColor, secondaryColor, hoverColor, isArrowSubmit, ariaLabel, ariaLabelledBy, getValueText, }: ReactStarsRatingProps) => import("react").JSX.Element;
114
130
  export { ReactStarsRating };
115
131
  export default ReactStarsRating;
package/dist/index.d.ts CHANGED
@@ -5,18 +5,28 @@ export type ReactStarsRatingProps = {
5
5
  */
6
6
  id?: string;
7
7
  /**
8
- * Current rating. Values outside `0` to {@link ReactStarsRatingProps.count}
9
- * are clamped before they are reported to assistive technology.
8
+ * Controlled current rating. Values outside `0` to
9
+ * {@link ReactStarsRatingProps.count} are clamped. When omitted, the
10
+ * component manages its own value.
11
+ */
12
+ value?: number;
13
+ /**
14
+ * Initial value when the component is uncontrolled. Ignored when
15
+ * {@link ReactStarsRatingProps.value} is provided.
10
16
  *
11
17
  * @defaultValue 0
12
18
  */
13
- value?: number;
19
+ defaultValue?: number;
14
20
  /**
15
21
  * Called with the new rating on click, on `Enter`, and on blur — and on
16
22
  * every arrow key when {@link ReactStarsRatingProps.isArrowSubmit} is set.
17
23
  * Hovering never calls it.
18
24
  */
19
25
  onChange?: (value: number) => void;
26
+ /** Name of the hidden input contributed to the nearest HTML form. */
27
+ name?: string;
28
+ /** Disable interaction and native form submission. */
29
+ disabled?: boolean;
20
30
  /**
21
31
  * Whether the rating can be changed. When `false` the control has no hover
22
32
  * preview, no keyboard handling, and is removed from the tab order.
@@ -98,6 +108,12 @@ export type ReactStarsRatingProps = {
98
108
  * {@link ReactStarsRatingProps.ariaLabel}.
99
109
  */
100
110
  ariaLabelledBy?: string;
111
+ /**
112
+ * Formats the accessible value description.
113
+ *
114
+ * @defaultValue `(value, count) => `${value} of ${count}``
115
+ */
116
+ getValueText?: (value: number, count: number) => string;
101
117
  };
102
118
  /**
103
119
  * A star rating control. Renders as a single `role="slider"` element that
@@ -110,6 +126,6 @@ export type ReactStarsRatingProps = {
110
126
  * <ReactStarsRating value={value} onChange={setValue} isHalf size={32} />
111
127
  * ```
112
128
  */
113
- declare const ReactStarsRating: ({ id, value, onChange, isEdit, isHalf, count, size, starGap, className, primaryColor, secondaryColor, hoverColor, isArrowSubmit, ariaLabel, ariaLabelledBy, }: ReactStarsRatingProps) => import("react").JSX.Element;
129
+ declare const ReactStarsRating: ({ id, value, defaultValue, onChange, name, disabled, isEdit, isHalf, count, size, starGap, className, primaryColor, secondaryColor, hoverColor, isArrowSubmit, ariaLabel, ariaLabelledBy, getValueText, }: ReactStarsRatingProps) => import("react").JSX.Element;
114
130
  export { ReactStarsRating };
115
131
  export default ReactStarsRating;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- "use client";import{useEffect as e,useId as t,useMemo as n,useRef as r,useState as i}from"react";import{jsx as a,jsxs as o}from"react/jsx-runtime";var s=(e,t)=>Math.min(100,Math.max(0,Math.round((e-(t-1))*1e4)/100)),c=({primaryColor:e,secondaryColor:t,offset:n=50,index:r,value:i,fullId:c,halfId:l,noneId:u,hoverColor:d,hoverValue:f=null,committedValue:p=i,hoverGradientId:m})=>{if(d&&f!==null&&m){let n=Math.min(p,f),i=Math.max(p,f),o=s(n,r),c=s(i,r),l=[{start:0,end:o,color:f<=p?d:e},{start:o,end:c,color:f<=p?e:d},{start:c,end:100,color:t}].filter(({start:e,end:t})=>t>e);return a(`defs`,{children:a(`linearGradient`,{id:m,children:l.flatMap(({start:e,end:t,color:n},r)=>[a(`stop`,{offset:`${e}%`,stopColor:n},`${r}-start`),a(`stop`,{offset:`${t}%`,stopColor:n},`${r}-end`)])})})}let h=n;return r===1&&(h=Math.round(i%1*1e4)/100),r===1?o(`defs`,{children:[a(`linearGradient`,{id:c,children:a(`stop`,{offset:`100%`,stopColor:e})}),a(`linearGradient`,{id:u,children:a(`stop`,{offset:`100%`,stopColor:t})}),o(`linearGradient`,{id:l,children:[a(`stop`,{offset:`${h}%`,stopColor:e}),a(`stop`,{offset:`${h}%`,stopColor:t})]})]}):null},l=({viewBox:e=`0 0 306 306`,size:t,onMouseMove:n,onMouseLeave:r,onChange:i,index:s,value:l,isHalf:u,primaryColor:d,secondaryColor:f,hoverColor:p,hoverValue:m=null,committedValue:h=l,fill:g,offset:_=50,fullId:v,halfId:y,noneId:b})=>{let x=g,S=`${v}-hover-${s}`;return x=p&&m!==null?`url(#${S})`:s<=l?`url(#${v})`:u&&Math.ceil(l)===s?`url(#${y})`:`url(#${b})`,o(`svg`,{width:t,viewBox:e,xmlns:`http://www.w3.org/2000/svg`,xmlnsXlink:`http://www.w3.org/1999/xlink`,onMouseLeave:r,onClick:i,onMouseMove:n,children:[a(c,{primaryColor:d,secondaryColor:f,offset:_,index:s,value:l,fullId:v,halfId:y,noneId:b,hoverColor:p,hoverValue:m,committedValue:h,hoverGradientId:S}),a(`polygon`,{fill:x,points:`153,230.775 247.35,299.625 211.65,187.425 306,121.125 191.25,121.125 153,6.375 114.75,121.125 0,121.125 94.35,187.425 58.65,299.625`,pointerEvents:`none`})]})},u={activeContainer:{border:`none`,display:`inline-flex`},inActiveContainer:{border:`none`,outline:0,display:`inline-flex`}},d=({id:o,value:s=0,onChange:c=()=>{},isEdit:d=!0,isHalf:f=!0,count:p=5,size:m=25,starGap:h=0,className:g=``,primaryColor:_=`orange`,secondaryColor:v=`grey`,hoverColor:y,isArrowSubmit:b=!1,ariaLabel:x=`Star rating`,ariaLabelledBy:S})=>{let C=t().replace(/:/g,``),w=o??`react-stars-rating-${C}`,[T,E]=i(()=>({sourceValue:s,displayValue:s})),D=r(null),[O,k]=i(null),A=T.sourceValue===s?T.displayValue:s,j=e=>{E({sourceValue:s,displayValue:e})},M=n(()=>`fullId-${w}`,[w]),N=n(()=>`halfId-${w}`,[w]),P=n(()=>`noneId-${w}`,[w]);e(()=>{D.current=null},[s]);let F=e=>{let t=e.currentTarget.getBoundingClientRect();return e.clientX-t.left>t.width/2},I=(e,t)=>f?F(e)?t:t-.5:t,L=(e,t)=>{if(!d)return;let n=I(e,t);k(n),j(n)},R=()=>{d&&(k(null),j(s||0))},z=()=>{let e=D.current;e!==null&&(D.current=null,c(e))},B=(e,t)=>{if(!d)return;let n=I(e,t);j(n),D.current=null,c(n)},V=e=>{let t=Math.min(Math.max(e,0),p);t!==A&&(j(t),b?(D.current=null,c(t)):D.current=t)},H=e=>{let t=A%1==.5?A:Math.round(A);V(t+e)},U=e=>{switch(e.key){case`ArrowLeft`:case`ArrowDown`:e.preventDefault(),H(f?-.5:-1);break;case`ArrowRight`:case`ArrowUp`:e.preventDefault(),H(f?.5:1);break;case`Home`:e.preventDefault(),V(0);break;case`End`:e.preventDefault(),V(p);break;case`Enter`:e.preventDefault(),D.current=null,c(A)}},W=()=>Array.from({length:p},(e,t)=>{let n=t+1,r=n===p?void 0:{paddingRight:h};return a(`span`,{className:`star star-${n}`,style:r,children:a(l,{index:n,value:A,size:m,isHalf:f,fullId:M,halfId:N,noneId:P,primaryColor:_,secondaryColor:v,hoverColor:y,hoverValue:O,committedValue:s,onMouseMove:e=>L(e,n),onMouseLeave:R,onChange:e=>B(e,n)})},`react-stars-rating-char${n}`)}),G=d,K=Math.min(Math.max(A,0),p);return a(`span`,{id:w,role:`slider`,"aria-label":S?void 0:x,"aria-labelledby":S,"aria-valuemin":0,"aria-valuemax":p,"aria-valuenow":K,"aria-valuetext":`${K} of ${p}`,"aria-readonly":!d,tabIndex:G?0:-1,onKeyDown:G?U:void 0,onBlur:G?z:void 0,style:d?u.activeContainer:u.inActiveContainer,className:g,children:W()})};export{d as ReactStarsRating,d as default};
1
+ "use client";import{useEffect as e,useId as t,useMemo as n,useRef as r,useState as i}from"react";import{jsx as a,jsxs as o}from"react/jsx-runtime";var s=(e,t)=>Math.min(100,Math.max(0,Math.round((e-(t-1))*1e4)/100)),c=({primaryColor:e,secondaryColor:t,offset:n=50,index:r,value:i,fullId:c,halfId:l,noneId:u,hoverColor:d,hoverValue:f=null,committedValue:p=i,hoverGradientId:m})=>{if(d&&f!==null&&m){let n=Math.min(p,f),i=Math.max(p,f),o=s(n,r),c=s(i,r),l=[{start:0,end:o,color:f<=p?d:e},{start:o,end:c,color:f<=p?e:d},{start:c,end:100,color:t}].filter(({start:e,end:t})=>t>e);return a(`defs`,{children:a(`linearGradient`,{id:m,children:l.flatMap(({start:e,end:t,color:n},r)=>[a(`stop`,{offset:`${e}%`,stopColor:n},`${r}-start`),a(`stop`,{offset:`${t}%`,stopColor:n},`${r}-end`)])})})}let h=n;return r===1&&(h=Math.round(i%1*1e4)/100),r===1?o(`defs`,{children:[a(`linearGradient`,{id:c,children:a(`stop`,{offset:`100%`,stopColor:e})}),a(`linearGradient`,{id:u,children:a(`stop`,{offset:`100%`,stopColor:t})}),o(`linearGradient`,{id:l,children:[a(`stop`,{offset:`${h}%`,stopColor:e}),a(`stop`,{offset:`${h}%`,stopColor:t})]})]}):null},l=({viewBox:e=`0 0 306 306`,size:t,onPointerMove:n,onPointerLeave:r,onPointerDown:i,onPointerUp:s,onPointerCancel:l,index:u,value:d,isHalf:f,primaryColor:p,secondaryColor:m,hoverColor:h,hoverValue:g=null,committedValue:_=d,fill:v,offset:y=50,fullId:b,halfId:x,noneId:S})=>{let C=v,w=`${b}-hover-${u}`;return C=h&&g!==null?`url(#${w})`:u<=d?`url(#${b})`:f&&Math.ceil(d)===u?`url(#${x})`:`url(#${S})`,o(`svg`,{width:t,viewBox:e,xmlns:`http://www.w3.org/2000/svg`,xmlnsXlink:`http://www.w3.org/1999/xlink`,onPointerLeave:r,onPointerMove:n,onPointerDown:i,onPointerUp:s,onPointerCancel:l,children:[a(c,{primaryColor:p,secondaryColor:m,offset:y,index:u,value:d,fullId:b,halfId:x,noneId:S,hoverColor:h,hoverValue:g,committedValue:_,hoverGradientId:w}),a(`polygon`,{fill:C,points:`153,230.775 247.35,299.625 211.65,187.425 306,121.125 191.25,121.125 153,6.375 114.75,121.125 0,121.125 94.35,187.425 58.65,299.625`,pointerEvents:`none`})]})},u={activeContainer:{border:`none`,display:`inline-flex`},inActiveContainer:{border:`none`,outline:0,display:`inline-flex`}},d=e=>Number.isFinite(e)&&e>=1?Math.floor(e):5,f=(e,t,n=0)=>Number.isFinite(e)&&e>=n?e:t,p=(e,t,n)=>{let r=Math.min(Math.max(Number.isFinite(e)?e:0,0),t);return n?r:Math.round(r)},m=({id:s,value:c,defaultValue:m=0,onChange:h=()=>{},name:g,disabled:_=!1,isEdit:v=!0,isHalf:y=!0,count:b=5,size:x=25,starGap:S=0,className:C=``,primaryColor:w=`orange`,secondaryColor:T=`grey`,hoverColor:E,isArrowSubmit:ee=!1,ariaLabel:D=`Star rating`,ariaLabelledBy:O,getValueText:k=(e,t)=>`${e} of ${t}`})=>{let A=d(b),j=f(x,25,2**-52),M=f(S,0),N=c!==void 0,[te,P]=i(()=>p(m,A,y)),F=p(c??te,A,y),ne=t().replace(/:/g,``),I=s??`react-stars-rating-${ne}`,[L,R]=i(()=>({sourceValue:F,displayValue:F})),z=r(null),[B,V]=i(null),H=r(null),U=L.sourceValue===F?L.displayValue:F,W=e=>{R({sourceValue:F,displayValue:p(e,A,y)})},G=n(()=>`fullId-${I}`,[I]),K=n(()=>`halfId-${I}`,[I]),q=n(()=>`noneId-${I}`,[I]);e(()=>{z.current=null},[F]),e(()=>{if(N)return;let e=H.current?.closest(`form`),t=()=>{let e=p(m,A,y);z.current=null,V(null),P(e),R({sourceValue:e,displayValue:e})};return e?.addEventListener(`reset`,t),()=>e?.removeEventListener(`reset`,t)},[m,N,y,A]);let J=(e,t)=>{let n=Array.from(H.current?.querySelectorAll(`svg`)??[]),r=n.find(t=>{let n=t.getBoundingClientRect();return n.width>0&&e.clientX<=n.right})??n[n.length-1]??e.currentTarget,i=n.indexOf(r)+1||t;if(!y)return i;let a=r.getBoundingClientRect();return e.clientX-a.left>a.width/2?i:i-.5},re=(e,t)=>{if(!v||_)return;let n=typeof e.currentTarget.hasPointerCapture==`function`&&e.currentTarget.hasPointerCapture(e.pointerId);if(e.pointerType===`touch`&&!n)return;let r=J(e,t);z.current=null,V(r),W(r)},ie=e=>{!v||_||e.buttons!==0||(V(null),W(F))},ae=()=>{let e=z.current;e!==null&&(z.current=null,Y(e))},Y=e=>{let t=p(e,A,y);W(t),N||P(t),h(t)},oe=(e,t)=>{if(!v||_)return;H.current?.focus(),e.currentTarget.setPointerCapture?.(e.pointerId),z.current=null;let n=J(e,t);V(n),W(n)},se=(e,t)=>{!v||_||(Y(J(e,t)),e.currentTarget.releasePointerCapture?.(e.pointerId),e.pointerType===`touch`&&V(null))},ce=e=>{e.currentTarget.releasePointerCapture?.(e.pointerId),z.current=null,V(null),W(F)},X=e=>{let t=p(e,A,y);t!==U&&(W(t),ee?(z.current=null,Y(t)):z.current=t)},Z=e=>{let t=U%1==.5?U:Math.round(U);X(t+e)},le=e=>{switch(e.key){case`ArrowLeft`:case`ArrowDown`:e.preventDefault(),Z(y?-.5:-1);break;case`ArrowRight`:case`ArrowUp`:e.preventDefault(),Z(y?.5:1);break;case`Home`:e.preventDefault(),X(0);break;case`End`:e.preventDefault(),X(A);break;case`Enter`:e.preventDefault(),z.current=null,Y(U)}},ue=()=>Array.from({length:A},(e,t)=>{let n=t+1,r=n===A?void 0:{paddingRight:M};return a(`span`,{className:`star star-${n}`,style:r,children:a(l,{index:n,value:U,size:j,isHalf:y,fullId:G,halfId:K,noneId:q,primaryColor:w,secondaryColor:T,hoverColor:E,hoverValue:B,committedValue:F,onPointerMove:e=>re(e,n),onPointerLeave:ie,onPointerDown:e=>oe(e,n),onPointerUp:e=>se(e,n),onPointerCancel:ce})},`react-stars-rating-char${n}`)}),Q=v&&!_,$=p(U,A,y);return o(`span`,{ref:H,id:I,role:`slider`,"aria-label":O?void 0:D,"aria-labelledby":O,"aria-valuemin":0,"aria-valuemax":A,"aria-valuenow":$,"aria-valuetext":k($,A),"aria-orientation":`horizontal`,"aria-readonly":!v,"aria-disabled":_||void 0,tabIndex:Q?0:-1,onKeyDown:Q?le:void 0,onBlur:Q?ae:void 0,style:v?u.activeContainer:u.inActiveContainer,className:C,children:[ue(),g?a(`input`,{type:`hidden`,name:g,value:F,disabled:_}):null]})};export{m as ReactStarsRating,m as default};
@@ -1 +1 @@
1
- "use client";(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react")):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactAwesomeStarsRating={},e.React))})(this,function(e,t){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var n=(e,t)=>Math.min(100,Math.max(0,Math.round((e-(t-1))*1e4)/100)),r=({primaryColor:e,secondaryColor:t,offset:r=50,index:i,value:a,fullId:o,halfId:s,noneId:c,hoverColor:l,hoverValue:u=null,committedValue:d=a,hoverGradientId:f})=>{if(l&&u!==null&&f){let r=Math.min(d,u),a=Math.max(d,u),o=n(r,i),s=n(a,i),c=[{start:0,end:o,color:u<=d?l:e},{start:o,end:s,color:u<=d?e:l},{start:s,end:100,color:t}].filter(({start:e,end:t})=>t>e);return React.createElement(`defs`,null,React.createElement(`linearGradient`,{id:f},c.flatMap(({start:e,end:t,color:n},r)=>[React.createElement(`stop`,{key:`${r}-start`,offset:`${e}%`,stopColor:n}),React.createElement(`stop`,{key:`${r}-end`,offset:`${t}%`,stopColor:n})])))}let p=r;return i===1&&(p=Math.round(a%1*1e4)/100),i===1?React.createElement(`defs`,null,React.createElement(`linearGradient`,{id:o},React.createElement(`stop`,{offset:`100%`,stopColor:e})),React.createElement(`linearGradient`,{id:c},React.createElement(`stop`,{offset:`100%`,stopColor:t})),React.createElement(`linearGradient`,{id:s},React.createElement(`stop`,{offset:`${p}%`,stopColor:e}),React.createElement(`stop`,{offset:`${p}%`,stopColor:t}))):null},i=({viewBox:e=`0 0 306 306`,size:t,onMouseMove:n,onMouseLeave:i,onChange:a,index:o,value:s,isHalf:c,primaryColor:l,secondaryColor:u,hoverColor:d,hoverValue:f=null,committedValue:p=s,fill:m,offset:h=50,fullId:g,halfId:_,noneId:v})=>{let y=m,b=`${g}-hover-${o}`;return y=d&&f!==null?`url(#${b})`:o<=s?`url(#${g})`:c&&Math.ceil(s)===o?`url(#${_})`:`url(#${v})`,React.createElement(`svg`,{width:t,viewBox:e,xmlns:`http://www.w3.org/2000/svg`,xmlnsXlink:`http://www.w3.org/1999/xlink`,onMouseLeave:i,onClick:a,onMouseMove:n},React.createElement(r,{primaryColor:l,secondaryColor:u,offset:h,index:o,value:s,fullId:g,halfId:_,noneId:v,hoverColor:d,hoverValue:f,committedValue:p,hoverGradientId:b}),React.createElement(`polygon`,{fill:y,points:`153,230.775 247.35,299.625 211.65,187.425 306,121.125 191.25,121.125 153,6.375 114.75,121.125 0,121.125 94.35,187.425 58.65,299.625`,pointerEvents:`none`}))},a={activeContainer:{border:`none`,display:`inline-flex`},inActiveContainer:{border:`none`,outline:0,display:`inline-flex`}},o=({id:e,value:n=0,onChange:r=()=>{},isEdit:o=!0,isHalf:s=!0,count:c=5,size:l=25,starGap:u=0,className:d=``,primaryColor:f=`orange`,secondaryColor:p=`grey`,hoverColor:m,isArrowSubmit:h=!1,ariaLabel:g=`Star rating`,ariaLabelledBy:_})=>{let v=(0,t.useId)().replace(/:/g,``),y=e??`react-stars-rating-${v}`,[b,x]=(0,t.useState)(()=>({sourceValue:n,displayValue:n})),S=(0,t.useRef)(null),[C,w]=(0,t.useState)(null),T=b.sourceValue===n?b.displayValue:n,E=e=>{x({sourceValue:n,displayValue:e})},D=(0,t.useMemo)(()=>`fullId-${y}`,[y]),O=(0,t.useMemo)(()=>`halfId-${y}`,[y]),k=(0,t.useMemo)(()=>`noneId-${y}`,[y]);(0,t.useEffect)(()=>{S.current=null},[n]);let A=e=>{let t=e.currentTarget.getBoundingClientRect();return e.clientX-t.left>t.width/2},j=(e,t)=>s?A(e)?t:t-.5:t,M=(e,t)=>{if(!o)return;let n=j(e,t);w(n),E(n)},N=()=>{o&&(w(null),E(n||0))},P=()=>{let e=S.current;e!==null&&(S.current=null,r(e))},F=(e,t)=>{if(!o)return;let n=j(e,t);E(n),S.current=null,r(n)},I=e=>{let t=Math.min(Math.max(e,0),c);t!==T&&(E(t),h?(S.current=null,r(t)):S.current=t)},L=e=>{let t=T%1==.5?T:Math.round(T);I(t+e)},R=e=>{switch(e.key){case`ArrowLeft`:case`ArrowDown`:e.preventDefault(),L(s?-.5:-1);break;case`ArrowRight`:case`ArrowUp`:e.preventDefault(),L(s?.5:1);break;case`Home`:e.preventDefault(),I(0);break;case`End`:e.preventDefault(),I(c);break;case`Enter`:e.preventDefault(),S.current=null,r(T)}},z=()=>Array.from({length:c},(e,t)=>{let r=t+1,a=r===c?void 0:{paddingRight:u};return React.createElement(`span`,{key:`react-stars-rating-char${r}`,className:`star star-${r}`,style:a},React.createElement(i,{index:r,value:T,size:l,isHalf:s,fullId:D,halfId:O,noneId:k,primaryColor:f,secondaryColor:p,hoverColor:m,hoverValue:C,committedValue:n,onMouseMove:e=>M(e,r),onMouseLeave:N,onChange:e=>F(e,r)}))}),B=o,V=Math.min(Math.max(T,0),c);return React.createElement(`span`,{id:y,role:`slider`,"aria-label":_?void 0:g,"aria-labelledby":_,"aria-valuemin":0,"aria-valuemax":c,"aria-valuenow":V,"aria-valuetext":`${V} of ${c}`,"aria-readonly":!o,tabIndex:B?0:-1,onKeyDown:B?R:void 0,onBlur:B?P:void 0,style:o?a.activeContainer:a.inActiveContainer,className:d},z())};e.ReactStarsRating=o,e.default=o});
1
+ "use client";(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react")):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactAwesomeStarsRating={},e.React))})(this,function(e,t){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var n=(e,t)=>Math.min(100,Math.max(0,Math.round((e-(t-1))*1e4)/100)),r=({primaryColor:e,secondaryColor:t,offset:r=50,index:i,value:a,fullId:o,halfId:s,noneId:c,hoverColor:l,hoverValue:u=null,committedValue:d=a,hoverGradientId:f})=>{if(l&&u!==null&&f){let r=Math.min(d,u),a=Math.max(d,u),o=n(r,i),s=n(a,i),c=[{start:0,end:o,color:u<=d?l:e},{start:o,end:s,color:u<=d?e:l},{start:s,end:100,color:t}].filter(({start:e,end:t})=>t>e);return React.createElement(`defs`,null,React.createElement(`linearGradient`,{id:f},c.flatMap(({start:e,end:t,color:n},r)=>[React.createElement(`stop`,{key:`${r}-start`,offset:`${e}%`,stopColor:n}),React.createElement(`stop`,{key:`${r}-end`,offset:`${t}%`,stopColor:n})])))}let p=r;return i===1&&(p=Math.round(a%1*1e4)/100),i===1?React.createElement(`defs`,null,React.createElement(`linearGradient`,{id:o},React.createElement(`stop`,{offset:`100%`,stopColor:e})),React.createElement(`linearGradient`,{id:c},React.createElement(`stop`,{offset:`100%`,stopColor:t})),React.createElement(`linearGradient`,{id:s},React.createElement(`stop`,{offset:`${p}%`,stopColor:e}),React.createElement(`stop`,{offset:`${p}%`,stopColor:t}))):null},i=({viewBox:e=`0 0 306 306`,size:t,onPointerMove:n,onPointerLeave:i,onPointerDown:a,onPointerUp:o,onPointerCancel:s,index:c,value:l,isHalf:u,primaryColor:d,secondaryColor:f,hoverColor:p,hoverValue:m=null,committedValue:h=l,fill:g,offset:_=50,fullId:v,halfId:y,noneId:b})=>{let x=g,S=`${v}-hover-${c}`;return x=p&&m!==null?`url(#${S})`:c<=l?`url(#${v})`:u&&Math.ceil(l)===c?`url(#${y})`:`url(#${b})`,React.createElement(`svg`,{width:t,viewBox:e,xmlns:`http://www.w3.org/2000/svg`,xmlnsXlink:`http://www.w3.org/1999/xlink`,onPointerLeave:i,onPointerMove:n,onPointerDown:a,onPointerUp:o,onPointerCancel:s},React.createElement(r,{primaryColor:d,secondaryColor:f,offset:_,index:c,value:l,fullId:v,halfId:y,noneId:b,hoverColor:p,hoverValue:m,committedValue:h,hoverGradientId:S}),React.createElement(`polygon`,{fill:x,points:`153,230.775 247.35,299.625 211.65,187.425 306,121.125 191.25,121.125 153,6.375 114.75,121.125 0,121.125 94.35,187.425 58.65,299.625`,pointerEvents:`none`}))},a={activeContainer:{border:`none`,display:`inline-flex`},inActiveContainer:{border:`none`,outline:0,display:`inline-flex`}},o=e=>Number.isFinite(e)&&e>=1?Math.floor(e):5,s=(e,t,n=0)=>Number.isFinite(e)&&e>=n?e:t,c=(e,t,n)=>{let r=Math.min(Math.max(Number.isFinite(e)?e:0,0),t);return n?r:Math.round(r)},l=({id:e,value:n,defaultValue:r=0,onChange:l=()=>{},name:u,disabled:d=!1,isEdit:f=!0,isHalf:p=!0,count:m=5,size:h=25,starGap:g=0,className:_=``,primaryColor:v=`orange`,secondaryColor:y=`grey`,hoverColor:b,isArrowSubmit:x=!1,ariaLabel:S=`Star rating`,ariaLabelledBy:C,getValueText:w=(e,t)=>`${e} of ${t}`})=>{let T=o(m),E=s(h,25,2**-52),D=s(g,0),O=n!==void 0,[k,A]=(0,t.useState)(()=>c(r,T,p)),j=c(n??k,T,p),ee=(0,t.useId)().replace(/:/g,``),M=e??`react-stars-rating-${ee}`,[N,P]=(0,t.useState)(()=>({sourceValue:j,displayValue:j})),F=(0,t.useRef)(null),[I,L]=(0,t.useState)(null),R=(0,t.useRef)(null),z=N.sourceValue===j?N.displayValue:j,B=e=>{P({sourceValue:j,displayValue:c(e,T,p)})},V=(0,t.useMemo)(()=>`fullId-${M}`,[M]),H=(0,t.useMemo)(()=>`halfId-${M}`,[M]),U=(0,t.useMemo)(()=>`noneId-${M}`,[M]);(0,t.useEffect)(()=>{F.current=null},[j]),(0,t.useEffect)(()=>{if(O)return;let e=R.current?.closest(`form`),t=()=>{let e=c(r,T,p);F.current=null,L(null),A(e),P({sourceValue:e,displayValue:e})};return e?.addEventListener(`reset`,t),()=>e?.removeEventListener(`reset`,t)},[r,O,p,T]);let W=(e,t)=>{let n=Array.from(R.current?.querySelectorAll(`svg`)??[]),r=n.find(t=>{let n=t.getBoundingClientRect();return n.width>0&&e.clientX<=n.right})??n[n.length-1]??e.currentTarget,i=n.indexOf(r)+1||t;if(!p)return i;let a=r.getBoundingClientRect();return e.clientX-a.left>a.width/2?i:i-.5},G=(e,t)=>{if(!f||d)return;let n=typeof e.currentTarget.hasPointerCapture==`function`&&e.currentTarget.hasPointerCapture(e.pointerId);if(e.pointerType===`touch`&&!n)return;let r=W(e,t);F.current=null,L(r),B(r)},K=e=>{!f||d||e.buttons!==0||(L(null),B(j))},q=()=>{let e=F.current;e!==null&&(F.current=null,J(e))},J=e=>{let t=c(e,T,p);B(t),O||A(t),l(t)},Y=(e,t)=>{if(!f||d)return;R.current?.focus(),e.currentTarget.setPointerCapture?.(e.pointerId),F.current=null;let n=W(e,t);L(n),B(n)},te=(e,t)=>{!f||d||(J(W(e,t)),e.currentTarget.releasePointerCapture?.(e.pointerId),e.pointerType===`touch`&&L(null))},ne=e=>{e.currentTarget.releasePointerCapture?.(e.pointerId),F.current=null,L(null),B(j)},X=e=>{let t=c(e,T,p);t!==z&&(B(t),x?(F.current=null,J(t)):F.current=t)},Z=e=>{let t=z%1==.5?z:Math.round(z);X(t+e)},re=e=>{switch(e.key){case`ArrowLeft`:case`ArrowDown`:e.preventDefault(),Z(p?-.5:-1);break;case`ArrowRight`:case`ArrowUp`:e.preventDefault(),Z(p?.5:1);break;case`Home`:e.preventDefault(),X(0);break;case`End`:e.preventDefault(),X(T);break;case`Enter`:e.preventDefault(),F.current=null,J(z)}},ie=()=>Array.from({length:T},(e,t)=>{let n=t+1,r=n===T?void 0:{paddingRight:D};return React.createElement(`span`,{key:`react-stars-rating-char${n}`,className:`star star-${n}`,style:r},React.createElement(i,{index:n,value:z,size:E,isHalf:p,fullId:V,halfId:H,noneId:U,primaryColor:v,secondaryColor:y,hoverColor:b,hoverValue:I,committedValue:j,onPointerMove:e=>G(e,n),onPointerLeave:K,onPointerDown:e=>Y(e,n),onPointerUp:e=>te(e,n),onPointerCancel:ne}))}),Q=f&&!d,$=c(z,T,p);return React.createElement(`span`,{ref:R,id:M,role:`slider`,"aria-label":C?void 0:S,"aria-labelledby":C,"aria-valuemin":0,"aria-valuemax":T,"aria-valuenow":$,"aria-valuetext":w($,T),"aria-orientation":`horizontal`,"aria-readonly":!f,"aria-disabled":d||void 0,tabIndex:Q?0:-1,onKeyDown:Q?re:void 0,onBlur:Q?q:void 0,style:f?a.activeContainer:a.inActiveContainer,className:_},ie(),u?React.createElement(`input`,{type:`hidden`,name:u,value:j,disabled:d}):null)};e.ReactStarsRating=l,e.default=l});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-awesome-stars-rating",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Accessible star rating component for React, with half stars, keyboard control and any scale or palette.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -69,6 +69,7 @@
69
69
  "coverage": "vitest run --coverage",
70
70
  "verify:package": "node scripts/verify-package.mjs",
71
71
  "verify:release": "node scripts/verify-release-notes.mjs",
72
+ "verify:published": "node scripts/verify-published.mjs",
72
73
  "lint:package": "publint && attw --pack",
73
74
  "size": "size-limit",
74
75
  "typecheck": "tsc -p tsconfig.json --noEmit",
@@ -139,19 +140,19 @@
139
140
  {
140
141
  "name": "ESM entry",
141
142
  "path": "dist/index.mjs",
142
- "limit": "2 kB",
143
+ "limit": "2.55 kB",
143
144
  "gzip": true
144
145
  },
145
146
  {
146
147
  "name": "CJS entry",
147
148
  "path": "dist/index.cjs",
148
- "limit": "2.05 kB",
149
+ "limit": "2.6 kB",
149
150
  "gzip": true
150
151
  },
151
152
  {
152
153
  "name": "UMD bundle",
153
154
  "path": "dist/index.umd.cjs",
154
- "limit": "2.15 kB",
155
+ "limit": "2.7 kB",
155
156
  "gzip": true
156
157
  }
157
158
  ],
@@ -1,16 +0,0 @@
1
- type GradientProps = {
2
- primaryColor: string;
3
- secondaryColor: string;
4
- offset?: number;
5
- index: number;
6
- value: number;
7
- fullId: string;
8
- halfId: string;
9
- noneId: string;
10
- hoverColor?: string;
11
- hoverValue?: number | null;
12
- committedValue?: number;
13
- hoverGradientId?: string;
14
- };
15
- declare const Gradient: ({ primaryColor, secondaryColor, offset, index, value, fullId, halfId, noneId, hoverColor, hoverValue, committedValue, hoverGradientId, }: GradientProps) => import("react").JSX.Element | null;
16
- export default Gradient;
package/dist/star.d.ts DELETED
@@ -1,23 +0,0 @@
1
- import type { MouseEvent } from 'react';
2
- type StarProps = {
3
- viewBox?: string;
4
- size: number;
5
- primaryColor: string;
6
- secondaryColor: string;
7
- hoverColor?: string;
8
- hoverValue?: number | null;
9
- committedValue?: number;
10
- onMouseLeave?: (event: MouseEvent<SVGSVGElement>) => void;
11
- onMouseMove?: (event: MouseEvent<SVGSVGElement>) => void;
12
- onChange?: (event: MouseEvent<SVGSVGElement>) => void;
13
- isHalf: boolean;
14
- fill?: string;
15
- index: number;
16
- value: number;
17
- offset?: number;
18
- fullId: string;
19
- halfId: string;
20
- noneId: string;
21
- };
22
- declare const StarSVG: ({ viewBox, size, onMouseMove, onMouseLeave, onChange, index, value, isHalf, primaryColor, secondaryColor, hoverColor, hoverValue, committedValue, fill, offset, fullId, halfId, noneId, }: StarProps) => import("react").JSX.Element;
23
- export default StarSVG;
package/dist/styles.d.ts DELETED
@@ -1,12 +0,0 @@
1
- declare const styles: {
2
- activeContainer: {
3
- border: string;
4
- display: string;
5
- };
6
- inActiveContainer: {
7
- border: string;
8
- outline: number;
9
- display: string;
10
- };
11
- };
12
- export default styles;