@graphcommerce/next-ui 9.0.0-canary.96 → 9.0.0-canary.98
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/CHANGELOG.md +10 -0
- package/Intl/DateTimeFormat/DateTimeFormat.tsx +3 -8
- package/Intl/DateTimeFormat/toDate.ts +16 -0
- package/Intl/RelativeTimeFormat/RelativeTimeFormat.tsx +34 -0
- package/Intl/RelativeTimeFormat/RelativeToTimeFormat.tsx +35 -0
- package/Intl/RelativeTimeFormat/index.ts +2 -0
- package/Intl/RelativeTimeFormat/relativeTimeFormatAutoUnit.ts +23 -0
- package/Intl/index.ts +1 -1
- package/TimeAgo/TimeAgo.tsx +3 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 9.0.0-canary.98
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#2414](https://github.com/graphcommerce-org/graphcommerce/pull/2414) [`cd8e35b`](https://github.com/graphcommerce-org/graphcommerce/commit/cd8e35ba3dfafd34221b0875bf4f83c802955d66) - Added RelativeTimeFormat and RelativeToTimeFormat components to display relative dates in all locales. ([@Vignesh-M21](https://github.com/Vignesh-M21))
|
|
8
|
+
|
|
9
|
+
- [#2414](https://github.com/graphcommerce-org/graphcommerce/pull/2414) [`8b1a5a6`](https://github.com/graphcommerce-org/graphcommerce/commit/8b1a5a62a580cc8d08746cb19c4e5a4f52bd270c) - Date strings (12-12-2012) are not supported by older Safari browser versions. must be converted (12/12/2012) in order for it to function; otherwise, it will return NaN if we attempt to access the getTime() on an object. ([@Vignesh-M21](https://github.com/Vignesh-M21))
|
|
10
|
+
|
|
11
|
+
## 9.0.0-canary.97
|
|
12
|
+
|
|
3
13
|
## 9.0.0-canary.96
|
|
4
14
|
|
|
5
15
|
## 9.0.0-canary.95
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
2
|
import { useLocale } from '../../hooks/useLocale'
|
|
3
3
|
import { useMemoObject } from '../../hooks/useMemoObject'
|
|
4
|
+
import { DateValue, toDate } from './toDate'
|
|
4
5
|
|
|
5
6
|
export function useDateTimeFormatter(props: Intl.DateTimeFormatOptions) {
|
|
6
7
|
const locale = useLocale()
|
|
@@ -8,18 +9,12 @@ export function useDateTimeFormatter(props: Intl.DateTimeFormatOptions) {
|
|
|
8
9
|
return useMemo(() => new Intl.DateTimeFormat(locale, memoOptions), [locale, memoOptions])
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
type DateValue = Date | string | number | null | undefined
|
|
12
12
|
export type DateTimeFormatPropsType = { children: DateValue } & Intl.DateTimeFormatOptions
|
|
13
13
|
|
|
14
14
|
export function DateTimeFormat(props: DateTimeFormatPropsType) {
|
|
15
15
|
const { children } = props
|
|
16
16
|
const formatter = useDateTimeFormatter({ dateStyle: 'medium', timeStyle: 'short', ...props })
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{children
|
|
21
|
-
? formatter.format(typeof children === 'string' ? new Date(children) : children)
|
|
22
|
-
: null}
|
|
23
|
-
</span>
|
|
24
|
-
)
|
|
18
|
+
const dateValue = useMemo(() => toDate(children), [children])
|
|
19
|
+
return <span suppressHydrationWarning>{dateValue ? formatter.format(dateValue) : null}</span>
|
|
25
20
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type DateValue = Date | string | number | null | undefined
|
|
2
|
+
|
|
3
|
+
export function toDate(value: DateValue): Date | undefined {
|
|
4
|
+
let date: Date | undefined
|
|
5
|
+
|
|
6
|
+
if (value instanceof Date) {
|
|
7
|
+
date = value
|
|
8
|
+
} else if (typeof value === 'string') {
|
|
9
|
+
date = new Date(value.replace(/-/g, '/'))
|
|
10
|
+
} else if (typeof value === 'number') {
|
|
11
|
+
date = new Date(value)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (date && Number.isNaN(date.getTime())) return undefined
|
|
15
|
+
return date
|
|
16
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { forwardRef, useMemo } from 'react'
|
|
2
|
+
import { useLocale } from '../../hooks/useLocale'
|
|
3
|
+
import { useMemoObject } from '../../hooks/useMemoObject'
|
|
4
|
+
import { relativeTimeFormatUnitAuto } from './relativeTimeFormatAutoUnit'
|
|
5
|
+
|
|
6
|
+
export function useRelativeTimeFormatter(props: Intl.RelativeTimeFormatOptions) {
|
|
7
|
+
const locale = useLocale()
|
|
8
|
+
const memoOptions = useMemoObject(props)
|
|
9
|
+
return useMemo(() => new Intl.RelativeTimeFormat(locale, memoOptions), [locale, memoOptions])
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type RelativeTimeFormatProps = {
|
|
13
|
+
children: number
|
|
14
|
+
unit?: Intl.RelativeTimeFormatUnit
|
|
15
|
+
styleFormat?: Intl.RelativeTimeFormatStyle
|
|
16
|
+
} & Omit<Intl.RelativeTimeFormatOptions, 'style'>
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Alternative: {@link file://./RelativeToTimeFormat.tsx}
|
|
20
|
+
*/
|
|
21
|
+
export const RelativeTimeFormat = forwardRef<HTMLSpanElement, RelativeTimeFormatProps>(
|
|
22
|
+
(props, ref) => {
|
|
23
|
+
const { children, unit, styleFormat, localeMatcher, numeric, ...rest } = props
|
|
24
|
+
const formatter = useRelativeTimeFormatter({ localeMatcher, numeric, style: styleFormat })
|
|
25
|
+
|
|
26
|
+
const [value, autoUnit] = relativeTimeFormatUnitAuto({ value: children, unit })
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<span suppressHydrationWarning ref={ref} {...rest}>
|
|
30
|
+
{children ? formatter.format(value, autoUnit) : null}
|
|
31
|
+
</span>
|
|
32
|
+
)
|
|
33
|
+
},
|
|
34
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { forwardRef, useMemo } from 'react'
|
|
2
|
+
import { DateValue, toDate } from '../DateTimeFormat/toDate'
|
|
3
|
+
import { RelativeTimeFormat, RelativeTimeFormatProps } from './RelativeTimeFormat'
|
|
4
|
+
|
|
5
|
+
type RelativeToTimeFormatProps = Omit<RelativeTimeFormatProps, 'children'> & {
|
|
6
|
+
/**
|
|
7
|
+
* Date to format a relative value for.
|
|
8
|
+
*/
|
|
9
|
+
children: DateValue
|
|
10
|
+
/**
|
|
11
|
+
* If provided, the component will format a relative value to this date.
|
|
12
|
+
* Else, it will format a relative value to the current date.
|
|
13
|
+
*/
|
|
14
|
+
to?: DateValue
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const RelativeToTimeFormat = forwardRef<HTMLSpanElement, RelativeToTimeFormatProps>(
|
|
18
|
+
(props, ref) => {
|
|
19
|
+
const { children, to, ...rest } = props
|
|
20
|
+
|
|
21
|
+
const relativeTo = useMemo(() => {
|
|
22
|
+
const date = toDate(children)
|
|
23
|
+
if (!date) return 0
|
|
24
|
+
const toDateValue = (to && toDate(to)) || new Date()
|
|
25
|
+
|
|
26
|
+
return Math.round((date.getTime() - toDateValue.getTime()) / 1000)
|
|
27
|
+
}, [children, to])
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<RelativeTimeFormat {...rest} ref={ref}>
|
|
31
|
+
{relativeTo}
|
|
32
|
+
</RelativeTimeFormat>
|
|
33
|
+
)
|
|
34
|
+
},
|
|
35
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type UseRelativeTimeFormatUnitAutoProps = {
|
|
2
|
+
value: number
|
|
3
|
+
unit?: Intl.RelativeTimeFormatUnit
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function relativeTimeFormatUnitAuto(
|
|
7
|
+
props: UseRelativeTimeFormatUnitAutoProps,
|
|
8
|
+
): [number, Intl.RelativeTimeFormatUnit] {
|
|
9
|
+
const { value, unit } = props
|
|
10
|
+
|
|
11
|
+
if (unit) return [value, unit]
|
|
12
|
+
|
|
13
|
+
// Calculate the absolute value once
|
|
14
|
+
const absValue = Math.abs(value)
|
|
15
|
+
|
|
16
|
+
if (absValue >= 60 * 60 * 24 * 365) return [Math.round(value / (60 * 60 * 24 * 365)), 'year']
|
|
17
|
+
if (absValue >= 60 * 60 * 24 * 30) return [Math.round(value / (60 * 60 * 24 * 30)), 'month']
|
|
18
|
+
if (absValue >= 60 * 60 * 24 * 7) return [Math.round(value / (60 * 60 * 24 * 7)), 'week']
|
|
19
|
+
if (absValue >= 60 * 60 * 24) return [Math.round(value / (60 * 60 * 24)), 'day']
|
|
20
|
+
if (absValue >= 60 * 60) return [Math.round(value / (60 * 60)), 'hour']
|
|
21
|
+
if (absValue >= 60) return [Math.round(value / 60), 'minute']
|
|
22
|
+
return [Math.round(value), 'second']
|
|
23
|
+
}
|
package/Intl/index.ts
CHANGED
|
@@ -7,5 +7,5 @@ export * from './ListFormat' // Intl.ListFormat
|
|
|
7
7
|
// export * from './Locale' // Intl.Locale
|
|
8
8
|
export * from './NumberFormat' // Intl.NumberFormat
|
|
9
9
|
// export * from './PluralRules' // Intl.PluralRules
|
|
10
|
-
|
|
10
|
+
export * from './RelativeTimeFormat' // Intl.RelativeTimeFormat
|
|
11
11
|
// export * from './Segmenter' // Intl.Segmenter
|
package/TimeAgo/TimeAgo.tsx
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/next-ui",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "9.0.0-canary.
|
|
5
|
+
"version": "9.0.0-canary.98",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"typescript": "5.5.3"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@graphcommerce/eslint-config-pwa": "^9.0.0-canary.
|
|
30
|
-
"@graphcommerce/framer-next-pages": "^9.0.0-canary.
|
|
31
|
-
"@graphcommerce/framer-scroller": "^9.0.0-canary.
|
|
32
|
-
"@graphcommerce/framer-utils": "^9.0.0-canary.
|
|
33
|
-
"@graphcommerce/image": "^9.0.0-canary.
|
|
34
|
-
"@graphcommerce/prettier-config-pwa": "^9.0.0-canary.
|
|
35
|
-
"@graphcommerce/typescript-config-pwa": "^9.0.0-canary.
|
|
29
|
+
"@graphcommerce/eslint-config-pwa": "^9.0.0-canary.98",
|
|
30
|
+
"@graphcommerce/framer-next-pages": "^9.0.0-canary.98",
|
|
31
|
+
"@graphcommerce/framer-scroller": "^9.0.0-canary.98",
|
|
32
|
+
"@graphcommerce/framer-utils": "^9.0.0-canary.98",
|
|
33
|
+
"@graphcommerce/image": "^9.0.0-canary.98",
|
|
34
|
+
"@graphcommerce/prettier-config-pwa": "^9.0.0-canary.98",
|
|
35
|
+
"@graphcommerce/typescript-config-pwa": "^9.0.0-canary.98",
|
|
36
36
|
"@lingui/core": "^4.2.1",
|
|
37
37
|
"@lingui/macro": "^4.2.1",
|
|
38
38
|
"@lingui/react": "^4.2.1",
|