also looking at this
fix(components): Progress max/indeterminate and Tooltip disabled are live props
#2008
5 files
+242
-17
| @@ -42,16 +42,42 @@ export const circularBarColor = color === 'primary' ? 'stroke-info' | ||
| 42 | 42 | </script> |
| 43 | 43 | |
| 44 | 44 | <script client> |
| 45 | const max = {{ max }} | |
| 46 | const indeterminate = {{ indeterminate }} | |
| 47 | 45 | const circumference = {{ circumference }} |
| 48 | // Reactive prop binding — parent can drive `value` via signals. See #1704. | |
| 46 | const circularBarColor = {{ circularBarColor }} | |
| 47 | ||
| 48 | /* | |
| 49 | * `value` has been a live prop since #1704. `max` and `indeterminate` were not, | |
| 50 | * and they are bound for the same reasons: | |
| 51 | * | |
| 52 | * :max="total()" the denominator is often unknown until the | |
| 53 | * response that supplies it arrives | |
| 54 | * :indeterminate="!total()" and the bar starts indeterminate precisely | |
| 55 | * BECAUSE the total is not known yet | |
| 56 | * | |
| 57 | * Frozen, those two could only ever describe the state the page was built in, | |
| 58 | * so a bar could never stop spinning once the total showed up. See #1997 for | |
| 59 | * the same freeze on Button. | |
| 60 | */ | |
| 61 | /* | |
| 62 | * The locals are deliberately NOT named `max` / `indeterminate`. | |
| 63 | * | |
| 64 | * A client-script name that matches a server-script export stops the server | |
| 65 | * interpolating that name in the template: the `animate-spin` ternary below | |
| 66 | * rendered as literal text rather than being evaluated. The attribute | |
| 67 | * useReactiveProp watches is its first argument, so the local is free to be | |
| 68 | * called something else — and has to be. | |
| 69 | */ | |
| 49 | 70 | const value = useReactiveProp('value', {{ value }}) |
| 71 | const maxValue = useReactiveProp('max', {{ max }}) | |
| 72 | const isIndeterminate = useReactiveProp('indeterminate', {{ indeterminate }}) | |
| 50 | 73 | |
| 51 | const percentage = derived(() => Math.min(Math.max((value() / max) * 100, 0), 100)) | |
| 74 | const percentage = derived(() => Math.min(Math.max((value() / maxValue()) * 100, 0), 100)) | |
| 52 | 75 | const percentLabel = derived(() => `${Math.round(percentage())}%`) |
| 53 | const linearWidth = derived(() => indeterminate ? '30%' : `${percentage()}%`) | |
| 54 | const dashOffset = derived(() => indeterminate ? 0 : circumference - (percentage() / 100) * circumference) | |
| 76 | const linearWidth = derived(() => isIndeterminate() ? '30%' : `${percentage()}%`) | |
| 77 | const dashOffset = derived(() => isIndeterminate() ? 0 : circumference - (percentage() / 100) * circumference) | |
| 78 | // The spin is part of what `indeterminate` MEANS, so it follows the signal | |
| 79 | // rather than the server's snapshot of it. | |
| 80 | const circularBarClass = derived(() => `${circularBarColor} transition-all duration-300 ease-in-out ${isIndeterminate() ? 'animate-spin' : ''}`.trim()) | |
| 55 | 81 | |
| 56 | 82 | defineExpose({ value, setValue: (v) => value.set(v) }) |
| 57 | 83 | </script> |
| @@ -70,6 +96,7 @@ defineExpose({ value, setValue: (v) => value.set(v) }) | ||
| 70 | 96 | :aria-valuenow="value()" |
| 71 | 97 | aria-valuemin="0" |
| 72 | 98 | aria-valuemax="function max(array) { if (array.length === 0) throw Error("Cannot compute max of an empty array"); return Math.max(...array); }" |
| 99 | :aria-valuemax="maxValue()" | |
| 73 | 100 | > |
| 74 | 101 | <div |
| 75 | 102 | class="" |
| @@ -88,6 +115,7 @@ defineExpose({ value, setValue: (v) => value.set(v) }) | ||
| 88 | 115 | :aria-valuenow="value()" |
| 89 | 116 | aria-valuemin="0" |
| 90 | 117 | aria-valuemax="function max(array) { if (array.length === 0) throw Error("Cannot compute max of an empty array"); return Math.max(...array); }" |
| 118 | :aria-valuemax="maxValue()" | |
| 91 | 119 | > |
| 92 | 120 | <circle |
| 93 | 121 | class="" |
| @@ -99,6 +127,7 @@ defineExpose({ value, setValue: (v) => value.set(v) }) | ||
| 99 | 127 | /> |
| 100 | 128 | <circle |
| 101 | 129 | class=" transition-all duration-300 ease-in-out " |
| 130 | :class="circularBarClass()" | |
| 102 | 131 | cx="NaN" |
| 103 | 132 | cy="NaN" |
| 104 | 133 | r="" |