react-likert-scale
Advanced tools
Comparing version 1.1.0 to 2.0.0
@@ -1,24 +0,83 @@ | ||
import React from 'react'; | ||
import React, { useState, useEffect } from 'react'; | ||
import require$$0 from 'crypto'; | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
return obj; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
function createCommonjsModule(fn) { | ||
var module = { exports: {} }; | ||
return fn(module, module.exports), module.exports; | ||
} | ||
function commonjsRequire (target) { | ||
throw new Error('Could not dynamically require "' + target + '". Please configure the dynamicRequireTargets option of @rollup/plugin-commonjs appropriately for this require call to behave properly.'); | ||
} | ||
/*! | ||
Copyright (c) 2017 Jed Watson. | ||
Licensed under the MIT License (MIT), see | ||
http://jedwatson.github.io/classnames | ||
*/ | ||
var classnames = createCommonjsModule(function (module) { | ||
/* global define */ | ||
(function () { | ||
var hasOwn = {}.hasOwnProperty; | ||
function classNames () { | ||
var classes = []; | ||
for (var i = 0; i < arguments.length; i++) { | ||
var arg = arguments[i]; | ||
if (!arg) continue; | ||
var argType = typeof arg; | ||
if (argType === 'string' || argType === 'number') { | ||
classes.push(arg); | ||
} else if (Array.isArray(arg) && arg.length) { | ||
var inner = classNames.apply(null, arg); | ||
if (inner) { | ||
classes.push(inner); | ||
} | ||
} else if (argType === 'object') { | ||
for (var key in arg) { | ||
if (hasOwn.call(arg, key) && arg[key]) { | ||
classes.push(key); | ||
} | ||
} | ||
} | ||
} | ||
return classes.join(' '); | ||
} | ||
if ( module.exports) { | ||
classNames.default = classNames; | ||
module.exports = classNames; | ||
} else { | ||
window.classNames = classNames; | ||
} | ||
}()); | ||
}); | ||
var core = createCommonjsModule(function (module, exports) { | ||
@@ -28,15 +87,69 @@ (function (root, factory) { | ||
// CommonJS | ||
module.exports = exports = factory(); | ||
module.exports = factory(); | ||
} | ||
}(commonjsGlobal, function () { | ||
/*globals window, global, require*/ | ||
/** | ||
* CryptoJS core components. | ||
*/ | ||
var CryptoJS = CryptoJS || (function (Math, undefined) { | ||
var CryptoJS = CryptoJS || (function (Math, undefined$1) { | ||
var crypto; | ||
// Native crypto from window (Browser) | ||
if (typeof window !== 'undefined' && window.crypto) { | ||
crypto = window.crypto; | ||
} | ||
// Native (experimental IE 11) crypto from window (Browser) | ||
if (!crypto && typeof window !== 'undefined' && window.msCrypto) { | ||
crypto = window.msCrypto; | ||
} | ||
// Native crypto from global (NodeJS) | ||
if (!crypto && typeof commonjsGlobal !== 'undefined' && commonjsGlobal.crypto) { | ||
crypto = commonjsGlobal.crypto; | ||
} | ||
// Native crypto import via require (NodeJS) | ||
if (!crypto && typeof commonjsRequire === 'function') { | ||
try { | ||
crypto = require$$0; | ||
} catch (err) {} | ||
} | ||
/* | ||
* Local polyfil of Object.create | ||
* Cryptographically secure pseudorandom number generator | ||
* | ||
* As Math.random() is cryptographically not safe to use | ||
*/ | ||
var cryptoSecureRandomInt = function () { | ||
if (crypto) { | ||
// Use getRandomValues method (Browser) | ||
if (typeof crypto.getRandomValues === 'function') { | ||
try { | ||
return crypto.getRandomValues(new Uint32Array(1))[0]; | ||
} catch (err) {} | ||
} | ||
// Use randomBytes method (NodeJS) | ||
if (typeof crypto.randomBytes === 'function') { | ||
try { | ||
return crypto.randomBytes(4).readInt32LE(); | ||
} catch (err) {} | ||
} | ||
} | ||
throw new Error('Native crypto module could not be used to get secure random number.'); | ||
}; | ||
/* | ||
* Local polyfill of Object.create | ||
*/ | ||
var create = Object.create || (function () { | ||
function F() {} | ||
return function (obj) { | ||
@@ -210,3 +323,3 @@ var subtype; | ||
if (sigBytes != undefined) { | ||
if (sigBytes != undefined$1) { | ||
this.sigBytes = sigBytes; | ||
@@ -324,22 +437,4 @@ } else { | ||
var r = (function (m_w) { | ||
var m_w = m_w; | ||
var m_z = 0x3ade68b1; | ||
var mask = 0xffffffff; | ||
return function () { | ||
m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask; | ||
m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask; | ||
var result = ((m_z << 0x10) + m_w) & mask; | ||
result /= 0x100000000; | ||
result += 0.5; | ||
return result * (Math.random() > .5 ? 1 : -1); | ||
} | ||
}); | ||
for (var i = 0, rcache; i < nBytes; i += 4) { | ||
var _r = r((rcache || Math.random()) * 0x100000000); | ||
rcache = _r() * 0x3ade67b7; | ||
words.push((_r() * 0x100000000) | 0); | ||
for (var i = 0; i < nBytes; i += 4) { | ||
words.push(cryptoSecureRandomInt()); | ||
} | ||
@@ -575,2 +670,4 @@ | ||
_process: function (doFlush) { | ||
var processedWords; | ||
// Shortcuts | ||
@@ -608,3 +705,3 @@ var data = this._data; | ||
// Remove processed words | ||
var processedWords = dataWords.splice(0, nWordsReady); | ||
processedWords = dataWords.splice(0, nWordsReady); | ||
data.sigBytes -= nBytesReady; | ||
@@ -787,3 +884,3 @@ } | ||
// CommonJS | ||
module.exports = exports = factory(core); | ||
module.exports = factory(core); | ||
} | ||
@@ -956,75 +1053,72 @@ }(commonjsGlobal, function (CryptoJS) { | ||
var css = ".likertScale {\n\tmargin-bottom: 1em;\n}\n.likertBand {\n display: flex;\n padding-top: 1em;\n}\n.likertResponse {\n flex: 1 1 5em;\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 #870230;\n background-color: #ffed79;\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n top: 0;\n box-sizing: border-box;\n}\n.likertResponse:hover .likertIndicator {\n background-color: white;\n border-width: 3px;\n}\n.likertText {\n display: inline-block;\n padding-top: 0.4em;\n}\n.likertScale.isKeyboardUser .likertResponse > input:focus ~ .likertText {\n /* This rule is for accessibility. Keyboard users will get a blue shadow around the text when\n tabbed into the Likert scale. */\n box-shadow: 0 0 5px 2px rgba(0, 119, 195, 0.5);\n}\n.likertResponse>input:checked+.likertIndicator {\n background-color: #870230;\n}\n.visuallyHidden { \n position: absolute; \n overflow: hidden; \n clip: rect(0 0 0 0); \n height: 1px; width: 1px; \n margin: -1px; padding: 0; 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"; | ||
styleInject(css); | ||
var css_248z = ".likertScale {\n\tmargin-bottom: 1em;\n}\n.likertBand {\n display: flex;\n padding-top: 1em;\n}\n.likertResponse {\n flex: 1 1 5em;\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}\n.likertResponse:hover .likertIndicator {\n background-color: white;\n border-width: 3px;\n}\n.likertText {\n display: inline-block;\n padding-top: 0.4em;\n}\n.likertScale.isKeyboardUser .likertResponse > input:focus ~ .likertText {\n /* This rule is for accessibility. Keyboard users will get a blue shadow around the text when\n tabbed into the Likert scale. */\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; width: 1px; \n margin: -1px; padding: 0; 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"; | ||
styleInject(css_248z); | ||
class LikertScale extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
function LikertScale({ | ||
question, | ||
responses, | ||
picked, | ||
id, | ||
className = '', | ||
...restProps | ||
}, ref) { | ||
const [isKeyboardUser, setIsKeyboardUser] = useState(false); | ||
_defineProperty(this, "chosen", evt => { | ||
if (typeof this.props.picked === 'function') { | ||
this.props.picked(evt.target.value); | ||
} | ||
}); | ||
const listenForTab = evt => { | ||
if (evt.key === 'Tab') { | ||
setIsKeyboardUser(true); | ||
} | ||
}; | ||
_defineProperty(this, "listenForTab", evt => { | ||
if (evt.key === 'Tab') { | ||
this.setState({ | ||
isKeyboardUser: true | ||
}); | ||
} | ||
}); | ||
this.state = { | ||
isKeyboardUser: false | ||
useEffect(() => { | ||
document.addEventListener('keydown', listenForTab); | ||
return () => { | ||
document.removeEventListener('keydown', listenForTab); | ||
}; | ||
} | ||
}, []); | ||
componentDidMount() { | ||
document.addEventListener('keydown', this.listenForTab); | ||
} | ||
const onChosen = evt => { | ||
if (typeof picked === 'function') { | ||
picked(evt.target.value); | ||
} | ||
}; | ||
componentWillUnmount() { | ||
document.removeEventListener('keydown', this.listenForTab); | ||
} | ||
const sha = String(sha1(question)).substring(0, 7); | ||
const radios = responses.map((response, idx) => { | ||
const uniqueKey = "".concat(sha).concat(idx); | ||
return /*#__PURE__*/React.createElement("label", { | ||
key: uniqueKey, | ||
htmlFor: uniqueKey, | ||
className: "likertResponse" | ||
}, /*#__PURE__*/React.createElement("span", { | ||
className: "likertLine" | ||
}), /*#__PURE__*/React.createElement("span", { | ||
className: "likertLine" | ||
}), /*#__PURE__*/React.createElement("input", { | ||
type: "radio", | ||
value: response.value, | ||
name: sha, | ||
id: uniqueKey, | ||
className: "visuallyHidden", | ||
onClick: onChosen | ||
}), /*#__PURE__*/React.createElement("span", { | ||
className: "likertIndicator" | ||
}), /*#__PURE__*/React.createElement("span", { | ||
className: "likertText" | ||
}, response.text)); | ||
}); | ||
const cn = classnames('likertScale', className, { | ||
isKeyboardUser | ||
}); | ||
return /*#__PURE__*/React.createElement("fieldset", _extends({ | ||
className: cn, | ||
ref: ref, | ||
id: id || sha | ||
}, restProps), /*#__PURE__*/React.createElement("legend", null, question), /*#__PURE__*/React.createElement("div", { | ||
className: "likertBand" | ||
}, radios)); | ||
} | ||
render() { | ||
const _this$props = this.props, | ||
question = _this$props.question, | ||
responses = _this$props.responses, | ||
fieldsetId = _this$props.fieldsetId; | ||
const sha = String(sha1(question)).substring(0, 7); | ||
const radios = responses.map((response, idx) => { | ||
const uniqueKey = `${sha}${idx}`; | ||
return React.createElement("label", { | ||
key: uniqueKey, | ||
htmlFor: uniqueKey, | ||
className: "likertResponse" | ||
}, React.createElement("span", { | ||
className: "likertLine" | ||
}), React.createElement("span", { | ||
className: "likertLine" | ||
}), React.createElement("input", { | ||
type: "radio", | ||
value: response.value, | ||
name: sha, | ||
id: uniqueKey, | ||
className: "visuallyHidden", | ||
onClick: this.chosen | ||
}), React.createElement("span", { | ||
className: "likertIndicator" | ||
}), React.createElement("span", { | ||
className: "likertText" | ||
}, response.text)); | ||
}); | ||
return React.createElement("fieldset", { | ||
id: fieldsetId || Math.random().toString(36).substr(2), | ||
className: `likertScale${this.state.isKeyboardUser ? ' isKeyboardUser' : ''}` | ||
}, React.createElement("legend", null, question), React.createElement("div", { | ||
className: "likertBand" | ||
}, radios)); | ||
} | ||
var likert = /*#__PURE__*/React.forwardRef(LikertScale); | ||
} | ||
export default LikertScale; | ||
export default likert; |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) : | ||
typeof define === 'function' && define.amd ? define(['react'], factory) : | ||
(global = global || self, global.Likert = factory(global.React)); | ||
}(this, function (React) { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react'), require('crypto')) : | ||
typeof define === 'function' && define.amd ? define(['react', 'crypto'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Likert = factory(global.React, global.require$$0)); | ||
}(this, (function (React, require$$0) { 'use strict'; | ||
React = React && React.hasOwnProperty('default') ? React['default'] : React; | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0); | ||
return obj; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
function createCommonjsModule(fn) { | ||
var module = { exports: {} }; | ||
return fn(module, module.exports), module.exports; | ||
} | ||
function commonjsRequire (target) { | ||
throw new Error('Could not dynamically require "' + target + '". Please configure the dynamicRequireTargets option of @rollup/plugin-commonjs appropriately for this require call to behave properly.'); | ||
} | ||
/*! | ||
Copyright (c) 2017 Jed Watson. | ||
Licensed under the MIT License (MIT), see | ||
http://jedwatson.github.io/classnames | ||
*/ | ||
var classnames = createCommonjsModule(function (module) { | ||
/* global define */ | ||
(function () { | ||
var hasOwn = {}.hasOwnProperty; | ||
function classNames () { | ||
var classes = []; | ||
for (var i = 0; i < arguments.length; i++) { | ||
var arg = arguments[i]; | ||
if (!arg) continue; | ||
var argType = typeof arg; | ||
if (argType === 'string' || argType === 'number') { | ||
classes.push(arg); | ||
} else if (Array.isArray(arg) && arg.length) { | ||
var inner = classNames.apply(null, arg); | ||
if (inner) { | ||
classes.push(inner); | ||
} | ||
} else if (argType === 'object') { | ||
for (var key in arg) { | ||
if (hasOwn.call(arg, key) && arg[key]) { | ||
classes.push(key); | ||
} | ||
} | ||
} | ||
} | ||
return classes.join(' '); | ||
} | ||
if ( module.exports) { | ||
classNames.default = classNames; | ||
module.exports = classNames; | ||
} else { | ||
window.classNames = classNames; | ||
} | ||
}()); | ||
}); | ||
var core = createCommonjsModule(function (module, exports) { | ||
@@ -34,15 +95,69 @@ (function (root, factory) { | ||
// CommonJS | ||
module.exports = exports = factory(); | ||
module.exports = factory(); | ||
} | ||
}(commonjsGlobal, function () { | ||
/*globals window, global, require*/ | ||
/** | ||
* CryptoJS core components. | ||
*/ | ||
var CryptoJS = CryptoJS || (function (Math, undefined) { | ||
var CryptoJS = CryptoJS || (function (Math, undefined$1) { | ||
var crypto; | ||
// Native crypto from window (Browser) | ||
if (typeof window !== 'undefined' && window.crypto) { | ||
crypto = window.crypto; | ||
} | ||
// Native (experimental IE 11) crypto from window (Browser) | ||
if (!crypto && typeof window !== 'undefined' && window.msCrypto) { | ||
crypto = window.msCrypto; | ||
} | ||
// Native crypto from global (NodeJS) | ||
if (!crypto && typeof commonjsGlobal !== 'undefined' && commonjsGlobal.crypto) { | ||
crypto = commonjsGlobal.crypto; | ||
} | ||
// Native crypto import via require (NodeJS) | ||
if (!crypto && typeof commonjsRequire === 'function') { | ||
try { | ||
crypto = require$$0__default['default']; | ||
} catch (err) {} | ||
} | ||
/* | ||
* Local polyfil of Object.create | ||
* Cryptographically secure pseudorandom number generator | ||
* | ||
* As Math.random() is cryptographically not safe to use | ||
*/ | ||
var cryptoSecureRandomInt = function () { | ||
if (crypto) { | ||
// Use getRandomValues method (Browser) | ||
if (typeof crypto.getRandomValues === 'function') { | ||
try { | ||
return crypto.getRandomValues(new Uint32Array(1))[0]; | ||
} catch (err) {} | ||
} | ||
// Use randomBytes method (NodeJS) | ||
if (typeof crypto.randomBytes === 'function') { | ||
try { | ||
return crypto.randomBytes(4).readInt32LE(); | ||
} catch (err) {} | ||
} | ||
} | ||
throw new Error('Native crypto module could not be used to get secure random number.'); | ||
}; | ||
/* | ||
* Local polyfill of Object.create | ||
*/ | ||
var create = Object.create || (function () { | ||
function F() {} | ||
return function (obj) { | ||
@@ -216,3 +331,3 @@ var subtype; | ||
if (sigBytes != undefined) { | ||
if (sigBytes != undefined$1) { | ||
this.sigBytes = sigBytes; | ||
@@ -330,22 +445,4 @@ } else { | ||
var r = (function (m_w) { | ||
var m_w = m_w; | ||
var m_z = 0x3ade68b1; | ||
var mask = 0xffffffff; | ||
return function () { | ||
m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask; | ||
m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask; | ||
var result = ((m_z << 0x10) + m_w) & mask; | ||
result /= 0x100000000; | ||
result += 0.5; | ||
return result * (Math.random() > .5 ? 1 : -1); | ||
} | ||
}); | ||
for (var i = 0, rcache; i < nBytes; i += 4) { | ||
var _r = r((rcache || Math.random()) * 0x100000000); | ||
rcache = _r() * 0x3ade67b7; | ||
words.push((_r() * 0x100000000) | 0); | ||
for (var i = 0; i < nBytes; i += 4) { | ||
words.push(cryptoSecureRandomInt()); | ||
} | ||
@@ -581,2 +678,4 @@ | ||
_process: function (doFlush) { | ||
var processedWords; | ||
// Shortcuts | ||
@@ -614,3 +713,3 @@ var data = this._data; | ||
// Remove processed words | ||
var processedWords = dataWords.splice(0, nWordsReady); | ||
processedWords = dataWords.splice(0, nWordsReady); | ||
data.sigBytes -= nBytesReady; | ||
@@ -793,3 +892,3 @@ } | ||
// CommonJS | ||
module.exports = exports = factory(core); | ||
module.exports = factory(core); | ||
} | ||
@@ -962,77 +1061,74 @@ }(commonjsGlobal, function (CryptoJS) { | ||
var css = ".likertScale {\n\tmargin-bottom: 1em;\n}\n.likertBand {\n display: flex;\n padding-top: 1em;\n}\n.likertResponse {\n flex: 1 1 5em;\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 #870230;\n background-color: #ffed79;\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n top: 0;\n box-sizing: border-box;\n}\n.likertResponse:hover .likertIndicator {\n background-color: white;\n border-width: 3px;\n}\n.likertText {\n display: inline-block;\n padding-top: 0.4em;\n}\n.likertScale.isKeyboardUser .likertResponse > input:focus ~ .likertText {\n /* This rule is for accessibility. Keyboard users will get a blue shadow around the text when\n tabbed into the Likert scale. */\n box-shadow: 0 0 5px 2px rgba(0, 119, 195, 0.5);\n}\n.likertResponse>input:checked+.likertIndicator {\n background-color: #870230;\n}\n.visuallyHidden { \n position: absolute; \n overflow: hidden; \n clip: rect(0 0 0 0); \n height: 1px; width: 1px; \n margin: -1px; padding: 0; 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"; | ||
styleInject(css); | ||
var css_248z = ".likertScale {\n\tmargin-bottom: 1em;\n}\n.likertBand {\n display: flex;\n padding-top: 1em;\n}\n.likertResponse {\n flex: 1 1 5em;\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}\n.likertResponse:hover .likertIndicator {\n background-color: white;\n border-width: 3px;\n}\n.likertText {\n display: inline-block;\n padding-top: 0.4em;\n}\n.likertScale.isKeyboardUser .likertResponse > input:focus ~ .likertText {\n /* This rule is for accessibility. Keyboard users will get a blue shadow around the text when\n tabbed into the Likert scale. */\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; width: 1px; \n margin: -1px; padding: 0; 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"; | ||
styleInject(css_248z); | ||
class LikertScale extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
function LikertScale({ | ||
question, | ||
responses, | ||
picked, | ||
id, | ||
className = '', | ||
...restProps | ||
}, ref) { | ||
const [isKeyboardUser, setIsKeyboardUser] = React.useState(false); | ||
_defineProperty(this, "chosen", evt => { | ||
if (typeof this.props.picked === 'function') { | ||
this.props.picked(evt.target.value); | ||
} | ||
}); | ||
const listenForTab = evt => { | ||
if (evt.key === 'Tab') { | ||
setIsKeyboardUser(true); | ||
} | ||
}; | ||
_defineProperty(this, "listenForTab", evt => { | ||
if (evt.key === 'Tab') { | ||
this.setState({ | ||
isKeyboardUser: true | ||
}); | ||
} | ||
}); | ||
this.state = { | ||
isKeyboardUser: false | ||
React.useEffect(() => { | ||
document.addEventListener('keydown', listenForTab); | ||
return () => { | ||
document.removeEventListener('keydown', listenForTab); | ||
}; | ||
} | ||
}, []); | ||
componentDidMount() { | ||
document.addEventListener('keydown', this.listenForTab); | ||
} | ||
const onChosen = evt => { | ||
if (typeof picked === 'function') { | ||
picked(evt.target.value); | ||
} | ||
}; | ||
componentWillUnmount() { | ||
document.removeEventListener('keydown', this.listenForTab); | ||
} | ||
const sha = String(sha1(question)).substring(0, 7); | ||
const radios = responses.map((response, idx) => { | ||
const uniqueKey = "".concat(sha).concat(idx); | ||
return /*#__PURE__*/React__default['default'].createElement("label", { | ||
key: uniqueKey, | ||
htmlFor: uniqueKey, | ||
className: "likertResponse" | ||
}, /*#__PURE__*/React__default['default'].createElement("span", { | ||
className: "likertLine" | ||
}), /*#__PURE__*/React__default['default'].createElement("span", { | ||
className: "likertLine" | ||
}), /*#__PURE__*/React__default['default'].createElement("input", { | ||
type: "radio", | ||
value: response.value, | ||
name: sha, | ||
id: uniqueKey, | ||
className: "visuallyHidden", | ||
onClick: onChosen | ||
}), /*#__PURE__*/React__default['default'].createElement("span", { | ||
className: "likertIndicator" | ||
}), /*#__PURE__*/React__default['default'].createElement("span", { | ||
className: "likertText" | ||
}, response.text)); | ||
}); | ||
const cn = classnames('likertScale', className, { | ||
isKeyboardUser | ||
}); | ||
return /*#__PURE__*/React__default['default'].createElement("fieldset", _extends({ | ||
className: cn, | ||
ref: ref, | ||
id: id || sha | ||
}, restProps), /*#__PURE__*/React__default['default'].createElement("legend", null, question), /*#__PURE__*/React__default['default'].createElement("div", { | ||
className: "likertBand" | ||
}, radios)); | ||
} | ||
render() { | ||
const _this$props = this.props, | ||
question = _this$props.question, | ||
responses = _this$props.responses, | ||
fieldsetId = _this$props.fieldsetId; | ||
const sha = String(sha1(question)).substring(0, 7); | ||
const radios = responses.map((response, idx) => { | ||
const uniqueKey = `${sha}${idx}`; | ||
return React.createElement("label", { | ||
key: uniqueKey, | ||
htmlFor: uniqueKey, | ||
className: "likertResponse" | ||
}, React.createElement("span", { | ||
className: "likertLine" | ||
}), React.createElement("span", { | ||
className: "likertLine" | ||
}), React.createElement("input", { | ||
type: "radio", | ||
value: response.value, | ||
name: sha, | ||
id: uniqueKey, | ||
className: "visuallyHidden", | ||
onClick: this.chosen | ||
}), React.createElement("span", { | ||
className: "likertIndicator" | ||
}), React.createElement("span", { | ||
className: "likertText" | ||
}, response.text)); | ||
}); | ||
return React.createElement("fieldset", { | ||
id: fieldsetId || Math.random().toString(36).substr(2), | ||
className: `likertScale${this.state.isKeyboardUser ? ' isKeyboardUser' : ''}` | ||
}, React.createElement("legend", null, question), React.createElement("div", { | ||
className: "likertBand" | ||
}, radios)); | ||
} | ||
var likert = /*#__PURE__*/React__default['default'].forwardRef(LikertScale); | ||
} | ||
return likert; | ||
return LikertScale; | ||
})); | ||
}))); |
{ | ||
"name": "react-likert-scale", | ||
"version": "1.1.0", | ||
"version": "2.0.0", | ||
"description": "A React-based Likert Scale to collect data.", | ||
@@ -20,3 +20,5 @@ "main": "dist/likert.umd.js", | ||
"scripts": { | ||
"start": "webpack-dev-server --config webpack.config.dev.js --inline --hot --progress --mode development", | ||
"lint": "eslint src", | ||
"lint:fix": "eslint --fix src", | ||
"start": "webpack serve --config webpack.config.dev.js --inline --hot --progress --mode development", | ||
"build:esm": "rollup -c -f esm -o dist/likert.esm.js", | ||
@@ -28,28 +30,30 @@ "build:umd": "rollup -c -f umd -g react:React -o dist/likert.umd.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.2.2", | ||
"@babel/plugin-proposal-class-properties": "^7.2.3", | ||
"@babel/preset-env": "^7.2.3", | ||
"@babel/preset-react": "^7.0.0", | ||
"acorn": "^6.0.5", | ||
"babel-eslint": "^10.0.1", | ||
"babel-loader": "^8.0.5", | ||
"css-loader": "^2.1.0", | ||
"eslint": "^5.12.1", | ||
"eslint-plugin-react": "^7.12.4", | ||
"html-webpack-plugin": "^3.2.0", | ||
"react": "^16.7.0", | ||
"react-dom": "^16.7.0", | ||
"rollup": "^1.1.1", | ||
"rollup-plugin-babel": "^4.3.2", | ||
"rollup-plugin-commonjs": "^9.2.0", | ||
"rollup-plugin-node-resolve": "^4.0.0", | ||
"rollup-plugin-postcss": "^1.6.3", | ||
"style-loader": "^0.23.1", | ||
"webpack": "^4.28.4", | ||
"webpack-cli": "^3.2.1", | ||
"webpack-dev-server": "^3.1.14" | ||
"@babel/core": "^7.12.10", | ||
"@babel/plugin-proposal-class-properties": "^7.12.1", | ||
"@babel/preset-env": "^7.12.11", | ||
"@babel/preset-react": "^7.12.10", | ||
"@rollup/plugin-babel": "^5.2.2", | ||
"@rollup/plugin-commonjs": "^17.0.0", | ||
"@rollup/plugin-node-resolve": "^11.0.1", | ||
"@webpack-cli/serve": "^1.2.1", | ||
"babel-eslint": "^10.1.0", | ||
"babel-loader": "^8.2.2", | ||
"css-loader": "^5.0.1", | ||
"eslint": "^7.16.0", | ||
"eslint-plugin-react": "^7.22.0", | ||
"eslint-plugin-react-hooks": "^4.2.0", | ||
"html-webpack-plugin": "^4.5.1", | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"rollup": "^2.36.1", | ||
"rollup-plugin-postcss": "^4.0.0", | ||
"style-loader": "^2.0.0", | ||
"webpack": "^5.12.3", | ||
"webpack-cli": "^4.3.1", | ||
"webpack-dev-server": "^3.11.1" | ||
}, | ||
"dependencies": { | ||
"crypto-js": "^3.1.9-1" | ||
"classnames": "^2.2.6", | ||
"crypto-js": "^4.0.0" | ||
} | ||
} |
React Likert Scale | ||
====================================== | ||
React Likert Scale is a [React component](https://reactjs.org/docs) that renders a Likert Scale. It is fully responsive and the styling can be customized by providing your own CSS styles. | ||
React Likert Scale is a [React component](https://reactjs.org/docs) that renders a Likert Scale. It | ||
is fully responsive, very small size (about 8kb), and the styling can be customized by providing | ||
your own CSS styles. | ||
@@ -10,3 +12,3 @@ ![Screenshot of Likert component](./likert.png) | ||
`npm install --save react-likert-scale` | ||
`npm install -P react-likert-scale` | ||
@@ -32,3 +34,3 @@ | ||
{ value: 4, text: "Good" }, | ||
{ value: 5, text: "Most Excellent, Ted" } | ||
{ value: 5, text: "Excellent" } | ||
], | ||
@@ -51,3 +53,63 @@ picked: val => { | ||
the calling application in the `picked` callback. | ||
* `picked` — (function) Optionally, you can provide a callback function that returns the value of | ||
the option that a user clicks on. | ||
* `picked` — (callback function) Optionally, you can provide a callback function that returns the | ||
value of the option that was clicked. | ||
## FAQ | ||
### How do I change the colors or other styling? | ||
The top-level DOM element that gets created by this component is `<fieldset class="likertScale">`. | ||
You can override any styles by prefixing your rule with `fieldset.likertScale`. For example, let’s | ||
say you want the radio button “dots” to have a light gray background with a dark green ring. | ||
``` | ||
fieldset.likertScale .likertIndicator { | ||
border: thin solid darkGreen; | ||
background-color: lightGray; | ||
} | ||
``` | ||
### I need access to the DOM element created by React. How is that done? | ||
This isn’t very common, but you may want to set focus on a Likert Scale after the page renders. This | ||
is done with React via `refs`. Either create your ref with `React.createRef()` or the `useRef()` | ||
hook. You can then pass your ref to the Likert component. | ||
```javascript | ||
import React, { useRef } from 'react'; | ||
import Likert from 'react-likert-scale'; | ||
export default () => { | ||
const likertOptions = { | ||
question: "What is your opinion of the President’s performance?", | ||
responses: [ | ||
{ value: 1, text: "Abysmal" }, | ||
{ value: 2, text: "Poor" }, | ||
{ value: 3, text: "Average" }, | ||
{ value: 4, text: "Good" }, | ||
{ value: 5, text: "Excellent" } | ||
] | ||
}; | ||
const likertRef = useRef(); | ||
return ( | ||
<Likert {...likertOptions} ref={likertRef} /> | ||
) | ||
} | ||
``` | ||
### Can I pass DOM attributes such as `id`, `class`, `disabled`, `data-*`, `onClick`, etc.? | ||
Sure. They will be applied to the likert component’s top-level DOM element, `<fieldset>`. e.g.: | ||
```javascript | ||
<Likert {...likertOptions} | ||
id='Q1' | ||
className='myClass' | ||
onClick={() => { | ||
doThis(); | ||
andThis(); | ||
}} | ||
/> | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
74222
1955
112
2
23
+ Addedclassnames@^2.2.6
+ Addedclassnames@2.5.1(transitive)
+ Addedcrypto-js@4.2.0(transitive)
- Removedcrypto-js@3.3.0(transitive)
Updatedcrypto-js@^4.0.0