react-likert-scale
Advanced tools
Comparing version
@@ -9,6 +9,22 @@ Changelog | ||
[upcoming] | ||
---------------------------- | ||
* Example formatting in a grid. | ||
### Added | ||
* You can now have a radio button pre-checked on first render. | ||
### Changed | ||
* The `question` prop is now optional so that you can format as you wish. | ||
* The `id` props is now (mostly) required. If you have multiple Likert components on a page ... | ||
[4.0.0-1 alpha] 2021-02-06 | ||
---------------------------- | ||
### Added | ||
* Prop `flexible` controls the spacing between likert options. Set to 0 or `false` to pack the | ||
@@ -30,2 +46,3 @@ likert options as close together as possible. This is useful when you have several questions | ||
[3.0.2] - 2021-01-22 | ||
---------------------------- | ||
@@ -32,0 +49,0 @@ ### Added |
@@ -1,1 +0,1 @@ | ||
import e from"react";function n(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function t(){return(t=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i])}return e}).apply(this,arguments)}!function(e,n){void 0===n&&(n={});var t=n.insertAt;if(e&&"undefined"!=typeof document){var i=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===t&&i.firstChild?i.insertBefore(r,i.firstChild):i.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}(".likertScale {\n margin-bottom: 1em;\n border: none;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n}\n.likertLegend {\n flex: 1 1 auto;\n}\n.likertBand {\n flex-grow: 4; /* This can get overridden by the “flexible” prop. */\n flex-shrink: 0;\n flex-basis: auto;\n\n display: flex;\n padding-top: 0.6em;\n}\n.likertResponse {\n flex-grow: 1;\n flex-shrink: 1;\n flex-basis: 0; /* never set to auto */\n min-width: 1.6em;\n text-align: center;\n position: relative;\n}\n.likertLine {\n display: inline-block;\n width: 50%;\n vertical-align: top;\n margin-top: 0.5em;\n border-top: 3px solid dimgray;\n}\n.likertResponse:first-child .likertLine:first-child {\n visibility: hidden;\n}\n.likertResponse:last-child > .likertLine:nth-child(2) {\n visibility: hidden;\n}\n.likertIndicator {\n display: inline-block;\n width: 1em;\n height: 1em;\n border-radius: 0.5em;\n border: thin solid #006fc4;\n background-color: #faeabd;\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n top: 0;\n box-sizing: border-box;\n transition: all linear 200ms;\n}\n.likertResponse:hover .likertIndicator {\n background-color: white;\n border-width: 3px;\n transition: all linear 200ms;\n}\n.likertText {\n display: inline-block;\n padding-top: 0.4em;\n padding-left: 0.4em;\n padding-right: 0.4em;\n width: 100%;\n box-sizing: border-box;\n}\n.likertScale.isKeyboardUser .likertResponse > input:focus ~ .likertIndicator {\n /* Show outline for keyboard users. */\n box-shadow: 0 0 5px 2px rgba(0, 119, 195, 0.5);\n}\n.likertResponse > input:checked + .likertIndicator {\n background-color: #006fc4;\n}\n.visuallyHidden {\n position: absolute;\n overflow: hidden;\n clip: rect(0 0 0 0);\n height: 1px;\n width: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n}\n\n@media only print {\n .likertResponse > input:checked + .likertIndicator {\n border-width: 0.5em !important;\n border-color: black !important;\n }\n}\n");class i extends e.Component{constructor(e){super(e),n(this,"onChange",(e=>{"function"==typeof this.props.onChange?this.props.onChange(this.getResponsesItem(e.target.value)):"function"==typeof this.props.picked&&(console.warn("Deprecation: The “picked” callback has been renamed; use “onChange” instead."),this.props.picked(this.getResponsesItem(e.target.value)))})),n(this,"listenForTab",(e=>{"Tab"===e.key&&this.setState({isKeyboardUser:!0})})),n(this,"getResponsesItem",(e=>this.props.responses.find((n=>n.value==e)))),this.state={isKeyboardUser:!1}}componentDidMount(){document.addEventListener("keydown",this.listenForTab)}componentWillUnmount(){document.removeEventListener("keydown",this.listenForTab)}render(){const{question:n,responses:i,flexible:r=!0,id:o,className:a="",likertRef:s,...l}=this.props;delete l.picked,delete l.onChange;let d=null;r||(d={flexGrow:0}),"number"==typeof r&&4!==parseInt(r)&&(d={flexGrow:parseInt(r)});const c=function(e){let n=5381,t=e.length;for(;t;)n=33*n^e.charCodeAt(--t);return n>>>0}(n),p=i.map(((n,t)=>{const i="".concat(c).concat(t);return e.createElement("label",{key:i,htmlFor:i,className:"likertResponse"},e.createElement("span",{className:"likertLine"}),e.createElement("span",{className:"likertLine"}),e.createElement("input",{type:"radio",value:n.value,name:c,id:i,className:"visuallyHidden",onClick:this.onChange}),e.createElement("span",{className:"likertIndicator"}),e.createElement("span",{className:"likertText"},n.text))}));let h="likertScale";return h+=a?" ".concat(a):"",h+=this.state.isKeyboardUser?" isKeyboardUser":"",e.createElement("fieldset",t({className:h,ref:s,id:o||c},l,{"aria-labelledby":"legend-".concat(c)}),e.createElement("div",{id:"legend-".concat(c),className:"likertLegend"},n),e.createElement("div",{className:"likertBand",style:d},p))}}var r=e.forwardRef(((n,r)=>e.createElement(i,t({},n,{likertRef:r}))));export default r; | ||
import e from"react";function n(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function t(){return(t=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i])}return e}).apply(this,arguments)}!function(e,n){void 0===n&&(n={});var t=n.insertAt;if(e&&"undefined"!=typeof document){var i=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===t&&i.firstChild?i.insertBefore(r,i.firstChild):i.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}(".likertScale {\n margin-bottom: 1em;\n border: none;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n}\n.likertLegend {\n flex: 1 1 auto;\n}\n.likertBand {\n flex-grow: 4; /* This can get overridden by the “flexible” prop. */\n flex-shrink: 0;\n flex-basis: auto;\n\n display: flex;\n padding-top: 0.6em;\n}\n.likertResponse {\n flex-grow: 1;\n flex-shrink: 1;\n flex-basis: 0; /* never set to auto */\n min-width: 1.6em;\n text-align: center;\n position: relative;\n}\n.likertLine {\n display: inline-block;\n width: 50%;\n vertical-align: top;\n margin-top: 0.5em;\n border-top: 3px solid dimgray;\n}\n.likertResponse:first-child .likertLine:first-child {\n visibility: hidden;\n}\n.likertResponse:last-child > .likertLine:nth-child(2) {\n visibility: hidden;\n}\n.likertIndicator {\n display: inline-block;\n width: 1em;\n height: 1em;\n border-radius: 0.5em;\n border: thin solid #006fc4;\n background-color: #faeabd;\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n top: 0;\n box-sizing: border-box;\n transition: all linear 200ms;\n}\n.likertResponse:hover .likertIndicator {\n background-color: white;\n border-width: 3px;\n transition: all linear 200ms;\n}\n.likertText {\n display: inline-block;\n padding-top: 0.4em;\n padding-left: 0.4em;\n padding-right: 0.4em;\n width: 100%;\n box-sizing: border-box;\n}\n.likertScale.isKeyboardUser .likertResponse > input:focus ~ .likertIndicator {\n /* Show outline for keyboard users. */\n box-shadow: 0 0 5px 2px rgba(0, 119, 195, 0.5);\n}\n.likertResponse > input:checked + .likertIndicator {\n background-color: #006fc4;\n}\n.visuallyHidden {\n position: absolute;\n overflow: hidden;\n clip: rect(0 0 0 0);\n height: 1px;\n width: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n}\n\n@media only print {\n .likertResponse > input:checked + .likertIndicator {\n border-width: 0.5em !important;\n border-color: black !important;\n }\n}\n");class i extends e.Component{constructor(e){let t;super(e),n(this,"onChange",(e=>{this.setState({checkedIndex:parseInt(e.target.getAttribute("data-index"))}),"function"==typeof this.props.onChange?this.props.onChange(this.getResponsesItem(e.target.value)):"function"==typeof this.props.picked&&(console.warn("Deprecation: The “picked” callback has been renamed; use “onChange” instead."),this.props.picked(this.getResponsesItem(e.target.value)))})),n(this,"listenForTab",(e=>{"Tab"===e.key&&this.setState({isKeyboardUser:!0})})),n(this,"getResponsesItem",(e=>this.props.responses.find((n=>n.value==e)))),Array.isArray(e.responses)&&(t=e.responses.findIndex((e=>e.checked))),this.state={isKeyboardUser:!1,checkedIndex:t},e.id?this.id=e.id:e.question?this.id=function(e){let n=5381,t=e.length;for(;t;)n=33*n^e.charCodeAt(--t);return n>>>0}(e.question):this.id=Date.now()}componentDidMount(){document.addEventListener("keydown",this.listenForTab)}componentWillUnmount(){document.removeEventListener("keydown",this.listenForTab)}render(){const{responses:n,question:i,flexible:r=!0,className:s="",likertRef:a,...o}=this.props;delete o.picked,delete o.onChange;let l=null;r||(l={flexGrow:0}),"number"==typeof r&&4!==parseInt(r)&&(l={flexGrow:parseInt(r)});const d=n.map(((n,t)=>{const i="".concat(this.id).concat(t);return e.createElement("label",{key:i,htmlFor:i,className:"likertResponse"},e.createElement("span",{className:"likertLine"}),e.createElement("span",{className:"likertLine"}),e.createElement("input",{type:"radio",value:n.value,name:this.id,id:i,className:"visuallyHidden","data-index":t,onChange:this.onChange,checked:this.state.checkedIndex===t}),e.createElement("span",{className:"likertIndicator"}),e.createElement("span",{className:"likertText"},n.text))}));let c="likertScale";return c+=s?" ".concat(s):"",c+=this.state.isKeyboardUser?" isKeyboardUser":"",e.createElement("fieldset",t({className:c,ref:a,id:this.id},o,{"aria-labelledby":"legend-".concat(this.id)}),i&&e.createElement("div",{id:"legend-".concat(this.id),className:"likertLegend"},i),e.createElement("div",{className:"likertBand",style:l},d))}}var r=e.forwardRef(((n,r)=>e.createElement(i,t({},n,{likertRef:r}))));export default r; |
{ | ||
"name": "react-likert-scale", | ||
"version": "4.0.0-1", | ||
"version": "4.0.0-beta.0", | ||
"description": "A React component that makes a Likert Scale for collecting data.", | ||
@@ -22,3 +22,5 @@ "comments": [ | ||
"keywords": [ | ||
"Likert" | ||
"Likert", | ||
"react", | ||
"survey" | ||
], | ||
@@ -25,0 +27,0 @@ "author": "Craig Creeger", |
@@ -34,3 +34,3 @@ React Likert Scale | ||
{ value: 2, text: "Poor" }, | ||
{ value: 3, text: "Average" }, | ||
{ value: 3, text: "Average", checked: true }, | ||
{ value: 4, text: "Good" }, | ||
@@ -52,5 +52,9 @@ { value: 5, text: "Excellent" } | ||
This component has three `props`: | ||
* `question` — (string) This is the prompt that displays above the options. | ||
* `question` — (string) This is the prompt that displays above the options. It is optional. | ||
* `id` - (string) You are highly encouraged to always pass in a unique ID. This is used primarily | ||
for accessibility reasons (to associate the label to the radio button). If you are using the | ||
`question` prop and all you questions are unqiue then it is safe to omit the `id` prop. | ||
* `responses` — (array of objects) These are your options. The `value` key is what is returned to | ||
the calling application in the `onChange` callback. | ||
the calling application in the `onChange` callback. `text` is what’s shown on-screen. The optional | ||
`checked` key will pre-check a radio button when set to `true`. | ||
* `onChange` — (callback function) Optionally, you can provide a callback function that returns the | ||
@@ -57,0 +61,0 @@ value of the option that was clicked. |
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
21580
5.82%19
11.76%2
-33.33%126
3.28%