@slipmatio/control-knob
Advanced tools
Comparing version 0.0.1 to 0.1.0
@@ -66,2 +66,3 @@ import { defineComponent, ref, computed, watch, onBeforeUnmount, openBlock, createElementBlock, unref, normalizeClass, withModifiers, createElementVNode, createCommentVNode, toDisplayString } from "vue"; | ||
const _sfc_main = /* @__PURE__ */ defineComponent({ | ||
__name: "ControlKnob", | ||
props: { | ||
@@ -73,3 +74,3 @@ modelValue: null, | ||
setup(__props, { emit }) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A; | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C; | ||
const props = __props; | ||
@@ -110,2 +111,3 @@ const knobElement = ref(0); | ||
const valueTextClass = ((_A = props.options) == null ? void 0 : _A.valueTextClass) || "text-gray-50 text-[30px] font-normal font-mono"; | ||
const passiveEvents = ((_B = props.options) == null ? void 0 : _B.passiveEvents) === void 0 ? false : (_C = props.options) == null ? void 0 : _C.passiveEvents; | ||
const startValue = vModel.value; | ||
@@ -147,2 +149,3 @@ const tickStartX = computed(() => { | ||
prevY = event.clientY; | ||
preventScrolling(event); | ||
}; | ||
@@ -175,2 +178,8 @@ function moveListener(event) { | ||
const debouncedMoveListener = leadingDebounce(moveListener); | ||
function preventScrolling(event) { | ||
if (passiveEvents === false) { | ||
event.preventDefault(); | ||
event.stopPropagation(); | ||
} | ||
} | ||
const upListener = () => { | ||
@@ -203,4 +212,4 @@ mouseIsDown.value = false; | ||
} | ||
if (hasFocus.value && shiftModifier.value && (event.key === "ArrowUp" || event.key === "ArrowDown")) { | ||
event.preventDefault(); | ||
if (hasFocus.value && (event.key === "ArrowUp" || event.key === "ArrowDown")) { | ||
preventScrolling(event); | ||
} | ||
@@ -235,2 +244,3 @@ } | ||
changeValue(newValue); | ||
preventScrolling(event); | ||
} | ||
@@ -246,3 +256,3 @@ function mouseOverHandler() { | ||
element.addEventListener("mousedown", downListener); | ||
element.addEventListener("wheel", wheelListener); | ||
element.addEventListener("wheel", wheelListener, { passive: passiveEvents }); | ||
element.addEventListener("mouseenter", mouseOverHandler); | ||
@@ -276,7 +286,7 @@ element.addEventListener("mouseleave", mouseOutHandler); | ||
return openBlock(), createElementBlock("svg", { | ||
ref_key: "knobElement", | ||
ref: knobElement, | ||
width: unref(imageSize), | ||
height: unref(imageSize), | ||
viewBox: "0 0 100 100", | ||
ref_key: "knobElement", | ||
ref: knobElement, | ||
role: "slider", | ||
@@ -283,0 +293,0 @@ "aria-label": unref(ariaLabel), |
@@ -1,2 +0,2 @@ | ||
(function(e,h){typeof exports=="object"&&typeof module!="undefined"?module.exports=h(require("vue")):typeof define=="function"&&define.amd?define(["vue"],h):(e=typeof globalThis!="undefined"?globalThis:e||self,e.ControlKnob=h(e.Vue))})(this,function(e){"use strict";function c(a){return a*Math.PI/180}function fe(a,u=13){let t;return(...s)=>{t?clearTimeout(t):a.apply(this,s),t=setTimeout(()=>{t=void 0},u)}}function de(a,u,t=!1){let s=150;t&&(s=s*10);const r=(420-120)/s;return u*r}function I(a,u,t){let s;const r=u-a;return t===120?s=0:t===420?s=1:s=(t-120)/300,a+r*s}function w(a,u,t){let s;const r=u-a;return t===a?s=0:t===u?s=1:s=(t-a)/r,120+300*s}const me=["width","height","aria-label","aria-valuemin","aria-valuemax","aria-valuenow","tabindex","onClick"],pe=["cx","cy","r"],Ae=["stroke-width"],he=["d","stroke-width"],Ee=["x1","y1","x2","y2","stroke-width"],ke=["x","y"];return e.defineComponent({props:{modelValue:null,options:null},emits:["update:modelValue"],setup(a,{emit:u}){var U,O,T,F,$,Y,H,W,z,K,P,j,q,J,Q,Z,ee,te,oe,ne,se,le,ae,re,ie,ce,ue;const t=a,s=e.ref(0),n=e.ref(120),r=e.computed({get(){return t.modelValue},set(o){u("update:modelValue",o)}}),L=((U=t.options)==null?void 0:U.imageSize)||40,m=((O=t.options)==null?void 0:O.minValue)||0,p=((T=t.options)==null?void 0:T.maxValue)||100,Le=((F=t.options)==null?void 0:F.showTick)===void 0?!0:($=t.options)==null?void 0:$.showTick,_e=((Y=t.options)==null?void 0:Y.showValue)===void 0?!0:(H=t.options)==null?void 0:H.showTick,Me=((W=t.options)==null?void 0:W.hideDefaultValue)===void 0?!0:(z=t.options)==null?void 0:z.hideDefaultValue,N=((K=t.options)==null?void 0:K.tickLength)||18,V=((P=t.options)==null?void 0:P.tickOffset)||10,ve=((j=t.options)==null?void 0:j.tickStroke)||3,Ie=((q=t.options)==null?void 0:q.rimStroke)||11,we=((J=t.options)==null?void 0:J.valueArchStroke)||11,Ne=((Q=t.options)==null?void 0:Q.bgRadius)||34,Ve=((Z=t.options)==null?void 0:Z.wheelFactor)||10,Ce=((ee=t.options)==null?void 0:ee.keyFactor)||10,ge=((te=t.options)==null?void 0:te.tabIndex)||0,xe=((oe=t.options)==null?void 0:oe.ariaLabel)||"Knob",ye=((ne=t.options)==null?void 0:ne.valueTextX)||50,Xe=((se=t.options)==null?void 0:se.valueTextY)||62,Se=((le=t.options)==null?void 0:le.svgClass)||"select-none",Re=((ae=t.options)==null?void 0:ae.bgClass)||"text-[#868686]",Ge=((re=t.options)==null?void 0:re.rimClass)||"text-[#393939]",De=((ie=t.options)==null?void 0:ie.valueArchClass)||"text-[#53d769]",Be=((ce=t.options)==null?void 0:ce.tickClass)||"text-black",be=((ue=t.options)==null?void 0:ue.valueTextClass)||"text-gray-50 text-[30px] font-normal font-mono",Ue=r.value,Oe=e.computed(()=>50+Math.cos(c(n.value))*(40-N)),Te=e.computed(()=>50+Math.sin(c(n.value))*(40-N)),Fe=e.computed(()=>50+Math.cos(c(n.value))*(40-V)),$e=e.computed(()=>50+Math.sin(c(n.value))*(40-V)),C=50+-.5*40,g=50+Math.sin(c(120))*40,Ye=50+.5*40,He=50+Math.sin(c(420))*40,We=c(120),ze=e.computed(()=>c(n.value)),Ke=e.computed(()=>Math.abs(We-ze.value)<Math.PI?0:1),Pe=e.ref(1),je=e.computed(()=>50+Math.cos(c(n.value))*40),qe=e.computed(()=>50+Math.sin(c(n.value))*40),Je=`M ${C} ${g} A ${40} ${40} 0 1 1 ${Ye} ${He}`,Qe=e.computed(()=>`M ${C} ${g} A ${40} ${40} 0 ${Ke.value} ${Pe.value} ${je.value} ${qe.value}`);let A=0,E=0;const k=e.ref(!1),_=e.ref(!1),x=e.ref(!1),f=e.ref(!1),d=e.ref(!1),y=o=>{k.value=!0,x.value=!1,A=o.clientY};function Ze(o){if(x.value=!0,k.value){E=o.clientY;let l;const i=A-E;if(i<0?l="down":l="up",A!==E&&(l==="up"&&n.value<420||l==="down"&&n.value>120)){const v=de(A,i,d.value);n.value+v<120?n.value=120:n.value+v>420?n.value=420:n.value+=v,r.value=I(m,p,n.value)}A=E}}const X=fe(Ze),S=()=>{k.value=!1};function et(){n.value=120}function M(o){o>n.value&&(o<420?n.value=o:n.value=420),o<n.value&&(o<n.value&&o>120?n.value=o:n.value=120),r.value=I(m,p,n.value)}function R(o){o.key==="Shift"&&(d.value=!0),f.value&&d.value&&(o.key==="ArrowUp"||o.key==="ArrowDown")&&o.preventDefault()}function G(o){o.key==="Shift"&&(d.value=!1);let l;const i=d.value?1:Ce;f.value&&o.key==="ArrowUp"&&(l=n.value+1*i,M(l),d.value&&o.stopPropagation()),f.value&&o.key==="ArrowDown"&&(l=n.value-1*i,M(l))}function D(o){let l;const i=o.shiftKey?1:Ve;!o.shiftKey&&o.deltaY<0||o.shiftKey&&o.deltaX<0?l=n.value+1*i:l=n.value-1*i,M(l)}function B(){_.value=!0}function b(){_.value=!1}return e.watch(()=>s.value,(o,l)=>{if(o&&!l){o.addEventListener("mousedown",y),o.addEventListener("wheel",D),o.addEventListener("mouseenter",B),o.addEventListener("mouseleave",b),document.addEventListener("mouseup",S),document.addEventListener("mousemove",X),document.addEventListener("keydown",R),document.addEventListener("keyup",G);const i=w(m,p,t.modelValue);n.value=i}}),e.watch(()=>t.modelValue,o=>{if(_.value===!1&&k.value===!1&&f.value===!1){const l=w(m,p,o);n.value=l}}),e.onBeforeUnmount(()=>{s.value.removeEventListener("mousedown",y),s.value.removeEventListener("wheel",D),s.value.removeEventListener("mouseenter",B),s.value.removeEventListener("mouseleave",b),document.removeEventListener("mouseup",S),document.removeEventListener("mousemove",X),document.removeEventListener("keydown",R),document.removeEventListener("keyup",G)}),(o,l)=>(e.openBlock(),e.createElementBlock("svg",{width:e.unref(L),height:e.unref(L),viewBox:"0 0 100 100",ref_key:"knobElement",ref:s,role:"slider","aria-label":e.unref(xe),"aria-valuemin":e.unref(m),"aria-valuemax":e.unref(p),"aria-valuenow":e.unref(r),tabindex:e.unref(ge),class:e.normalizeClass(e.unref(Se)),onClick:e.withModifiers(et,["alt"]),onFocus:l[0]||(l[0]=i=>f.value=!0),onBlur:l[1]||(l[1]=i=>f.value=!1)},[e.createElementVNode("circle",{cx:e.unref(50),cy:e.unref(50),r:e.unref(Ne),stroke:"currentColor",fill:"currentColor",class:e.normalizeClass(e.unref(Re)),"stroke-width":1},null,10,pe),e.createElementVNode("path",{d:Je,"stroke-width":e.unref(Ie),stroke:"currentColor",fill:"none",class:e.normalizeClass(e.unref(Ge))},null,10,Ae),n.value>120?(e.openBlock(),e.createElementBlock("path",{key:0,d:e.unref(Qe),"stroke-width":e.unref(we),stroke:"currentColor",fill:"none",class:e.normalizeClass(e.unref(De))},null,10,he)):e.createCommentVNode("",!0),e.unref(Le)?(e.openBlock(),e.createElementBlock("line",{key:1,x1:e.unref(Oe),y1:e.unref(Te),x2:e.unref(Fe),y2:e.unref($e),stroke:"currentColor","stroke-width":e.unref(ve),class:e.normalizeClass(e.unref(Be))},null,10,Ee)):e.createCommentVNode("",!0),e.unref(_e)&&(!e.unref(Me)||e.unref(Ue)!==e.unref(r))?(e.openBlock(),e.createElementBlock("text",{key:2,x:e.unref(ye),y:e.unref(Xe),"text-anchor":"middle",fill:"currentColor",class:e.normalizeClass(e.unref(be))},e.toDisplayString(Math.ceil(e.unref(r))),11,ke)):e.createCommentVNode("",!0)],42,me))}})}); | ||
(function(e,E){typeof exports=="object"&&typeof module!="undefined"?module.exports=E(require("vue")):typeof define=="function"&&define.amd?define(["vue"],E):(e=typeof globalThis!="undefined"?globalThis:e||self,e.ControlKnob=E(e.Vue))})(this,function(e){"use strict";function c(a){return a*Math.PI/180}function Ae(a,u=13){let t;return(...s)=>{t?clearTimeout(t):a.apply(this,s),t=setTimeout(()=>{t=void 0},u)}}function Ee(a,u,t=!1){let s=150;t&&(s=s*10);const r=(420-120)/s;return u*r}function w(a,u,t){let s;const r=u-a;return t===120?s=0:t===420?s=1:s=(t-120)/300,a+r*s}function N(a,u,t){let s;const r=u-a;return t===a?s=0:t===u?s=1:s=(t-a)/r,120+300*s}const he=["width","height","aria-label","aria-valuemin","aria-valuemax","aria-valuenow","tabindex","onClick"],ke=["cx","cy","r"],Le=["stroke-width"],ve=["d","stroke-width"],_e=["x1","y1","x2","y2","stroke-width"],Me=["x","y"];return e.defineComponent({__name:"ControlKnob",props:{modelValue:null,options:null},emits:["update:modelValue"],setup(a,{emit:u}){var T,F,$,Y,H,W,z,K,P,j,q,J,Q,Z,ee,te,oe,ne,se,le,ae,re,ie,ce,ue,fe,de,me,pe;const t=a,s=e.ref(0),n=e.ref(120),r=e.computed({get(){return t.modelValue},set(o){u("update:modelValue",o)}}),L=((T=t.options)==null?void 0:T.imageSize)||40,d=((F=t.options)==null?void 0:F.minValue)||0,m=(($=t.options)==null?void 0:$.maxValue)||100,Ie=((Y=t.options)==null?void 0:Y.showTick)===void 0?!0:(H=t.options)==null?void 0:H.showTick,we=((W=t.options)==null?void 0:W.showValue)===void 0?!0:(z=t.options)==null?void 0:z.showTick,Ne=((K=t.options)==null?void 0:K.hideDefaultValue)===void 0?!0:(P=t.options)==null?void 0:P.hideDefaultValue,V=((j=t.options)==null?void 0:j.tickLength)||18,g=((q=t.options)==null?void 0:q.tickOffset)||10,Ve=((J=t.options)==null?void 0:J.tickStroke)||3,ge=((Q=t.options)==null?void 0:Q.rimStroke)||11,Ce=((Z=t.options)==null?void 0:Z.valueArchStroke)||11,xe=((ee=t.options)==null?void 0:ee.bgRadius)||34,ye=((te=t.options)==null?void 0:te.wheelFactor)||10,Se=((oe=t.options)==null?void 0:oe.keyFactor)||10,Xe=((ne=t.options)==null?void 0:ne.tabIndex)||0,Re=((se=t.options)==null?void 0:se.ariaLabel)||"Knob",Ge=((le=t.options)==null?void 0:le.valueTextX)||50,De=((ae=t.options)==null?void 0:ae.valueTextY)||62,Be=((re=t.options)==null?void 0:re.svgClass)||"select-none",be=((ie=t.options)==null?void 0:ie.bgClass)||"text-[#868686]",Ue=((ce=t.options)==null?void 0:ce.rimClass)||"text-[#393939]",Oe=((ue=t.options)==null?void 0:ue.valueArchClass)||"text-[#53d769]",Te=((fe=t.options)==null?void 0:fe.tickClass)||"text-black",Fe=((de=t.options)==null?void 0:de.valueTextClass)||"text-gray-50 text-[30px] font-normal font-mono",C=((me=t.options)==null?void 0:me.passiveEvents)===void 0?!1:(pe=t.options)==null?void 0:pe.passiveEvents,$e=r.value,Ye=e.computed(()=>50+Math.cos(c(n.value))*(40-V)),He=e.computed(()=>50+Math.sin(c(n.value))*(40-V)),We=e.computed(()=>50+Math.cos(c(n.value))*(40-g)),ze=e.computed(()=>50+Math.sin(c(n.value))*(40-g)),x=50+-.5*40,y=50+Math.sin(c(120))*40,Ke=50+.5*40,Pe=50+Math.sin(c(420))*40,je=c(120),qe=e.computed(()=>c(n.value)),Je=e.computed(()=>Math.abs(je-qe.value)<Math.PI?0:1),Qe=e.ref(1),Ze=e.computed(()=>50+Math.cos(c(n.value))*40),et=e.computed(()=>50+Math.sin(c(n.value))*40),tt=`M ${x} ${y} A ${40} ${40} 0 1 1 ${Ke} ${Pe}`,ot=e.computed(()=>`M ${x} ${y} A ${40} ${40} 0 ${Je.value} ${Qe.value} ${Ze.value} ${et.value}`);let p=0,h=0;const k=e.ref(!1),v=e.ref(!1),S=e.ref(!1),f=e.ref(!1),A=e.ref(!1),X=o=>{k.value=!0,S.value=!1,p=o.clientY,_(o)};function nt(o){if(S.value=!0,k.value){h=o.clientY;let l;const i=p-h;if(i<0?l="down":l="up",p!==h&&(l==="up"&&n.value<420||l==="down"&&n.value>120)){const I=Ee(p,i,A.value);n.value+I<120?n.value=120:n.value+I>420?n.value=420:n.value+=I,r.value=w(d,m,n.value)}p=h}}const R=Ae(nt);function _(o){C===!1&&(o.preventDefault(),o.stopPropagation())}const G=()=>{k.value=!1};function st(){n.value=120}function M(o){o>n.value&&(o<420?n.value=o:n.value=420),o<n.value&&(o<n.value&&o>120?n.value=o:n.value=120),r.value=w(d,m,n.value)}function D(o){o.key==="Shift"&&(A.value=!0),f.value&&(o.key==="ArrowUp"||o.key==="ArrowDown")&&_(o)}function B(o){o.key==="Shift"&&(A.value=!1);let l;const i=A.value?1:Se;f.value&&o.key==="ArrowUp"&&(l=n.value+1*i,M(l),A.value&&o.stopPropagation()),f.value&&o.key==="ArrowDown"&&(l=n.value-1*i,M(l))}function b(o){let l;const i=o.shiftKey?1:ye;!o.shiftKey&&o.deltaY<0||o.shiftKey&&o.deltaX<0?l=n.value+1*i:l=n.value-1*i,M(l),_(o)}function U(){v.value=!0}function O(){v.value=!1}return e.watch(()=>s.value,(o,l)=>{if(o&&!l){o.addEventListener("mousedown",X),o.addEventListener("wheel",b,{passive:C}),o.addEventListener("mouseenter",U),o.addEventListener("mouseleave",O),document.addEventListener("mouseup",G),document.addEventListener("mousemove",R),document.addEventListener("keydown",D),document.addEventListener("keyup",B);const i=N(d,m,t.modelValue);n.value=i}}),e.watch(()=>t.modelValue,o=>{if(v.value===!1&&k.value===!1&&f.value===!1){const l=N(d,m,o);n.value=l}}),e.onBeforeUnmount(()=>{s.value.removeEventListener("mousedown",X),s.value.removeEventListener("wheel",b),s.value.removeEventListener("mouseenter",U),s.value.removeEventListener("mouseleave",O),document.removeEventListener("mouseup",G),document.removeEventListener("mousemove",R),document.removeEventListener("keydown",D),document.removeEventListener("keyup",B)}),(o,l)=>(e.openBlock(),e.createElementBlock("svg",{ref_key:"knobElement",ref:s,width:e.unref(L),height:e.unref(L),viewBox:"0 0 100 100",role:"slider","aria-label":e.unref(Re),"aria-valuemin":e.unref(d),"aria-valuemax":e.unref(m),"aria-valuenow":e.unref(r),tabindex:e.unref(Xe),class:e.normalizeClass(e.unref(Be)),onClick:e.withModifiers(st,["alt"]),onFocus:l[0]||(l[0]=i=>f.value=!0),onBlur:l[1]||(l[1]=i=>f.value=!1)},[e.createElementVNode("circle",{cx:e.unref(50),cy:e.unref(50),r:e.unref(xe),stroke:"currentColor",fill:"currentColor",class:e.normalizeClass(e.unref(be)),"stroke-width":1},null,10,ke),e.createElementVNode("path",{d:tt,"stroke-width":e.unref(ge),stroke:"currentColor",fill:"none",class:e.normalizeClass(e.unref(Ue))},null,10,Le),n.value>120?(e.openBlock(),e.createElementBlock("path",{key:0,d:e.unref(ot),"stroke-width":e.unref(Ce),stroke:"currentColor",fill:"none",class:e.normalizeClass(e.unref(Oe))},null,10,ve)):e.createCommentVNode("",!0),e.unref(Ie)?(e.openBlock(),e.createElementBlock("line",{key:1,x1:e.unref(Ye),y1:e.unref(He),x2:e.unref(We),y2:e.unref(ze),stroke:"currentColor","stroke-width":e.unref(Ve),class:e.normalizeClass(e.unref(Te))},null,10,_e)):e.createCommentVNode("",!0),e.unref(we)&&(!e.unref(Ne)||e.unref($e)!==e.unref(r))?(e.openBlock(),e.createElementBlock("text",{key:2,x:e.unref(Ge),y:e.unref(De),"text-anchor":"middle",fill:"currentColor",class:e.normalizeClass(e.unref(Fe))},e.toDisplayString(Math.ceil(e.unref(r))),11,Me)):e.createCommentVNode("",!0)],42,he))}})}); | ||
//# sourceMappingURL=index.umd.js.map |
{ | ||
"name": "@slipmatio/control-knob", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"main": "dist/index.es.js", | ||
@@ -16,52 +16,36 @@ "module": "dist/index.es.js", | ||
"license": "MIT", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "vite build", | ||
"preview": "vite build --config ./vite.test.config.ts && vite preview --port 3001 --config ./vite.test.config.ts", | ||
"start": "yarn dev & wait-on tcp:3000 -v", | ||
"test": "vitest", | ||
"test-e2e": "cypress open", | ||
"test-e2e-headless": "cypress run --headless", | ||
"test-components": "cypress open-ct", | ||
"test:ci": "vitest run --coverage", | ||
"test:ci-e2e": "start-server-and-test 'yarn preview' http://localhost:3001/ 'yarn test-e2e-headless'", | ||
"test:ci-components": "cypress run-ct", | ||
"coverage": "vitest run --coverage", | ||
"report": "nyc report --reporter=text-summary" | ||
}, | ||
"devDependencies": { | ||
"@cypress/code-coverage": "^3.9.12", | ||
"@cypress/vite-dev-server": "~2.2", | ||
"@cypress/vue": "~3.1", | ||
"@tailwindcss/aspect-ratio": "~0.4", | ||
"@tailwindcss/forms": "~0.4", | ||
"@tailwindcss/line-clamp": "~0.3", | ||
"@tailwindcss/typography": "~0.5", | ||
"@typescript-eslint/eslint-plugin": "~5", | ||
"@typescript-eslint/parser": "~5", | ||
"@vitejs/plugin-vue": "~2", | ||
"@vue/eslint-config-standard": "~6.1", | ||
"@vue/eslint-config-typescript": "~10", | ||
"autoprefixer": "~10", | ||
"c8": "~7", | ||
"cypress": "~9.5", | ||
"eslint": "~8.10", | ||
"eslint-config-prettier": "~8.4", | ||
"eslint-plugin-import": "~2", | ||
"eslint-plugin-node": "~11.1", | ||
"eslint-plugin-promise": "~6.0", | ||
"eslint-plugin-vue": "~8", | ||
"nyc": "^15.1.0", | ||
"postcss": "~8.4", | ||
"postcss-import": "~14", | ||
"postcss-nesting": "~10", | ||
"start-server-and-test": "^1.14.0", | ||
"tailwindcss": "~3", | ||
"typescript": "~4.5", | ||
"vite": "~2.8", | ||
"vite-plugin-dts": "^0.9.9", | ||
"vite-plugin-istanbul": "^2.5.0", | ||
"vitest": "~0.5", | ||
"vue": "~3.2", | ||
"wait-on": "~6.0" | ||
"@playwright/experimental-ct-vue": "1.23.2", | ||
"@playwright/test": "1.23.2", | ||
"@tailwindcss/aspect-ratio": "0.4.0", | ||
"@tailwindcss/forms": "0.5.2", | ||
"@tailwindcss/line-clamp": "0.4.0", | ||
"@tailwindcss/typography": "0.5.3", | ||
"@typescript-eslint/eslint-plugin": "5.30.5", | ||
"@typescript-eslint/parser": "5.30.5", | ||
"@vitejs/plugin-vue": "2.3.3", | ||
"@vue/test-utils": "2.0.2", | ||
"autoprefixer": "10.4.7", | ||
"c8": "7.11.3", | ||
"eslint": "8.19.0", | ||
"eslint-config-prettier": "8.5.0", | ||
"eslint-plugin-import": "2.26.0", | ||
"eslint-plugin-node": "11.1.0", | ||
"eslint-plugin-promise": "6.0.0", | ||
"eslint-plugin-security": "1.5.0", | ||
"eslint-plugin-vue": "9.2.0", | ||
"happy-dom": "^6.0.2", | ||
"nyc": "15.1.0", | ||
"postcss": "8.4.14", | ||
"postcss-import": "14.1.0", | ||
"postcss-nesting": "10.1.10", | ||
"start-server-and-test": "1.14.0", | ||
"tailwindcss": "3.1.5", | ||
"typescript": "4.7.4", | ||
"vite": "2.9.14", | ||
"vite-plugin-dts": "1.2.1", | ||
"vite-plugin-istanbul": "2.8.0", | ||
"vitest": "0.18.0", | ||
"vue": "3.2.37", | ||
"wait-on": "6.0.1" | ||
}, | ||
@@ -91,3 +75,12 @@ "files": [ | ||
}, | ||
"homepage": "https://github.com/slipmatio/control-knob" | ||
"homepage": "https://github.com/slipmatio/control-knob", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "vite build", | ||
"preview": "vite build --config ./vite.test.config.ts && vite preview --port 3001 --config ./vite.test.config.ts", | ||
"start": "yarn dev & wait-on tcp:3000 -v", | ||
"test": "vitest", | ||
"test:ci": "vitest run --coverage", | ||
"report": "nyc report --reporter=text-summary" | ||
} | ||
} |
# Vue Control Knob | ||
Rotary control knob component for Vue 3 that behaves like native audio app controls in Logic Pro or Ableton Live. Component is fully customizable and rendered as an ARIA-friendly SVG element. | ||
Fully customizable rotary control knob component for Vue 3 that behaves like native audio app controls in Logic Pro or Ableton Live. Component is rendered as an ARIA-friendly SVG element. | ||
@@ -20,40 +20,40 @@ ![Screenshot](src/assets/knob-screenshot.webp) | ||
1. Install the package from npm: `yarn add @slipmatio/control-knob` | ||
1. Import Vue component to your project: `import ControlKnob from '@slipmatio/control-knob` | ||
2. Configure v-model and options | ||
1. Install `@slipmatio/control-knob` package from npm | ||
2. Import Vue component to your project: `import ControlKnob from '@slipmatio/control-knob'` | ||
3. Configure v-model and options | ||
### Configuration | ||
All configuration options are optional. The options referencing inner coordinate positions are based on 100x100 coordinate system that is not affected by the imageSize. | ||
**All configuration options are optional**. The options referencing inner coordinate positions are based on 100x100 coordinate system that is not affected by the imageSize. | ||
| Option | Default | Description | | ||
| --- | --- | --- | | ||
| imageSize | 40 | Rendered SVG width and lenght in pixels. | | ||
| minValue | 0 | Minimum value of the knob v-model. | | ||
| maxValue | 100 | Maximum value of the knob v-model. | | ||
| showTick | true | Show visible marker of the knob position. | | ||
| showValue | true | Show value label inside the knob. | | ||
| hideDefaultValue | false | Hide value label if value hasn't been changed. | | ||
| tickLength | 18 | Tick length in pixels. | | ||
| tickOffset | 10 | Tick offset in pixels. | | ||
| tickStroke | 3 | Tick stroke width. | | ||
| rimStroke | 11 | Outer rim stroke width. | | ||
| valueArchStroke | 11 | Value arch stroke width. | | ||
| bgRadius | 34 | Radius of the background circle. | | ||
| wheelFactor | 10 | Modifier to factor any mousewheel ticks. | | ||
| keyFactor | 10 | Modifier to factor any arrow-key presses. | | ||
| tabIndex | 0 | Tabindex for the HTML element. | | ||
| ariaLabel | 'Knob' | ARIA label for the HTML element. | | ||
| valueTextX | 50 | X-position of the value text label. | | ||
| valueTextY | 62 | Y-position of the value text label. | | ||
| svgClass | 'select-none' | CSS class for the SVG element. | | ||
| bgClass | 'text-[#868686]' | CSS class for the background circle. | | ||
| rimClass | 'text-[#393939]' | CSS class for the outer rim. | | ||
| valueArchClass | 'text-[#53d769]' | CSS class for the value arch. | | ||
| tickClass | 'text-black' | CSS class for the tick line. | | ||
| valueTextClass | 'text-gray-50 text-[30px] font-normal font-mono' | CSS class for the value text. | | ||
| Option | Default | Description | | ||
| ---------------- | ------------------------------------------------ | ---------------------------------------------------------- | | ||
| imageSize | 40 | Rendered SVG width and lenght in pixels. | | ||
| minValue | 0 | Minimum value of the knob v-model. | | ||
| maxValue | 100 | Maximum value of the knob v-model. | | ||
| showTick | true | Show visible marker of the knob position. | | ||
| showValue | true | Show value label inside the knob. | | ||
| hideDefaultValue | false | Hide value label if value hasn't been changed. | | ||
| tickLength | 18 | Tick length in pixels. | | ||
| tickOffset | 10 | Tick offset in pixels. | | ||
| tickStroke | 3 | Tick stroke width. | | ||
| rimStroke | 11 | Outer rim stroke width. | | ||
| valueArchStroke | 11 | Value arch stroke width. | | ||
| bgRadius | 34 | Radius of the background circle. | | ||
| wheelFactor | 10 | Modifier to factor any mousewheel ticks. | | ||
| keyFactor | 10 | Modifier to factor any arrow-key presses. | | ||
| tabIndex | 0 | Tabindex for the HTML element. | | ||
| ariaLabel | 'Knob' | ARIA label for the HTML element. | | ||
| valueTextX | 50 | X-position of the value text label. | | ||
| valueTextY | 62 | Y-position of the value text label. | | ||
| svgClass | 'select-none' | CSS class for the SVG element. | | ||
| bgClass | 'text-[#868686]' | CSS class for the background circle. | | ||
| rimClass | 'text-[#393939]' | CSS class for the outer rim. | | ||
| valueArchClass | 'text-[#53d769]' | CSS class for the value arch. | | ||
| tickClass | 'text-black' | CSS class for the tick line. | | ||
| valueTextClass | 'text-gray-50 text-[30px] font-normal font-mono' | CSS class for the value text. | | ||
| passiveEvents | false | When set, propagation of handeled events is not prevented. | | ||
**Note** that if you're using Tailwind CSS with automatic purge, you'll probably want to add the default classes as options so PurgeCSS catches them (or you can just whitelist them): | ||
**Note** that if you're using Tailwind CSS with automatic purge, you'll probably want to add the default classes as options so PurgeCSS catches them (or you can just whutelist them): | ||
Default Tailwind CSS classes: | ||
@@ -71,2 +71,3 @@ | ||
``` | ||
## Development | ||
@@ -76,11 +77,11 @@ | ||
`yarn` | ||
`pnpm i` | ||
### Run development server | ||
`yarn dev` | ||
`pnpm dev` | ||
### Run tests | ||
`yarn test` | ||
`pnpm test` | ||
@@ -93,2 +94,2 @@ ## Contributing | ||
[Follow @uninen](https://twitter.com/uninen) on Twitter | ||
[Follow @uninen](https://twitter.com/uninen) on Twitter |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
69118
33
92
7
369