react-awesome-stars-rating 1.2.0 → 1.4.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 +132 -22
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +169 -10
- package/dist/index.d.ts +169 -10
- package/dist/index.mjs +1 -1
- package/dist/index.umd.cjs +1 -1
- package/package.json +28 -24
- package/dist/gradient.d.ts +0 -16
- package/dist/star.d.ts +0 -23
- package/dist/styles.d.ts +0 -12
package/README.md
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
[](https://github.com/fedoryakubovich/react-awesome-stars-rating/actions/workflows/ci.yml)
|
|
5
5
|
[](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
|
|
7
|
+
An accessible star rating component for React. Half stars from pointer position, full keyboard control, any scale or palette — in approximately 3 kB gzipped with no runtime dependencies.
|
|
8
8
|
|
|
9
|
-
**[Live demo](https://react-awesome-stars-rating.vercel.app)** · **[Storybook](https://react-awesome-stars-rating.vercel.app/storybook)**
|
|
9
|
+
**[Live demo](https://react-awesome-stars-rating-orpin.vercel.app/)** · **[Storybook](https://react-awesome-stars-rating-orpin.vercel.app/storybook/)**
|
|
10
10
|
|
|
11
11
|

|
|
12
12
|
|
|
13
13
|
## Highlights
|
|
14
14
|
|
|
15
|
-
-
|
|
15
|
+
- Approximately 3 kB gzipped (ESM under 3 kB), 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,32 @@ export default function Example() {
|
|
|
69
69
|
|
|
70
70
|
## Props
|
|
71
71
|
|
|
72
|
-
| Name
|
|
73
|
-
|
|
|
74
|
-
| id
|
|
75
|
-
| value
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
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
|
+
| onBlur / onFocus | Native slider focus callbacks | `React.FocusEventHandler<HTMLSpanElement>` | `undefined` |
|
|
79
|
+
| dir | Layout, fill and horizontal key direction | `'ltr' \| 'rtl'` | `'ltr'` |
|
|
80
|
+
| name | Hidden native form input name | `string` | `undefined` |
|
|
81
|
+
| form | Associated form ID | `string` | `undefined` |
|
|
82
|
+
| disabled | Disable interaction and form submission | `boolean` | `false` |
|
|
83
|
+
| readOnly | Prevent editing | `boolean` | `false` |
|
|
84
|
+
| isEdit | Deprecated inverse editing switch | `boolean` | `true` |
|
|
85
|
+
| isHalf | Allow half stars | `boolean` | `true` |
|
|
86
|
+
| count | Number of stars | `number` | `5` |
|
|
87
|
+
| size | Star size (px) | `number` | `25` |
|
|
88
|
+
| starGap | Gap between stars | `number` | `0` |
|
|
89
|
+
| className | Container class | `string` | `''` |
|
|
90
|
+
| style | Container style and CSS variables | `ReactStarsRatingStyle` | `undefined` |
|
|
91
|
+
| primaryColor | Active star color | `string` | `'orange'` |
|
|
92
|
+
| secondaryColor | Inactive star color | `string` | `'grey'` |
|
|
93
|
+
| hoverColor | Optional pointer-preview color | `string` | `undefined` |
|
|
94
|
+
| isArrowSubmit | Arrow keys trigger `onChange` immediately | `boolean` | `false` |
|
|
95
|
+
| ariaLabel | Accessible label (if no `ariaLabelledBy`) | `string` | `'Star rating'` |
|
|
96
|
+
| ariaLabelledBy | ID of element that labels the control | `string` | `undefined` |
|
|
97
|
+
| getValueText | Formats accessible value text | `(value, count) => string` | English text |
|
|
89
98
|
|
|
90
99
|
## Keyboard and accessibility
|
|
91
100
|
|
|
@@ -101,7 +110,37 @@ The control renders as a single `role="slider"` element with `aria-valuemin`, `a
|
|
|
101
110
|
|
|
102
111
|
With `isArrowSubmit`, each arrow step reports through `onChange` immediately rather than waiting for `Enter` or blur.
|
|
103
112
|
|
|
104
|
-
|
|
113
|
+
Pointer changes commit only when a primary, left-button gesture starts on the
|
|
114
|
+
control and completes. Right/middle clicks, unrelated releases and canceled
|
|
115
|
+
gestures do not submit a rating. Touch dragging uses the same gesture tracking.
|
|
116
|
+
|
|
117
|
+
`onFocus` and `onBlur` receive native React focus events without replacing the
|
|
118
|
+
internal focus handling. A pending keyboard change is committed before `onBlur`,
|
|
119
|
+
so form libraries can mark the field touched with its latest value.
|
|
120
|
+
|
|
121
|
+
When `readOnly` is `true` the control is inert regardless of `isArrowSubmit`: no hover preview, no keyboard, `tabIndex={-1}`, and `aria-readonly="true"`. The older `isEdit={false}` API remains supported but is deprecated.
|
|
122
|
+
|
|
123
|
+
The slider explicitly reports `aria-orientation="horizontal"`. Use
|
|
124
|
+
`getValueText` to localize its spoken value:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
<ReactStarsRating
|
|
128
|
+
value={2.5}
|
|
129
|
+
getValueText={(value, count) => `${value} von ${count} Sternen`}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Right-to-left layouts
|
|
134
|
+
|
|
135
|
+
Pass `dir="rtl"` explicitly to reverse star order, half-star filling, pointer
|
|
136
|
+
selection and horizontal keyboard direction. The default is `ltr`, independent
|
|
137
|
+
of ancestor direction. In RTL, `ArrowLeft` increases and `ArrowRight` decreases;
|
|
138
|
+
`ArrowUp`, `ArrowDown`, `Home` and `End` retain their normal behavior. Star gaps
|
|
139
|
+
use logical spacing in both directions.
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
<ReactStarsRating dir="rtl" defaultValue={2.5} ariaLabel="التقييم" />
|
|
143
|
+
```
|
|
105
144
|
|
|
106
145
|
### Hover preview color
|
|
107
146
|
|
|
@@ -123,12 +162,59 @@ remainder of the saved value uses `primaryColor`, and inactive stars use
|
|
|
123
162
|
`secondaryColor`. When previewing above the saved value, only the additional
|
|
124
163
|
preview region uses `hoverColor`.
|
|
125
164
|
|
|
165
|
+
### Styling
|
|
166
|
+
|
|
167
|
+
The forwarded `ref`, `className`, `style`, `title`, and `data-*` attributes
|
|
168
|
+
target the slider container. CSS variables provide lightweight theming:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<ReactStarsRating
|
|
172
|
+
defaultValue={3.5}
|
|
173
|
+
style={{
|
|
174
|
+
'--stars-rating-primary-color': '#f59e0b',
|
|
175
|
+
'--stars-rating-secondary-color': '#475569',
|
|
176
|
+
'--stars-rating-focus-color': '#2563eb',
|
|
177
|
+
'--stars-rating-size': '2rem',
|
|
178
|
+
'--stars-rating-gap': '0.25rem',
|
|
179
|
+
}}
|
|
180
|
+
/>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The default focus-visible ring uses the system `Highlight` color, and SVG
|
|
184
|
+
stars allow browser forced-colors adjustments for high-contrast modes.
|
|
185
|
+
|
|
126
186
|
## Server components
|
|
127
187
|
|
|
128
188
|
The package carries the `'use client'` directive, so it can be imported directly from a server component in the Next.js App Router without a wrapper.
|
|
129
189
|
|
|
130
190
|
## Form Integrations
|
|
131
191
|
|
|
192
|
+
### Native HTML forms
|
|
193
|
+
|
|
194
|
+
Pass `name` to contribute a hidden value to `FormData`. `defaultValue` enables
|
|
195
|
+
uncontrolled usage and native form reset behavior.
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
<form action="/reviews" method="post">
|
|
199
|
+
<ReactStarsRating name="rating" defaultValue={3} />
|
|
200
|
+
<button type="submit">Submit</button>
|
|
201
|
+
<button type="reset">Reset</button>
|
|
202
|
+
</form>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Use `value` with `onChange` for controlled state. Supplying `value` always
|
|
206
|
+
takes precedence over `defaultValue`. Use `form="form-id"` when the rating is
|
|
207
|
+
rendered outside its associated form.
|
|
208
|
+
|
|
209
|
+
An uncanceled native reset restores `defaultValue` without calling `onChange`.
|
|
210
|
+
Calling `event.preventDefault()` in the form's `onReset` preserves the rating.
|
|
211
|
+
Controlled values remain the responsibility of the parent.
|
|
212
|
+
|
|
213
|
+
HTML hidden inputs do not participate in native constraint validation, so a
|
|
214
|
+
`required` attribute would be misleading and is intentionally not exposed.
|
|
215
|
+
For required ratings, validate the controlled value or submitted `FormData`
|
|
216
|
+
and expose the result with `aria-invalid` and descriptive error text.
|
|
217
|
+
|
|
132
218
|
### React Hook Form
|
|
133
219
|
|
|
134
220
|
```tsx
|
|
@@ -141,7 +227,12 @@ const { control } = useForm({ defaultValues: { rating: 3.5 } });
|
|
|
141
227
|
control={control}
|
|
142
228
|
name="rating"
|
|
143
229
|
render={({ field }) => (
|
|
144
|
-
<ReactStarsRating
|
|
230
|
+
<ReactStarsRating
|
|
231
|
+
ref={field.ref}
|
|
232
|
+
value={field.value}
|
|
233
|
+
onChange={field.onChange}
|
|
234
|
+
onBlur={field.onBlur}
|
|
235
|
+
/>
|
|
145
236
|
)}
|
|
146
237
|
/>;
|
|
147
238
|
```
|
|
@@ -157,6 +248,7 @@ import ReactStarsRating from 'react-awesome-stars-rating';
|
|
|
157
248
|
<ReactStarsRating
|
|
158
249
|
value={field.value}
|
|
159
250
|
onChange={(value) => form.setFieldValue('rating', value)}
|
|
251
|
+
onBlur={() => form.setFieldTouched('rating', true)}
|
|
160
252
|
/>
|
|
161
253
|
)}
|
|
162
254
|
</Field>;
|
|
@@ -188,6 +280,7 @@ const form = useForm<FormValues>({
|
|
|
188
280
|
<ReactStarsRating
|
|
189
281
|
value={field.state.value}
|
|
190
282
|
onChange={field.handleChange}
|
|
283
|
+
onBlur={field.handleBlur}
|
|
191
284
|
/>
|
|
192
285
|
)}
|
|
193
286
|
</form.Field>
|
|
@@ -209,6 +302,9 @@ npm run build # library build (ESM + CJS + UMD + types) → dist/
|
|
|
209
302
|
npm run verify:package # render every entry point from dist/
|
|
210
303
|
npm run lint:package # publint + are-the-types-wrong on the packed tarball
|
|
211
304
|
npm run size # size-limit budgets for every entry point
|
|
305
|
+
npm run test:e2e # Chromium, Firefox and WebKit interaction/a11y tests
|
|
306
|
+
npm run verify:links # README HTTPS links (requires network)
|
|
307
|
+
npm run verify:site # public demo + Storybook smoke tests (requires Chromium/network)
|
|
212
308
|
npm run build:site # demo site → dist-site/
|
|
213
309
|
```
|
|
214
310
|
|
|
@@ -219,6 +315,20 @@ Pre-commit (Husky) runs lint-staged (Prettier + ESLint on staged files) and comm
|
|
|
219
315
|
- **CI** — on push/PR to `main`: format, lint, commitlint, typecheck, tests, coverage, build, package verification, publint/attw, size budgets, Storybook and site builds.
|
|
220
316
|
- **Deploy** — Vercel builds the demo site on every push (see `vercel.json`), serving Storybook at `/storybook`.
|
|
221
317
|
- **Release** — [semantic-release](https://github.com/semantic-release/semantic-release) on push to `main`: analyzes Conventional Commits, publishes to npm and creates a GitHub release.
|
|
318
|
+
- **Recovery** — the manually dispatched `Verify or repair a published release` workflow verifies an exact npm version and its provenance, and can recreate a missing GitHub release only when its tag already exists.
|
|
319
|
+
- **Security** — CodeQL and OpenSSF Scorecard publish findings to GitHub code scanning; dependency review checks pull requests for vulnerable dependencies.
|
|
320
|
+
- **Documentation health** — changed documentation/check scripts, pushes to `main`, a weekly schedule and manual runs check README links and the deployed demo/Storybook. These external-service checks are separate from release gates. If npm's website blocks automated requests, the check explicitly reports that limitation and verifies the package through the registry instead.
|
|
321
|
+
|
|
322
|
+
Browser failures retain screenshots, traces and an HTML report in GitHub Actions
|
|
323
|
+
artifacts for seven days. Local browser tests require `npx playwright install`.
|
|
324
|
+
Development and release tooling use the Node 22 version in `.nvmrc`; consumer
|
|
325
|
+
compatibility is tested separately.
|
|
326
|
+
|
|
327
|
+
Published-release verification cryptographically checks the Sigstore signature
|
|
328
|
+
and transparency proofs, requires this repository's `ci.yml` identity on `main`,
|
|
329
|
+
and checks the signed package digest against the downloaded tarball. The signed
|
|
330
|
+
source commit must match the version's Git tag; release CI also requires it to
|
|
331
|
+
match the current build commit. Verification never republishes the package.
|
|
222
332
|
|
|
223
333
|
Publishing uses npm trusted publishing (OIDC) from `.github/workflows/ci.yml`; the workflow does not use an npm token.
|
|
224
334
|
|
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,
|
|
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,isRtl:f,onLostPointerCapture:p,primaryColor:m,secondaryColor:h,hoverColor:g,hoverValue:_=null,committedValue:v=u,fill:y,offset:b=50,fullId:x,halfId:S,noneId:C})=>{let w=y,T=`${x}-hover-${l}`;return w=g&&_!==null?`url(#${T})`:l<=u?`url(#${x})`:d&&Math.ceil(u)===l?`url(#${S})`:`url(#${C})`,(0,t.jsxs)(`svg`,{width:n,style:{forcedColorAdjust:`auto`,width:`var(--stars-rating-size)`,transform:f?`scaleX(-1)`:void 0},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,onLostPointerCapture:p,children:[(0,t.jsx)(r,{primaryColor:m,secondaryColor:h,offset:b,index:l,value:u,fullId:x,halfId:S,noneId:C,hoverColor:g,hoverValue:_,committedValue:v,hoverGradientId:T}),(0,t.jsx)(`polygon`,{fill:w,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=(0,e.forwardRef)(function({id:n,value:r,defaultValue:l=0,onChange:u=()=>{},onBlur:d,onFocus:f,name:p,form:m,disabled:h=!1,readOnly:g=!1,isEdit:_=!0,isHalf:v=!0,count:y=5,size:b=25,starGap:x=0,className:S=``,style:C,dir:w=`ltr`,primaryColor:T=`var(--stars-rating-primary-color, orange)`,secondaryColor:ee=`var(--stars-rating-secondary-color, grey)`,hoverColor:E,isArrowSubmit:te=!1,ariaLabel:ne=`Star rating`,ariaLabelledBy:D,getValueText:re=(e,t)=>`${e} of ${t}`,...ie},O){let k=w===`rtl`,A=_&&!g,j=o(y),M=s(b,25,2**-52),ae=s(x,0),N=r!==void 0,[oe,P]=(0,e.useState)(()=>c(l,j,v)),F=c(r??oe,j,v),I=(0,e.useId)().replace(/:/g,``),L=n??`react-stars-rating-${I}`,[R,z]=(0,e.useState)(()=>({sourceValue:F,displayValue:F})),B=(0,e.useRef)(null),V=(0,e.useRef)(null),[se,H]=(0,e.useState)(null),[ce,U]=(0,e.useState)(!1),W=(0,e.useRef)(null);(0,e.useImperativeHandle)(O,()=>W.current,[]);let G=R.sourceValue===F?R.displayValue:F,K=e=>{z({sourceValue:F,displayValue:c(e,j,v)})},le=(0,e.useMemo)(()=>`fullId-${L}`,[L]),ue=(0,e.useMemo)(()=>`halfId-${L}`,[L]),de=(0,e.useMemo)(()=>`noneId-${L}`,[L]);(0,e.useEffect)(()=>{B.current=null},[F]),(0,e.useEffect)(()=>{if(N)return;let e=m?document.getElementById(m):W.current?.closest(`form`),t=!0,n=e=>{setTimeout(()=>{if(!t||e.defaultPrevented)return;let n=c(l,j,v);B.current=null,V.current=null,H(null),P(n),z({sourceValue:n,displayValue:n})})};return e?.addEventListener(`reset`,n),()=>{t=!1,e?.removeEventListener(`reset`,n)}},[l,m,N,v,j]);let q=(e,t)=>{let n=Array.from(W.current?.querySelectorAll(`svg`)??[]),r=n.find(t=>{let n=t.getBoundingClientRect();return n.width>0&&(k?e.clientX>=n.left:e.clientX<=n.right)})??n[n.length-1]??e.currentTarget,i=n.indexOf(r)+1||t;if(!v)return i;let a=r.getBoundingClientRect();return(k?a.right-e.clientX:e.clientX-a.left)>a.width/2?i:i-.5},fe=(e,t)=>{if(!A||h)return;let n=V.current;if(n!==null&&n!==e.pointerId||n===null&&(e.pointerType===`touch`||e.buttons!==0))return;let r=q(e,t);B.current=null,H(r),K(r)},pe=e=>{!A||h||e.buttons!==0||(H(null),K(F))},me=e=>{U(!1);let t=B.current;B.current=null,A&&!h&&t!==null&&J(t),d?.(e)},J=e=>{let t=c(e,j,v);K(t),N||P(t),u(t)},he=(e,t)=>{if(!A||h||e.button!==0||e.isPrimary===!1||V.current!==null)return;W.current?.focus(),V.current=e.pointerId,e.currentTarget.setPointerCapture?.(e.pointerId),B.current=null;let n=q(e,t);H(n),K(n)},ge=(e,t)=>{V.current===e.pointerId&&e.button===0&&(V.current=null,e.currentTarget.releasePointerCapture?.(e.pointerId),!(!A||h)&&(J(q(e,t)),e.pointerType===`touch`&&H(null)))},Y=e=>{V.current===e.pointerId&&(V.current=null,B.current=null,H(null),K(F))},X=e=>{let t=c(e,j,v);t!==G&&(K(t),te?(B.current=null,J(t)):B.current=t)},Z=e=>{let t=G%1==.5?G:Math.round(G);X(t+e)},_e=e=>{switch(e.key){case`ArrowLeft`:e.preventDefault(),Z((v?.5:1)*(k?1:-1));break;case`ArrowRight`:e.preventDefault(),Z((v?.5:1)*(k?-1:1));break;case`ArrowDown`:e.preventDefault(),Z(v?-.5:-1);break;case`ArrowUp`:e.preventDefault(),Z(v?.5:1);break;case`Home`:e.preventDefault(),X(0);break;case`End`:e.preventDefault(),X(j);break;case`Enter`:e.preventDefault(),B.current=null,J(G)}},ve=()=>Array.from({length:j},(e,n)=>{let r=n+1,a=r!==j;return(0,t.jsx)(`span`,{className:`star star-${r}`,style:a?{paddingInlineEnd:`var(--stars-rating-gap)`}:void 0,children:(0,t.jsx)(i,{index:r,value:G,size:M,isHalf:v,isRtl:k,fullId:le,halfId:ue,noneId:de,primaryColor:T,secondaryColor:ee,hoverColor:E,hoverValue:se,committedValue:F,onPointerMove:e=>fe(e,r),onPointerLeave:pe,onPointerDown:e=>he(e,r),onPointerUp:e=>ge(e,r),onPointerCancel:Y,onLostPointerCapture:Y})},`react-stars-rating-char${r}`)}),Q=A&&!h,$=c(G,j,v),ye=e=>{U(e.currentTarget.matches(`:focus-visible`)),f?.(e)},be={...A?a.activeContainer:a.inActiveContainer,"--stars-rating-gap":`${ae}px`,"--stars-rating-size":`${M}px`,...ce?{outline:`2px solid var(--stars-rating-focus-color, highlight)`,outlineOffset:2}:void 0,...C};return(0,t.jsxs)(`span`,{...ie,ref:W,id:L,dir:w,role:`slider`,"aria-label":D?void 0:ne,"aria-labelledby":D,"aria-valuemin":0,"aria-valuemax":j,"aria-valuenow":$,"aria-valuetext":re($,j),"aria-orientation":`horizontal`,"aria-readonly":!A,"aria-disabled":h||void 0,tabIndex:Q?0:-1,onKeyDown:Q?_e:void 0,onBlur:me,onFocus:ye,style:be,className:S,children:[ve(),p?(0,t.jsx)(`input`,{type:`hidden`,name:p,value:F,disabled:h,form:m}):null]})});exports.ReactStarsRating=l,exports.default=l;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,27 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ComponentPropsWithoutRef, type CSSProperties } from 'react';
|
|
2
|
+
type ReservedSpanProps = 'aria-disabled' | 'aria-label' | 'aria-labelledby' | 'aria-orientation' | 'aria-readonly' | 'aria-valuemax' | 'aria-valuemin' | 'aria-valuenow' | 'aria-valuetext' | 'children' | 'className' | 'dangerouslySetInnerHTML' | 'defaultValue' | 'dir' | 'id' | 'onChange' | 'onKeyDown' | 'onPointerCancel' | 'onPointerDown' | 'onPointerLeave' | 'onPointerMove' | 'onPointerUp' | 'role' | 'style' | 'tabIndex';
|
|
3
|
+
export type ReactStarsRatingStyle = CSSProperties & {
|
|
4
|
+
'--stars-rating-focus-color'?: string;
|
|
5
|
+
'--stars-rating-gap'?: string;
|
|
6
|
+
'--stars-rating-primary-color'?: string;
|
|
7
|
+
'--stars-rating-secondary-color'?: string;
|
|
8
|
+
'--stars-rating-size'?: string;
|
|
9
|
+
};
|
|
10
|
+
export type ReactStarsRatingProps = Omit<ComponentPropsWithoutRef<'span'>, ReservedSpanProps> & {
|
|
2
11
|
/**
|
|
3
12
|
* `id` of the rendered element. Defaults to a generated, SSR-safe id, so
|
|
4
13
|
* only set this when something else needs to reference the control.
|
|
5
14
|
*/
|
|
6
15
|
id?: string;
|
|
7
16
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
17
|
+
* Controlled current rating. Values outside `0` to
|
|
18
|
+
* {@link ReactStarsRatingProps.count} are clamped. When omitted, the
|
|
19
|
+
* component manages its own value.
|
|
20
|
+
*/
|
|
21
|
+
value?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Initial value when the component is uncontrolled. Ignored when
|
|
24
|
+
* {@link ReactStarsRatingProps.value} is provided.
|
|
10
25
|
*
|
|
11
26
|
* @defaultValue 0
|
|
12
27
|
*/
|
|
13
|
-
|
|
28
|
+
defaultValue?: number;
|
|
14
29
|
/**
|
|
15
|
-
* Called
|
|
30
|
+
* Called when a pointer gesture commits, on `Enter`, and on blur — and on
|
|
16
31
|
* every arrow key when {@link ReactStarsRatingProps.isArrowSubmit} is set.
|
|
17
|
-
*
|
|
32
|
+
* Pointer previews never call it.
|
|
18
33
|
*/
|
|
19
34
|
onChange?: (value: number) => void;
|
|
35
|
+
/** Name of the hidden input contributed to the nearest HTML form. */
|
|
36
|
+
name?: string;
|
|
37
|
+
/** `id` of a form to associate with the hidden input. */
|
|
38
|
+
form?: string;
|
|
39
|
+
/** Layout, fill and horizontal keyboard direction. Defaults to `ltr`. */
|
|
40
|
+
dir?: 'ltr' | 'rtl';
|
|
41
|
+
/** Disable interaction and native form submission. */
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
/** Prevent editing while keeping the current value exposed to assistive technology. */
|
|
44
|
+
readOnly?: boolean;
|
|
20
45
|
/**
|
|
21
46
|
* Whether the rating can be changed. When `false` the control has no hover
|
|
22
47
|
* preview, no keyboard handling, and is removed from the tab order.
|
|
23
48
|
*
|
|
24
49
|
* @defaultValue true
|
|
50
|
+
* @deprecated Prefer {@link ReactStarsRatingProps.readOnly}.
|
|
25
51
|
*/
|
|
26
52
|
isEdit?: boolean;
|
|
27
53
|
/**
|
|
@@ -45,7 +71,7 @@ export type ReactStarsRatingProps = {
|
|
|
45
71
|
*/
|
|
46
72
|
size?: number;
|
|
47
73
|
/**
|
|
48
|
-
* Space between stars, in pixels. Applied as
|
|
74
|
+
* Space between stars, in pixels. Applied as inline-end padding to every star
|
|
49
75
|
* except the last.
|
|
50
76
|
*
|
|
51
77
|
* @defaultValue 0
|
|
@@ -58,16 +84,18 @@ export type ReactStarsRatingProps = {
|
|
|
58
84
|
* @defaultValue ''
|
|
59
85
|
*/
|
|
60
86
|
className?: string;
|
|
87
|
+
/** Container styles, including the documented `--stars-rating-*` variables. */
|
|
88
|
+
style?: ReactStarsRatingStyle;
|
|
61
89
|
/**
|
|
62
90
|
* Any CSS color for the filled part of a star.
|
|
63
91
|
*
|
|
64
|
-
* @defaultValue 'orange'
|
|
92
|
+
* @defaultValue 'var(--stars-rating-primary-color, orange)'
|
|
65
93
|
*/
|
|
66
94
|
primaryColor?: string;
|
|
67
95
|
/**
|
|
68
96
|
* Any CSS color for the empty part of a star.
|
|
69
97
|
*
|
|
70
|
-
* @defaultValue 'grey'
|
|
98
|
+
* @defaultValue 'var(--stars-rating-secondary-color, grey)'
|
|
71
99
|
*/
|
|
72
100
|
secondaryColor?: string;
|
|
73
101
|
/**
|
|
@@ -98,6 +126,12 @@ export type ReactStarsRatingProps = {
|
|
|
98
126
|
* {@link ReactStarsRatingProps.ariaLabel}.
|
|
99
127
|
*/
|
|
100
128
|
ariaLabelledBy?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Formats the accessible value description.
|
|
131
|
+
*
|
|
132
|
+
* @defaultValue `(value, count) => `${value} of ${count}``
|
|
133
|
+
*/
|
|
134
|
+
getValueText?: (value: number, count: number) => string;
|
|
101
135
|
};
|
|
102
136
|
/**
|
|
103
137
|
* A star rating control. Renders as a single `role="slider"` element that
|
|
@@ -110,6 +144,131 @@ export type ReactStarsRatingProps = {
|
|
|
110
144
|
* <ReactStarsRating value={value} onChange={setValue} isHalf size={32} />
|
|
111
145
|
* ```
|
|
112
146
|
*/
|
|
113
|
-
declare const ReactStarsRating: (
|
|
147
|
+
declare const ReactStarsRating: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref">, ReservedSpanProps> & {
|
|
148
|
+
/**
|
|
149
|
+
* `id` of the rendered element. Defaults to a generated, SSR-safe id, so
|
|
150
|
+
* only set this when something else needs to reference the control.
|
|
151
|
+
*/
|
|
152
|
+
id?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Controlled current rating. Values outside `0` to
|
|
155
|
+
* {@link ReactStarsRatingProps.count} are clamped. When omitted, the
|
|
156
|
+
* component manages its own value.
|
|
157
|
+
*/
|
|
158
|
+
value?: number;
|
|
159
|
+
/**
|
|
160
|
+
* Initial value when the component is uncontrolled. Ignored when
|
|
161
|
+
* {@link ReactStarsRatingProps.value} is provided.
|
|
162
|
+
*
|
|
163
|
+
* @defaultValue 0
|
|
164
|
+
*/
|
|
165
|
+
defaultValue?: number;
|
|
166
|
+
/**
|
|
167
|
+
* Called when a pointer gesture commits, on `Enter`, and on blur — and on
|
|
168
|
+
* every arrow key when {@link ReactStarsRatingProps.isArrowSubmit} is set.
|
|
169
|
+
* Pointer previews never call it.
|
|
170
|
+
*/
|
|
171
|
+
onChange?: (value: number) => void;
|
|
172
|
+
/** Name of the hidden input contributed to the nearest HTML form. */
|
|
173
|
+
name?: string;
|
|
174
|
+
/** `id` of a form to associate with the hidden input. */
|
|
175
|
+
form?: string;
|
|
176
|
+
/** Layout, fill and horizontal keyboard direction. Defaults to `ltr`. */
|
|
177
|
+
dir?: "ltr" | "rtl";
|
|
178
|
+
/** Disable interaction and native form submission. */
|
|
179
|
+
disabled?: boolean;
|
|
180
|
+
/** Prevent editing while keeping the current value exposed to assistive technology. */
|
|
181
|
+
readOnly?: boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Whether the rating can be changed. When `false` the control has no hover
|
|
184
|
+
* preview, no keyboard handling, and is removed from the tab order.
|
|
185
|
+
*
|
|
186
|
+
* @defaultValue true
|
|
187
|
+
* @deprecated Prefer {@link ReactStarsRatingProps.readOnly}.
|
|
188
|
+
*/
|
|
189
|
+
isEdit?: boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Whether half stars can be selected. When `true` the half of the star the
|
|
192
|
+
* pointer is over decides between `n - 0.5` and `n`, and the arrow keys step
|
|
193
|
+
* by `0.5` instead of `1`.
|
|
194
|
+
*
|
|
195
|
+
* @defaultValue true
|
|
196
|
+
*/
|
|
197
|
+
isHalf?: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* How many stars to render. Also becomes `aria-valuemax`.
|
|
200
|
+
*
|
|
201
|
+
* @defaultValue 5
|
|
202
|
+
*/
|
|
203
|
+
count?: number;
|
|
204
|
+
/**
|
|
205
|
+
* Width of one star, in pixels.
|
|
206
|
+
*
|
|
207
|
+
* @defaultValue 25
|
|
208
|
+
*/
|
|
209
|
+
size?: number;
|
|
210
|
+
/**
|
|
211
|
+
* Space between stars, in pixels. Applied as inline-end padding to every star
|
|
212
|
+
* except the last.
|
|
213
|
+
*
|
|
214
|
+
* @defaultValue 0
|
|
215
|
+
*/
|
|
216
|
+
starGap?: number;
|
|
217
|
+
/**
|
|
218
|
+
* Class name for the container element. The stars themselves always carry
|
|
219
|
+
* `star` and `star-1`, `star-2`, … class names.
|
|
220
|
+
*
|
|
221
|
+
* @defaultValue ''
|
|
222
|
+
*/
|
|
223
|
+
className?: string;
|
|
224
|
+
/** Container styles, including the documented `--stars-rating-*` variables. */
|
|
225
|
+
style?: ReactStarsRatingStyle;
|
|
226
|
+
/**
|
|
227
|
+
* Any CSS color for the filled part of a star.
|
|
228
|
+
*
|
|
229
|
+
* @defaultValue 'var(--stars-rating-primary-color, orange)'
|
|
230
|
+
*/
|
|
231
|
+
primaryColor?: string;
|
|
232
|
+
/**
|
|
233
|
+
* Any CSS color for the empty part of a star.
|
|
234
|
+
*
|
|
235
|
+
* @defaultValue 'var(--stars-rating-secondary-color, grey)'
|
|
236
|
+
*/
|
|
237
|
+
secondaryColor?: string;
|
|
238
|
+
/**
|
|
239
|
+
* Optional color for the portion being previewed by the pointer. The saved
|
|
240
|
+
* value keeps {@link ReactStarsRatingProps.primaryColor}, so moving below an
|
|
241
|
+
* existing rating can display preview, saved, and inactive regions at once.
|
|
242
|
+
* When omitted, hover previews retain the original two-color behavior.
|
|
243
|
+
*/
|
|
244
|
+
hoverColor?: string;
|
|
245
|
+
/**
|
|
246
|
+
* Report every arrow-key step through
|
|
247
|
+
* {@link ReactStarsRatingProps.onChange} immediately, instead of waiting for
|
|
248
|
+
* `Enter` or blur.
|
|
249
|
+
*
|
|
250
|
+
* @defaultValue false
|
|
251
|
+
*/
|
|
252
|
+
isArrowSubmit?: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* Accessible name for the control. Ignored when
|
|
255
|
+
* {@link ReactStarsRatingProps.ariaLabelledBy} is set.
|
|
256
|
+
*
|
|
257
|
+
* @defaultValue 'Star rating'
|
|
258
|
+
*/
|
|
259
|
+
ariaLabel?: string;
|
|
260
|
+
/**
|
|
261
|
+
* `id` of an element that labels this control, for when the label already
|
|
262
|
+
* exists on the page. Takes precedence over
|
|
263
|
+
* {@link ReactStarsRatingProps.ariaLabel}.
|
|
264
|
+
*/
|
|
265
|
+
ariaLabelledBy?: string;
|
|
266
|
+
/**
|
|
267
|
+
* Formats the accessible value description.
|
|
268
|
+
*
|
|
269
|
+
* @defaultValue `(value, count) => `${value} of ${count}``
|
|
270
|
+
*/
|
|
271
|
+
getValueText?: (value: number, count: number) => string;
|
|
272
|
+
} & import("react").RefAttributes<HTMLSpanElement>>;
|
|
114
273
|
export { ReactStarsRating };
|
|
115
274
|
export default ReactStarsRating;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ComponentPropsWithoutRef, type CSSProperties } from 'react';
|
|
2
|
+
type ReservedSpanProps = 'aria-disabled' | 'aria-label' | 'aria-labelledby' | 'aria-orientation' | 'aria-readonly' | 'aria-valuemax' | 'aria-valuemin' | 'aria-valuenow' | 'aria-valuetext' | 'children' | 'className' | 'dangerouslySetInnerHTML' | 'defaultValue' | 'dir' | 'id' | 'onChange' | 'onKeyDown' | 'onPointerCancel' | 'onPointerDown' | 'onPointerLeave' | 'onPointerMove' | 'onPointerUp' | 'role' | 'style' | 'tabIndex';
|
|
3
|
+
export type ReactStarsRatingStyle = CSSProperties & {
|
|
4
|
+
'--stars-rating-focus-color'?: string;
|
|
5
|
+
'--stars-rating-gap'?: string;
|
|
6
|
+
'--stars-rating-primary-color'?: string;
|
|
7
|
+
'--stars-rating-secondary-color'?: string;
|
|
8
|
+
'--stars-rating-size'?: string;
|
|
9
|
+
};
|
|
10
|
+
export type ReactStarsRatingProps = Omit<ComponentPropsWithoutRef<'span'>, ReservedSpanProps> & {
|
|
2
11
|
/**
|
|
3
12
|
* `id` of the rendered element. Defaults to a generated, SSR-safe id, so
|
|
4
13
|
* only set this when something else needs to reference the control.
|
|
5
14
|
*/
|
|
6
15
|
id?: string;
|
|
7
16
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
17
|
+
* Controlled current rating. Values outside `0` to
|
|
18
|
+
* {@link ReactStarsRatingProps.count} are clamped. When omitted, the
|
|
19
|
+
* component manages its own value.
|
|
20
|
+
*/
|
|
21
|
+
value?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Initial value when the component is uncontrolled. Ignored when
|
|
24
|
+
* {@link ReactStarsRatingProps.value} is provided.
|
|
10
25
|
*
|
|
11
26
|
* @defaultValue 0
|
|
12
27
|
*/
|
|
13
|
-
|
|
28
|
+
defaultValue?: number;
|
|
14
29
|
/**
|
|
15
|
-
* Called
|
|
30
|
+
* Called when a pointer gesture commits, on `Enter`, and on blur — and on
|
|
16
31
|
* every arrow key when {@link ReactStarsRatingProps.isArrowSubmit} is set.
|
|
17
|
-
*
|
|
32
|
+
* Pointer previews never call it.
|
|
18
33
|
*/
|
|
19
34
|
onChange?: (value: number) => void;
|
|
35
|
+
/** Name of the hidden input contributed to the nearest HTML form. */
|
|
36
|
+
name?: string;
|
|
37
|
+
/** `id` of a form to associate with the hidden input. */
|
|
38
|
+
form?: string;
|
|
39
|
+
/** Layout, fill and horizontal keyboard direction. Defaults to `ltr`. */
|
|
40
|
+
dir?: 'ltr' | 'rtl';
|
|
41
|
+
/** Disable interaction and native form submission. */
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
/** Prevent editing while keeping the current value exposed to assistive technology. */
|
|
44
|
+
readOnly?: boolean;
|
|
20
45
|
/**
|
|
21
46
|
* Whether the rating can be changed. When `false` the control has no hover
|
|
22
47
|
* preview, no keyboard handling, and is removed from the tab order.
|
|
23
48
|
*
|
|
24
49
|
* @defaultValue true
|
|
50
|
+
* @deprecated Prefer {@link ReactStarsRatingProps.readOnly}.
|
|
25
51
|
*/
|
|
26
52
|
isEdit?: boolean;
|
|
27
53
|
/**
|
|
@@ -45,7 +71,7 @@ export type ReactStarsRatingProps = {
|
|
|
45
71
|
*/
|
|
46
72
|
size?: number;
|
|
47
73
|
/**
|
|
48
|
-
* Space between stars, in pixels. Applied as
|
|
74
|
+
* Space between stars, in pixels. Applied as inline-end padding to every star
|
|
49
75
|
* except the last.
|
|
50
76
|
*
|
|
51
77
|
* @defaultValue 0
|
|
@@ -58,16 +84,18 @@ export type ReactStarsRatingProps = {
|
|
|
58
84
|
* @defaultValue ''
|
|
59
85
|
*/
|
|
60
86
|
className?: string;
|
|
87
|
+
/** Container styles, including the documented `--stars-rating-*` variables. */
|
|
88
|
+
style?: ReactStarsRatingStyle;
|
|
61
89
|
/**
|
|
62
90
|
* Any CSS color for the filled part of a star.
|
|
63
91
|
*
|
|
64
|
-
* @defaultValue 'orange'
|
|
92
|
+
* @defaultValue 'var(--stars-rating-primary-color, orange)'
|
|
65
93
|
*/
|
|
66
94
|
primaryColor?: string;
|
|
67
95
|
/**
|
|
68
96
|
* Any CSS color for the empty part of a star.
|
|
69
97
|
*
|
|
70
|
-
* @defaultValue 'grey'
|
|
98
|
+
* @defaultValue 'var(--stars-rating-secondary-color, grey)'
|
|
71
99
|
*/
|
|
72
100
|
secondaryColor?: string;
|
|
73
101
|
/**
|
|
@@ -98,6 +126,12 @@ export type ReactStarsRatingProps = {
|
|
|
98
126
|
* {@link ReactStarsRatingProps.ariaLabel}.
|
|
99
127
|
*/
|
|
100
128
|
ariaLabelledBy?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Formats the accessible value description.
|
|
131
|
+
*
|
|
132
|
+
* @defaultValue `(value, count) => `${value} of ${count}``
|
|
133
|
+
*/
|
|
134
|
+
getValueText?: (value: number, count: number) => string;
|
|
101
135
|
};
|
|
102
136
|
/**
|
|
103
137
|
* A star rating control. Renders as a single `role="slider"` element that
|
|
@@ -110,6 +144,131 @@ export type ReactStarsRatingProps = {
|
|
|
110
144
|
* <ReactStarsRating value={value} onChange={setValue} isHalf size={32} />
|
|
111
145
|
* ```
|
|
112
146
|
*/
|
|
113
|
-
declare const ReactStarsRating: (
|
|
147
|
+
declare const ReactStarsRating: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref">, ReservedSpanProps> & {
|
|
148
|
+
/**
|
|
149
|
+
* `id` of the rendered element. Defaults to a generated, SSR-safe id, so
|
|
150
|
+
* only set this when something else needs to reference the control.
|
|
151
|
+
*/
|
|
152
|
+
id?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Controlled current rating. Values outside `0` to
|
|
155
|
+
* {@link ReactStarsRatingProps.count} are clamped. When omitted, the
|
|
156
|
+
* component manages its own value.
|
|
157
|
+
*/
|
|
158
|
+
value?: number;
|
|
159
|
+
/**
|
|
160
|
+
* Initial value when the component is uncontrolled. Ignored when
|
|
161
|
+
* {@link ReactStarsRatingProps.value} is provided.
|
|
162
|
+
*
|
|
163
|
+
* @defaultValue 0
|
|
164
|
+
*/
|
|
165
|
+
defaultValue?: number;
|
|
166
|
+
/**
|
|
167
|
+
* Called when a pointer gesture commits, on `Enter`, and on blur — and on
|
|
168
|
+
* every arrow key when {@link ReactStarsRatingProps.isArrowSubmit} is set.
|
|
169
|
+
* Pointer previews never call it.
|
|
170
|
+
*/
|
|
171
|
+
onChange?: (value: number) => void;
|
|
172
|
+
/** Name of the hidden input contributed to the nearest HTML form. */
|
|
173
|
+
name?: string;
|
|
174
|
+
/** `id` of a form to associate with the hidden input. */
|
|
175
|
+
form?: string;
|
|
176
|
+
/** Layout, fill and horizontal keyboard direction. Defaults to `ltr`. */
|
|
177
|
+
dir?: "ltr" | "rtl";
|
|
178
|
+
/** Disable interaction and native form submission. */
|
|
179
|
+
disabled?: boolean;
|
|
180
|
+
/** Prevent editing while keeping the current value exposed to assistive technology. */
|
|
181
|
+
readOnly?: boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Whether the rating can be changed. When `false` the control has no hover
|
|
184
|
+
* preview, no keyboard handling, and is removed from the tab order.
|
|
185
|
+
*
|
|
186
|
+
* @defaultValue true
|
|
187
|
+
* @deprecated Prefer {@link ReactStarsRatingProps.readOnly}.
|
|
188
|
+
*/
|
|
189
|
+
isEdit?: boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Whether half stars can be selected. When `true` the half of the star the
|
|
192
|
+
* pointer is over decides between `n - 0.5` and `n`, and the arrow keys step
|
|
193
|
+
* by `0.5` instead of `1`.
|
|
194
|
+
*
|
|
195
|
+
* @defaultValue true
|
|
196
|
+
*/
|
|
197
|
+
isHalf?: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* How many stars to render. Also becomes `aria-valuemax`.
|
|
200
|
+
*
|
|
201
|
+
* @defaultValue 5
|
|
202
|
+
*/
|
|
203
|
+
count?: number;
|
|
204
|
+
/**
|
|
205
|
+
* Width of one star, in pixels.
|
|
206
|
+
*
|
|
207
|
+
* @defaultValue 25
|
|
208
|
+
*/
|
|
209
|
+
size?: number;
|
|
210
|
+
/**
|
|
211
|
+
* Space between stars, in pixels. Applied as inline-end padding to every star
|
|
212
|
+
* except the last.
|
|
213
|
+
*
|
|
214
|
+
* @defaultValue 0
|
|
215
|
+
*/
|
|
216
|
+
starGap?: number;
|
|
217
|
+
/**
|
|
218
|
+
* Class name for the container element. The stars themselves always carry
|
|
219
|
+
* `star` and `star-1`, `star-2`, … class names.
|
|
220
|
+
*
|
|
221
|
+
* @defaultValue ''
|
|
222
|
+
*/
|
|
223
|
+
className?: string;
|
|
224
|
+
/** Container styles, including the documented `--stars-rating-*` variables. */
|
|
225
|
+
style?: ReactStarsRatingStyle;
|
|
226
|
+
/**
|
|
227
|
+
* Any CSS color for the filled part of a star.
|
|
228
|
+
*
|
|
229
|
+
* @defaultValue 'var(--stars-rating-primary-color, orange)'
|
|
230
|
+
*/
|
|
231
|
+
primaryColor?: string;
|
|
232
|
+
/**
|
|
233
|
+
* Any CSS color for the empty part of a star.
|
|
234
|
+
*
|
|
235
|
+
* @defaultValue 'var(--stars-rating-secondary-color, grey)'
|
|
236
|
+
*/
|
|
237
|
+
secondaryColor?: string;
|
|
238
|
+
/**
|
|
239
|
+
* Optional color for the portion being previewed by the pointer. The saved
|
|
240
|
+
* value keeps {@link ReactStarsRatingProps.primaryColor}, so moving below an
|
|
241
|
+
* existing rating can display preview, saved, and inactive regions at once.
|
|
242
|
+
* When omitted, hover previews retain the original two-color behavior.
|
|
243
|
+
*/
|
|
244
|
+
hoverColor?: string;
|
|
245
|
+
/**
|
|
246
|
+
* Report every arrow-key step through
|
|
247
|
+
* {@link ReactStarsRatingProps.onChange} immediately, instead of waiting for
|
|
248
|
+
* `Enter` or blur.
|
|
249
|
+
*
|
|
250
|
+
* @defaultValue false
|
|
251
|
+
*/
|
|
252
|
+
isArrowSubmit?: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* Accessible name for the control. Ignored when
|
|
255
|
+
* {@link ReactStarsRatingProps.ariaLabelledBy} is set.
|
|
256
|
+
*
|
|
257
|
+
* @defaultValue 'Star rating'
|
|
258
|
+
*/
|
|
259
|
+
ariaLabel?: string;
|
|
260
|
+
/**
|
|
261
|
+
* `id` of an element that labels this control, for when the label already
|
|
262
|
+
* exists on the page. Takes precedence over
|
|
263
|
+
* {@link ReactStarsRatingProps.ariaLabel}.
|
|
264
|
+
*/
|
|
265
|
+
ariaLabelledBy?: string;
|
|
266
|
+
/**
|
|
267
|
+
* Formats the accessible value description.
|
|
268
|
+
*
|
|
269
|
+
* @defaultValue `(value, count) => `${value} of ${count}``
|
|
270
|
+
*/
|
|
271
|
+
getValueText?: (value: number, count: number) => string;
|
|
272
|
+
} & import("react").RefAttributes<HTMLSpanElement>>;
|
|
114
273
|
export { ReactStarsRating };
|
|
115
274
|
export default ReactStarsRating;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{
|
|
1
|
+
"use client";import{forwardRef as e,useEffect as t,useId as n,useImperativeHandle as r,useMemo as i,useRef as a,useState as o}from"react";import{jsx as s,jsxs as c}from"react/jsx-runtime";var l=(e,t)=>Math.min(100,Math.max(0,Math.round((e-(t-1))*1e4)/100)),u=({primaryColor:e,secondaryColor:t,offset:n=50,index:r,value:i,fullId:a,halfId:o,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),a=l(n,r),o=l(i,r),c=[{start:0,end:a,color:f<=p?d:e},{start:a,end:o,color:f<=p?e:d},{start:o,end:100,color:t}].filter(({start:e,end:t})=>t>e);return s(`defs`,{children:s(`linearGradient`,{id:m,children:c.flatMap(({start:e,end:t,color:n},r)=>[s(`stop`,{offset:`${e}%`,stopColor:n},`${r}-start`),s(`stop`,{offset:`${t}%`,stopColor:n},`${r}-end`)])})})}let h=n;return r===1&&(h=Math.round(i%1*1e4)/100),r===1?c(`defs`,{children:[s(`linearGradient`,{id:a,children:s(`stop`,{offset:`100%`,stopColor:e})}),s(`linearGradient`,{id:u,children:s(`stop`,{offset:`100%`,stopColor:t})}),c(`linearGradient`,{id:o,children:[s(`stop`,{offset:`${h}%`,stopColor:e}),s(`stop`,{offset:`${h}%`,stopColor:t})]})]}):null},d=({viewBox:e=`0 0 306 306`,size:t,onPointerMove:n,onPointerLeave:r,onPointerDown:i,onPointerUp:a,onPointerCancel:o,index:l,value:d,isHalf:f,isRtl:p,onLostPointerCapture:m,primaryColor:h,secondaryColor:g,hoverColor:_,hoverValue:v=null,committedValue:y=d,fill:b,offset:x=50,fullId:S,halfId:C,noneId:w})=>{let T=b,E=`${S}-hover-${l}`;return T=_&&v!==null?`url(#${E})`:l<=d?`url(#${S})`:f&&Math.ceil(d)===l?`url(#${C})`:`url(#${w})`,c(`svg`,{width:t,style:{forcedColorAdjust:`auto`,width:`var(--stars-rating-size)`,transform:p?`scaleX(-1)`:void 0},viewBox:e,xmlns:`http://www.w3.org/2000/svg`,xmlnsXlink:`http://www.w3.org/1999/xlink`,onPointerLeave:r,onPointerMove:n,onPointerDown:i,onPointerUp:a,onPointerCancel:o,onLostPointerCapture:m,children:[s(u,{primaryColor:h,secondaryColor:g,offset:x,index:l,value:d,fullId:S,halfId:C,noneId:w,hoverColor:_,hoverValue:v,committedValue:y,hoverGradientId:E}),s(`polygon`,{fill:T,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`})]})},f={activeContainer:{border:`none`,display:`inline-flex`},inActiveContainer:{border:`none`,outline:0,display:`inline-flex`}},p=e=>Number.isFinite(e)&&e>=1?Math.floor(e):5,m=(e,t,n=0)=>Number.isFinite(e)&&e>=n?e:t,h=(e,t,n)=>{let r=Math.min(Math.max(Number.isFinite(e)?e:0,0),t);return n?r:Math.round(r)},g=e(function({id:e,value:l,defaultValue:u=0,onChange:g=()=>{},onBlur:_,onFocus:v,name:y,form:b,disabled:x=!1,readOnly:S=!1,isEdit:C=!0,isHalf:w=!0,count:T=5,size:E=25,starGap:ee=0,className:te=``,style:ne,dir:D=`ltr`,primaryColor:re=`var(--stars-rating-primary-color, orange)`,secondaryColor:ie=`var(--stars-rating-secondary-color, grey)`,hoverColor:ae,isArrowSubmit:oe=!1,ariaLabel:se=`Star rating`,ariaLabelledBy:O,getValueText:k=(e,t)=>`${e} of ${t}`,...ce},le){let A=D===`rtl`,j=C&&!S,M=p(T),N=m(E,25,2**-52),ue=m(ee,0),P=l!==void 0,[de,F]=o(()=>h(u,M,w)),I=h(l??de,M,w),fe=n().replace(/:/g,``),L=e??`react-stars-rating-${fe}`,[R,z]=o(()=>({sourceValue:I,displayValue:I})),B=a(null),V=a(null),[pe,H]=o(null),[me,U]=o(!1),W=a(null);r(le,()=>W.current,[]);let G=R.sourceValue===I?R.displayValue:I,K=e=>{z({sourceValue:I,displayValue:h(e,M,w)})},he=i(()=>`fullId-${L}`,[L]),ge=i(()=>`halfId-${L}`,[L]),_e=i(()=>`noneId-${L}`,[L]);t(()=>{B.current=null},[I]),t(()=>{if(P)return;let e=b?document.getElementById(b):W.current?.closest(`form`),t=!0,n=e=>{setTimeout(()=>{if(!t||e.defaultPrevented)return;let n=h(u,M,w);B.current=null,V.current=null,H(null),F(n),z({sourceValue:n,displayValue:n})})};return e?.addEventListener(`reset`,n),()=>{t=!1,e?.removeEventListener(`reset`,n)}},[u,b,P,w,M]);let q=(e,t)=>{let n=Array.from(W.current?.querySelectorAll(`svg`)??[]),r=n.find(t=>{let n=t.getBoundingClientRect();return n.width>0&&(A?e.clientX>=n.left:e.clientX<=n.right)})??n[n.length-1]??e.currentTarget,i=n.indexOf(r)+1||t;if(!w)return i;let a=r.getBoundingClientRect();return(A?a.right-e.clientX:e.clientX-a.left)>a.width/2?i:i-.5},ve=(e,t)=>{if(!j||x)return;let n=V.current;if(n!==null&&n!==e.pointerId||n===null&&(e.pointerType===`touch`||e.buttons!==0))return;let r=q(e,t);B.current=null,H(r),K(r)},ye=e=>{!j||x||e.buttons!==0||(H(null),K(I))},be=e=>{U(!1);let t=B.current;B.current=null,j&&!x&&t!==null&&J(t),_?.(e)},J=e=>{let t=h(e,M,w);K(t),P||F(t),g(t)},xe=(e,t)=>{if(!j||x||e.button!==0||e.isPrimary===!1||V.current!==null)return;W.current?.focus(),V.current=e.pointerId,e.currentTarget.setPointerCapture?.(e.pointerId),B.current=null;let n=q(e,t);H(n),K(n)},Se=(e,t)=>{V.current===e.pointerId&&e.button===0&&(V.current=null,e.currentTarget.releasePointerCapture?.(e.pointerId),!(!j||x)&&(J(q(e,t)),e.pointerType===`touch`&&H(null)))},Y=e=>{V.current===e.pointerId&&(V.current=null,B.current=null,H(null),K(I))},X=e=>{let t=h(e,M,w);t!==G&&(K(t),oe?(B.current=null,J(t)):B.current=t)},Z=e=>{let t=G%1==.5?G:Math.round(G);X(t+e)},Ce=e=>{switch(e.key){case`ArrowLeft`:e.preventDefault(),Z((w?.5:1)*(A?1:-1));break;case`ArrowRight`:e.preventDefault(),Z((w?.5:1)*(A?-1:1));break;case`ArrowDown`:e.preventDefault(),Z(w?-.5:-1);break;case`ArrowUp`:e.preventDefault(),Z(w?.5:1);break;case`Home`:e.preventDefault(),X(0);break;case`End`:e.preventDefault(),X(M);break;case`Enter`:e.preventDefault(),B.current=null,J(G)}},we=()=>Array.from({length:M},(e,t)=>{let n=t+1,r=n!==M;return s(`span`,{className:`star star-${n}`,style:r?{paddingInlineEnd:`var(--stars-rating-gap)`}:void 0,children:s(d,{index:n,value:G,size:N,isHalf:w,isRtl:A,fullId:he,halfId:ge,noneId:_e,primaryColor:re,secondaryColor:ie,hoverColor:ae,hoverValue:pe,committedValue:I,onPointerMove:e=>ve(e,n),onPointerLeave:ye,onPointerDown:e=>xe(e,n),onPointerUp:e=>Se(e,n),onPointerCancel:Y,onLostPointerCapture:Y})},`react-stars-rating-char${n}`)}),Q=j&&!x,$=h(G,M,w),Te=e=>{U(e.currentTarget.matches(`:focus-visible`)),v?.(e)},Ee={...j?f.activeContainer:f.inActiveContainer,"--stars-rating-gap":`${ue}px`,"--stars-rating-size":`${N}px`,...me?{outline:`2px solid var(--stars-rating-focus-color, highlight)`,outlineOffset:2}:void 0,...ne};return c(`span`,{...ce,ref:W,id:L,dir:D,role:`slider`,"aria-label":O?void 0:se,"aria-labelledby":O,"aria-valuemin":0,"aria-valuemax":M,"aria-valuenow":$,"aria-valuetext":k($,M),"aria-orientation":`horizontal`,"aria-readonly":!j,"aria-disabled":x||void 0,tabIndex:Q?0:-1,onKeyDown:Q?Ce:void 0,onBlur:be,onFocus:Te,style:Ee,className:te,children:[we(),y?s(`input`,{type:`hidden`,name:y,value:I,disabled:x,form:b}):null]})});export{g as ReactStarsRating,g as default};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -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,
|
|
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,isRtl:d,onLostPointerCapture:f,primaryColor:p,secondaryColor:m,hoverColor:h,hoverValue:g=null,committedValue:_=l,fill:v,offset:y=50,fullId:b,halfId:x,noneId:S})=>{let C=v,w=`${b}-hover-${c}`;return C=h&&g!==null?`url(#${w})`:c<=l?`url(#${b})`:u&&Math.ceil(l)===c?`url(#${x})`:`url(#${S})`,React.createElement(`svg`,{width:t,style:{forcedColorAdjust:`auto`,width:`var(--stars-rating-size)`,transform:d?`scaleX(-1)`:void 0},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,onLostPointerCapture:f},React.createElement(r,{primaryColor:p,secondaryColor:m,offset:y,index:c,value:l,fullId:b,halfId:x,noneId:S,hoverColor:h,hoverValue:g,committedValue:_,hoverGradientId:w}),React.createElement(`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`}))},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=(0,t.forwardRef)(function({id:e,value:n,defaultValue:r=0,onChange:l=()=>{},onBlur:u,onFocus:d,name:f,form:p,disabled:m=!1,readOnly:h=!1,isEdit:g=!0,isHalf:_=!0,count:v=5,size:y=25,starGap:b=0,className:x=``,style:S,dir:C=`ltr`,primaryColor:w=`var(--stars-rating-primary-color, orange)`,secondaryColor:ee=`var(--stars-rating-secondary-color, grey)`,hoverColor:te,isArrowSubmit:T=!1,ariaLabel:ne=`Star rating`,ariaLabelledBy:E,getValueText:re=(e,t)=>`${e} of ${t}`,...ie},D){let O=C===`rtl`,k=g&&!h,A=o(v),j=s(y,25,2**-52),ae=s(b,0),M=n!==void 0,[oe,N]=(0,t.useState)(()=>c(r,A,_)),P=c(n??oe,A,_),F=(0,t.useId)().replace(/:/g,``),I=e??`react-stars-rating-${F}`,[L,R]=(0,t.useState)(()=>({sourceValue:P,displayValue:P})),z=(0,t.useRef)(null),B=(0,t.useRef)(null),[se,V]=(0,t.useState)(null),[ce,H]=(0,t.useState)(!1),U=(0,t.useRef)(null);(0,t.useImperativeHandle)(D,()=>U.current,[]);let W=L.sourceValue===P?L.displayValue:P,G=e=>{R({sourceValue:P,displayValue:c(e,A,_)})},le=(0,t.useMemo)(()=>`fullId-${I}`,[I]),ue=(0,t.useMemo)(()=>`halfId-${I}`,[I]),de=(0,t.useMemo)(()=>`noneId-${I}`,[I]);(0,t.useEffect)(()=>{z.current=null},[P]),(0,t.useEffect)(()=>{if(M)return;let e=p?document.getElementById(p):U.current?.closest(`form`),t=!0,n=e=>{setTimeout(()=>{if(!t||e.defaultPrevented)return;let n=c(r,A,_);z.current=null,B.current=null,V(null),N(n),R({sourceValue:n,displayValue:n})})};return e?.addEventListener(`reset`,n),()=>{t=!1,e?.removeEventListener(`reset`,n)}},[r,p,M,_,A]);let K=(e,t)=>{let n=Array.from(U.current?.querySelectorAll(`svg`)??[]),r=n.find(t=>{let n=t.getBoundingClientRect();return n.width>0&&(O?e.clientX>=n.left:e.clientX<=n.right)})??n[n.length-1]??e.currentTarget,i=n.indexOf(r)+1||t;if(!_)return i;let a=r.getBoundingClientRect();return(O?a.right-e.clientX:e.clientX-a.left)>a.width/2?i:i-.5},fe=(e,t)=>{if(!k||m)return;let n=B.current;if(n!==null&&n!==e.pointerId||n===null&&(e.pointerType===`touch`||e.buttons!==0))return;let r=K(e,t);z.current=null,V(r),G(r)},pe=e=>{!k||m||e.buttons!==0||(V(null),G(P))},me=e=>{H(!1);let t=z.current;z.current=null,k&&!m&&t!==null&&q(t),u?.(e)},q=e=>{let t=c(e,A,_);G(t),M||N(t),l(t)},he=(e,t)=>{if(!k||m||e.button!==0||e.isPrimary===!1||B.current!==null)return;U.current?.focus(),B.current=e.pointerId,e.currentTarget.setPointerCapture?.(e.pointerId),z.current=null;let n=K(e,t);V(n),G(n)},ge=(e,t)=>{B.current===e.pointerId&&e.button===0&&(B.current=null,e.currentTarget.releasePointerCapture?.(e.pointerId),!(!k||m)&&(q(K(e,t)),e.pointerType===`touch`&&V(null)))},J=e=>{B.current===e.pointerId&&(B.current=null,z.current=null,V(null),G(P))},Y=e=>{let t=c(e,A,_);t!==W&&(G(t),T?(z.current=null,q(t)):z.current=t)},X=e=>{let t=W%1==.5?W:Math.round(W);Y(t+e)},Z=e=>{switch(e.key){case`ArrowLeft`:e.preventDefault(),X((_?.5:1)*(O?1:-1));break;case`ArrowRight`:e.preventDefault(),X((_?.5:1)*(O?-1:1));break;case`ArrowDown`:e.preventDefault(),X(_?-.5:-1);break;case`ArrowUp`:e.preventDefault(),X(_?.5:1);break;case`Home`:e.preventDefault(),Y(0);break;case`End`:e.preventDefault(),Y(A);break;case`Enter`:e.preventDefault(),z.current=null,q(W)}},_e=()=>Array.from({length:A},(e,t)=>{let n=t+1,r=n!==A;return React.createElement(`span`,{key:`react-stars-rating-char${n}`,className:`star star-${n}`,style:r?{paddingInlineEnd:`var(--stars-rating-gap)`}:void 0},React.createElement(i,{index:n,value:W,size:j,isHalf:_,isRtl:O,fullId:le,halfId:ue,noneId:de,primaryColor:w,secondaryColor:ee,hoverColor:te,hoverValue:se,committedValue:P,onPointerMove:e=>fe(e,n),onPointerLeave:pe,onPointerDown:e=>he(e,n),onPointerUp:e=>ge(e,n),onPointerCancel:J,onLostPointerCapture:J}))}),Q=k&&!m,$=c(W,A,_),ve=e=>{H(e.currentTarget.matches(`:focus-visible`)),d?.(e)},ye={...k?a.activeContainer:a.inActiveContainer,"--stars-rating-gap":`${ae}px`,"--stars-rating-size":`${j}px`,...ce?{outline:`2px solid var(--stars-rating-focus-color, highlight)`,outlineOffset:2}:void 0,...S};return React.createElement(`span`,{...ie,ref:U,id:I,dir:C,role:`slider`,"aria-label":E?void 0:ne,"aria-labelledby":E,"aria-valuemin":0,"aria-valuemax":A,"aria-valuenow":$,"aria-valuetext":re($,A),"aria-orientation":`horizontal`,"aria-readonly":!k,"aria-disabled":m||void 0,tabIndex:Q?0:-1,onKeyDown:Q?Z:void 0,onBlur:me,onFocus:ve,style:ye,className:x},_e(),f?React.createElement(`input`,{type:`hidden`,name:f,value:P,disabled:m,form:p}):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.
|
|
3
|
+
"version": "1.4.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",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"type": "git",
|
|
49
49
|
"url": "git+https://github.com/fedoryakubovich/react-awesome-stars-rating.git"
|
|
50
50
|
},
|
|
51
|
-
"homepage": "https://react-awesome-stars-rating.vercel.app",
|
|
51
|
+
"homepage": "https://react-awesome-stars-rating-orpin.vercel.app/",
|
|
52
52
|
"author": "Fedor Yakubovich",
|
|
53
53
|
"bugs": {
|
|
54
54
|
"url": "https://github.com/fedoryakubovich/react-awesome-stars-rating/issues"
|
|
@@ -59,9 +59,10 @@
|
|
|
59
59
|
"build": "vite build && vite build -c vite.umd.config.ts && tsc -p tsconfig.build.json && node scripts/emit-cjs-types.mjs",
|
|
60
60
|
"build:site": "vite build --config vite.site.config.ts",
|
|
61
61
|
"preview": "vite preview",
|
|
62
|
-
"lint": "
|
|
63
|
-
"
|
|
64
|
-
"format
|
|
62
|
+
"lint": "oxlint .",
|
|
63
|
+
"verify:lint": "node scripts/verify-lint.mjs",
|
|
64
|
+
"format": "oxfmt --check .",
|
|
65
|
+
"format:write": "oxfmt --write .",
|
|
65
66
|
"test": "vitest run",
|
|
66
67
|
"test:watch": "vitest",
|
|
67
68
|
"test:e2e": "playwright test",
|
|
@@ -69,6 +70,9 @@
|
|
|
69
70
|
"coverage": "vitest run --coverage",
|
|
70
71
|
"verify:package": "node scripts/verify-package.mjs",
|
|
71
72
|
"verify:release": "node scripts/verify-release-notes.mjs",
|
|
73
|
+
"verify:published": "node scripts/verify-published.mjs",
|
|
74
|
+
"verify:links": "node scripts/verify-links.mjs",
|
|
75
|
+
"verify:site": "playwright test --config playwright.deployed.config.ts",
|
|
72
76
|
"lint:package": "publint && attw --pack",
|
|
73
77
|
"size": "size-limit",
|
|
74
78
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
@@ -93,70 +97,70 @@
|
|
|
93
97
|
"@semantic-release/github": "^12.0.9",
|
|
94
98
|
"@semantic-release/npm": "^13.1.5",
|
|
95
99
|
"@size-limit/file": "^13.0.3",
|
|
96
|
-
"@storybook/addon-a11y": "^10.
|
|
97
|
-
"@storybook/addon-links": "^10.
|
|
98
|
-
"@storybook/react-vite": "^10.
|
|
100
|
+
"@storybook/addon-a11y": "^10.6.0",
|
|
101
|
+
"@storybook/addon-links": "^10.6.0",
|
|
102
|
+
"@storybook/react-vite": "^10.6.0",
|
|
99
103
|
"@tailwindcss/postcss": "^4.3.3",
|
|
100
104
|
"@tanstack/react-form": "^1.33.5",
|
|
101
105
|
"@testing-library/dom": "^10.4.1",
|
|
102
106
|
"@testing-library/jest-dom": "^7.0.1",
|
|
103
107
|
"@testing-library/react": "^16.3.3",
|
|
104
|
-
"@testing-library/user-event": "^14.6.
|
|
108
|
+
"@testing-library/user-event": "^14.6.7",
|
|
105
109
|
"@types/react": "^19.2.18",
|
|
106
|
-
"@types/react-dom": "^19.2.
|
|
107
|
-
"@typescript-eslint/eslint-plugin": "^8.68.0",
|
|
108
|
-
"@typescript-eslint/parser": "^8.68.0",
|
|
110
|
+
"@types/react-dom": "^19.2.7",
|
|
109
111
|
"@vitejs/plugin-react": "^6.1.1",
|
|
110
|
-
"@vitest/coverage-v8": "^
|
|
112
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
111
113
|
"axe-core": "^4.13.0",
|
|
112
114
|
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
113
115
|
"conventional-commits-filter": "^6.0.1",
|
|
114
116
|
"eslint": "^9.39.5",
|
|
115
|
-
"eslint-config-prettier": "^10.1.8",
|
|
116
|
-
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
117
117
|
"eslint-plugin-react": "^7.37.5",
|
|
118
118
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
119
|
-
"eslint-plugin-storybook": "10.5.10",
|
|
120
119
|
"formik": "^2.4.9",
|
|
121
120
|
"husky": "^9.1.7",
|
|
122
121
|
"jsdom": "^30.0.1",
|
|
123
122
|
"lint-staged": "^17.4.1",
|
|
124
|
-
"
|
|
123
|
+
"oxfmt": "^0.66.0",
|
|
124
|
+
"oxlint": "^1.81.0",
|
|
125
125
|
"publint": "^0.3.24",
|
|
126
126
|
"react": "^19.2.8",
|
|
127
127
|
"react-dom": "^19.2.8",
|
|
128
128
|
"react-hook-form": "^7.87.0",
|
|
129
129
|
"rimraf": "^6.1.3",
|
|
130
130
|
"semantic-release": "^25.0.9",
|
|
131
|
+
"sigstore": "^5.0.0",
|
|
131
132
|
"size-limit": "^13.0.3",
|
|
132
|
-
"storybook": "^10.
|
|
133
|
+
"storybook": "^10.6.0",
|
|
133
134
|
"tailwindcss": "^4.3.3",
|
|
134
135
|
"typescript": "^6.0.3",
|
|
135
136
|
"vite": "^8.2.2",
|
|
136
|
-
"vitest": "^
|
|
137
|
+
"vitest": "^5.0.0"
|
|
137
138
|
},
|
|
138
139
|
"size-limit": [
|
|
139
140
|
{
|
|
140
141
|
"name": "ESM entry",
|
|
141
142
|
"path": "dist/index.mjs",
|
|
142
|
-
"limit": "
|
|
143
|
+
"limit": "3 kB",
|
|
143
144
|
"gzip": true
|
|
144
145
|
},
|
|
145
146
|
{
|
|
146
147
|
"name": "CJS entry",
|
|
147
148
|
"path": "dist/index.cjs",
|
|
148
|
-
"limit": "
|
|
149
|
+
"limit": "3.05 kB",
|
|
149
150
|
"gzip": true
|
|
150
151
|
},
|
|
151
152
|
{
|
|
152
153
|
"name": "UMD bundle",
|
|
153
154
|
"path": "dist/index.umd.cjs",
|
|
154
|
-
"limit": "
|
|
155
|
+
"limit": "3.1 kB",
|
|
155
156
|
"gzip": true
|
|
156
157
|
}
|
|
157
158
|
],
|
|
158
159
|
"lint-staged": {
|
|
159
|
-
"*.{ts,tsx,js,jsx,mjs,cjs
|
|
160
|
-
|
|
160
|
+
"*.{ts,tsx,js,jsx,mjs,cjs}": [
|
|
161
|
+
"oxlint --fix",
|
|
162
|
+
"oxfmt --write"
|
|
163
|
+
],
|
|
164
|
+
"*.{json,jsonc,css,md,yml,yaml,html}": "oxfmt --write"
|
|
161
165
|
}
|
|
162
166
|
}
|
package/dist/gradient.d.ts
DELETED
|
@@ -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;
|