@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/progress",
3
- "version": "1.0.1-beta.59",
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.59",
22
- "@tamagui/core": "^1.0.1-beta.59",
23
- "@tamagui/create-context": "^1.0.1-beta.59",
24
- "@tamagui/stacks": "^1.0.1-beta.59"
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.59",
33
+ "@tamagui/build": "^1.0.1-beta.62",
33
34
  "@types/react-native": "^0.67.3",
34
35
  "react": "*",
35
36
  "react-dom": "*",
@@ -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'