This commit is contained in:
13
node_modules/@react-stately/utils/src/index.ts
generated
vendored
Normal file
13
node_modules/@react-stately/utils/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2020 Adobe. All rights reserved.
|
||||
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
||||
* OF ANY KIND, either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
export {useControlledState} from './useControlledState';
|
||||
export {clamp, snapValueToStep, toFixedNumber} from './number';
|
||||
62
node_modules/@react-stately/utils/src/number.ts
generated
vendored
Normal file
62
node_modules/@react-stately/utils/src/number.ts
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2020 Adobe. All rights reserved.
|
||||
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
||||
* OF ANY KIND, either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Takes a value and forces it to the closest min/max if it's outside. Also forces it to the closest valid step.
|
||||
*/
|
||||
export function clamp(value: number, min: number = -Infinity, max: number = Infinity): number {
|
||||
let newValue = Math.min(Math.max(value, min), max);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
export function roundToStepPrecision(value: number, step: number): number {
|
||||
let roundedValue = value;
|
||||
let stepString = step.toString();
|
||||
let pointIndex = stepString.indexOf('.');
|
||||
let precision = pointIndex >= 0 ? stepString.length - pointIndex : 0;
|
||||
if (precision > 0) {
|
||||
let pow = Math.pow(10, precision);
|
||||
roundedValue = Math.round(roundedValue * pow) / pow;
|
||||
}
|
||||
return roundedValue;
|
||||
}
|
||||
|
||||
export function snapValueToStep(value: number, min: number | undefined, max: number | undefined, step: number): number {
|
||||
min = Number(min);
|
||||
max = Number(max);
|
||||
let remainder = ((value - (isNaN(min) ? 0 : min)) % step);
|
||||
let snappedValue = roundToStepPrecision(Math.abs(remainder) * 2 >= step
|
||||
? value + Math.sign(remainder) * (step - Math.abs(remainder))
|
||||
: value - remainder, step);
|
||||
|
||||
if (!isNaN(min)) {
|
||||
if (snappedValue < min) {
|
||||
snappedValue = min;
|
||||
} else if (!isNaN(max) && snappedValue > max) {
|
||||
snappedValue = min + Math.floor(roundToStepPrecision((max - min) / step, step)) * step;
|
||||
}
|
||||
} else if (!isNaN(max) && snappedValue > max) {
|
||||
snappedValue = Math.floor(roundToStepPrecision(max / step, step)) * step;
|
||||
}
|
||||
|
||||
// correct floating point behavior by rounding to step precision
|
||||
snappedValue = roundToStepPrecision(snappedValue, step);
|
||||
|
||||
return snappedValue;
|
||||
}
|
||||
|
||||
/* Takes a value and rounds off to the number of digits. */
|
||||
export function toFixedNumber(value: number, digits: number, base: number = 10): number {
|
||||
const pow = Math.pow(base, digits);
|
||||
|
||||
return Math.round(value * pow) / pow;
|
||||
}
|
||||
75
node_modules/@react-stately/utils/src/useControlledState.ts
generated
vendored
Normal file
75
node_modules/@react-stately/utils/src/useControlledState.ts
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2020 Adobe. All rights reserved.
|
||||
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
||||
* OF ANY KIND, either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
import {useCallback, useEffect, useRef, useState} from 'react';
|
||||
|
||||
export function useControlledState<T, C = T>(value: Exclude<T, undefined>, defaultValue: Exclude<T, undefined> | undefined, onChange?: (v: C, ...args: any[]) => void): [T, (value: T, ...args: any[]) => void];
|
||||
export function useControlledState<T, C = T>(value: Exclude<T, undefined> | undefined, defaultValue: Exclude<T, undefined>, onChange?: (v: C, ...args: any[]) => void): [T, (value: T, ...args: any[]) => void];
|
||||
export function useControlledState<T, C = T>(value: T, defaultValue: T, onChange?: (v: C, ...args: any[]) => void): [T, (value: T, ...args: any[]) => void] {
|
||||
let [stateValue, setStateValue] = useState(value || defaultValue);
|
||||
|
||||
let isControlledRef = useRef(value !== undefined);
|
||||
let isControlled = value !== undefined;
|
||||
useEffect(() => {
|
||||
let wasControlled = isControlledRef.current;
|
||||
if (wasControlled !== isControlled && process.env.NODE_ENV !== 'production') {
|
||||
console.warn(`WARN: A component changed from ${wasControlled ? 'controlled' : 'uncontrolled'} to ${isControlled ? 'controlled' : 'uncontrolled'}.`);
|
||||
}
|
||||
isControlledRef.current = isControlled;
|
||||
}, [isControlled]);
|
||||
|
||||
let currentValue = isControlled ? value : stateValue;
|
||||
let setValue = useCallback((value, ...args) => {
|
||||
let onChangeCaller = (value, ...onChangeArgs) => {
|
||||
if (onChange) {
|
||||
if (!Object.is(currentValue, value)) {
|
||||
onChange(value, ...onChangeArgs);
|
||||
}
|
||||
}
|
||||
if (!isControlled) {
|
||||
// If uncontrolled, mutate the currentValue local variable so that
|
||||
// calling setState multiple times with the same value only emits onChange once.
|
||||
// We do not use a ref for this because we specifically _do_ want the value to
|
||||
// reset every render, and assigning to a ref in render breaks aborted suspended renders.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
currentValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof value === 'function') {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.warn('We can not support a function callback. See Github Issues for details https://github.com/adobe/react-spectrum/issues/2320');
|
||||
}
|
||||
// this supports functional updates https://reactjs.org/docs/hooks-reference.html#functional-updates
|
||||
// when someone using useControlledState calls setControlledState(myFunc)
|
||||
// this will call our useState setState with a function as well which invokes myFunc and calls onChange with the value from myFunc
|
||||
// if we're in an uncontrolled state, then we also return the value of myFunc which to setState looks as though it was just called with myFunc from the beginning
|
||||
// otherwise we just return the controlled value, which won't cause a rerender because React knows to bail out when the value is the same
|
||||
let updateFunction = (oldValue, ...functionArgs) => {
|
||||
let interceptedValue = value(isControlled ? currentValue : oldValue, ...functionArgs);
|
||||
onChangeCaller(interceptedValue, ...args);
|
||||
if (!isControlled) {
|
||||
return interceptedValue;
|
||||
}
|
||||
return oldValue;
|
||||
};
|
||||
setStateValue(updateFunction);
|
||||
} else {
|
||||
if (!isControlled) {
|
||||
setStateValue(value);
|
||||
}
|
||||
onChangeCaller(value, ...args);
|
||||
}
|
||||
}, [isControlled, currentValue, onChange]);
|
||||
|
||||
return [currentValue, setValue];
|
||||
}
|
||||
Reference in New Issue
Block a user