@tamagui/progress 1.0.1-beta.59 → 1.0.1-beta.62
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 +7 -6
- package/src/Progress.tsx +215 -0
- package/src/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/progress",
|
|
3
|
-
"version": "1.0.1-beta.
|
|
3
|
+
"version": "1.0.1-beta.62",
|
|
4
4
|
"sideEffects": true,
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"types": "./types/index.d.ts",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"module": "dist/esm",
|
|
9
9
|
"module:jsx": "dist/jsx",
|
|
10
10
|
"files": [
|
|
11
|
+
"src",
|
|
11
12
|
"types",
|
|
12
13
|
"dist"
|
|
13
14
|
],
|
|
@@ -18,10 +19,10 @@
|
|
|
18
19
|
"clean:build": "tamagui-build clean:build"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@tamagui/compose-refs": "^1.0.1-beta.
|
|
22
|
-
"@tamagui/core": "^1.0.1-beta.
|
|
23
|
-
"@tamagui/create-context": "^1.0.1-beta.
|
|
24
|
-
"@tamagui/stacks": "^1.0.1-beta.
|
|
22
|
+
"@tamagui/compose-refs": "^1.0.1-beta.62",
|
|
23
|
+
"@tamagui/core": "^1.0.1-beta.62",
|
|
24
|
+
"@tamagui/create-context": "^1.0.1-beta.62",
|
|
25
|
+
"@tamagui/stacks": "^1.0.1-beta.62"
|
|
25
26
|
},
|
|
26
27
|
"peerDependencies": {
|
|
27
28
|
"react": "*",
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
"react-native": "*"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"@tamagui/build": "^1.0.1-beta.
|
|
33
|
+
"@tamagui/build": "^1.0.1-beta.62",
|
|
33
34
|
"@types/react-native": "^0.67.3",
|
|
34
35
|
"react": "*",
|
|
35
36
|
"react-dom": "*",
|
package/src/Progress.tsx
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// forked from Radix UI
|
|
2
|
+
// https://github.com/radix-ui/primitives/blob/main/packages/react/progress/src/Progress.tsx
|
|
3
|
+
|
|
4
|
+
import { GetProps, getSize, getVariableValue, styled, withStaticProperties } from '@tamagui/core'
|
|
5
|
+
import { Scope, createContextScope } from '@tamagui/create-context'
|
|
6
|
+
import { ThemeableStack, YStackProps } from '@tamagui/stacks'
|
|
7
|
+
import * as React from 'react'
|
|
8
|
+
import { View } from 'react-native'
|
|
9
|
+
|
|
10
|
+
const PROGRESS_NAME = 'Progress'
|
|
11
|
+
|
|
12
|
+
const [createProgressContext, createProgressScope] = createContextScope(PROGRESS_NAME)
|
|
13
|
+
type ProgressContextValue = { value: number | null; max: number; width: number }
|
|
14
|
+
const [ProgressProvider, useProgressContext] =
|
|
15
|
+
createProgressContext<ProgressContextValue>(PROGRESS_NAME)
|
|
16
|
+
|
|
17
|
+
/* -------------------------------------------------------------------------------------------------
|
|
18
|
+
* ProgressIndicator
|
|
19
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
20
|
+
|
|
21
|
+
const INDICATOR_NAME = 'ProgressIndicator'
|
|
22
|
+
|
|
23
|
+
type ProgressIndicatorElement = TamaguiElement
|
|
24
|
+
interface ProgressIndicatorProps extends YStackProps {}
|
|
25
|
+
|
|
26
|
+
const ProgressIndicatorFrame = styled(ThemeableStack, {
|
|
27
|
+
name: INDICATOR_NAME,
|
|
28
|
+
height: '100%',
|
|
29
|
+
width: '100%',
|
|
30
|
+
backgrounded: true,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const ProgressIndicator = ProgressIndicatorFrame.extractable(
|
|
34
|
+
React.forwardRef<ProgressIndicatorElement, ProgressIndicatorProps>(
|
|
35
|
+
(props: ScopedProps<ProgressIndicatorProps>, forwardedRef) => {
|
|
36
|
+
const { __scopeProgress, ...indicatorProps } = props
|
|
37
|
+
const context = useProgressContext(INDICATOR_NAME, __scopeProgress)
|
|
38
|
+
const pct = context.max - (context.value ?? 0)
|
|
39
|
+
const x = -context.width * (pct / 100)
|
|
40
|
+
return (
|
|
41
|
+
<ProgressIndicatorFrame
|
|
42
|
+
data-state={getProgressState(context.value, context.max)}
|
|
43
|
+
data-value={context.value ?? undefined}
|
|
44
|
+
data-max={context.max}
|
|
45
|
+
x={x}
|
|
46
|
+
width={context.width}
|
|
47
|
+
{...indicatorProps}
|
|
48
|
+
ref={forwardedRef}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
ProgressIndicator.displayName = INDICATOR_NAME
|
|
56
|
+
|
|
57
|
+
/* ---------------------------------------------------------------------------------------------- */
|
|
58
|
+
|
|
59
|
+
function defaultGetValueLabel(value: number, max: number) {
|
|
60
|
+
return `${Math.round((value / max) * 100)}%`
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getProgressState(value: number | undefined | null, maxValue: number): ProgressState {
|
|
64
|
+
return value == null ? 'indeterminate' : value === maxValue ? 'complete' : 'loading'
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isNumber(value: any): value is number {
|
|
68
|
+
return typeof value === 'number'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isValidMaxNumber(max: any): max is number {
|
|
72
|
+
// prettier-ignore
|
|
73
|
+
return (
|
|
74
|
+
isNumber(max) &&
|
|
75
|
+
!isNaN(max) &&
|
|
76
|
+
max > 0
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isValidValueNumber(value: any, max: number): value is number {
|
|
81
|
+
// prettier-ignore
|
|
82
|
+
return (
|
|
83
|
+
isNumber(value) &&
|
|
84
|
+
!isNaN(value) &&
|
|
85
|
+
value <= max &&
|
|
86
|
+
value >= 0
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Split this out for clearer readability of the error message.
|
|
91
|
+
function getInvalidMaxError(propValue: string, componentName: string) {
|
|
92
|
+
return `Invalid prop \`max\` of value \`${propValue}\` supplied to \`${componentName}\`. Only numbers greater than 0 are valid max values. Defaulting to \`${DEFAULT_MAX}\`.`
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getInvalidValueError(propValue: string, componentName: string) {
|
|
96
|
+
return `Invalid prop \`value\` of value \`${propValue}\` supplied to \`${componentName}\`. The \`value\` prop must be:
|
|
97
|
+
- a positive number
|
|
98
|
+
- less than the value passed to \`max\` (or ${DEFAULT_MAX} if no \`max\` prop is set)
|
|
99
|
+
- \`null\` if the progress is indeterminate.
|
|
100
|
+
|
|
101
|
+
Defaulting to \`null\`.`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* -------------------------------------------------------------------------------------------------
|
|
105
|
+
* Progress
|
|
106
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
107
|
+
|
|
108
|
+
const DEFAULT_MAX = 100
|
|
109
|
+
|
|
110
|
+
type ScopedProps<P> = P & { __scopeProgress?: Scope }
|
|
111
|
+
|
|
112
|
+
type ProgressState = 'indeterminate' | 'complete' | 'loading'
|
|
113
|
+
|
|
114
|
+
type TamaguiElement = HTMLElement | View
|
|
115
|
+
|
|
116
|
+
type ProgressElement = TamaguiElement
|
|
117
|
+
|
|
118
|
+
const ProgressFrame = styled(ThemeableStack, {
|
|
119
|
+
name: PROGRESS_NAME,
|
|
120
|
+
borderRadius: 100_000,
|
|
121
|
+
overflow: 'hidden',
|
|
122
|
+
backgrounded: true,
|
|
123
|
+
|
|
124
|
+
variants: {
|
|
125
|
+
size: {
|
|
126
|
+
'...size': (val) => {
|
|
127
|
+
const size = Math.round(getVariableValue(getSize(val)) * 0.25)
|
|
128
|
+
return {
|
|
129
|
+
height: size,
|
|
130
|
+
minWidth: getVariableValue(size) * 20,
|
|
131
|
+
width: '100%',
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
type ProgressProps = GetProps<typeof ProgressFrame> & {
|
|
139
|
+
value?: number | null | undefined
|
|
140
|
+
max?: number
|
|
141
|
+
getValueLabel?(value: number, max: number): string
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const Progress = withStaticProperties(
|
|
145
|
+
ProgressFrame.extractable(
|
|
146
|
+
React.forwardRef<ProgressElement, ProgressProps>(
|
|
147
|
+
(props: ScopedProps<ProgressProps>, forwardedRef) => {
|
|
148
|
+
const {
|
|
149
|
+
__scopeProgress,
|
|
150
|
+
value: valueProp,
|
|
151
|
+
max: maxProp,
|
|
152
|
+
getValueLabel = defaultGetValueLabel,
|
|
153
|
+
size = '$4',
|
|
154
|
+
...progressProps
|
|
155
|
+
} = props
|
|
156
|
+
|
|
157
|
+
const max = isValidMaxNumber(maxProp) ? maxProp : DEFAULT_MAX
|
|
158
|
+
const value = isValidValueNumber(valueProp, max) ? valueProp : null
|
|
159
|
+
const valueLabel = isNumber(value) ? getValueLabel(value, max) : undefined
|
|
160
|
+
const [width, setWidth] = React.useState(0)
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<ProgressProvider scope={__scopeProgress} value={value} max={max} width={width}>
|
|
164
|
+
<ProgressFrame
|
|
165
|
+
size={size}
|
|
166
|
+
aria-valuemax={max}
|
|
167
|
+
aria-valuemin={0}
|
|
168
|
+
aria-valuenow={isNumber(value) ? value : undefined}
|
|
169
|
+
aria-valuetext={valueLabel}
|
|
170
|
+
// @ts-ignore
|
|
171
|
+
role="progressbar"
|
|
172
|
+
data-state={getProgressState(value, max)}
|
|
173
|
+
data-value={value ?? undefined}
|
|
174
|
+
data-max={max}
|
|
175
|
+
{...progressProps}
|
|
176
|
+
onLayout={(e) => {
|
|
177
|
+
setWidth(e.nativeEvent.layout.width)
|
|
178
|
+
progressProps.onLayout?.(e)
|
|
179
|
+
}}
|
|
180
|
+
ref={forwardedRef}
|
|
181
|
+
/>
|
|
182
|
+
</ProgressProvider>
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
),
|
|
187
|
+
{
|
|
188
|
+
Indicator: ProgressIndicator,
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
Progress.displayName = PROGRESS_NAME
|
|
193
|
+
|
|
194
|
+
Progress.propTypes = {
|
|
195
|
+
max(props, propName, componentName) {
|
|
196
|
+
const propValue = props[propName]
|
|
197
|
+
const strVal = String(propValue)
|
|
198
|
+
if (propValue && !isValidMaxNumber(propValue)) {
|
|
199
|
+
return new Error(getInvalidMaxError(strVal, componentName))
|
|
200
|
+
}
|
|
201
|
+
return null
|
|
202
|
+
},
|
|
203
|
+
value(props, propName, componentName) {
|
|
204
|
+
const valueProp = props[propName]
|
|
205
|
+
const strVal = String(valueProp)
|
|
206
|
+
const max = isValidMaxNumber(props.max) ? props.max : DEFAULT_MAX
|
|
207
|
+
if (valueProp != null && !isValidValueNumber(valueProp, max)) {
|
|
208
|
+
return new Error(getInvalidValueError(strVal, componentName))
|
|
209
|
+
}
|
|
210
|
+
return null
|
|
211
|
+
},
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export { createProgressScope, Progress, ProgressIndicator }
|
|
215
|
+
export type { ProgressProps, ProgressIndicatorProps }
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Progress'
|