or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aggregation.mdbasic-math.mdgeneric-math.mdindex.mdlogical.mdprojection.mdvalue-control.md

value-control.mddocs/

0

# Value Control Functions

1

2

Utilities for clamping values within bounds and controlling numerical precision with configurable rounding methods. These functions provide fine-grained control over numeric values with reactive behavior.

3

4

## Capabilities

5

6

### useClamp

7

8

Reactively clamps a value between minimum and maximum bounds. Returns different ref types based on the input type to optimize for readonly vs writable scenarios.

9

10

```typescript { .api }

11

/**

12

* Clamp a readonly value between min and max bounds

13

* @param value - Readonly reactive number or getter

14

* @param min - Minimum bound (reactive)

15

* @param max - Maximum bound (reactive)

16

* @returns ComputedRef with clamped value

17

*/

18

function useClamp(

19

value: ReadonlyRefOrGetter<number>,

20

min: MaybeRefOrGetter<number>,

21

max: MaybeRefOrGetter<number>

22

): ComputedRef<number>;

23

24

/**

25

* Clamp a writable value between min and max bounds

26

* @param value - Writable reactive number

27

* @param min - Minimum bound (reactive)

28

* @param max - Maximum bound (reactive)

29

* @returns Writable Ref that clamps on both get and set

30

*/

31

function useClamp(

32

value: MaybeRefOrGetter<number>,

33

min: MaybeRefOrGetter<number>,

34

max: MaybeRefOrGetter<number>

35

): Ref<number>;

36

```

37

38

**Usage Examples:**

39

40

```typescript

41

import { ref } from "vue";

42

import { useClamp } from "@vueuse/math";

43

44

// Basic clamping with writable ref

45

const value = ref(15);

46

const clamped = useClamp(value, 0, 10);

47

48

console.log(clamped.value); // 10 (clamped from 15)

49

50

// Setting the clamped value also clamps

51

clamped.value = 20;

52

console.log(clamped.value); // 10 (clamped)

53

console.log(value.value); // 10 (original ref is updated)

54

55

clamped.value = 5;

56

console.log(clamped.value); // 5 (within bounds)

57

58

// Reactive bounds

59

const minBound = ref(0);

60

const maxBound = ref(100);

61

const input = ref(150);

62

const boundedValue = useClamp(input, minBound, maxBound);

63

64

console.log(boundedValue.value); // 100

65

66

// Changing bounds affects the result

67

maxBound.value = 200;

68

console.log(boundedValue.value); // 150 (now within new bounds)

69

70

// Readonly usage (computed or getter)

71

const readonlyValue = useClamp(() => Math.random() * 200, 50, 100);

72

console.log(readonlyValue.value); // Between 50-100

73

```

74

75

### usePrecision

76

77

Reactively sets the precision of a number using configurable rounding methods.

78

79

```typescript { .api }

80

/**

81

* Set the precision of a number with configurable rounding

82

* @param value - The number to set precision for

83

* @param digits - Number of decimal digits to preserve

84

* @param options - Optional configuration for rounding method

85

* @returns ComputedRef containing the precision-controlled number

86

*/

87

function usePrecision(

88

value: MaybeRefOrGetter<number>,

89

digits: MaybeRefOrGetter<number>,

90

options?: MaybeRefOrGetter<UsePrecisionOptions>

91

): ComputedRef<number>;

92

93

/**

94

* Configuration options for precision control

95

*/

96

interface UsePrecisionOptions {

97

/**

98

* Method to use for rounding

99

* @default 'round'

100

*/

101

math?: 'floor' | 'ceil' | 'round';

102

}

103

```

104

105

**Usage Examples:**

106

107

```typescript

108

import { ref } from "vue";

109

import { usePrecision } from "@vueuse/math";

110

111

// Basic precision control

112

const value = ref(3.14159265);

113

const precise = usePrecision(value, 2);

114

115

console.log(precise.value); // 3.14

116

117

// Different rounding methods

118

const number = ref(3.7869);

119

120

const rounded = usePrecision(number, 2, { math: 'round' });

121

const floored = usePrecision(number, 2, { math: 'floor' });

122

const ceiled = usePrecision(number, 2, { math: 'ceil' });

123

124

console.log(rounded.value); // 3.79 (default rounding)

125

console.log(floored.value); // 3.78 (always round down)

126

console.log(ceiled.value); // 3.79 (always round up)

127

128

// Reactive precision

129

const price = ref(19.99567);

130

const decimalPlaces = ref(2);

131

const formattedPrice = usePrecision(price, decimalPlaces);

132

133

console.log(formattedPrice.value); // 20.00

134

135

decimalPlaces.value = 3;

136

console.log(formattedPrice.value); // 19.996

137

138

// Different rounding methods with negative numbers

139

const negative = ref(-2.456);

140

const roundedNeg = usePrecision(negative, 1, { math: 'round' });

141

const flooredNeg = usePrecision(negative, 1, { math: 'floor' });

142

const ceiledNeg = usePrecision(negative, 1, { math: 'ceil' });

143

144

console.log(roundedNeg.value); // -2.5

145

console.log(flooredNeg.value); // -2.5 (floor toward negative infinity)

146

console.log(ceiledNeg.value); // -2.4 (ceil toward positive infinity)

147

```

148

149

## Advanced Usage Patterns

150

151

### Dynamic Bounds and Precision

152

153

```typescript

154

import { ref, computed } from "vue";

155

import { useClamp, usePrecision } from "@vueuse/math";

156

157

// Create a controlled input with dynamic bounds and precision

158

const rawInput = ref(0);

159

const minValue = ref(0);

160

const maxValue = ref(100);

161

const precision = ref(1);

162

163

// Clamp first, then apply precision

164

const clampedInput = useClamp(rawInput, minValue, maxValue);

165

const preciseInput = usePrecision(clampedInput, precision);

166

167

// UI control that updates all values

168

const slider = computed({

169

get: () => preciseInput.value,

170

set: (val: number) => {

171

rawInput.value = val;

172

}

173

});

174

175

// Example usage

176

rawInput.value = 123.456789;

177

console.log(slider.value); // 100.0 (clamped to max, then precision applied)

178

179

maxValue.value = 150;

180

console.log(slider.value); // 123.5 (now within bounds, precision applied)

181

```

182

183

### Financial Calculations

184

185

```typescript

186

import { ref, computed } from "vue";

187

import { useClamp, usePrecision } from "@vueuse/math";

188

189

// Financial calculation with proper precision

190

const principal = ref(10000);

191

const interestRate = ref(0.05); // 5%

192

const years = ref(10);

193

194

// Ensure reasonable bounds for financial inputs

195

const clampedPrincipal = useClamp(principal, 0, 1000000);

196

const clampedRate = useClamp(interestRate, 0, 1); // 0-100%

197

const clampedYears = useClamp(years, 1, 50);

198

199

// Calculate compound interest

200

const futureValue = computed(() => {

201

const p = clampedPrincipal.value;

202

const r = clampedRate.value;

203

const t = clampedYears.value;

204

return p * Math.pow(1 + r, t);

205

});

206

207

// Format for display with proper precision

208

const formattedFutureValue = usePrecision(futureValue, 2);

209

210

console.log(formattedFutureValue.value); // 16288.95

211

212

// Interest calculation stays within bounds even with extreme inputs

213

principal.value = -5000; // Invalid negative

214

interestRate.value = 2.5; // Invalid > 100%

215

console.log(formattedFutureValue.value); // Still gives valid result due to clamping

216

```

217

218

### Animation Value Control

219

220

```typescript

221

import { ref, computed } from "vue";

222

import { useClamp, usePrecision } from "@vueuse/math";

223

224

// Animation progress control

225

const animationProgress = ref(0);

226

const duration = ref(1000); // ms

227

const currentTime = ref(0);

228

229

// Calculate normalized progress (0-1)

230

const rawProgress = computed(() => currentTime.value / duration.value);

231

const clampedProgress = useClamp(rawProgress, 0, 1);

232

const preciseProgress = usePrecision(clampedProgress, 3);

233

234

// Convert to percentage for display

235

const percentProgress = computed(() => preciseProgress.value * 100);

236

const displayPercent = usePrecision(percentProgress, 1);

237

238

// Simulate animation frames

239

function animate() {

240

currentTime.value += 16; // ~60fps

241

242

console.log(`Progress: ${displayPercent.value}%`);

243

244

if (preciseProgress.value < 1) {

245

requestAnimationFrame(animate);

246

}

247

}

248

249

animate();

250

```