@hanzo/ui 4.3.7 → 4.4.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "4.3.7",
3
+ "version": "4.4.0",
4
4
  "description": "Library that contains shared UI primitives, support for a common design system, and other boilerplate support.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -14,7 +14,6 @@
14
14
  "url": "git+https://github.com/hanzoai/react-sdk.git",
15
15
  "directory": "pkg/ui"
16
16
  },
17
- "types": "./declare.d.ts",
18
17
  "keywords": [
19
18
  "components",
20
19
  "ecommerce",
@@ -1,4 +1,3 @@
1
- // @ts-nocheck
2
1
  'use client'
3
2
  import * as React from "react"
4
3
  import * as LabelPrimitive from "@radix-ui/react-label"
@@ -7,7 +6,7 @@ import { Slot } from "@radix-ui/react-slot"
7
6
  import {
8
7
  Controller,
9
8
  type ControllerProps,
10
- FieldPath,
9
+ type FieldPath,
11
10
  type FieldValues,
12
11
  FormProvider,
13
12
  useFormContext,
@@ -27,4 +27,22 @@ const TooltipContent = React.forwardRef<
27
27
  ))
28
28
  TooltipContent.displayName = TooltipPrimitive.Content.displayName
29
29
 
30
- export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
30
+ const TooltipWrapper: React.FC<{
31
+ text: string
32
+ tooltipClx?: string
33
+ } & React.PropsWithChildren> = ({
34
+ children,
35
+ text,
36
+ tooltipClx=''
37
+ }) => (
38
+ <Tooltip>
39
+ <TooltipTrigger asChild>
40
+ {children}
41
+ </TooltipTrigger>
42
+ <TooltipContent className={tooltipClx}>
43
+ {text}
44
+ </TooltipContent>
45
+ </Tooltip>
46
+ )
47
+
48
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, TooltipWrapper }
@@ -0,0 +1,119 @@
1
+ import Abbr, { type QuantityAbbrSymbol, ABBR_SYMBOLS_ARRAY } from './number-abbreviate'
2
+
3
+ interface FormatThreshold {
4
+ from: number
5
+ use: QuantityAbbrSymbol
6
+ }
7
+
8
+ const formatAndAbbreviateAsCurrency = (
9
+ n: number | null,
10
+ thresholds: FormatThreshold[] = [{
11
+ from: 1000000000,
12
+ use: 'M'
13
+ }],
14
+ /**
15
+ * Chars that will be added by ui if the number is rounded.
16
+ * For example, if the desired output for 10.15 is "~10.1",
17
+ * the tilda counts as 1 char.
18
+ */
19
+ roundingAdds: number = 1,
20
+ maxDecimal: number = 2
21
+ ): {
22
+ full: string
23
+ result: string
24
+ change: 'rounded' | 'none' | 'abbr' | 'empty'
25
+ } => {
26
+ if (n === null) {
27
+ return {
28
+ full: '',
29
+ result: '',
30
+ change: 'empty'
31
+ }
32
+ }
33
+
34
+ const usdFormatter = Intl.NumberFormat('en-US', {
35
+ style: 'currency',
36
+ currency: 'USD',
37
+ minimumFractionDigits: 0
38
+ })
39
+ const formatted = usdFormatter.format(n)
40
+
41
+ if (n < thresholds[0].from) {
42
+ return {
43
+ full: formatted,
44
+ result: formatted,
45
+ change: 'none'
46
+ }
47
+ }
48
+
49
+ // Get operative FormatThreshold pair...
50
+ let threshold: FormatThreshold
51
+ for (
52
+ let i = 0, threshold = thresholds[0];
53
+ i < thresholds.length, n >= thresholds[i].from;
54
+ i++
55
+ ) {}
56
+
57
+ // Build up units array to all units
58
+ // up to threshold.use
59
+ const units: QuantityAbbrSymbol[] = []
60
+ for (let i = 0; i < ABBR_SYMBOLS_ARRAY.length; i++) {
61
+ const current = ABBR_SYMBOLS_ARRAY[i]
62
+ units.push(current)
63
+ if (current === threshold!.use) {
64
+ break
65
+ }
66
+ }
67
+
68
+ const abbreviator = new Abbr(units)
69
+
70
+ // Use thresholdFrom as a guide to how many chars are available
71
+ // first digit + comma = 2
72
+ // Possible trailing cents: '.xx'.length = 3
73
+ // 3 - 2 = 1
74
+ const charsAvail = usdFormatter.format(threshold!.from).length + 1
75
+ const abbr = abbreviator.abbreviate(n, charsAvail) // arbitrary, but good approx
76
+ const numStr = abbr.slice(0, -1)
77
+ const abbreviation = abbr.slice(-1)
78
+ const numerical = parseFloat(numStr)
79
+
80
+ const integral = Math.floor(numerical)
81
+ const integralString = usdFormatter.format(integral)
82
+ const commas = integralString.split(',').length - 1
83
+
84
+ // minus abbr, dec point, dollar sign, and roundingAdds / tilda,
85
+ // (1 + 1 + 1 + roundingAdds)
86
+ // ("precision" does NOT include the decimal point itself,
87
+ // so we have to explicitly factor it in.)
88
+ const roundedString = numerical.toPrecision(charsAvail - commas - (3 + roundingAdds))
89
+ // remove trailing zeros, if any
90
+ const roundedNumerical = parseFloat(roundedString)
91
+ const roundedIntegral = Math.trunc(roundedNumerical)
92
+ const roundedIntegralString = usdFormatter.format(roundedIntegral)
93
+
94
+ let decimalPortion = roundedNumerical - roundedIntegral
95
+ let result
96
+ if (decimalPortion !== 0) {
97
+ // remove trailing zeros if any
98
+ decimalPortion = parseFloat(decimalPortion.toFixed(maxDecimal))
99
+ const decimalPortionString = decimalPortion.toString()
100
+ const afterDecimalString = decimalPortionString.slice(decimalPortionString.indexOf('.') + 1)
101
+ result = roundedIntegralString + '.' + afterDecimalString + abbreviation
102
+ }
103
+ else {
104
+ result = roundedIntegralString + abbreviation
105
+ }
106
+ // Did we lose any precision?
107
+ const rounded = (roundedIntegral + decimalPortion !== n)
108
+ return {
109
+ full: formatted,
110
+ result,
111
+ change: rounded ? 'rounded' : 'abbr'
112
+ }
113
+ }
114
+
115
+ export {
116
+ formatAndAbbreviateAsCurrency as default,
117
+ type FormatThreshold,
118
+ type QuantityAbbrSymbol
119
+ }
@@ -5,15 +5,15 @@ const abbr = new Abbr(['K', 'M', 'B', 'T'])
5
5
  const formatToMaxChar = (
6
6
  n: number | null,
7
7
  maxChars: number,
8
- /**
9
- * Chars that will be added by ui if the number is rounded.
10
- * For example, if the desired output for 10.15 is "~10.1",
11
- * the tilda counts as 1 char.
12
- */
8
+ /**
9
+ * Chars that will be added by ui if the number is rounded.
10
+ * For example, if the desired output for 10.15 is "~10.1",
11
+ * the tilda counts as 1 char.
12
+ */
13
13
  roundingAdds: number = 1
14
14
  ): {
15
15
  result: string
16
- change: 'rounded' | 'none' | 'empty'
16
+ change: 'rounded' | 'none' | 'abbr' | 'empty'
17
17
  } => {
18
18
  if (n === null) {
19
19
  return {
@@ -40,10 +40,12 @@ const formatToMaxChar = (
40
40
  }
41
41
  }
42
42
  else {
43
+
43
44
  const str = abbr.abbreviate(n, maxChars)
44
45
  const numStr = str.slice(0, -1)
45
46
  const abbreviation = str.slice(-1)
46
47
  const numerical = parseFloat(numStr)
48
+
47
49
  // minus abbr, dec point, and roundingAdds / tilda,
48
50
  // (1 + 1 + roundingAdds)
49
51
  // ("precision" does NOT include the decimal point itself,
@@ -53,7 +55,7 @@ const formatToMaxChar = (
53
55
  const roundedNumerical = parseFloat(roundedString)
54
56
  return {
55
57
  result: roundedNumerical.toString() + abbreviation,
56
- change: 'rounded'
58
+ change: roundedNumerical === numerical ? 'abbr' : 'rounded'
57
59
  }
58
60
  }
59
61
  }
package/util/index.ts CHANGED
@@ -67,6 +67,12 @@ export const capitalize = (str: string): string => (
67
67
 
68
68
  export { default as spreadToTransform } from './spread-to-transform'
69
69
  export { default as formatToMaxChar } from './format-to-max-char'
70
- // Must be imported from 'use client'
70
+ export {
71
+ default as formatAndAbbreviateAsCurrency,
72
+ type FormatThreshold,
73
+ type QuantityAbbrSymbol
74
+ } from './format-and-abbreviate-as-currency'
75
+
76
+ // Must be imported from 'use client', so can't include this...
71
77
  // export * from './step-animation'
72
78
 
@@ -1,16 +1,21 @@
1
1
  // cf: https://github.com/domharrington/js-number-abbreviate/blob/master/index.js
2
2
 
3
- const DEF_ABBREVIATIONS = ['K', 'M', 'B', 'T']
3
+ type QuantityAbbrSymbol = 'K' | 'M' | 'B' | 'T'
4
+ const ABBR_SYMBOLS_ARRAY = ['K', 'M', 'B', 'T'] satisfies QuantityAbbrSymbol[]
4
5
 
5
6
  class NumberAbbreviator {
6
7
 
7
- private _units: string[]
8
+ private _units: QuantityAbbrSymbol[]
8
9
 
9
- constructor(units?: string[]) {
10
- this._units = units ?? DEF_ABBREVIATIONS
10
+ constructor(units?: QuantityAbbrSymbol[]) {
11
+ this._units = units ?? ABBR_SYMBOLS_ARRAY
11
12
  }
12
13
 
13
- private _abbreviate = (n: number, decPlaces: number): string => {
14
+ private _abbreviate = (
15
+ n: number,
16
+ decPlaces: number,
17
+ log: boolean = false
18
+ ): string => {
14
19
 
15
20
  const _decPlaces = Math.pow(10, decPlaces)
16
21
  let _n = n
@@ -31,70 +36,14 @@ class NumberAbbreviator {
31
36
  return _n.toString() + (_unit ?? '')
32
37
  }
33
38
 
34
- abbreviate = (n: number, decPlaces: number) => {
35
- const abbreviatedNumber = this._abbreviate(Math.abs(n), decPlaces || 0)
39
+ abbreviate = (n: number, decPlaces: number, log: boolean = false) => {
40
+ const abbreviatedNumber = this._abbreviate(Math.abs(n), decPlaces, log)
36
41
  return n < 0 ? '-' + abbreviatedNumber : abbreviatedNumber
37
42
  }
38
43
  }
39
44
 
40
-
41
- export default NumberAbbreviator
42
-
43
- /*
44
- (function(root){
45
- 'use strict';
46
-
47
- function NumberAbbreviate() {
48
- var units
49
- if (!(this instanceof NumberAbbreviate)) {
50
- // function usage: abbrev(n, decPlaces, units)
51
- var n = arguments[0]
52
- var decPlaces = arguments[1]
53
- units = arguments[2]
54
- var ab = new NumberAbbreviate(units)
55
- return ab.abbreviate(n, decPlaces)
56
- }
57
- // class usage: new NumberAbbreviate(units)
58
- units = arguments[0]
59
- this.units = units == null ? ['k', 'm', 'b', 't'] : units
60
- }
61
-
62
- NumberAbbreviate.prototype._abbreviate = function(number, decPlaces) {
63
- decPlaces = Math.pow(10, decPlaces)
64
-
65
- for (var i = this.units.length - 1; i >= 0; i--) {
66
-
67
- var size = Math.pow(10, (i + 1) * 3)
68
-
69
- if (size <= number) {
70
- number = Math.round(number * decPlaces / size) / decPlaces
71
-
72
- if ((number === 1000) && (i < this.units.length - 1)) {
73
- number = 1
74
- i++
75
- }
76
-
77
- number += this.units[i]
78
-
79
- break
80
- }
81
- }
82
-
83
- return number
84
- }
85
-
86
- NumberAbbreviate.prototype.abbreviate = function(number, decPlaces) {
87
- var isNegative = number < 0
88
- var abbreviatedNumber = this._abbreviate(Math.abs(number), decPlaces || 0)
89
-
90
- return isNegative ? '-' + abbreviatedNumber : abbreviatedNumber;
91
- }
92
-
93
- if (typeof module !== 'undefined' && module.exports) {
94
- module.exports = NumberAbbreviate
95
- } else {
96
- root.NumberAbbreviate = NumberAbbreviate
97
- }
98
-
99
- })(this);
100
- */
45
+ export {
46
+ type QuantityAbbrSymbol,
47
+ ABBR_SYMBOLS_ARRAY,
48
+ NumberAbbreviator as default
49
+ }