An Image Texture node samples the texture in a normalized $0…1$ space on both $x$ and $y$ axes (also called UV), where $0$ means (the center of) the first pixel (first row or first column) and $1$ means last pixel (last row or last column).

Well actually the second coordinate ($y$ or $v$) should have $1$ at the top, but I won't redo the image now that I realized my mistake ♂️
And so a question arises, if you try to sample a value higher than $1$ (or lower than $0$, i.e. a negative number) on either axis, what should happen?
- Clip will just return (transparent) black
- Extend will return nearest valid pixel (it will clamp the coordinate, so if it's greater than 1 it will be 1, if it's negative it will become 0)
- Repeat will repeat the $0…1$ range:

I achieved the above line chart using Desmos with the simple formula $y=\operatorname{mod}\left(x,1\right)$, so that's what you want to do in Blender, except Blender's modulo is 1 lower for negative input (Looping Hue Animate), so use Wrap instead, or even better, Fraction, which is the same as Wrap with hard-coded $0…1$ range (discards the number to the left of the dot):

Beware of the problem that $1$ is mapped to $0$, and so you may want to check against this specific value and in such case output $1$ instead…