zds-pickers 4.0.12 → 4.0.13
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/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +13 -13
- package/dist/index.es.js.map +1 -1
- package/dist/midi/export.js +43 -1
- package/dist/pickers/ResponseCurve.js +10 -52
- package/dist/pickers/ResponseCurvePicker.js +3 -2
- package/dist/types/midi/export.d.ts +12 -1
- package/dist/types/pickers/ResponseCurve.d.ts +2 -13
- package/dist/types/pickers/ResponseCurvePicker.d.ts +1 -1
- package/lib/midi/export.ts +58 -2
- package/lib/pickers/ResponseCurve.tsx +14 -67
- package/lib/pickers/ResponseCurvePicker.tsx +3 -2
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("react/jsx-runtime");require("react");const e={noteOff:8,noteOn:9,aftertouch:10,controlChange:11,programChange:12,channelPressure:13,pitchWheel:14},l=15,n=240,s=[{value:e.noteOn,label:"Note On"},{value:e.noteOff,label:"Note Stack"},{value:e.controlChange,label:"Control Change"},{value:e.programChange,label:"Program Change"},{value:e.aftertouch,label:"Aftertouch"},{value:e.channelPressure,label:"Channel Pressure"},{value:e.pitchWheel,label:"Pitch Wheel"}],
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("react/jsx-runtime");require("react");const e={noteOff:8,noteOn:9,aftertouch:10,controlChange:11,programChange:12,channelPressure:13,pitchWheel:14},l=15,n=240,s=[{value:e.noteOn,label:"Note On"},{value:e.noteOff,label:"Note Stack"},{value:e.controlChange,label:"Control Change"},{value:e.programChange,label:"Program Change"},{value:e.aftertouch,label:"Aftertouch"},{value:e.channelPressure,label:"Channel Pressure"},{value:e.pitchWheel,label:"Pitch Wheel"}],u=t=>{var a;return((a=s.filter(({value:o})=>o===t)[0])==null?void 0:a.label)||"???"},E=(t,a)=>t|a<<4,c=t=>({status:(t&n)>>4|8,channel:t&l}),r=0,S=1,i=2,_=3,h=4,v=5,C=6,b=7,N=[{value:b,label:"Always maxed out."},{value:C,label:"Most sensitive."},{value:v,label:"Moderately sensitive."},{value:h,label:"A little sensitive."},{value:r,label:"Linear, no change."},{value:S,label:"A little less sensitive."},{value:i,label:"Even less sensitive."},{value:_,label:"Least sensitive."}],R="__react_svg_text_measurement_id";exports.MASK_CHANNEL=l;exports.MASK_STATUS=n;exports.MEASUREMENT_ELEMENT_ID=R;exports.Statuses=e;exports.combineStatusWithChannel=E;exports.extractStatusAndChannel=c;exports.getStatusLabel=u;exports.responseCurves=N;exports.statusOptions=s;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../lib/midi/export.ts","../lib/other/SVGText.tsx","../lib/pickers/ResponseCurve.tsx"],"sourcesContent":["import type { Option } from 'lib/pickers/Select'\n\nconst Statuses = {\n noteOff: 8, // 1000\n noteOn: 9, // 1001\n aftertouch: 10, // 1010\n controlChange: 11, // 1011\n programChange: 12, // 1100\n channelPressure: 13, // 1101\n pitchWheel: 14, // 1110\n} as const\n\ntype Status = (typeof Statuses)[keyof typeof Statuses]\n\nconst MASK_CHANNEL = 15 // 00001111\nconst MASK_STATUS = 240 // 01110000\n\nconst statusOptions: Option<Status>[] = [\n { value: Statuses.noteOn, label: 'Note On' },\n { value: Statuses.noteOff, label: 'Note Stack' },\n { value: Statuses.controlChange, label: 'Control Change' },\n { value: Statuses.programChange, label: 'Program Change' },\n { value: Statuses.aftertouch, label: 'Aftertouch' },\n { value: Statuses.channelPressure, label: 'Channel Pressure' },\n { value: Statuses.pitchWheel, label: 'Pitch Wheel' },\n]\n\nconst getStatusLabel = (val: Status) =>\n statusOptions.filter(({ value }) => value === val)[0]?.label || '???'\n\nconst combineStatusWithChannel = (channel: number, status: Status) =>\n channel | (status << 4)\n\nconst extractStatusAndChannel = (\n status: number,\n): {\n status: Status\n channel: number\n} => ({\n status: (((status & MASK_STATUS) >> 4) | 8) as Status,\n channel: status & MASK_CHANNEL,\n})\n\nexport {\n combineStatusWithChannel,\n extractStatusAndChannel,\n getStatusLabel,\n MASK_CHANNEL,\n MASK_STATUS,\n statusOptions,\n Statuses,\n type Status,\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nconst MEASUREMENT_ELEMENT_ID = '__react_svg_text_measurement_id'\n\ntype WordsByLine = {\n words: string[]\n width: number\n showLine: boolean\n}\n\nconst calculateWordsByLines = (\n text: string,\n wordWidths: WordWidths,\n maxWidth: number,\n maxHeight: number,\n) => {\n const { lineHeight, spaceWidth, wordsWithComputedWidth } = wordWidths\n\n return text.split(/\\s+/).reduce((result: WordsByLine[], word) => {\n const wordWidth = wordsWithComputedWidth[word]\n const currentLine = result[result.length - 1]\n if (currentLine && currentLine.width + wordWidth + spaceWidth < maxWidth) {\n // Word can be added to an existing line\n currentLine.words.push(word)\n currentLine.width += wordWidth + spaceWidth\n } else {\n // Add first word to line or word is too long to scaleToFit on existing line\n const newLine: WordsByLine = {\n words: [word],\n width: wordWidth,\n showLine: maxHeight\n ? lineHeight * (result.length + 1) < maxHeight\n : true,\n }\n result.push(newLine)\n }\n return result\n }, [])\n}\n\ntype WordWidths = {\n wordsWithComputedWidth: Record<string, number>\n spaceWidth: number\n lineHeight: number\n}\n\nconst calculateWordWidths = (\n style?: CSSStyleDeclaration,\n textNode?: SVGGraphicsElement | null,\n text?: string,\n): WordWidths | undefined => {\n if (style && textNode) {\n // biome-ignore lint/complexity/noForEach: <explanation>\n Array.from(style).forEach(key =>\n textNode.style.setProperty(\n key,\n style.getPropertyValue(key),\n style.getPropertyPriority(key),\n ),\n )\n const wordArray = [...new Set(String(text).split(/\\s+/))]\n const wordsWithComputedWidth = wordArray.reduce((wordMap, word) => {\n textNode.textContent = word\n // biome-ignore lint/performance/noAccumulatingSpread: <explanation>\n return { ...wordMap, [word]: textNode.getBBox().width }\n }, {})\n\n textNode.textContent = '\\u00A0'\n\n const spaceWidth =\n (textNode as SVGTextContentElement)?.getComputedTextLength?.() || 8\n const lineHeight = textNode.getBBox().height\n\n textNode.setAttribute('style', '')\n return { wordsWithComputedWidth, spaceWidth, lineHeight }\n }\n return undefined\n}\n\ntype TextProps = Partial<HTMLOrSVGElement> & {\n className?: string\n dx?: number\n dy?: number\n maxHeight?: number\n maxWidth?: number\n transform?: string\n text: string\n textAnchor?: React.CSSProperties['textAnchor']\n verticalAnchor?: 'start' | 'middle' | 'end'\n x?: number\n y?: number\n}\n\nconst Text = (props: TextProps) => {\n const {\n className = '',\n dx = 0,\n dy = 0,\n maxHeight = 1000,\n maxWidth = 1000,\n // textAnchor = 'start',\n text = '',\n verticalAnchor = 'start',\n x = 0,\n y = 0,\n transform = '',\n ...rest\n } = props\n const [wordWidths, setWordWidths] = useState<WordWidths>()\n const [textLines, setTextLines] = useState<WordsByLine[]>([])\n const [style, setComputedStyle] = useState<CSSStyleDeclaration>()\n const measureRef = useRef<SVGSVGElement | HTMLElement>({} as HTMLElement)\n\n const displayedLines: WordsByLine[] = useMemo(() => {\n const result = textLines.filter(({ showLine }) => showLine)\n return result.length\n ? result\n : text\n .split(/\\n/)\n .map(line => ({ words: [line], width: 0, showLine: true }))\n }, [textLines, text])\n\n const ref: React.LegacyRef<SVGTextElement> = useCallback(\n (node: SVGTextElement | null) => {\n setComputedStyle(\n node !== null ? window.getComputedStyle(node) : undefined,\n )\n },\n [],\n )\n\n useEffect(() => {\n const el = document.getElementById(MEASUREMENT_ELEMENT_ID)\n if (el === null) {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n svg.setAttribute('id', MEASUREMENT_ELEMENT_ID)\n document.body.appendChild(svg)\n svg.appendChild(\n document.createElementNS('http://www.w3.org/2000/svg', 'text'),\n )\n measureRef.current = svg\n return () => {\n document.body.removeChild(svg)\n }\n }\n measureRef.current = el\n }, [])\n\n useEffect(() => {\n const wordWithWidths = calculateWordWidths(\n style,\n measureRef.current as SVGGraphicsElement | null,\n text,\n )\n\n setWordWidths(wordWithWidths)\n }, [text, style])\n\n useEffect(() => {\n if (maxWidth && wordWidths) {\n const lines = text\n .split(/\\n/)\n .flatMap(line =>\n calculateWordsByLines(line, wordWidths, maxWidth, maxHeight),\n )\n\n setTextLines(lines)\n }\n }, [maxHeight, maxWidth, wordWidths, text])\n\n const startDy = useMemo(() => {\n if (wordWidths?.lineHeight) {\n switch (verticalAnchor) {\n case 'start':\n return wordWidths.lineHeight\n\n case 'middle':\n return -(((displayedLines.length - 1) * wordWidths.lineHeight) / 2)\n\n default:\n return -(displayedLines.length - 1) * wordWidths.lineHeight\n }\n }\n return 0\n }, [displayedLines.length, verticalAnchor, wordWidths?.lineHeight])\n\n return (\n <text\n className={className}\n ref={ref}\n dx={dx}\n dy={dy}\n x={x}\n y={y}\n // textAnchor={textAnchor}\n transform={transform}\n {...rest}>\n <>\n {displayedLines.map((line, idx) => (\n <tspan\n dx={x + dx}\n dy={idx === 0 ? startDy + dy : wordWidths?.lineHeight || 0}\n key={idx}\n x={0}>\n {line.words.join(' ')}\n </tspan>\n ))}\n {textLines.length && displayedLines.length !== textLines.length && (\n <>\n <tspan>...</tspan>\n <title>{text}</title>\n </>\n )}\n </>\n </text>\n )\n}\n\nexport default Text\n\nexport { MEASUREMENT_ELEMENT_ID }\n\nexport type { TextProps, WordWidths, WordsByLine }\n","import { useRef } from 'react'\nimport useComponentSize from '../hooks/useComponentSize'\nimport DefaultTooltip, { type TooltipProps } from '../other/DefaultTooltip'\nimport SVGText from '../other/SVGText'\nimport type { Option } from './Select'\n\nconst RESPONSE_CURVE_0 = 0\nconst RESPONSE_CURVE_1 = 1\nconst RESPONSE_CURVE_2 = 2\nconst RESPONSE_CURVE_3 = 3\nconst RESPONSE_CURVE_4 = 4\nconst RESPONSE_CURVE_5 = 5\nconst RESPONSE_CURVE_6 = 6\nconst RESPONSE_CURVE_7 = 7\n\ntype Curve =\n | typeof RESPONSE_CURVE_0\n | typeof RESPONSE_CURVE_1\n | typeof RESPONSE_CURVE_2\n | typeof RESPONSE_CURVE_3\n | typeof RESPONSE_CURVE_4\n | typeof RESPONSE_CURVE_5\n | typeof RESPONSE_CURVE_6\n | typeof RESPONSE_CURVE_7\n\ntype ResponseCurve = {\n value: Curve\n label: React.ReactNode\n c1: number\n c2: number\n x1: number\n y1: number\n x2: number\n y2: number\n labelX: number\n labelY: number\n}\n\nconst RESPONSE_CURVES: Option<Curve>[] = [\n {\n value: RESPONSE_CURVE_7,\n label: 'Always maxed out.',\n },\n {\n value: RESPONSE_CURVE_6,\n label: 'Most sensitive.',\n },\n {\n value: RESPONSE_CURVE_5,\n label: 'Moderately sensitive.',\n },\n {\n value: RESPONSE_CURVE_4,\n label: 'A little sensitive.',\n },\n {\n value: RESPONSE_CURVE_0,\n label: 'Linear, no change.',\n },\n {\n value: RESPONSE_CURVE_1,\n label: 'A little less sensitive.',\n },\n {\n value: RESPONSE_CURVE_2,\n label: 'Even less sensitive.',\n },\n {\n value: RESPONSE_CURVE_3,\n label: 'Least sensitive.',\n },\n]\n\n// const width = 218\n// const height = 150\nconst axisOffset = 20\nconst buttonSize = 15\n\nconst axisX1 = axisOffset\nconst axisY1 = axisOffset\n\ntype ResponseCurveProps = {\n autosize: boolean\n disabled?: boolean\n inverted: boolean\n onChange: (event: { target: { value: Curve } }) => void\n Tooltip: React.FC<TooltipProps>\n value: Curve\n}\n\nconst ResponseCurve = (props: ResponseCurveProps) => {\n const {\n Tooltip = DefaultTooltip,\n autosize,\n disabled,\n inverted,\n onChange,\n value: responseCurve,\n } = props\n\n const ref = useRef(null)\n const svgRef = useRef(null)\n const { height: ourHeight, width: ourWidth } = useComponentSize(ref)\n\n const width = autosize ? ourWidth || 218 : 218\n const height = autosize ? ourHeight || 150 : 150\n\n const axisX2 = width - axisOffset\n const axisY2 = height - axisOffset\n\n const xMid = width / 2\n const yMid = height / 2\n\n const svgProps = { ref: svgRef }\n\n const responseCurves = RESPONSE_CURVES.map(\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>\n ({ value, label }): ResponseCurve => {\n let c1 = 0\n let c2 = 0\n let x1 = axisX1\n let y1 = inverted ? axisY1 : axisY2\n let x2 = axisX2\n let y2 = inverted ? axisY2 : axisY1\n let labelX = xMid\n let labelY = yMid\n switch (value) {\n case RESPONSE_CURVE_0:\n c1 = xMid\n c2 = yMid\n labelY += 3\n\n break\n case RESPONSE_CURVE_1:\n c1 = inverted ? xMid + width * 0.13 : xMid - width * 0.13\n c2 = yMid - height * 0.13\n labelX = inverted ? xMid + width * 0.1 : xMid - width * 0.1\n labelY = yMid - height * 0.09\n break\n\n case RESPONSE_CURVE_2:\n c1 = inverted ? xMid + width * 0.25 : xMid - width * 0.25\n c2 = yMid - height * 0.25\n labelX = inverted ? xMid + width * 0.2 : xMid - width * 0.2\n labelY = yMid - height * 0.17\n break\n\n case RESPONSE_CURVE_3:\n c1 = inverted ? xMid + width * 0.35 : xMid - width * 0.35\n c2 = yMid - height * 0.35\n labelX = inverted ? xMid + width * 0.28 : xMid - width * 0.28\n labelY = yMid - height * 0.25\n break\n\n case RESPONSE_CURVE_4:\n c1 = inverted ? xMid - width * 0.13 : xMid + width * 0.13\n c2 = yMid + height * 0.13\n labelX = inverted ? xMid - width * 0.1 : xMid + width * 0.1\n labelY = yMid + height * 0.1\n break\n\n case RESPONSE_CURVE_5:\n c1 = inverted ? xMid - width * 0.25 : xMid + width * 0.25\n c2 = yMid + height * 0.25\n labelX = inverted ? xMid - width * 0.2 : xMid + width * 0.2\n labelY = yMid + height * 0.18\n break\n\n case RESPONSE_CURVE_6:\n c1 = inverted ? xMid - width * 0.35 : xMid + width * 0.35\n c2 = yMid + height * 0.35\n labelX = inverted ? xMid - width * 0.28 : xMid + width * 0.28\n labelY = yMid + height * 0.25\n break\n\n case RESPONSE_CURVE_7:\n x1 = inverted ? axisX1 : axisX2\n y1 = axisY1\n x2 = x1\n y2 = axisY2\n c1 = x1\n c2 = yMid\n labelX = x1 - 5\n labelY = height - 30\n break\n\n default:\n break\n }\n return {\n value,\n label,\n c1,\n c2,\n x1,\n y1,\n x2,\n y2,\n labelX,\n labelY,\n }\n },\n )\n\n return (\n <div\n className=\"response-curve-picker\"\n ref={ref}>\n <svg {...svgProps}>\n <rect\n className=\"container\"\n height={height}\n rx={3}\n ry={3}\n width={width}\n x={0}\n y={0}\n />\n\n <SVGText\n className=\"axis\"\n textAnchor=\"middle\"\n transform={`translate(${axisX1 - 14} ${height / 2}) rotate(90)`}\n x={0}\n y={0}\n text=\"Applied force\"\n />\n\n <SVGText\n className=\"axis\"\n textAnchor=\"middle\"\n transform={`translate(${width / 2} ${axisY2 + 13})`}\n x={0}\n y={0}\n text=\"Output (velocity)\"\n />\n\n <line\n className=\"axis\"\n x1={axisX1}\n x2={axisX1}\n y1={axisY1}\n y2={axisY2}\n />\n <line\n className=\"axis\"\n x1={axisX1}\n x2={axisX2}\n y1={axisY2}\n y2={axisY2}\n />\n\n {responseCurves.map(\n ({ value, label, x1, y1, x2, y2, c1, c2, labelX, labelY }) => (\n <g key={value}>\n <path\n className={value === responseCurve ? 'curve-selected' : 'curve'}\n d={`M${x1} ${y1} C ${c1} ${c2}, ${c1} ${c2}, ${x2} ${y2}`}\n />\n\n <Tooltip\n placement=\"left\"\n title={label}>\n <rect\n className={\n value === responseCurve ? 'button-selected' : 'button'\n }\n height={buttonSize}\n onClick={\n disabled\n ? f => f\n : () =>\n onChange({\n target: {\n value: Number.parseInt(String(value)) as Curve,\n },\n })\n }\n transform={`translate(${labelX + 3} ${labelY - buttonSize / 1.05}) rotate(45)`}\n width={buttonSize}\n />\n </Tooltip>\n\n <text\n className={\n value === responseCurve ? 'button-selected' : 'button'\n }\n transform={`translate(${labelX} ${labelY})`}>\n {value}\n <title>{label}</title>\n </text>\n </g>\n ),\n )}\n </svg>\n </div>\n )\n}\n\nexport default ResponseCurve\n\nexport { RESPONSE_CURVES }\n\nexport type { Curve, ResponseCurve, ResponseCurveProps }\n"],"names":["Statuses","MASK_CHANNEL","MASK_STATUS","statusOptions","getStatusLabel","val","_a","value","combineStatusWithChannel","channel","status","extractStatusAndChannel","MEASUREMENT_ELEMENT_ID","RESPONSE_CURVE_0","RESPONSE_CURVE_1","RESPONSE_CURVE_2","RESPONSE_CURVE_3","RESPONSE_CURVE_4","RESPONSE_CURVE_5","RESPONSE_CURVE_6","RESPONSE_CURVE_7","RESPONSE_CURVES"],"mappings":"8HAEA,MAAMA,EAAW,CACf,QAAS,EACT,OAAQ,EACR,WAAY,GACZ,cAAe,GACf,cAAe,GACf,gBAAiB,GACjB,WAAY,EACd,EAIMC,EAAe,GACfC,EAAc,IAEdC,EAAkC,CACtC,CAAE,MAAOH,EAAS,OAAQ,MAAO,SAAU,EAC3C,CAAE,MAAOA,EAAS,QAAS,MAAO,YAAa,EAC/C,CAAE,MAAOA,EAAS,cAAe,MAAO,gBAAiB,EACzD,CAAE,MAAOA,EAAS,cAAe,MAAO,gBAAiB,EACzD,CAAE,MAAOA,EAAS,WAAY,MAAO,YAAa,EAClD,CAAE,MAAOA,EAAS,gBAAiB,MAAO,kBAAmB,EAC7D,CAAE,MAAOA,EAAS,WAAY,MAAO,aAAc,CACrD,EAEMI,EAAkBC,UACtB,QAAAC,EAAAH,EAAc,OAAO,CAAC,CAAE,MAAAI,CAAM,IAAMA,IAAUF,CAAG,EAAE,CAAC,IAApD,YAAAC,EAAuD,QAAS,OAE5DE,EAA2B,CAACC,EAAiBC,IACjDD,EAAWC,GAAU,EAEjBC,EACJD,IAII,CACJ,QAAWA,EAASR,IAAgB,EAAK,EACzC,QAASQ,EAAST,CACpB,GCvCMW,EAAyB,kCCIzBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EAyBnBC,EAAmC,CACvC,CACE,MAAOD,EACP,MAAO,mBACT,EACA,CACE,MAAOD,EACP,MAAO,iBACT,EACA,CACE,MAAOD,EACP,MAAO,uBACT,EACA,CACE,MAAOD,EACP,MAAO,qBACT,EACA,CACE,MAAOJ,EACP,MAAO,oBACT,EACA,CACE,MAAOC,EACP,MAAO,0BACT,EACA,CACE,MAAOC,EACP,MAAO,sBACT,EACA,CACE,MAAOC,EACP,MAAO,kBAAA,CAEX"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../lib/midi/export.ts","../lib/other/SVGText.tsx"],"sourcesContent":["import type { Option } from 'lib/pickers/Select'\n\nconst Statuses = {\n noteOff: 8, // 1000\n noteOn: 9, // 1001\n aftertouch: 10, // 1010\n controlChange: 11, // 1011\n programChange: 12, // 1100\n channelPressure: 13, // 1101\n pitchWheel: 14, // 1110\n} as const\n\ntype Status = (typeof Statuses)[keyof typeof Statuses]\n\nconst MASK_CHANNEL = 15 // 00001111\nconst MASK_STATUS = 240 // 01110000\n\nconst statusOptions: Option<Status>[] = [\n { value: Statuses.noteOn, label: 'Note On' },\n { value: Statuses.noteOff, label: 'Note Stack' },\n { value: Statuses.controlChange, label: 'Control Change' },\n { value: Statuses.programChange, label: 'Program Change' },\n { value: Statuses.aftertouch, label: 'Aftertouch' },\n { value: Statuses.channelPressure, label: 'Channel Pressure' },\n { value: Statuses.pitchWheel, label: 'Pitch Wheel' },\n]\n\nconst getStatusLabel = (val: Status) =>\n statusOptions.filter(({ value }) => value === val)[0]?.label || '???'\n\nconst combineStatusWithChannel = (channel: number, status: Status) =>\n channel | (status << 4)\n\nconst extractStatusAndChannel = (\n status: number,\n): {\n status: Status\n channel: number\n} => ({\n status: (((status & MASK_STATUS) >> 4) | 8) as Status,\n channel: status & MASK_CHANNEL,\n})\n\nconst RESPONSE_CURVE_0 = 0\nconst RESPONSE_CURVE_1 = 1\nconst RESPONSE_CURVE_2 = 2\nconst RESPONSE_CURVE_3 = 3\nconst RESPONSE_CURVE_4 = 4\nconst RESPONSE_CURVE_5 = 5\nconst RESPONSE_CURVE_6 = 6\nconst RESPONSE_CURVE_7 = 7\n\ntype Curve =\n | typeof RESPONSE_CURVE_0\n | typeof RESPONSE_CURVE_1\n | typeof RESPONSE_CURVE_2\n | typeof RESPONSE_CURVE_3\n | typeof RESPONSE_CURVE_4\n | typeof RESPONSE_CURVE_5\n | typeof RESPONSE_CURVE_6\n | typeof RESPONSE_CURVE_7\n\nconst responseCurves: Option<Curve>[] = [\n {\n value: RESPONSE_CURVE_7,\n label: 'Always maxed out.',\n },\n {\n value: RESPONSE_CURVE_6,\n label: 'Most sensitive.',\n },\n {\n value: RESPONSE_CURVE_5,\n label: 'Moderately sensitive.',\n },\n {\n value: RESPONSE_CURVE_4,\n label: 'A little sensitive.',\n },\n {\n value: RESPONSE_CURVE_0,\n label: 'Linear, no change.',\n },\n {\n value: RESPONSE_CURVE_1,\n label: 'A little less sensitive.',\n },\n {\n value: RESPONSE_CURVE_2,\n label: 'Even less sensitive.',\n },\n {\n value: RESPONSE_CURVE_3,\n label: 'Least sensitive.',\n },\n]\n\nexport {\n combineStatusWithChannel,\n extractStatusAndChannel,\n getStatusLabel,\n MASK_CHANNEL,\n MASK_STATUS,\n responseCurves,\n Statuses,\n statusOptions,\n}\n\nexport type { Curve, Status }\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nconst MEASUREMENT_ELEMENT_ID = '__react_svg_text_measurement_id'\n\ntype WordsByLine = {\n words: string[]\n width: number\n showLine: boolean\n}\n\nconst calculateWordsByLines = (\n text: string,\n wordWidths: WordWidths,\n maxWidth: number,\n maxHeight: number,\n) => {\n const { lineHeight, spaceWidth, wordsWithComputedWidth } = wordWidths\n\n return text.split(/\\s+/).reduce((result: WordsByLine[], word) => {\n const wordWidth = wordsWithComputedWidth[word]\n const currentLine = result[result.length - 1]\n if (currentLine && currentLine.width + wordWidth + spaceWidth < maxWidth) {\n // Word can be added to an existing line\n currentLine.words.push(word)\n currentLine.width += wordWidth + spaceWidth\n } else {\n // Add first word to line or word is too long to scaleToFit on existing line\n const newLine: WordsByLine = {\n words: [word],\n width: wordWidth,\n showLine: maxHeight\n ? lineHeight * (result.length + 1) < maxHeight\n : true,\n }\n result.push(newLine)\n }\n return result\n }, [])\n}\n\ntype WordWidths = {\n wordsWithComputedWidth: Record<string, number>\n spaceWidth: number\n lineHeight: number\n}\n\nconst calculateWordWidths = (\n style?: CSSStyleDeclaration,\n textNode?: SVGGraphicsElement | null,\n text?: string,\n): WordWidths | undefined => {\n if (style && textNode) {\n // biome-ignore lint/complexity/noForEach: <explanation>\n Array.from(style).forEach(key =>\n textNode.style.setProperty(\n key,\n style.getPropertyValue(key),\n style.getPropertyPriority(key),\n ),\n )\n const wordArray = [...new Set(String(text).split(/\\s+/))]\n const wordsWithComputedWidth = wordArray.reduce((wordMap, word) => {\n textNode.textContent = word\n // biome-ignore lint/performance/noAccumulatingSpread: <explanation>\n return { ...wordMap, [word]: textNode.getBBox().width }\n }, {})\n\n textNode.textContent = '\\u00A0'\n\n const spaceWidth =\n (textNode as SVGTextContentElement)?.getComputedTextLength?.() || 8\n const lineHeight = textNode.getBBox().height\n\n textNode.setAttribute('style', '')\n return { wordsWithComputedWidth, spaceWidth, lineHeight }\n }\n return undefined\n}\n\ntype TextProps = Partial<HTMLOrSVGElement> & {\n className?: string\n dx?: number\n dy?: number\n maxHeight?: number\n maxWidth?: number\n transform?: string\n text: string\n textAnchor?: React.CSSProperties['textAnchor']\n verticalAnchor?: 'start' | 'middle' | 'end'\n x?: number\n y?: number\n}\n\nconst Text = (props: TextProps) => {\n const {\n className = '',\n dx = 0,\n dy = 0,\n maxHeight = 1000,\n maxWidth = 1000,\n // textAnchor = 'start',\n text = '',\n verticalAnchor = 'start',\n x = 0,\n y = 0,\n transform = '',\n ...rest\n } = props\n const [wordWidths, setWordWidths] = useState<WordWidths>()\n const [textLines, setTextLines] = useState<WordsByLine[]>([])\n const [style, setComputedStyle] = useState<CSSStyleDeclaration>()\n const measureRef = useRef<SVGSVGElement | HTMLElement>({} as HTMLElement)\n\n const displayedLines: WordsByLine[] = useMemo(() => {\n const result = textLines.filter(({ showLine }) => showLine)\n return result.length\n ? result\n : text\n .split(/\\n/)\n .map(line => ({ words: [line], width: 0, showLine: true }))\n }, [textLines, text])\n\n const ref: React.LegacyRef<SVGTextElement> = useCallback(\n (node: SVGTextElement | null) => {\n setComputedStyle(\n node !== null ? window.getComputedStyle(node) : undefined,\n )\n },\n [],\n )\n\n useEffect(() => {\n const el = document.getElementById(MEASUREMENT_ELEMENT_ID)\n if (el === null) {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n svg.setAttribute('id', MEASUREMENT_ELEMENT_ID)\n document.body.appendChild(svg)\n svg.appendChild(\n document.createElementNS('http://www.w3.org/2000/svg', 'text'),\n )\n measureRef.current = svg\n return () => {\n document.body.removeChild(svg)\n }\n }\n measureRef.current = el\n }, [])\n\n useEffect(() => {\n const wordWithWidths = calculateWordWidths(\n style,\n measureRef.current as SVGGraphicsElement | null,\n text,\n )\n\n setWordWidths(wordWithWidths)\n }, [text, style])\n\n useEffect(() => {\n if (maxWidth && wordWidths) {\n const lines = text\n .split(/\\n/)\n .flatMap(line =>\n calculateWordsByLines(line, wordWidths, maxWidth, maxHeight),\n )\n\n setTextLines(lines)\n }\n }, [maxHeight, maxWidth, wordWidths, text])\n\n const startDy = useMemo(() => {\n if (wordWidths?.lineHeight) {\n switch (verticalAnchor) {\n case 'start':\n return wordWidths.lineHeight\n\n case 'middle':\n return -(((displayedLines.length - 1) * wordWidths.lineHeight) / 2)\n\n default:\n return -(displayedLines.length - 1) * wordWidths.lineHeight\n }\n }\n return 0\n }, [displayedLines.length, verticalAnchor, wordWidths?.lineHeight])\n\n return (\n <text\n className={className}\n ref={ref}\n dx={dx}\n dy={dy}\n x={x}\n y={y}\n // textAnchor={textAnchor}\n transform={transform}\n {...rest}>\n <>\n {displayedLines.map((line, idx) => (\n <tspan\n dx={x + dx}\n dy={idx === 0 ? startDy + dy : wordWidths?.lineHeight || 0}\n key={idx}\n x={0}>\n {line.words.join(' ')}\n </tspan>\n ))}\n {textLines.length && displayedLines.length !== textLines.length && (\n <>\n <tspan>...</tspan>\n <title>{text}</title>\n </>\n )}\n </>\n </text>\n )\n}\n\nexport default Text\n\nexport { MEASUREMENT_ELEMENT_ID }\n\nexport type { TextProps, WordWidths, WordsByLine }\n"],"names":["Statuses","MASK_CHANNEL","MASK_STATUS","statusOptions","getStatusLabel","val","_a","value","combineStatusWithChannel","channel","status","extractStatusAndChannel","RESPONSE_CURVE_0","RESPONSE_CURVE_1","RESPONSE_CURVE_2","RESPONSE_CURVE_3","RESPONSE_CURVE_4","RESPONSE_CURVE_5","RESPONSE_CURVE_6","RESPONSE_CURVE_7","responseCurves","MEASUREMENT_ELEMENT_ID"],"mappings":"8HAEA,MAAMA,EAAW,CACf,QAAS,EACT,OAAQ,EACR,WAAY,GACZ,cAAe,GACf,cAAe,GACf,gBAAiB,GACjB,WAAY,EACd,EAIMC,EAAe,GACfC,EAAc,IAEdC,EAAkC,CACtC,CAAE,MAAOH,EAAS,OAAQ,MAAO,SAAU,EAC3C,CAAE,MAAOA,EAAS,QAAS,MAAO,YAAa,EAC/C,CAAE,MAAOA,EAAS,cAAe,MAAO,gBAAiB,EACzD,CAAE,MAAOA,EAAS,cAAe,MAAO,gBAAiB,EACzD,CAAE,MAAOA,EAAS,WAAY,MAAO,YAAa,EAClD,CAAE,MAAOA,EAAS,gBAAiB,MAAO,kBAAmB,EAC7D,CAAE,MAAOA,EAAS,WAAY,MAAO,aAAc,CACrD,EAEMI,EAAkBC,UACtB,QAAAC,EAAAH,EAAc,OAAO,CAAC,CAAE,MAAAI,CAAM,IAAMA,IAAUF,CAAG,EAAE,CAAC,IAApD,YAAAC,EAAuD,QAAS,OAE5DE,EAA2B,CAACC,EAAiBC,IACjDD,EAAWC,GAAU,EAEjBC,EACJD,IAII,CACJ,QAAWA,EAASR,IAAgB,EAAK,EACzC,QAASQ,EAAST,CACpB,GAEMW,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EACnBC,EAAmB,EAYnBC,EAAkC,CACtC,CACE,MAAOD,EACP,MAAO,mBACT,EACA,CACE,MAAOD,EACP,MAAO,iBACT,EACA,CACE,MAAOD,EACP,MAAO,uBACT,EACA,CACE,MAAOD,EACP,MAAO,qBACT,EACA,CACE,MAAOJ,EACP,MAAO,oBACT,EACA,CACE,MAAOC,EACP,MAAO,0BACT,EACA,CACE,MAAOC,EACP,MAAO,sBACT,EACA,CACE,MAAOC,EACP,MAAO,kBAAA,CAEX,EC7FMM,EAAyB"}
|
package/dist/index.es.js
CHANGED
|
@@ -23,15 +23,15 @@ const e = {
|
|
|
23
23
|
{ value: e.aftertouch, label: "Aftertouch" },
|
|
24
24
|
{ value: e.channelPressure, label: "Channel Pressure" },
|
|
25
25
|
{ value: e.pitchWheel, label: "Pitch Wheel" }
|
|
26
|
-
],
|
|
26
|
+
], b = (t) => {
|
|
27
27
|
var l;
|
|
28
28
|
return ((l = o.filter(({ value: a }) => a === t)[0]) == null ? void 0 : l.label) || "???";
|
|
29
|
-
},
|
|
29
|
+
}, R = (t, l) => t | l << 4, N = (t) => ({
|
|
30
30
|
status: (t & s) >> 4 | 8,
|
|
31
31
|
channel: t & n
|
|
32
|
-
}),
|
|
32
|
+
}), c = 0, E = 1, r = 2, u = 3, S = 4, _ = 5, i = 6, v = 7, O = [
|
|
33
33
|
{
|
|
34
|
-
value:
|
|
34
|
+
value: v,
|
|
35
35
|
label: "Always maxed out."
|
|
36
36
|
},
|
|
37
37
|
{
|
|
@@ -43,35 +43,35 @@ const e = {
|
|
|
43
43
|
label: "Moderately sensitive."
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
|
-
value:
|
|
46
|
+
value: S,
|
|
47
47
|
label: "A little sensitive."
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
|
-
value:
|
|
50
|
+
value: c,
|
|
51
51
|
label: "Linear, no change."
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
|
-
value:
|
|
54
|
+
value: E,
|
|
55
55
|
label: "A little less sensitive."
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
|
-
value:
|
|
58
|
+
value: r,
|
|
59
59
|
label: "Even less sensitive."
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
value: u,
|
|
63
63
|
label: "Least sensitive."
|
|
64
64
|
}
|
|
65
|
-
];
|
|
65
|
+
], P = "__react_svg_text_measurement_id";
|
|
66
66
|
export {
|
|
67
67
|
n as MASK_CHANNEL,
|
|
68
68
|
s as MASK_STATUS,
|
|
69
|
-
|
|
70
|
-
P as RESPONSE_CURVES,
|
|
69
|
+
P as MEASUREMENT_ELEMENT_ID,
|
|
71
70
|
e as Statuses,
|
|
72
|
-
|
|
71
|
+
R as combineStatusWithChannel,
|
|
73
72
|
N as extractStatusAndChannel,
|
|
74
|
-
|
|
73
|
+
b as getStatusLabel,
|
|
74
|
+
O as responseCurves,
|
|
75
75
|
o as statusOptions
|
|
76
76
|
};
|
|
77
77
|
//# sourceMappingURL=index.es.js.map
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../lib/midi/export.ts","../lib/other/SVGText.tsx","../lib/pickers/ResponseCurve.tsx"],"sourcesContent":["import type { Option } from 'lib/pickers/Select'\n\nconst Statuses = {\n noteOff: 8, // 1000\n noteOn: 9, // 1001\n aftertouch: 10, // 1010\n controlChange: 11, // 1011\n programChange: 12, // 1100\n channelPressure: 13, // 1101\n pitchWheel: 14, // 1110\n} as const\n\ntype Status = (typeof Statuses)[keyof typeof Statuses]\n\nconst MASK_CHANNEL = 15 // 00001111\nconst MASK_STATUS = 240 // 01110000\n\nconst statusOptions: Option<Status>[] = [\n { value: Statuses.noteOn, label: 'Note On' },\n { value: Statuses.noteOff, label: 'Note Stack' },\n { value: Statuses.controlChange, label: 'Control Change' },\n { value: Statuses.programChange, label: 'Program Change' },\n { value: Statuses.aftertouch, label: 'Aftertouch' },\n { value: Statuses.channelPressure, label: 'Channel Pressure' },\n { value: Statuses.pitchWheel, label: 'Pitch Wheel' },\n]\n\nconst getStatusLabel = (val: Status) =>\n statusOptions.filter(({ value }) => value === val)[0]?.label || '???'\n\nconst combineStatusWithChannel = (channel: number, status: Status) =>\n channel | (status << 4)\n\nconst extractStatusAndChannel = (\n status: number,\n): {\n status: Status\n channel: number\n} => ({\n status: (((status & MASK_STATUS) >> 4) | 8) as Status,\n channel: status & MASK_CHANNEL,\n})\n\nexport {\n combineStatusWithChannel,\n extractStatusAndChannel,\n getStatusLabel,\n MASK_CHANNEL,\n MASK_STATUS,\n statusOptions,\n Statuses,\n type Status,\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nconst MEASUREMENT_ELEMENT_ID = '__react_svg_text_measurement_id'\n\ntype WordsByLine = {\n words: string[]\n width: number\n showLine: boolean\n}\n\nconst calculateWordsByLines = (\n text: string,\n wordWidths: WordWidths,\n maxWidth: number,\n maxHeight: number,\n) => {\n const { lineHeight, spaceWidth, wordsWithComputedWidth } = wordWidths\n\n return text.split(/\\s+/).reduce((result: WordsByLine[], word) => {\n const wordWidth = wordsWithComputedWidth[word]\n const currentLine = result[result.length - 1]\n if (currentLine && currentLine.width + wordWidth + spaceWidth < maxWidth) {\n // Word can be added to an existing line\n currentLine.words.push(word)\n currentLine.width += wordWidth + spaceWidth\n } else {\n // Add first word to line or word is too long to scaleToFit on existing line\n const newLine: WordsByLine = {\n words: [word],\n width: wordWidth,\n showLine: maxHeight\n ? lineHeight * (result.length + 1) < maxHeight\n : true,\n }\n result.push(newLine)\n }\n return result\n }, [])\n}\n\ntype WordWidths = {\n wordsWithComputedWidth: Record<string, number>\n spaceWidth: number\n lineHeight: number\n}\n\nconst calculateWordWidths = (\n style?: CSSStyleDeclaration,\n textNode?: SVGGraphicsElement | null,\n text?: string,\n): WordWidths | undefined => {\n if (style && textNode) {\n // biome-ignore lint/complexity/noForEach: <explanation>\n Array.from(style).forEach(key =>\n textNode.style.setProperty(\n key,\n style.getPropertyValue(key),\n style.getPropertyPriority(key),\n ),\n )\n const wordArray = [...new Set(String(text).split(/\\s+/))]\n const wordsWithComputedWidth = wordArray.reduce((wordMap, word) => {\n textNode.textContent = word\n // biome-ignore lint/performance/noAccumulatingSpread: <explanation>\n return { ...wordMap, [word]: textNode.getBBox().width }\n }, {})\n\n textNode.textContent = '\\u00A0'\n\n const spaceWidth =\n (textNode as SVGTextContentElement)?.getComputedTextLength?.() || 8\n const lineHeight = textNode.getBBox().height\n\n textNode.setAttribute('style', '')\n return { wordsWithComputedWidth, spaceWidth, lineHeight }\n }\n return undefined\n}\n\ntype TextProps = Partial<HTMLOrSVGElement> & {\n className?: string\n dx?: number\n dy?: number\n maxHeight?: number\n maxWidth?: number\n transform?: string\n text: string\n textAnchor?: React.CSSProperties['textAnchor']\n verticalAnchor?: 'start' | 'middle' | 'end'\n x?: number\n y?: number\n}\n\nconst Text = (props: TextProps) => {\n const {\n className = '',\n dx = 0,\n dy = 0,\n maxHeight = 1000,\n maxWidth = 1000,\n // textAnchor = 'start',\n text = '',\n verticalAnchor = 'start',\n x = 0,\n y = 0,\n transform = '',\n ...rest\n } = props\n const [wordWidths, setWordWidths] = useState<WordWidths>()\n const [textLines, setTextLines] = useState<WordsByLine[]>([])\n const [style, setComputedStyle] = useState<CSSStyleDeclaration>()\n const measureRef = useRef<SVGSVGElement | HTMLElement>({} as HTMLElement)\n\n const displayedLines: WordsByLine[] = useMemo(() => {\n const result = textLines.filter(({ showLine }) => showLine)\n return result.length\n ? result\n : text\n .split(/\\n/)\n .map(line => ({ words: [line], width: 0, showLine: true }))\n }, [textLines, text])\n\n const ref: React.LegacyRef<SVGTextElement> = useCallback(\n (node: SVGTextElement | null) => {\n setComputedStyle(\n node !== null ? window.getComputedStyle(node) : undefined,\n )\n },\n [],\n )\n\n useEffect(() => {\n const el = document.getElementById(MEASUREMENT_ELEMENT_ID)\n if (el === null) {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n svg.setAttribute('id', MEASUREMENT_ELEMENT_ID)\n document.body.appendChild(svg)\n svg.appendChild(\n document.createElementNS('http://www.w3.org/2000/svg', 'text'),\n )\n measureRef.current = svg\n return () => {\n document.body.removeChild(svg)\n }\n }\n measureRef.current = el\n }, [])\n\n useEffect(() => {\n const wordWithWidths = calculateWordWidths(\n style,\n measureRef.current as SVGGraphicsElement | null,\n text,\n )\n\n setWordWidths(wordWithWidths)\n }, [text, style])\n\n useEffect(() => {\n if (maxWidth && wordWidths) {\n const lines = text\n .split(/\\n/)\n .flatMap(line =>\n calculateWordsByLines(line, wordWidths, maxWidth, maxHeight),\n )\n\n setTextLines(lines)\n }\n }, [maxHeight, maxWidth, wordWidths, text])\n\n const startDy = useMemo(() => {\n if (wordWidths?.lineHeight) {\n switch (verticalAnchor) {\n case 'start':\n return wordWidths.lineHeight\n\n case 'middle':\n return -(((displayedLines.length - 1) * wordWidths.lineHeight) / 2)\n\n default:\n return -(displayedLines.length - 1) * wordWidths.lineHeight\n }\n }\n return 0\n }, [displayedLines.length, verticalAnchor, wordWidths?.lineHeight])\n\n return (\n <text\n className={className}\n ref={ref}\n dx={dx}\n dy={dy}\n x={x}\n y={y}\n // textAnchor={textAnchor}\n transform={transform}\n {...rest}>\n <>\n {displayedLines.map((line, idx) => (\n <tspan\n dx={x + dx}\n dy={idx === 0 ? startDy + dy : wordWidths?.lineHeight || 0}\n key={idx}\n x={0}>\n {line.words.join(' ')}\n </tspan>\n ))}\n {textLines.length && displayedLines.length !== textLines.length && (\n <>\n <tspan>...</tspan>\n <title>{text}</title>\n </>\n )}\n </>\n </text>\n )\n}\n\nexport default Text\n\nexport { MEASUREMENT_ELEMENT_ID }\n\nexport type { TextProps, WordWidths, WordsByLine }\n","import { useRef } from 'react'\nimport useComponentSize from '../hooks/useComponentSize'\nimport DefaultTooltip, { type TooltipProps } from '../other/DefaultTooltip'\nimport SVGText from '../other/SVGText'\nimport type { Option } from './Select'\n\nconst RESPONSE_CURVE_0 = 0\nconst RESPONSE_CURVE_1 = 1\nconst RESPONSE_CURVE_2 = 2\nconst RESPONSE_CURVE_3 = 3\nconst RESPONSE_CURVE_4 = 4\nconst RESPONSE_CURVE_5 = 5\nconst RESPONSE_CURVE_6 = 6\nconst RESPONSE_CURVE_7 = 7\n\ntype Curve =\n | typeof RESPONSE_CURVE_0\n | typeof RESPONSE_CURVE_1\n | typeof RESPONSE_CURVE_2\n | typeof RESPONSE_CURVE_3\n | typeof RESPONSE_CURVE_4\n | typeof RESPONSE_CURVE_5\n | typeof RESPONSE_CURVE_6\n | typeof RESPONSE_CURVE_7\n\ntype ResponseCurve = {\n value: Curve\n label: React.ReactNode\n c1: number\n c2: number\n x1: number\n y1: number\n x2: number\n y2: number\n labelX: number\n labelY: number\n}\n\nconst RESPONSE_CURVES: Option<Curve>[] = [\n {\n value: RESPONSE_CURVE_7,\n label: 'Always maxed out.',\n },\n {\n value: RESPONSE_CURVE_6,\n label: 'Most sensitive.',\n },\n {\n value: RESPONSE_CURVE_5,\n label: 'Moderately sensitive.',\n },\n {\n value: RESPONSE_CURVE_4,\n label: 'A little sensitive.',\n },\n {\n value: RESPONSE_CURVE_0,\n label: 'Linear, no change.',\n },\n {\n value: RESPONSE_CURVE_1,\n label: 'A little less sensitive.',\n },\n {\n value: RESPONSE_CURVE_2,\n label: 'Even less sensitive.',\n },\n {\n value: RESPONSE_CURVE_3,\n label: 'Least sensitive.',\n },\n]\n\n// const width = 218\n// const height = 150\nconst axisOffset = 20\nconst buttonSize = 15\n\nconst axisX1 = axisOffset\nconst axisY1 = axisOffset\n\ntype ResponseCurveProps = {\n autosize: boolean\n disabled?: boolean\n inverted: boolean\n onChange: (event: { target: { value: Curve } }) => void\n Tooltip: React.FC<TooltipProps>\n value: Curve\n}\n\nconst ResponseCurve = (props: ResponseCurveProps) => {\n const {\n Tooltip = DefaultTooltip,\n autosize,\n disabled,\n inverted,\n onChange,\n value: responseCurve,\n } = props\n\n const ref = useRef(null)\n const svgRef = useRef(null)\n const { height: ourHeight, width: ourWidth } = useComponentSize(ref)\n\n const width = autosize ? ourWidth || 218 : 218\n const height = autosize ? ourHeight || 150 : 150\n\n const axisX2 = width - axisOffset\n const axisY2 = height - axisOffset\n\n const xMid = width / 2\n const yMid = height / 2\n\n const svgProps = { ref: svgRef }\n\n const responseCurves = RESPONSE_CURVES.map(\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>\n ({ value, label }): ResponseCurve => {\n let c1 = 0\n let c2 = 0\n let x1 = axisX1\n let y1 = inverted ? axisY1 : axisY2\n let x2 = axisX2\n let y2 = inverted ? axisY2 : axisY1\n let labelX = xMid\n let labelY = yMid\n switch (value) {\n case RESPONSE_CURVE_0:\n c1 = xMid\n c2 = yMid\n labelY += 3\n\n break\n case RESPONSE_CURVE_1:\n c1 = inverted ? xMid + width * 0.13 : xMid - width * 0.13\n c2 = yMid - height * 0.13\n labelX = inverted ? xMid + width * 0.1 : xMid - width * 0.1\n labelY = yMid - height * 0.09\n break\n\n case RESPONSE_CURVE_2:\n c1 = inverted ? xMid + width * 0.25 : xMid - width * 0.25\n c2 = yMid - height * 0.25\n labelX = inverted ? xMid + width * 0.2 : xMid - width * 0.2\n labelY = yMid - height * 0.17\n break\n\n case RESPONSE_CURVE_3:\n c1 = inverted ? xMid + width * 0.35 : xMid - width * 0.35\n c2 = yMid - height * 0.35\n labelX = inverted ? xMid + width * 0.28 : xMid - width * 0.28\n labelY = yMid - height * 0.25\n break\n\n case RESPONSE_CURVE_4:\n c1 = inverted ? xMid - width * 0.13 : xMid + width * 0.13\n c2 = yMid + height * 0.13\n labelX = inverted ? xMid - width * 0.1 : xMid + width * 0.1\n labelY = yMid + height * 0.1\n break\n\n case RESPONSE_CURVE_5:\n c1 = inverted ? xMid - width * 0.25 : xMid + width * 0.25\n c2 = yMid + height * 0.25\n labelX = inverted ? xMid - width * 0.2 : xMid + width * 0.2\n labelY = yMid + height * 0.18\n break\n\n case RESPONSE_CURVE_6:\n c1 = inverted ? xMid - width * 0.35 : xMid + width * 0.35\n c2 = yMid + height * 0.35\n labelX = inverted ? xMid - width * 0.28 : xMid + width * 0.28\n labelY = yMid + height * 0.25\n break\n\n case RESPONSE_CURVE_7:\n x1 = inverted ? axisX1 : axisX2\n y1 = axisY1\n x2 = x1\n y2 = axisY2\n c1 = x1\n c2 = yMid\n labelX = x1 - 5\n labelY = height - 30\n break\n\n default:\n break\n }\n return {\n value,\n label,\n c1,\n c2,\n x1,\n y1,\n x2,\n y2,\n labelX,\n labelY,\n }\n },\n )\n\n return (\n <div\n className=\"response-curve-picker\"\n ref={ref}>\n <svg {...svgProps}>\n <rect\n className=\"container\"\n height={height}\n rx={3}\n ry={3}\n width={width}\n x={0}\n y={0}\n />\n\n <SVGText\n className=\"axis\"\n textAnchor=\"middle\"\n transform={`translate(${axisX1 - 14} ${height / 2}) rotate(90)`}\n x={0}\n y={0}\n text=\"Applied force\"\n />\n\n <SVGText\n className=\"axis\"\n textAnchor=\"middle\"\n transform={`translate(${width / 2} ${axisY2 + 13})`}\n x={0}\n y={0}\n text=\"Output (velocity)\"\n />\n\n <line\n className=\"axis\"\n x1={axisX1}\n x2={axisX1}\n y1={axisY1}\n y2={axisY2}\n />\n <line\n className=\"axis\"\n x1={axisX1}\n x2={axisX2}\n y1={axisY2}\n y2={axisY2}\n />\n\n {responseCurves.map(\n ({ value, label, x1, y1, x2, y2, c1, c2, labelX, labelY }) => (\n <g key={value}>\n <path\n className={value === responseCurve ? 'curve-selected' : 'curve'}\n d={`M${x1} ${y1} C ${c1} ${c2}, ${c1} ${c2}, ${x2} ${y2}`}\n />\n\n <Tooltip\n placement=\"left\"\n title={label}>\n <rect\n className={\n value === responseCurve ? 'button-selected' : 'button'\n }\n height={buttonSize}\n onClick={\n disabled\n ? f => f\n : () =>\n onChange({\n target: {\n value: Number.parseInt(String(value)) as Curve,\n },\n })\n }\n transform={`translate(${labelX + 3} ${labelY - buttonSize / 1.05}) rotate(45)`}\n width={buttonSize}\n />\n </Tooltip>\n\n <text\n className={\n value === responseCurve ? 'button-selected' : 'button'\n }\n transform={`translate(${labelX} ${labelY})`}>\n {value}\n <title>{label}</title>\n </text>\n </g>\n ),\n )}\n </svg>\n </div>\n )\n}\n\nexport default ResponseCurve\n\nexport { RESPONSE_CURVES }\n\nexport type { Curve, ResponseCurve, ResponseCurveProps }\n"],"names":["Statuses","MASK_CHANNEL","MASK_STATUS","statusOptions","getStatusLabel","val","_a","value","combineStatusWithChannel","channel","status","extractStatusAndChannel","MEASUREMENT_ELEMENT_ID","RESPONSE_CURVE_0","RESPONSE_CURVE_1","RESPONSE_CURVE_2","RESPONSE_CURVE_3","RESPONSE_CURVE_4","RESPONSE_CURVE_5","RESPONSE_CURVE_6","RESPONSE_CURVE_7","RESPONSE_CURVES"],"mappings":";;AAEA,MAAMA,IAAW;AAAA,EACf,SAAS;AAAA;AAAA,EACT,QAAQ;AAAA;AAAA,EACR,YAAY;AAAA;AAAA,EACZ,eAAe;AAAA;AAAA,EACf,eAAe;AAAA;AAAA,EACf,iBAAiB;AAAA;AAAA,EACjB,YAAY;AAAA;AACd,GAIMC,IAAe,IACfC,IAAc,KAEdC,IAAkC;AAAA,EACtC,EAAE,OAAOH,EAAS,QAAQ,OAAO,UAAU;AAAA,EAC3C,EAAE,OAAOA,EAAS,SAAS,OAAO,aAAa;AAAA,EAC/C,EAAE,OAAOA,EAAS,eAAe,OAAO,iBAAiB;AAAA,EACzD,EAAE,OAAOA,EAAS,eAAe,OAAO,iBAAiB;AAAA,EACzD,EAAE,OAAOA,EAAS,YAAY,OAAO,aAAa;AAAA,EAClD,EAAE,OAAOA,EAAS,iBAAiB,OAAO,mBAAmB;AAAA,EAC7D,EAAE,OAAOA,EAAS,YAAY,OAAO,cAAc;AACrD,GAEMI,IAAiB,CAACC;;AACtB,WAAAC,IAAAH,EAAc,OAAO,CAAC,EAAE,OAAAI,EAAM,MAAMA,MAAUF,CAAG,EAAE,CAAC,MAApD,gBAAAC,EAAuD,UAAS;AAAA,GAE5DE,IAA2B,CAACC,GAAiBC,MACjDD,IAAWC,KAAU,GAEjBC,IAA0B,CAC9BD,OAII;AAAA,EACJ,SAAWA,IAASR,MAAgB,IAAK;AAAA,EACzC,SAASQ,IAAST;AACpB,ICvCMW,IAAyB,mCCIzBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GAyBnBC,IAAmC;AAAA,EACvC;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOJ;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOC;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOC;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOC;AAAA,IACP,OAAO;AAAA,EAAA;AAEX;"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../lib/midi/export.ts","../lib/other/SVGText.tsx"],"sourcesContent":["import type { Option } from 'lib/pickers/Select'\n\nconst Statuses = {\n noteOff: 8, // 1000\n noteOn: 9, // 1001\n aftertouch: 10, // 1010\n controlChange: 11, // 1011\n programChange: 12, // 1100\n channelPressure: 13, // 1101\n pitchWheel: 14, // 1110\n} as const\n\ntype Status = (typeof Statuses)[keyof typeof Statuses]\n\nconst MASK_CHANNEL = 15 // 00001111\nconst MASK_STATUS = 240 // 01110000\n\nconst statusOptions: Option<Status>[] = [\n { value: Statuses.noteOn, label: 'Note On' },\n { value: Statuses.noteOff, label: 'Note Stack' },\n { value: Statuses.controlChange, label: 'Control Change' },\n { value: Statuses.programChange, label: 'Program Change' },\n { value: Statuses.aftertouch, label: 'Aftertouch' },\n { value: Statuses.channelPressure, label: 'Channel Pressure' },\n { value: Statuses.pitchWheel, label: 'Pitch Wheel' },\n]\n\nconst getStatusLabel = (val: Status) =>\n statusOptions.filter(({ value }) => value === val)[0]?.label || '???'\n\nconst combineStatusWithChannel = (channel: number, status: Status) =>\n channel | (status << 4)\n\nconst extractStatusAndChannel = (\n status: number,\n): {\n status: Status\n channel: number\n} => ({\n status: (((status & MASK_STATUS) >> 4) | 8) as Status,\n channel: status & MASK_CHANNEL,\n})\n\nconst RESPONSE_CURVE_0 = 0\nconst RESPONSE_CURVE_1 = 1\nconst RESPONSE_CURVE_2 = 2\nconst RESPONSE_CURVE_3 = 3\nconst RESPONSE_CURVE_4 = 4\nconst RESPONSE_CURVE_5 = 5\nconst RESPONSE_CURVE_6 = 6\nconst RESPONSE_CURVE_7 = 7\n\ntype Curve =\n | typeof RESPONSE_CURVE_0\n | typeof RESPONSE_CURVE_1\n | typeof RESPONSE_CURVE_2\n | typeof RESPONSE_CURVE_3\n | typeof RESPONSE_CURVE_4\n | typeof RESPONSE_CURVE_5\n | typeof RESPONSE_CURVE_6\n | typeof RESPONSE_CURVE_7\n\nconst responseCurves: Option<Curve>[] = [\n {\n value: RESPONSE_CURVE_7,\n label: 'Always maxed out.',\n },\n {\n value: RESPONSE_CURVE_6,\n label: 'Most sensitive.',\n },\n {\n value: RESPONSE_CURVE_5,\n label: 'Moderately sensitive.',\n },\n {\n value: RESPONSE_CURVE_4,\n label: 'A little sensitive.',\n },\n {\n value: RESPONSE_CURVE_0,\n label: 'Linear, no change.',\n },\n {\n value: RESPONSE_CURVE_1,\n label: 'A little less sensitive.',\n },\n {\n value: RESPONSE_CURVE_2,\n label: 'Even less sensitive.',\n },\n {\n value: RESPONSE_CURVE_3,\n label: 'Least sensitive.',\n },\n]\n\nexport {\n combineStatusWithChannel,\n extractStatusAndChannel,\n getStatusLabel,\n MASK_CHANNEL,\n MASK_STATUS,\n responseCurves,\n Statuses,\n statusOptions,\n}\n\nexport type { Curve, Status }\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nconst MEASUREMENT_ELEMENT_ID = '__react_svg_text_measurement_id'\n\ntype WordsByLine = {\n words: string[]\n width: number\n showLine: boolean\n}\n\nconst calculateWordsByLines = (\n text: string,\n wordWidths: WordWidths,\n maxWidth: number,\n maxHeight: number,\n) => {\n const { lineHeight, spaceWidth, wordsWithComputedWidth } = wordWidths\n\n return text.split(/\\s+/).reduce((result: WordsByLine[], word) => {\n const wordWidth = wordsWithComputedWidth[word]\n const currentLine = result[result.length - 1]\n if (currentLine && currentLine.width + wordWidth + spaceWidth < maxWidth) {\n // Word can be added to an existing line\n currentLine.words.push(word)\n currentLine.width += wordWidth + spaceWidth\n } else {\n // Add first word to line or word is too long to scaleToFit on existing line\n const newLine: WordsByLine = {\n words: [word],\n width: wordWidth,\n showLine: maxHeight\n ? lineHeight * (result.length + 1) < maxHeight\n : true,\n }\n result.push(newLine)\n }\n return result\n }, [])\n}\n\ntype WordWidths = {\n wordsWithComputedWidth: Record<string, number>\n spaceWidth: number\n lineHeight: number\n}\n\nconst calculateWordWidths = (\n style?: CSSStyleDeclaration,\n textNode?: SVGGraphicsElement | null,\n text?: string,\n): WordWidths | undefined => {\n if (style && textNode) {\n // biome-ignore lint/complexity/noForEach: <explanation>\n Array.from(style).forEach(key =>\n textNode.style.setProperty(\n key,\n style.getPropertyValue(key),\n style.getPropertyPriority(key),\n ),\n )\n const wordArray = [...new Set(String(text).split(/\\s+/))]\n const wordsWithComputedWidth = wordArray.reduce((wordMap, word) => {\n textNode.textContent = word\n // biome-ignore lint/performance/noAccumulatingSpread: <explanation>\n return { ...wordMap, [word]: textNode.getBBox().width }\n }, {})\n\n textNode.textContent = '\\u00A0'\n\n const spaceWidth =\n (textNode as SVGTextContentElement)?.getComputedTextLength?.() || 8\n const lineHeight = textNode.getBBox().height\n\n textNode.setAttribute('style', '')\n return { wordsWithComputedWidth, spaceWidth, lineHeight }\n }\n return undefined\n}\n\ntype TextProps = Partial<HTMLOrSVGElement> & {\n className?: string\n dx?: number\n dy?: number\n maxHeight?: number\n maxWidth?: number\n transform?: string\n text: string\n textAnchor?: React.CSSProperties['textAnchor']\n verticalAnchor?: 'start' | 'middle' | 'end'\n x?: number\n y?: number\n}\n\nconst Text = (props: TextProps) => {\n const {\n className = '',\n dx = 0,\n dy = 0,\n maxHeight = 1000,\n maxWidth = 1000,\n // textAnchor = 'start',\n text = '',\n verticalAnchor = 'start',\n x = 0,\n y = 0,\n transform = '',\n ...rest\n } = props\n const [wordWidths, setWordWidths] = useState<WordWidths>()\n const [textLines, setTextLines] = useState<WordsByLine[]>([])\n const [style, setComputedStyle] = useState<CSSStyleDeclaration>()\n const measureRef = useRef<SVGSVGElement | HTMLElement>({} as HTMLElement)\n\n const displayedLines: WordsByLine[] = useMemo(() => {\n const result = textLines.filter(({ showLine }) => showLine)\n return result.length\n ? result\n : text\n .split(/\\n/)\n .map(line => ({ words: [line], width: 0, showLine: true }))\n }, [textLines, text])\n\n const ref: React.LegacyRef<SVGTextElement> = useCallback(\n (node: SVGTextElement | null) => {\n setComputedStyle(\n node !== null ? window.getComputedStyle(node) : undefined,\n )\n },\n [],\n )\n\n useEffect(() => {\n const el = document.getElementById(MEASUREMENT_ELEMENT_ID)\n if (el === null) {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n svg.setAttribute('id', MEASUREMENT_ELEMENT_ID)\n document.body.appendChild(svg)\n svg.appendChild(\n document.createElementNS('http://www.w3.org/2000/svg', 'text'),\n )\n measureRef.current = svg\n return () => {\n document.body.removeChild(svg)\n }\n }\n measureRef.current = el\n }, [])\n\n useEffect(() => {\n const wordWithWidths = calculateWordWidths(\n style,\n measureRef.current as SVGGraphicsElement | null,\n text,\n )\n\n setWordWidths(wordWithWidths)\n }, [text, style])\n\n useEffect(() => {\n if (maxWidth && wordWidths) {\n const lines = text\n .split(/\\n/)\n .flatMap(line =>\n calculateWordsByLines(line, wordWidths, maxWidth, maxHeight),\n )\n\n setTextLines(lines)\n }\n }, [maxHeight, maxWidth, wordWidths, text])\n\n const startDy = useMemo(() => {\n if (wordWidths?.lineHeight) {\n switch (verticalAnchor) {\n case 'start':\n return wordWidths.lineHeight\n\n case 'middle':\n return -(((displayedLines.length - 1) * wordWidths.lineHeight) / 2)\n\n default:\n return -(displayedLines.length - 1) * wordWidths.lineHeight\n }\n }\n return 0\n }, [displayedLines.length, verticalAnchor, wordWidths?.lineHeight])\n\n return (\n <text\n className={className}\n ref={ref}\n dx={dx}\n dy={dy}\n x={x}\n y={y}\n // textAnchor={textAnchor}\n transform={transform}\n {...rest}>\n <>\n {displayedLines.map((line, idx) => (\n <tspan\n dx={x + dx}\n dy={idx === 0 ? startDy + dy : wordWidths?.lineHeight || 0}\n key={idx}\n x={0}>\n {line.words.join(' ')}\n </tspan>\n ))}\n {textLines.length && displayedLines.length !== textLines.length && (\n <>\n <tspan>...</tspan>\n <title>{text}</title>\n </>\n )}\n </>\n </text>\n )\n}\n\nexport default Text\n\nexport { MEASUREMENT_ELEMENT_ID }\n\nexport type { TextProps, WordWidths, WordsByLine }\n"],"names":["Statuses","MASK_CHANNEL","MASK_STATUS","statusOptions","getStatusLabel","val","_a","value","combineStatusWithChannel","channel","status","extractStatusAndChannel","RESPONSE_CURVE_0","RESPONSE_CURVE_1","RESPONSE_CURVE_2","RESPONSE_CURVE_3","RESPONSE_CURVE_4","RESPONSE_CURVE_5","RESPONSE_CURVE_6","RESPONSE_CURVE_7","responseCurves","MEASUREMENT_ELEMENT_ID"],"mappings":";;AAEA,MAAMA,IAAW;AAAA,EACf,SAAS;AAAA;AAAA,EACT,QAAQ;AAAA;AAAA,EACR,YAAY;AAAA;AAAA,EACZ,eAAe;AAAA;AAAA,EACf,eAAe;AAAA;AAAA,EACf,iBAAiB;AAAA;AAAA,EACjB,YAAY;AAAA;AACd,GAIMC,IAAe,IACfC,IAAc,KAEdC,IAAkC;AAAA,EACtC,EAAE,OAAOH,EAAS,QAAQ,OAAO,UAAU;AAAA,EAC3C,EAAE,OAAOA,EAAS,SAAS,OAAO,aAAa;AAAA,EAC/C,EAAE,OAAOA,EAAS,eAAe,OAAO,iBAAiB;AAAA,EACzD,EAAE,OAAOA,EAAS,eAAe,OAAO,iBAAiB;AAAA,EACzD,EAAE,OAAOA,EAAS,YAAY,OAAO,aAAa;AAAA,EAClD,EAAE,OAAOA,EAAS,iBAAiB,OAAO,mBAAmB;AAAA,EAC7D,EAAE,OAAOA,EAAS,YAAY,OAAO,cAAc;AACrD,GAEMI,IAAiB,CAACC;;AACtB,WAAAC,IAAAH,EAAc,OAAO,CAAC,EAAE,OAAAI,EAAM,MAAMA,MAAUF,CAAG,EAAE,CAAC,MAApD,gBAAAC,EAAuD,UAAS;AAAA,GAE5DE,IAA2B,CAACC,GAAiBC,MACjDD,IAAWC,KAAU,GAEjBC,IAA0B,CAC9BD,OAII;AAAA,EACJ,SAAWA,IAASR,MAAgB,IAAK;AAAA,EACzC,SAASQ,IAAST;AACpB,IAEMW,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GACnBC,IAAmB,GAYnBC,IAAkC;AAAA,EACtC;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOD;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOJ;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOC;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOC;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAOC;AAAA,IACP,OAAO;AAAA,EAAA;AAEX,GC7FMM,IAAyB;"}
|
package/dist/midi/export.js
CHANGED
|
@@ -24,4 +24,46 @@ const extractStatusAndChannel = (status) => ({
|
|
|
24
24
|
status: (((status & MASK_STATUS) >> 4) | 8),
|
|
25
25
|
channel: status & MASK_CHANNEL,
|
|
26
26
|
});
|
|
27
|
-
|
|
27
|
+
const RESPONSE_CURVE_0 = 0;
|
|
28
|
+
const RESPONSE_CURVE_1 = 1;
|
|
29
|
+
const RESPONSE_CURVE_2 = 2;
|
|
30
|
+
const RESPONSE_CURVE_3 = 3;
|
|
31
|
+
const RESPONSE_CURVE_4 = 4;
|
|
32
|
+
const RESPONSE_CURVE_5 = 5;
|
|
33
|
+
const RESPONSE_CURVE_6 = 6;
|
|
34
|
+
const RESPONSE_CURVE_7 = 7;
|
|
35
|
+
const responseCurves = [
|
|
36
|
+
{
|
|
37
|
+
value: RESPONSE_CURVE_7,
|
|
38
|
+
label: 'Always maxed out.',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
value: RESPONSE_CURVE_6,
|
|
42
|
+
label: 'Most sensitive.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
value: RESPONSE_CURVE_5,
|
|
46
|
+
label: 'Moderately sensitive.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
value: RESPONSE_CURVE_4,
|
|
50
|
+
label: 'A little sensitive.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
value: RESPONSE_CURVE_0,
|
|
54
|
+
label: 'Linear, no change.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
value: RESPONSE_CURVE_1,
|
|
58
|
+
label: 'A little less sensitive.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
value: RESPONSE_CURVE_2,
|
|
62
|
+
label: 'Even less sensitive.',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
value: RESPONSE_CURVE_3,
|
|
66
|
+
label: 'Least sensitive.',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
export { combineStatusWithChannel, extractStatusAndChannel, getStatusLabel, MASK_CHANNEL, MASK_STATUS, responseCurves, Statuses, statusOptions, };
|
|
@@ -1,50 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
import useComponentSize from '../hooks/useComponentSize';
|
|
4
|
+
import { responseCurves as origResponseCurves, } from '../midi/export';
|
|
4
5
|
import DefaultTooltip from '../other/DefaultTooltip';
|
|
5
6
|
import SVGText from '../other/SVGText';
|
|
6
|
-
const RESPONSE_CURVE_0 = 0;
|
|
7
|
-
const RESPONSE_CURVE_1 = 1;
|
|
8
|
-
const RESPONSE_CURVE_2 = 2;
|
|
9
|
-
const RESPONSE_CURVE_3 = 3;
|
|
10
|
-
const RESPONSE_CURVE_4 = 4;
|
|
11
|
-
const RESPONSE_CURVE_5 = 5;
|
|
12
|
-
const RESPONSE_CURVE_6 = 6;
|
|
13
|
-
const RESPONSE_CURVE_7 = 7;
|
|
14
|
-
const RESPONSE_CURVES = [
|
|
15
|
-
{
|
|
16
|
-
value: RESPONSE_CURVE_7,
|
|
17
|
-
label: 'Always maxed out.',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
value: RESPONSE_CURVE_6,
|
|
21
|
-
label: 'Most sensitive.',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
value: RESPONSE_CURVE_5,
|
|
25
|
-
label: 'Moderately sensitive.',
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
value: RESPONSE_CURVE_4,
|
|
29
|
-
label: 'A little sensitive.',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
value: RESPONSE_CURVE_0,
|
|
33
|
-
label: 'Linear, no change.',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
value: RESPONSE_CURVE_1,
|
|
37
|
-
label: 'A little less sensitive.',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
value: RESPONSE_CURVE_2,
|
|
41
|
-
label: 'Even less sensitive.',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
value: RESPONSE_CURVE_3,
|
|
45
|
-
label: 'Least sensitive.',
|
|
46
|
-
},
|
|
47
|
-
];
|
|
48
7
|
// const width = 218
|
|
49
8
|
// const height = 150
|
|
50
9
|
const axisOffset = 20;
|
|
@@ -63,7 +22,7 @@ const ResponseCurve = (props) => {
|
|
|
63
22
|
const xMid = width / 2;
|
|
64
23
|
const yMid = height / 2;
|
|
65
24
|
const svgProps = { ref: svgRef };
|
|
66
|
-
const responseCurves =
|
|
25
|
+
const responseCurves = origResponseCurves.map(
|
|
67
26
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>
|
|
68
27
|
({ value, label }) => {
|
|
69
28
|
let c1 = 0;
|
|
@@ -75,48 +34,48 @@ const ResponseCurve = (props) => {
|
|
|
75
34
|
let labelX = xMid;
|
|
76
35
|
let labelY = yMid;
|
|
77
36
|
switch (value) {
|
|
78
|
-
case
|
|
37
|
+
case responseCurves[0].value:
|
|
79
38
|
c1 = xMid;
|
|
80
39
|
c2 = yMid;
|
|
81
40
|
labelY += 3;
|
|
82
41
|
break;
|
|
83
|
-
case
|
|
42
|
+
case responseCurves[1].value:
|
|
84
43
|
c1 = inverted ? xMid + width * 0.13 : xMid - width * 0.13;
|
|
85
44
|
c2 = yMid - height * 0.13;
|
|
86
45
|
labelX = inverted ? xMid + width * 0.1 : xMid - width * 0.1;
|
|
87
46
|
labelY = yMid - height * 0.09;
|
|
88
47
|
break;
|
|
89
|
-
case
|
|
48
|
+
case responseCurves[2].value:
|
|
90
49
|
c1 = inverted ? xMid + width * 0.25 : xMid - width * 0.25;
|
|
91
50
|
c2 = yMid - height * 0.25;
|
|
92
51
|
labelX = inverted ? xMid + width * 0.2 : xMid - width * 0.2;
|
|
93
52
|
labelY = yMid - height * 0.17;
|
|
94
53
|
break;
|
|
95
|
-
case
|
|
54
|
+
case responseCurves[3].value:
|
|
96
55
|
c1 = inverted ? xMid + width * 0.35 : xMid - width * 0.35;
|
|
97
56
|
c2 = yMid - height * 0.35;
|
|
98
57
|
labelX = inverted ? xMid + width * 0.28 : xMid - width * 0.28;
|
|
99
58
|
labelY = yMid - height * 0.25;
|
|
100
59
|
break;
|
|
101
|
-
case
|
|
60
|
+
case responseCurves[4].value:
|
|
102
61
|
c1 = inverted ? xMid - width * 0.13 : xMid + width * 0.13;
|
|
103
62
|
c2 = yMid + height * 0.13;
|
|
104
63
|
labelX = inverted ? xMid - width * 0.1 : xMid + width * 0.1;
|
|
105
64
|
labelY = yMid + height * 0.1;
|
|
106
65
|
break;
|
|
107
|
-
case
|
|
66
|
+
case responseCurves[5].value:
|
|
108
67
|
c1 = inverted ? xMid - width * 0.25 : xMid + width * 0.25;
|
|
109
68
|
c2 = yMid + height * 0.25;
|
|
110
69
|
labelX = inverted ? xMid - width * 0.2 : xMid + width * 0.2;
|
|
111
70
|
labelY = yMid + height * 0.18;
|
|
112
71
|
break;
|
|
113
|
-
case
|
|
72
|
+
case responseCurves[6].value:
|
|
114
73
|
c1 = inverted ? xMid - width * 0.35 : xMid + width * 0.35;
|
|
115
74
|
c2 = yMid + height * 0.35;
|
|
116
75
|
labelX = inverted ? xMid - width * 0.28 : xMid + width * 0.28;
|
|
117
76
|
labelY = yMid + height * 0.25;
|
|
118
77
|
break;
|
|
119
|
-
case
|
|
78
|
+
case responseCurves[7].value:
|
|
120
79
|
x1 = inverted ? axisX1 : axisX2;
|
|
121
80
|
y1 = axisY1;
|
|
122
81
|
x2 = x1;
|
|
@@ -151,4 +110,3 @@ const ResponseCurve = (props) => {
|
|
|
151
110
|
}), transform: `translate(${labelX + 3} ${labelY - buttonSize / 1.05}) rotate(45)`, width: buttonSize }) }), _jsxs("text", { className: value === responseCurve ? 'button-selected' : 'button', transform: `translate(${labelX} ${labelY})`, children: [value, _jsx("title", { children: label })] })] }, value)))] }) }));
|
|
152
111
|
};
|
|
153
112
|
export default ResponseCurve;
|
|
154
|
-
export { RESPONSE_CURVES };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useCallback } from 'react';
|
|
3
|
+
import { responseCurves } from '../midi/export';
|
|
3
4
|
import DefaultTooltip from '../other/DefaultTooltip';
|
|
4
5
|
import { findObj } from '../utils';
|
|
5
|
-
import ResponseCurve
|
|
6
|
+
import ResponseCurve from './ResponseCurve';
|
|
6
7
|
import Select from './Select';
|
|
7
8
|
const ResponseCurvePicker = forwardRef((props, ref) => {
|
|
8
9
|
const { Tooltip = DefaultTooltip, inverted = false, onChange, value, ...rest } = props;
|
|
9
|
-
const Placeholder = useCallback(() => (_jsx("div", { className: "singleValue", children: findObj('value', value)(
|
|
10
|
+
const Placeholder = useCallback(() => (_jsx("div", { className: "singleValue", children: findObj('value', value)(responseCurves)?.label })), [value]);
|
|
10
11
|
const MenuList = useCallback(({ setValue }) => (_jsx(ResponseCurve, { autosize: true, inverted: inverted, onChange: ({ target: { value: v } }) => {
|
|
11
12
|
setValue(v);
|
|
12
13
|
onChange(v);
|
|
@@ -18,4 +18,15 @@ declare const extractStatusAndChannel: (status: number) => {
|
|
|
18
18
|
status: Status;
|
|
19
19
|
channel: number;
|
|
20
20
|
};
|
|
21
|
-
|
|
21
|
+
declare const RESPONSE_CURVE_0 = 0;
|
|
22
|
+
declare const RESPONSE_CURVE_1 = 1;
|
|
23
|
+
declare const RESPONSE_CURVE_2 = 2;
|
|
24
|
+
declare const RESPONSE_CURVE_3 = 3;
|
|
25
|
+
declare const RESPONSE_CURVE_4 = 4;
|
|
26
|
+
declare const RESPONSE_CURVE_5 = 5;
|
|
27
|
+
declare const RESPONSE_CURVE_6 = 6;
|
|
28
|
+
declare const RESPONSE_CURVE_7 = 7;
|
|
29
|
+
type Curve = typeof RESPONSE_CURVE_0 | typeof RESPONSE_CURVE_1 | typeof RESPONSE_CURVE_2 | typeof RESPONSE_CURVE_3 | typeof RESPONSE_CURVE_4 | typeof RESPONSE_CURVE_5 | typeof RESPONSE_CURVE_6 | typeof RESPONSE_CURVE_7;
|
|
30
|
+
declare const responseCurves: Option<Curve>[];
|
|
31
|
+
export { combineStatusWithChannel, extractStatusAndChannel, getStatusLabel, MASK_CHANNEL, MASK_STATUS, responseCurves, Statuses, statusOptions, };
|
|
32
|
+
export type { Curve, Status };
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
+
import { type Curve } from '../midi/export';
|
|
1
2
|
import { type TooltipProps } from '../other/DefaultTooltip';
|
|
2
|
-
import type { Option } from './Select';
|
|
3
|
-
declare const RESPONSE_CURVE_0 = 0;
|
|
4
|
-
declare const RESPONSE_CURVE_1 = 1;
|
|
5
|
-
declare const RESPONSE_CURVE_2 = 2;
|
|
6
|
-
declare const RESPONSE_CURVE_3 = 3;
|
|
7
|
-
declare const RESPONSE_CURVE_4 = 4;
|
|
8
|
-
declare const RESPONSE_CURVE_5 = 5;
|
|
9
|
-
declare const RESPONSE_CURVE_6 = 6;
|
|
10
|
-
declare const RESPONSE_CURVE_7 = 7;
|
|
11
|
-
type Curve = typeof RESPONSE_CURVE_0 | typeof RESPONSE_CURVE_1 | typeof RESPONSE_CURVE_2 | typeof RESPONSE_CURVE_3 | typeof RESPONSE_CURVE_4 | typeof RESPONSE_CURVE_5 | typeof RESPONSE_CURVE_6 | typeof RESPONSE_CURVE_7;
|
|
12
3
|
type ResponseCurve = {
|
|
13
4
|
value: Curve;
|
|
14
5
|
label: React.ReactNode;
|
|
@@ -21,7 +12,6 @@ type ResponseCurve = {
|
|
|
21
12
|
labelX: number;
|
|
22
13
|
labelY: number;
|
|
23
14
|
};
|
|
24
|
-
declare const RESPONSE_CURVES: Option<Curve>[];
|
|
25
15
|
type ResponseCurveProps = {
|
|
26
16
|
autosize: boolean;
|
|
27
17
|
disabled?: boolean;
|
|
@@ -36,5 +26,4 @@ type ResponseCurveProps = {
|
|
|
36
26
|
};
|
|
37
27
|
declare const ResponseCurve: (props: ResponseCurveProps) => import("react/jsx-runtime").JSX.Element;
|
|
38
28
|
export default ResponseCurve;
|
|
39
|
-
export {
|
|
40
|
-
export type { Curve, ResponseCurve, ResponseCurveProps };
|
|
29
|
+
export type { ResponseCurve, ResponseCurveProps };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GroupBase, SelectInstance } from 'react-select';
|
|
2
|
+
import { type Curve } from '../midi/export';
|
|
2
3
|
import { type TooltipProps } from '../other/DefaultTooltip';
|
|
3
|
-
import { type Curve } from './ResponseCurve';
|
|
4
4
|
import type { Option, SelectProps } from './Select';
|
|
5
5
|
type ResponseCurvePickerProps = SelectProps<Curve> & {
|
|
6
6
|
inverted?: boolean;
|
package/lib/midi/export.ts
CHANGED
|
@@ -41,13 +41,69 @@ const extractStatusAndChannel = (
|
|
|
41
41
|
channel: status & MASK_CHANNEL,
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
+
const RESPONSE_CURVE_0 = 0
|
|
45
|
+
const RESPONSE_CURVE_1 = 1
|
|
46
|
+
const RESPONSE_CURVE_2 = 2
|
|
47
|
+
const RESPONSE_CURVE_3 = 3
|
|
48
|
+
const RESPONSE_CURVE_4 = 4
|
|
49
|
+
const RESPONSE_CURVE_5 = 5
|
|
50
|
+
const RESPONSE_CURVE_6 = 6
|
|
51
|
+
const RESPONSE_CURVE_7 = 7
|
|
52
|
+
|
|
53
|
+
type Curve =
|
|
54
|
+
| typeof RESPONSE_CURVE_0
|
|
55
|
+
| typeof RESPONSE_CURVE_1
|
|
56
|
+
| typeof RESPONSE_CURVE_2
|
|
57
|
+
| typeof RESPONSE_CURVE_3
|
|
58
|
+
| typeof RESPONSE_CURVE_4
|
|
59
|
+
| typeof RESPONSE_CURVE_5
|
|
60
|
+
| typeof RESPONSE_CURVE_6
|
|
61
|
+
| typeof RESPONSE_CURVE_7
|
|
62
|
+
|
|
63
|
+
const responseCurves: Option<Curve>[] = [
|
|
64
|
+
{
|
|
65
|
+
value: RESPONSE_CURVE_7,
|
|
66
|
+
label: 'Always maxed out.',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
value: RESPONSE_CURVE_6,
|
|
70
|
+
label: 'Most sensitive.',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
value: RESPONSE_CURVE_5,
|
|
74
|
+
label: 'Moderately sensitive.',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
value: RESPONSE_CURVE_4,
|
|
78
|
+
label: 'A little sensitive.',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
value: RESPONSE_CURVE_0,
|
|
82
|
+
label: 'Linear, no change.',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
value: RESPONSE_CURVE_1,
|
|
86
|
+
label: 'A little less sensitive.',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
value: RESPONSE_CURVE_2,
|
|
90
|
+
label: 'Even less sensitive.',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
value: RESPONSE_CURVE_3,
|
|
94
|
+
label: 'Least sensitive.',
|
|
95
|
+
},
|
|
96
|
+
]
|
|
97
|
+
|
|
44
98
|
export {
|
|
45
99
|
combineStatusWithChannel,
|
|
46
100
|
extractStatusAndChannel,
|
|
47
101
|
getStatusLabel,
|
|
48
102
|
MASK_CHANNEL,
|
|
49
103
|
MASK_STATUS,
|
|
50
|
-
|
|
104
|
+
responseCurves,
|
|
51
105
|
Statuses,
|
|
52
|
-
|
|
106
|
+
statusOptions,
|
|
53
107
|
}
|
|
108
|
+
|
|
109
|
+
export type { Curve, Status }
|
|
@@ -1,27 +1,11 @@
|
|
|
1
1
|
import { useRef } from 'react'
|
|
2
2
|
import useComponentSize from '../hooks/useComponentSize'
|
|
3
|
+
import {
|
|
4
|
+
type Curve,
|
|
5
|
+
responseCurves as origResponseCurves,
|
|
6
|
+
} from '../midi/export'
|
|
3
7
|
import DefaultTooltip, { type TooltipProps } from '../other/DefaultTooltip'
|
|
4
8
|
import SVGText from '../other/SVGText'
|
|
5
|
-
import type { Option } from './Select'
|
|
6
|
-
|
|
7
|
-
const RESPONSE_CURVE_0 = 0
|
|
8
|
-
const RESPONSE_CURVE_1 = 1
|
|
9
|
-
const RESPONSE_CURVE_2 = 2
|
|
10
|
-
const RESPONSE_CURVE_3 = 3
|
|
11
|
-
const RESPONSE_CURVE_4 = 4
|
|
12
|
-
const RESPONSE_CURVE_5 = 5
|
|
13
|
-
const RESPONSE_CURVE_6 = 6
|
|
14
|
-
const RESPONSE_CURVE_7 = 7
|
|
15
|
-
|
|
16
|
-
type Curve =
|
|
17
|
-
| typeof RESPONSE_CURVE_0
|
|
18
|
-
| typeof RESPONSE_CURVE_1
|
|
19
|
-
| typeof RESPONSE_CURVE_2
|
|
20
|
-
| typeof RESPONSE_CURVE_3
|
|
21
|
-
| typeof RESPONSE_CURVE_4
|
|
22
|
-
| typeof RESPONSE_CURVE_5
|
|
23
|
-
| typeof RESPONSE_CURVE_6
|
|
24
|
-
| typeof RESPONSE_CURVE_7
|
|
25
9
|
|
|
26
10
|
type ResponseCurve = {
|
|
27
11
|
value: Curve
|
|
@@ -36,41 +20,6 @@ type ResponseCurve = {
|
|
|
36
20
|
labelY: number
|
|
37
21
|
}
|
|
38
22
|
|
|
39
|
-
const RESPONSE_CURVES: Option<Curve>[] = [
|
|
40
|
-
{
|
|
41
|
-
value: RESPONSE_CURVE_7,
|
|
42
|
-
label: 'Always maxed out.',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
value: RESPONSE_CURVE_6,
|
|
46
|
-
label: 'Most sensitive.',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
value: RESPONSE_CURVE_5,
|
|
50
|
-
label: 'Moderately sensitive.',
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
value: RESPONSE_CURVE_4,
|
|
54
|
-
label: 'A little sensitive.',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
value: RESPONSE_CURVE_0,
|
|
58
|
-
label: 'Linear, no change.',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
value: RESPONSE_CURVE_1,
|
|
62
|
-
label: 'A little less sensitive.',
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
value: RESPONSE_CURVE_2,
|
|
66
|
-
label: 'Even less sensitive.',
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
value: RESPONSE_CURVE_3,
|
|
70
|
-
label: 'Least sensitive.',
|
|
71
|
-
},
|
|
72
|
-
]
|
|
73
|
-
|
|
74
23
|
// const width = 218
|
|
75
24
|
// const height = 150
|
|
76
25
|
const axisOffset = 20
|
|
@@ -113,7 +62,7 @@ const ResponseCurve = (props: ResponseCurveProps) => {
|
|
|
113
62
|
|
|
114
63
|
const svgProps = { ref: svgRef }
|
|
115
64
|
|
|
116
|
-
const responseCurves =
|
|
65
|
+
const responseCurves = origResponseCurves.map(
|
|
117
66
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>
|
|
118
67
|
({ value, label }): ResponseCurve => {
|
|
119
68
|
let c1 = 0
|
|
@@ -125,55 +74,55 @@ const ResponseCurve = (props: ResponseCurveProps) => {
|
|
|
125
74
|
let labelX = xMid
|
|
126
75
|
let labelY = yMid
|
|
127
76
|
switch (value) {
|
|
128
|
-
case
|
|
77
|
+
case responseCurves[0].value:
|
|
129
78
|
c1 = xMid
|
|
130
79
|
c2 = yMid
|
|
131
80
|
labelY += 3
|
|
132
81
|
|
|
133
82
|
break
|
|
134
|
-
case
|
|
83
|
+
case responseCurves[1].value:
|
|
135
84
|
c1 = inverted ? xMid + width * 0.13 : xMid - width * 0.13
|
|
136
85
|
c2 = yMid - height * 0.13
|
|
137
86
|
labelX = inverted ? xMid + width * 0.1 : xMid - width * 0.1
|
|
138
87
|
labelY = yMid - height * 0.09
|
|
139
88
|
break
|
|
140
89
|
|
|
141
|
-
case
|
|
90
|
+
case responseCurves[2].value:
|
|
142
91
|
c1 = inverted ? xMid + width * 0.25 : xMid - width * 0.25
|
|
143
92
|
c2 = yMid - height * 0.25
|
|
144
93
|
labelX = inverted ? xMid + width * 0.2 : xMid - width * 0.2
|
|
145
94
|
labelY = yMid - height * 0.17
|
|
146
95
|
break
|
|
147
96
|
|
|
148
|
-
case
|
|
97
|
+
case responseCurves[3].value:
|
|
149
98
|
c1 = inverted ? xMid + width * 0.35 : xMid - width * 0.35
|
|
150
99
|
c2 = yMid - height * 0.35
|
|
151
100
|
labelX = inverted ? xMid + width * 0.28 : xMid - width * 0.28
|
|
152
101
|
labelY = yMid - height * 0.25
|
|
153
102
|
break
|
|
154
103
|
|
|
155
|
-
case
|
|
104
|
+
case responseCurves[4].value:
|
|
156
105
|
c1 = inverted ? xMid - width * 0.13 : xMid + width * 0.13
|
|
157
106
|
c2 = yMid + height * 0.13
|
|
158
107
|
labelX = inverted ? xMid - width * 0.1 : xMid + width * 0.1
|
|
159
108
|
labelY = yMid + height * 0.1
|
|
160
109
|
break
|
|
161
110
|
|
|
162
|
-
case
|
|
111
|
+
case responseCurves[5].value:
|
|
163
112
|
c1 = inverted ? xMid - width * 0.25 : xMid + width * 0.25
|
|
164
113
|
c2 = yMid + height * 0.25
|
|
165
114
|
labelX = inverted ? xMid - width * 0.2 : xMid + width * 0.2
|
|
166
115
|
labelY = yMid + height * 0.18
|
|
167
116
|
break
|
|
168
117
|
|
|
169
|
-
case
|
|
118
|
+
case responseCurves[6].value:
|
|
170
119
|
c1 = inverted ? xMid - width * 0.35 : xMid + width * 0.35
|
|
171
120
|
c2 = yMid + height * 0.35
|
|
172
121
|
labelX = inverted ? xMid - width * 0.28 : xMid + width * 0.28
|
|
173
122
|
labelY = yMid + height * 0.25
|
|
174
123
|
break
|
|
175
124
|
|
|
176
|
-
case
|
|
125
|
+
case responseCurves[7].value:
|
|
177
126
|
x1 = inverted ? axisX1 : axisX2
|
|
178
127
|
y1 = axisY1
|
|
179
128
|
x2 = x1
|
|
@@ -299,6 +248,4 @@ const ResponseCurve = (props: ResponseCurveProps) => {
|
|
|
299
248
|
|
|
300
249
|
export default ResponseCurve
|
|
301
250
|
|
|
302
|
-
export {
|
|
303
|
-
|
|
304
|
-
export type { Curve, ResponseCurve, ResponseCurveProps }
|
|
251
|
+
export type { ResponseCurve, ResponseCurveProps }
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { forwardRef, useCallback } from 'react'
|
|
2
2
|
import type { GroupBase, SelectInstance } from 'react-select'
|
|
3
|
+
import { type Curve, responseCurves } from '../midi/export'
|
|
3
4
|
import DefaultTooltip, { type TooltipProps } from '../other/DefaultTooltip'
|
|
4
5
|
import { findObj } from '../utils'
|
|
5
|
-
import ResponseCurve
|
|
6
|
+
import ResponseCurve from './ResponseCurve'
|
|
6
7
|
import Select from './Select'
|
|
7
8
|
import type { Option, SelectProps } from './Select'
|
|
8
9
|
|
|
@@ -32,7 +33,7 @@ const ResponseCurvePicker = forwardRef<
|
|
|
32
33
|
const Placeholder = useCallback(
|
|
33
34
|
() => (
|
|
34
35
|
<div className="singleValue">
|
|
35
|
-
{(findObj('value', value)(
|
|
36
|
+
{(findObj('value', value)(responseCurves) as Option<Curve>)?.label}
|
|
36
37
|
</div>
|
|
37
38
|
),
|
|
38
39
|
[value],
|