Stubs tests. Updates types for controls.

This commit is contained in:
Steve Ruiz 2021-06-25 11:28:52 +01:00
parent 32922b3f85
commit 85dc3028b4
33 changed files with 1391 additions and 1191 deletions

View file

@ -1,3 +0,0 @@
{
"presets": ["next/babel"]
}

View file

@ -13270,13 +13270,9 @@ Object {
"code": "
const draw = new Draw({
points: [
[0, 0],
[0, 50],
[20, 80],
[56, 56],
[52, 52],
[80, 20],
[90, 90],
...Utils.getPointsBetween([0, 0], [20, 50]),
...Utils.getPointsBetween([20, 50], [100, 20], 3),
...Utils.getPointsBetween([100, 20], [100, 100], 10),
[100, 100],
],
})

69
__tests__/code.test.ts Normal file
View file

@ -0,0 +1,69 @@
import state from 'state'
import { generateFromCode } from 'state/code/generate'
import { getShapes } from 'utils'
import * as json from './__mocks__/document.json'
jest.useRealTimers()
state.reset()
state.send('MOUNTED').send('LOADED_FROM_FILE', { json: JSON.stringify(json) })
state.send('CLEARED_PAGE')
describe('selection', () => {
it('opens and closes the code panel', () => {
expect(state.data.settings.isCodeOpen).toBe(false)
state.send('TOGGLED_CODE_PANEL_OPEN')
expect(state.data.settings.isCodeOpen).toBe(true)
state.send('TOGGLED_CODE_PANEL_OPEN')
expect(state.data.settings.isCodeOpen).toBe(false)
})
it('saves changes to code', () => {
expect(getShapes(state.data).length).toBe(0)
const code = `// hello world!`
state.send('SAVED_CODE', { code })
expect(state.data.document.code[state.data.currentCodeFileId].code).toBe(
code
)
})
it('generates shapes', async () => {
const code = `
const rectangle = new Rectangle({
name: 'Test Rectangle',
point: [100, 100],
size: [200, 200],
style: {
size: SizeStyle.Medium,
color: ColorStyle.Red,
dash: DashStyle.Dotted,
},
})
`
const { controls, shapes } = await generateFromCode(state.data, code)
state.send('GENERATED_FROM_CODE', { controls, shapes })
expect(getShapes(state.data).length).toBe(1)
})
it('creates a code control', () => {
null
})
it('updates a code control', () => {
null
})
it('updates a code control', () => {
null
})
/* -------------------- Readonly -------------------- */
it('does not saves changes to code when readonly', () => {
null
})
})

24
__tests__/create.test.ts Normal file
View file

@ -0,0 +1,24 @@
import state from 'state'
import * as json from './__mocks__/document.json'
state.reset()
state.send('MOUNTED').send('LOADED_FROM_FILE', { json: JSON.stringify(json) })
state.send('CLEARED_PAGE')
describe('arrow shape', () => {
it('creates a shape', () => {
null
})
it('cancels shape while creating', () => {
null
})
it('removes shape on undo and restores it on redo', () => {
null
})
it('does not create shape when readonly', () => {
null
})
})

View file

@ -0,0 +1,68 @@
import state from 'state'
import * as json from '../__mocks__/document.json'
state.reset()
state.send('MOUNTED').send('LOADED_FROM_FILE', { json: JSON.stringify(json) })
state.send('CLEARED_PAGE')
describe('arrow shape', () => {
it('creates shape', () => {
null
})
it('cancels shape while creating', () => {
null
})
it('moves shape', () => {
null
})
it('rotates shape', () => {
null
})
it('measures bounds', () => {
null
})
it('measures rotated bounds', () => {
null
})
it('transforms single', () => {
null
})
it('transforms in a group', () => {
null
})
/* -------------------- Specific -------------------- */
it('creates compass-aligned shape with shift key', () => {
null
})
it('changes start handle', () => {
null
})
it('changes end handle', () => {
null
})
it('changes bend handle', () => {
null
})
it('resets bend handle when double-pointed', () => {
null
})
/* -------------------- Readonly -------------------- */
it('does not create shape when readonly', () => {
null
})
})

View file

@ -46,3 +46,11 @@ export function idsAreSelected(
ids.every((id) => selectedIds.has(id))
)
}
export async function asyncDelay<T>(fn: () => T): Promise<T> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(fn())
}, 100)
})
}

3
babel.config.js Normal file
View file

@ -0,0 +1,3 @@
module.exports = {
presets: ['next/babel'],
}

View file

@ -82,8 +82,11 @@ export default function CodePanel(): JSX.Element {
let error = null
try {
const { shapes, controls } = generateFromCode(state.data, data.code)
state.send('GENERATED_FROM_CODE', { shapes, controls })
generateFromCode(state.data, data.code).then(
({ shapes, controls }) => {
state.send('GENERATED_FROM_CODE', { shapes, controls })
}
)
} catch (e) {
console.error('Got an error!', e)
error = { message: e.message, ...getErrorLineAndColumn(e) }

File diff suppressed because it is too large Load diff

View file

@ -50,14 +50,21 @@ function NumberControl({ id, min, max, step, value }: NumberCodeControl) {
)
}
function VectorControl({ id, value, isNormalized }: VectorCodeControl) {
function VectorControl({
id,
value,
min = -Infinity,
max = Infinity,
step = 0.01,
isNormalized = false,
}: VectorCodeControl) {
return (
<Inputs>
<input
type="range"
min={isNormalized ? -1 : -Infinity}
max={isNormalized ? 1 : Infinity}
step={0.01}
min={isNormalized ? -1 : min}
max={isNormalized ? 1 : max}
step={step}
value={value[0]}
onChange={(e) =>
state.send('CHANGED_CODE_CONTROL', {
@ -67,9 +74,9 @@ function VectorControl({ id, value, isNormalized }: VectorCodeControl) {
/>
<input
type="number"
min={isNormalized ? -1 : -Infinity}
max={isNormalized ? 1 : Infinity}
step={0.01}
min={isNormalized ? -1 : min}
max={isNormalized ? 1 : max}
step={step}
value={value[0]}
onChange={(e) =>
state.send('CHANGED_CODE_CONTROL', {
@ -79,9 +86,9 @@ function VectorControl({ id, value, isNormalized }: VectorCodeControl) {
/>
<input
type="range"
min={isNormalized ? -1 : -Infinity}
max={isNormalized ? 1 : Infinity}
step={0.01}
min={isNormalized ? -1 : min}
max={isNormalized ? 1 : max}
step={step}
value={value[1]}
onChange={(e) =>
state.send('CHANGED_CODE_CONTROL', {
@ -91,9 +98,9 @@ function VectorControl({ id, value, isNormalized }: VectorCodeControl) {
/>
<input
type="number"
min={isNormalized ? -1 : -Infinity}
max={isNormalized ? 1 : Infinity}
step={0.01}
min={isNormalized ? -1 : min}
max={isNormalized ? 1 : max}
step={step}
value={value[1]}
onChange={(e) =>
state.send('CHANGED_CODE_CONTROL', {

View file

@ -17,7 +17,12 @@ export default function ControlPanel(): JSX.Element {
const isOpen = useSelector((s) => Object.keys(s.data.codeControls).length > 0)
return (
<Panel.Root data-bp-desktop ref={rContainer} isOpen={isOpen}>
<Panel.Root
data-bp-desktop
ref={rContainer}
isOpen={isOpen}
variant="controls"
>
{isOpen ? (
<Panel.Layout>
<Panel.Header>

View file

@ -7,6 +7,7 @@ import StylePanel from './style-panel/style-panel'
import styled from 'styles'
import PagePanel from './page-panel/page-panel'
import CodePanel from './code-panel/code-panel'
import ControlsPanel from './controls-panel/controls-panel'
export default function Editor(): JSX.Element {
useKeyboardEvents()
@ -16,6 +17,7 @@ export default function Editor(): JSX.Element {
<Layout>
<CodePanel />
<PagePanel />
<ControlsPanel />
<Spacer />
<StylePanel />
<Canvas />

View file

@ -18,6 +18,10 @@ export const Root = styled('div', {
},
variant: {
code: {},
controls: {
position: 'absolute',
right: 156,
},
},
isOpen: {
true: {},

View file

@ -1,9 +1,7 @@
module.exports = {
roots: ['<rootDir>'],
testEnvironment: 'jsdom',
moduleFileExtensions: ['ts', 'tsx', 'mjs', 'js', 'json', 'jsx'],
testPathIgnorePatterns: ['<rootDir>[/\\\\](node_modules|.next)[/\\\\]'],
transformIgnorePatterns: ['node_modules/(?!(browser-fs-access)/)'],
testPathIgnorePatterns: ['node_modules', '.next'],
transformIgnorePatterns: ['node_modules/(?!(sucrase|browser-fs-access)/)'],
transform: {
'^.+\\.(ts|tsx|mjs)$': 'babel-jest',
},

View file

@ -8,12 +8,12 @@
"dev": "next dev",
"format": "prettier --write .",
"lint": "eslint . --ext ts --ext tsx --ext js",
"scripts": "node scripts/type-gen && yarn format",
"scripts": "node scripts/type-gen && prettier --write './components/code-panel/types-import.ts'",
"start": "next start",
"test-all": "yarn lint && yarn type-check && yarn test",
"test:update": "jest --updateSnapshot",
"test:watch": "jest --watchAll",
"test": "jest",
"test": "jest --watchAll=false",
"type-check": "tsc --pretty --noEmit"
},
"husky": {
@ -53,7 +53,7 @@
"idb-keyval": "^5.0.6",
"ismobilejs": "^1.1.1",
"monaco-editor": "^0.25.2",
"next": "latest",
"next": "^11.0.1",
"next-auth": "^3.27.0",
"next-pwa": "^5.2.21",
"perfect-freehand": "^0.4.9",
@ -66,8 +66,7 @@
"uuid": "^8.3.2"
},
"devDependencies": {
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^13.1.9",
"@babel/core": "^7.14.6",
"@types/jest": "^26.0.23",
"@types/node": "^14.14.25",
"@types/react": "^17.0.1",
@ -80,7 +79,8 @@
"eslint-plugin-react": "^7.19.0",
"husky": "^4.2.3",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.0.4",
"jest": "^27.0.5",
"jest-esm-transformer": "^1.0.0",
"jest-watch-typeahead": "^0.6.1",
"lint-staged": "^10.0.10",
"prettier": "^2.3.1",

View file

@ -1,52 +1,36 @@
// @ts-check
/*
Type gen script
This script will generate TypeScript content for the code editor. It inlines
the content of several files into one large string which can be passed to the
Monaco editor as an extraLib.
This script will generate TypeScript declarations for the code editor. It reads
the global types, as well as all of the code classes, and writes them into a
single file as a string. This string is fed into the Monaco editor as an extraLib.
Important notes:
- Files must include the "Start Copy Here" comment indicated below.
- This comment must be placed BELOW any import statements.
Run the script with `yarn scripts`.
*/
const fs = require('fs/promises')
const root = process.cwd()
async function inlineFileContents(path) {
console.log(`📄 Inlining contents of ${path}`)
const text = await fs.readFile(`${root}${path}`, 'utf-8')
return text
.match(
/\/\* ----------------- Start Copy Here ---------------- \*\/(.|\n)*$/g
)[0]
.replaceAll('/* ----------------- Start Copy Here ---------------- */', '')
.replaceAll('export default', '')
.replaceAll('export ', '')
}
async function copyTypesToFile() {
const types = await fs.readFile(__dirname + '/../types.ts', 'utf8')
const codeIndex = await fs.readFile(
__dirname + '/../state/code/index.ts',
'utf8'
)
const codeDot = await fs.readFile(__dirname + '/../state/code/dot.ts', 'utf8')
const codeEllipse = await fs.readFile(
__dirname + '/../state/code/ellipse.ts',
'utf8'
)
const codeLine = await fs.readFile(
__dirname + '/../state/code/line.ts',
'utf8'
)
const codePolyline = await fs.readFile(
__dirname + '/../state/code/polyline.ts',
'utf8'
)
const codeRay = await fs.readFile(__dirname + '/../state/code/ray.ts', 'utf8')
const codeArrow = await fs.readFile(
__dirname + '/../state/code/arrow.ts',
'utf8'
)
const codeDraw = await fs.readFile(
__dirname + '/../state/code/draw.ts',
'utf8'
)
const codeRectangle = await fs.readFile(
__dirname + '/../state/code/rectangle.ts',
'utf8'
)
const codeVector = await fs.readFile(__dirname + '/../utils/vec.ts', 'utf8')
const codeUtils = await fs.readFile(
__dirname + '/../state/code/utils.ts',
'utf8'
)
console.log('⚙️ Generating types-import.ts')
const content =
`
@ -59,28 +43,42 @@ export default {` +
name: "types.ts",
content: \`
${types}
${codeIndex.match(/export default(.|\n)*$/g)[0]}
${codeDot.match(/\/\*\*(.|\n)*$/g)[0]}
${codeEllipse.match(/\/\*\*(.|\n)*$/g)[0]}
${codeLine.match(/\/\*\*(.|\n)*$/g)[0]}
${codePolyline.match(/\/\*\*(.|\n)*$/g)[0]}
${codeRay.match(/\/\*\*(.|\n)*$/g)[0]}
${codeRectangle.match(/\/\*\*(.|\n)*$/g)[0]}
${codeArrow.match(/\/\*\*(.|\n)*$/g)[0]}
${codeDraw.match(/\/\*\*(.|\n)*$/g)[0]}
${codeUtils.match(/\/\*\*(.|\n)*$/g)[0]}
${codeVector}
\`
}`
.replaceAll('export default', '')
.replaceAll('export ', '')
${await inlineFileContents('/types.ts')}
${await inlineFileContents('/utils/vec.ts')}
${await inlineFileContents('/state/code/utils.ts')}
${await inlineFileContents('/state/code/index.ts')}
${await inlineFileContents('/state/code/dot.ts')}
${await inlineFileContents('/state/code/ellipse.ts')}
${await inlineFileContents('/state/code/line.ts')}
${await inlineFileContents('/state/code/polyline.ts')}
${await inlineFileContents('/state/code/ray.ts')}
${await inlineFileContents('/state/code/arrow.ts')}
${await inlineFileContents('/state/code/draw.ts')}
${await inlineFileContents('/state/code/rectangle.ts')}
${await inlineFileContents('/state/code/control.ts')}
declare const controls: {[key:string]: any} = {}
\`}`
await fs.writeFile(
__dirname + '/../components/code-panel/types-import.ts',
content
)
console.log('✅ Process complete')
}
// Kickoff

View file

@ -5,9 +5,8 @@ import { defaultStyle } from 'state/shape-styles'
import { getShapeUtils } from 'state/shape-utils'
import Vec from 'utils/vec'
/**
* ## Draw
*/
/* ----------------- Start Copy Here ---------------- */
export default class Arrow extends CodeShape<ArrowShape> {
constructor(
props = {} as ShapeProps<ArrowShape> & { start: number[]; end: number[] }

View file

@ -10,6 +10,8 @@ export const controls: Record<string, any> = {}
export const codeControls = new Set<CodeControl>([])
/* ----------------- Start Copy Here ---------------- */
export class Control<T extends CodeControl> {
control: T
@ -29,14 +31,25 @@ export class Control<T extends CodeControl> {
codeControls.delete(this.control)
delete controls[this.control.label]
}
get value(): T['value'] {
return this.control.value
}
set value(value: T['value']) {
this.control.value = value
}
}
type ControlProps<T extends CodeControl> = Omit<Partial<T>, 'id' | 'type'>
export class NumberControl extends Control<NumberCodeControl> {
constructor(options: Omit<NumberCodeControl, 'id' | 'type'>) {
const { value = 0, step = 1 } = options
constructor(options: ControlProps<NumberCodeControl>) {
const { label = 'Number', value = 0, step = 1 } = options
super({
type: ControlType.Number,
...options,
label,
value,
step,
})
@ -44,11 +57,12 @@ export class NumberControl extends Control<NumberCodeControl> {
}
export class VectorControl extends Control<VectorCodeControl> {
constructor(options: Omit<VectorCodeControl, 'id' | 'type'>) {
const { value = [0, 0], isNormalized = false } = options
constructor(options: ControlProps<VectorCodeControl>) {
const { label = 'Vector', value = [0, 0], isNormalized = false } = options
super({
type: ControlType.Vector,
...options,
label,
value,
isNormalized,
})

View file

@ -3,9 +3,8 @@ import { uniqueId } from 'utils'
import { DotShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
/**
* ## Dot
*/
/* ----------------- Start Copy Here ---------------- */
export default class Dot extends CodeShape<DotShape> {
constructor(props = {} as ShapeProps<DotShape>) {
super({

View file

@ -3,9 +3,8 @@ import { uniqueId } from 'utils'
import { DrawShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
/**
* ## Draw
*/
/* ----------------- Start Copy Here ---------------- */
export default class Draw extends CodeShape<DrawShape> {
constructor(props = {} as ShapeProps<DrawShape>) {
super({
@ -13,8 +12,8 @@ export default class Draw extends CodeShape<DrawShape> {
seed: Math.random(),
type: ShapeType.Draw,
isGenerated: false,
parentId: (window as any).currentPageId,
name: 'Draw',
parentId: 'page1',
childIndex: 0,
point: [0, 0],
points: [],

View file

@ -3,9 +3,8 @@ import { uniqueId } from 'utils'
import { EllipseShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
/**
* ## Ellipse
*/
/* ----------------- Start Copy Here ---------------- */
export default class Ellipse extends CodeShape<EllipseShape> {
constructor(props = {} as ShapeProps<EllipseShape>) {
super({

View file

@ -44,13 +44,13 @@ const baseScope = {
* collected shapes as an array.
* @param code
*/
export function generateFromCode(
export async function generateFromCode(
data: Data,
code: string
): {
): Promise<{
shapes: Shape[]
controls: CodeControl[]
} {
}> {
codeControls.clear()
codeShapes.clear()
;(window as any).isUpdatingCode = false
@ -59,7 +59,9 @@ export function generateFromCode(
const { currentPageId } = data
const scope = { ...baseScope, controls, currentPageId }
const transformed = transform(code, { transforms: ['typescript'] }).code
const transformed = transform(code, {
transforms: ['typescript'],
}).code
new Function(...Object.keys(scope), `${transformed}`)(...Object.values(scope))
@ -87,34 +89,50 @@ export function generateFromCode(
* collected shapes as an array.
* @param code
*/
export function updateFromCode(
export async function updateFromCode(
data: Data,
code: string
): {
): Promise<{
shapes: Shape[]
} {
}> {
codeShapes.clear()
;(window as any).isUpdatingCode = true
;(window as any).currentPageId = data.currentPageId
const { currentPageId } = data
const newControls = Object.fromEntries(
Object.entries(data.codeControls).map(([_, control]) => [
control.label,
control.value,
])
)
const scope = {
...baseScope,
currentPageId,
controls: Object.fromEntries(
Object.entries(controls).map(([_, control]) => [
control.label,
control.value,
])
),
controls: newControls,
}
new Function(...Object.keys(scope), `${code}`)(...Object.values(scope))
const startingChildIndex =
getShapes(data)
.filter((shape) => shape.parentId === data.currentPageId)
.sort((a, b) => a.childIndex - b.childIndex)[0]?.childIndex || 1
const generatedShapes = Array.from(codeShapes.values()).map(
(instance) => instance.shape
)
const transformed = transform(code, {
transforms: ['typescript'],
}).code
new Function(...Object.keys(scope), `${transformed}`)(...Object.values(scope))
const generatedShapes = Array.from(codeShapes.values())
.sort((a, b) => a.shape.childIndex - b.shape.childIndex)
.map((instance, i) => ({
...instance.shape,
isGenerated: true,
parentId: getPage(data).id,
childIndex: startingChildIndex + i,
}))
return { shapes: generatedShapes }
}

View file

@ -21,6 +21,9 @@ function getOrderedShapes() {
* A base class for code shapes. Note that creating a shape adds it to the
* shape map, while deleting it removes it from the collected shapes set
*/
/* ----------------- Start Copy Here ---------------- */
export default class CodeShape<T extends Shape> {
private _shape: Mutable<T>
private utils: ShapeUtility<T>

View file

@ -3,9 +3,8 @@ import { uniqueId } from 'utils'
import { LineShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
/**
* ## Line
*/
/* ----------------- Start Copy Here ---------------- */
export default class Line extends CodeShape<LineShape> {
constructor(props = {} as ShapeProps<LineShape>) {
super({

View file

@ -3,9 +3,8 @@ import { uniqueId } from 'utils'
import { PolylineShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
/**
* ## Polyline
*/
/* ----------------- Start Copy Here ---------------- */
export default class Polyline extends CodeShape<PolylineShape> {
constructor(props = {} as ShapeProps<PolylineShape>) {
super({
@ -22,8 +21,11 @@ export default class Polyline extends CodeShape<PolylineShape> {
isAspectRatioLocked: false,
isLocked: false,
isHidden: false,
style: defaultStyle,
...props,
style: {
...defaultStyle,
...props.style,
},
})
}

View file

@ -3,9 +3,8 @@ import { uniqueId } from 'utils'
import { RayShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
/**
* ## Ray
*/
/* ----------------- Start Copy Here ---------------- */
export default class Ray extends CodeShape<RayShape> {
constructor(props = {} as ShapeProps<RayShape>) {
super({

View file

@ -3,9 +3,8 @@ import { uniqueId } from 'utils'
import { RectangleShape, ShapeProps, ShapeType } from 'types'
import { defaultStyle } from 'state/shape-styles'
/**
* ## Rectangle
*/
/* ----------------- Start Copy Here ---------------- */
export default class Rectangle extends CodeShape<RectangleShape> {
constructor(props = {} as ShapeProps<RectangleShape>) {
super({
@ -24,7 +23,10 @@ export default class Rectangle extends CodeShape<RectangleShape> {
isLocked: false,
isHidden: false,
...props,
style: { ...defaultStyle, ...props.style },
style: {
...defaultStyle,
...props.style,
},
})
}

View file

@ -1,9 +1,8 @@
import { Bounds } from 'types'
import vec from 'utils/vec'
/**
* ## Utils
*/
/* ----------------- Start Copy Here ---------------- */
export default class Utils {
/**
* Linear interpolation betwen two numbers.

View file

@ -1,3 +1,5 @@
/* ----------------- Start Copy Here ---------------- */
export interface VectorOptions {
x: number
y: number
@ -8,9 +10,6 @@ export interface Point {
y: number
}
/**
* ## Vector
*/
export default class Vector {
x = 0
y = 0

View file

@ -268,11 +268,11 @@ const state = createState({
do: ['setCodeControls', 'setGeneratedShapes'],
},
UNDO: {
unless: 'isInSession',
unless: ['isReadOnly', 'isInSession'],
do: 'undo',
},
REDO: {
unless: 'isInSession',
unless: ['isReadOnly', 'isInSession'],
do: 'redo',
},
SAVED: {
@ -1763,12 +1763,10 @@ const state = createState({
setSelectedIds(data, [])
try {
const { shapes } = updateFromCode(
updateFromCode(
data,
data.document.code[data.currentCodeFileId].code
)
commands.generate(data, shapes)
).then(({ shapes }) => commands.generate(data, shapes))
} catch (e) {
console.error(e)
}

View file

@ -57,6 +57,8 @@ export interface PageState {
}
}
/* ----------------- Start Copy Here ---------------- */
export enum ShapeType {
Dot = 'dot',
Ellipse = 'ellipse',
@ -383,17 +385,20 @@ export interface BaseCodeControl {
export interface NumberCodeControl extends BaseCodeControl {
type: ControlType.Number
value: number
min?: number
max?: number
value: number
step: number
step?: number
format?: (value: number) => number
}
export interface VectorCodeControl extends BaseCodeControl {
type: ControlType.Vector
value: number[]
isNormalized: boolean
min?: number
max?: number
step?: number
isNormalized?: boolean
format?: (value: number[]) => number[]
}

View file

@ -1,5 +1,7 @@
// A big collection of vector utilities. Collected into a class to improve logging / packaging.
/* ----------------- Start Copy Here ---------------- */
export default class Vec {
/**
* Clamp a value into a range.

106
yarn.lock
View file

@ -21,7 +21,7 @@
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08"
integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==
"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.14.6", "@babel/core@^7.4.4", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.6.tgz#e0814ec1a950032ff16c13a2721de39a8416fcab"
integrity sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==
@ -637,7 +637,7 @@
"@babel/helper-plugin-utils" "^7.14.5"
babel-plugin-dynamic-import-node "^2.3.3"
"@babel/plugin-transform-modules-commonjs@^7.14.5":
"@babel/plugin-transform-modules-commonjs@^7.14.5", "@babel/plugin-transform-modules-commonjs@^7.4.4":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz#7aaee0ea98283de94da98b28f8c35701429dad97"
integrity sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==
@ -1238,25 +1238,25 @@
require_optional "^1.0.1"
typeorm "^0.2.30"
"@next/env@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@next/env/-/env-11.0.0.tgz#bdd306a45e88ba3e4e7a36aa91806f6486bb61d0"
integrity sha512-VKpmDvTYeCpEQjREg3J4pCmVs/QjEzoLmkM8shGFK6e9AmFd0G9QXOL8HGA8qKhy/XmNb7dHeMqrcMiBua4OgA==
"@next/env@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@next/env/-/env-11.0.1.tgz#6dc96ac76f1663ab747340e907e8933f190cc8fd"
integrity sha512-yZfKh2U6R9tEYyNUrs2V3SBvCMufkJ07xMH5uWy8wqcl5gAXoEw6A/1LDqwX3j7pUutF9d1ZxpdGDA3Uag+aQQ==
"@next/eslint-plugin-next@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-11.0.0.tgz#e6fb93a00bdaba371904f2b2698b184e6278d369"
integrity sha512-fPZ0904yY1box6bRpR9rJqIkNxJdvzzxH7doXS+cdjyBAdptMR7wj3mcx1hEikBHzWduU8BOXBvRg2hWc09YDQ==
"@next/polyfill-module@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-11.0.0.tgz#cb2f46b323bbe7f8a337ccd80fb82314d4039403"
integrity sha512-gydtFzRqsT549U8+sY8382I/f4HFcelD8gdUGnAofQJa/jEU1jkxmjCHC8tmEiyeMLidl7iDZgchfSCpmMzzUg==
"@next/polyfill-module@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-11.0.1.tgz#ca2a110c1c44672cbcff6c2b983f0c0549d87291"
integrity sha512-Cjs7rrKCg4CF4Jhri8PCKlBXhszTfOQNl9AjzdNy4K5jXFyxyoSzuX2rK4IuoyE+yGp5A3XJCBEmOQ4xbUp9Mg==
"@next/react-dev-overlay@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-11.0.0.tgz#6befb4d00d952551db1b3909023074eb5778ac5d"
integrity sha512-q+Wp+eStEMThe77zxdeJ/nbuODkHR6P+/dfUqYXZSqbLf6x5c5xwLBauwwVbkCYFZpAlDuL8Jk8QSAH1OsqC2w==
"@next/react-dev-overlay@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-11.0.1.tgz#3c481e83347255abd466dcf7e59ac8a79a0d7fd6"
integrity sha512-lvUjMVpLsgzADs9Q8wtC5LNqvfdN+M0BDMSrqr04EDWAyyX0vURHC9hkvLbyEYWyh+WW32pwjKBXdkMnJhoqMg==
dependencies:
"@babel/code-frame" "7.12.11"
anser "1.4.9"
@ -1270,10 +1270,10 @@
stacktrace-parser "0.1.10"
strip-ansi "6.0.0"
"@next/react-refresh-utils@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-11.0.0.tgz#cb671723c50b904eaa44b4b45c0845476ecd8825"
integrity sha512-hi5eY+KBn4QGtUv7VL2OptdM33fI2hxhd7+omOFmAK+S0hDWhg1uqHqqGJk0W1IfqlWEzzL10WvTJDPRAtDugQ==
"@next/react-refresh-utils@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-11.0.1.tgz#a7509f22b6f70c13101a26573afd295295f1c020"
integrity sha512-K347DM6Z7gBSE+TfUaTTceWvbj0B6iNAsFZXbFZOlfg3uyz2sbKpzPYYFocCc27yjLaS8OfR8DEdS2mZXi8Saw==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@ -1932,45 +1932,11 @@
ejs "^2.6.1"
magic-string "^0.25.0"
"@testing-library/dom@^7.28.1":
version "7.31.2"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.31.2.tgz#df361db38f5212b88555068ab8119f5d841a8c4a"
integrity sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/runtime" "^7.12.5"
"@types/aria-query" "^4.2.0"
aria-query "^4.2.2"
chalk "^4.1.0"
dom-accessibility-api "^0.5.6"
lz-string "^1.4.4"
pretty-format "^26.6.2"
"@testing-library/react@^11.2.5":
version "11.2.7"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.7.tgz#b29e2e95c6765c815786c0bc1d5aed9cb2bf7818"
integrity sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==
dependencies:
"@babel/runtime" "^7.12.5"
"@testing-library/dom" "^7.28.1"
"@testing-library/user-event@^13.1.9":
version "13.1.9"
resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.1.9.tgz#29e49a42659ac3c1023565ff56819e0153a82e99"
integrity sha512-NZr0zL2TMOs2qk+dNlqrAdbaRW5dAmYwd1yuQ4r7HpkVEOj0MWuUjDWwKhcLd/atdBy8ZSMHSKp+kXSQe47ezg==
dependencies:
"@babel/runtime" "^7.12.5"
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
"@types/aria-query@^4.2.0":
version "4.2.1"
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.1.tgz#78b5433344e2f92e8b306c06a5622c50c245bf6b"
integrity sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg==
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
version "7.1.14"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.14.tgz#faaeefc4185ec71c389f4501ee5ec84b170cc402"
@ -3422,11 +3388,6 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
dom-accessibility-api@^0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.6.tgz#3f5d43b52c7a3bd68b5fb63fa47b4e4c1fdf65a9"
integrity sha512-DplGLZd8L1lN64jlT27N9TVSESFR5STaEJvX+thCby7fuCHonfPpAlodYc3vuUYbDuDec5w8AMP7oCM5TWFsqw==
domain-browser@4.19.0:
version "4.19.0"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1"
@ -4906,6 +4867,14 @@ jest-environment-node@^27.0.5:
jest-mock "^27.0.3"
jest-util "^27.0.2"
jest-esm-transformer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/jest-esm-transformer/-/jest-esm-transformer-1.0.0.tgz#b6c58f496aa48194f96361a52f5c578fd2209726"
integrity sha512-FoPgeMMwy1/CEsc8tBI41i83CEO3x85RJuZi5iAMmWoARXhfgk6Jd7y+4d+z+HCkTKNVDvSWKGRhwjzU9PUbrw==
dependencies:
"@babel/core" "^7.4.4"
"@babel/plugin-transform-modules-commonjs" "^7.4.4"
jest-get-type@^26.3.0:
version "26.3.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0"
@ -5210,7 +5179,7 @@ jest-worker@^27.0.2:
merge-stream "^2.0.0"
supports-color "^8.0.0"
jest@^27.0.4:
jest@^27.0.5:
version "27.0.5"
resolved "https://registry.yarnpkg.com/jest/-/jest-27.0.5.tgz#141825e105514a834cc8d6e44670509e8d74c5f2"
integrity sha512-4NlVMS29gE+JOZvgmSAsz3eOjkSsHqjTajlIsah/4MVSmKvf3zFP/TvgcLoWe2UVHiE9KF741sReqhF0p4mqbQ==
@ -5626,11 +5595,6 @@ lru_map@^0.3.3:
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=
lz-string@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=
magic-string@^0.25.0, magic-string@^0.25.7:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
@ -5814,17 +5778,17 @@ next-pwa@^5.2.21:
workbox-webpack-plugin "^6.1.5"
workbox-window "^6.1.5"
next@latest:
version "11.0.0"
resolved "https://registry.yarnpkg.com/next/-/next-11.0.0.tgz#866b833f192f5a94ddb3267d5cc0f4b0ce405ac7"
integrity sha512-1OA0ccCTwVtdLats/1v7ReiBVx+Akya0UVhHo9IBr8ZkpDI3/SGNcaruJBp5agy8ROF97VDKkZamoUXxRB9NUA==
next@^11.0.1:
version "11.0.1"
resolved "https://registry.yarnpkg.com/next/-/next-11.0.1.tgz#b8e3914d153aaf7143cb98c09bcd3c8230eeb17a"
integrity sha512-yR7be7asNbvpVNpi6xxEg28wZ7Gqmj1nOt0sABH9qORmF3+pms2KZ7Cng33oK5nqPIzEEFJD0pp2PCe3/ueMIg==
dependencies:
"@babel/runtime" "7.12.5"
"@hapi/accept" "5.0.2"
"@next/env" "11.0.0"
"@next/polyfill-module" "11.0.0"
"@next/react-dev-overlay" "11.0.0"
"@next/react-refresh-utils" "11.0.0"
"@next/env" "11.0.1"
"@next/polyfill-module" "11.0.1"
"@next/react-dev-overlay" "11.0.1"
"@next/react-refresh-utils" "11.0.1"
assert "2.0.0"
ast-types "0.13.2"
browserify-zlib "0.2.0"