Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F100101655
TouchRipple.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jan 28, 05:05
Size
9 KB
Mime Type
text/x-java
Expires
Thu, Jan 30, 05:05 (2 d)
Engine
blob
Format
Raw Data
Handle
23877702
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
TouchRipple.js
View Options
import
_extends
from
"@babel/runtime/helpers/esm/extends"
;
import
_objectWithoutPropertiesLoose
from
"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"
;
const
_excluded
=
[
"center"
,
"classes"
,
"className"
];
let
_
=
t
=>
t
,
_t
,
_t2
,
_t3
,
_t4
;
import
*
as
React
from
'react'
;
import
PropTypes
from
'prop-types'
;
import
{
TransitionGroup
}
from
'react-transition-group'
;
import
clsx
from
'clsx'
;
import
{
keyframes
}
from
'@mui/system'
;
import
styled
from
'../styles/styled'
;
import
useThemeProps
from
'../styles/useThemeProps'
;
import
Ripple
from
'./Ripple'
;
import
touchRippleClasses
from
'./touchRippleClasses'
;
import
{
jsx
as
_jsx
}
from
"react/jsx-runtime"
;
const
DURATION
=
550
;
export
const
DELAY_RIPPLE
=
80
;
const
enterKeyframe
=
keyframes
(
_t
||
(
_t
=
_
`
0
%
{
transform
:
scale
(
0
);
opacity
:
0.1
;
}
100
%
{
transform
:
scale
(
1
);
opacity
:
0.3
;
}
`
));
const
exitKeyframe
=
keyframes
(
_t2
||
(
_t2
=
_
`
0
%
{
opacity
:
1
;
}
100
%
{
opacity
:
0
;
}
`
));
const
pulsateKeyframe
=
keyframes
(
_t3
||
(
_t3
=
_
`
0
%
{
transform
:
scale
(
1
);
}
50
%
{
transform
:
scale
(
0.92
);
}
100
%
{
transform
:
scale
(
1
);
}
`
));
export
const
TouchRippleRoot
=
styled
(
'span'
,
{
name
:
'MuiTouchRipple'
,
slot
:
'Root'
})({
overflow
:
'hidden'
,
pointerEvents
:
'none'
,
position
:
'absolute'
,
zIndex
:
0
,
top
:
0
,
right
:
0
,
bottom
:
0
,
left
:
0
,
borderRadius
:
'inherit'
});
// This `styled()` function invokes keyframes. `styled-components` only supports keyframes
// in string templates. Do not convert these styles in JS object as it will break.
export
const
TouchRippleRipple
=
styled
(
Ripple
,
{
name
:
'MuiTouchRipple'
,
slot
:
'Ripple'
})(
_t4
||
(
_t4
=
_
`
opacity
:
0
;
position
:
absolute
;
&
.
$
{
0
}
{
opacity
:
0.3
;
transform
:
scale
(
1
);
animation
-
name
:
$
{
0
};
animation
-
duration
:
$
{
0
}
ms
;
animation
-
timing
-
function
:
$
{
0
};
}
&
.
$
{
0
}
{
animation
-
duration
:
$
{
0
}
ms
;
}
&
.
$
{
0
}
{
opacity
:
1
;
display
:
block
;
width
:
100
%
;
height
:
100
%
;
border
-
radius
:
50
%
;
background
-
color
:
currentColor
;
}
&
.
$
{
0
}
{
opacity
:
0
;
animation
-
name
:
$
{
0
};
animation
-
duration
:
$
{
0
}
ms
;
animation
-
timing
-
function
:
$
{
0
};
}
&
.
$
{
0
}
{
position
:
absolute
;
/* @noflip */
left
:
0
px
;
top
:
0
;
animation
-
name
:
$
{
0
};
animation
-
duration
:
2500
ms
;
animation
-
timing
-
function
:
$
{
0
};
animation
-
iteration
-
count
:
infinite
;
animation
-
delay
:
200
ms
;
}
`
),
touchRippleClasses
.
rippleVisible
,
enterKeyframe
,
DURATION
,
({
theme
})
=>
theme
.
transitions
.
easing
.
easeInOut
,
touchRippleClasses
.
ripplePulsate
,
({
theme
})
=>
theme
.
transitions
.
duration
.
shorter
,
touchRippleClasses
.
child
,
touchRippleClasses
.
childLeaving
,
exitKeyframe
,
DURATION
,
({
theme
})
=>
theme
.
transitions
.
easing
.
easeInOut
,
touchRippleClasses
.
childPulsate
,
pulsateKeyframe
,
({
theme
})
=>
theme
.
transitions
.
easing
.
easeInOut
);
/**
* @ignore - internal component.
*
* TODO v5: Make private
*/
const
TouchRipple
=
/*#__PURE__*/
React
.
forwardRef
(
function
TouchRipple
(
inProps
,
ref
)
{
const
props
=
useThemeProps
({
props
:
inProps
,
name
:
'MuiTouchRipple'
});
const
{
center
:
centerProp
=
false
,
classes
=
{},
className
}
=
props
,
other
=
_objectWithoutPropertiesLoose
(
props
,
_excluded
);
const
[
ripples
,
setRipples
]
=
React
.
useState
([]);
const
nextKey
=
React
.
useRef
(
0
);
const
rippleCallback
=
React
.
useRef
(
null
);
React
.
useEffect
(()
=>
{
if
(
rippleCallback
.
current
)
{
rippleCallback
.
current
();
rippleCallback
.
current
=
null
;
}
},
[
ripples
]);
// Used to filter out mouse emulated events on mobile.
const
ignoringMouseDown
=
React
.
useRef
(
false
);
// We use a timer in order to only show the ripples for touch "click" like events.
// We don't want to display the ripple for touch scroll events.
const
startTimer
=
React
.
useRef
(
null
);
// This is the hook called once the previous timeout is ready.
const
startTimerCommit
=
React
.
useRef
(
null
);
const
container
=
React
.
useRef
(
null
);
React
.
useEffect
(()
=>
{
return
()
=>
{
clearTimeout
(
startTimer
.
current
);
};
},
[]);
const
startCommit
=
React
.
useCallback
(
params
=>
{
const
{
pulsate
,
rippleX
,
rippleY
,
rippleSize
,
cb
}
=
params
;
setRipples
(
oldRipples
=>
[...
oldRipples
,
/*#__PURE__*/
_jsx
(
TouchRippleRipple
,
{
classes
:
{
ripple
:
clsx
(
classes
.
ripple
,
touchRippleClasses
.
ripple
),
rippleVisible
:
clsx
(
classes
.
rippleVisible
,
touchRippleClasses
.
rippleVisible
),
ripplePulsate
:
clsx
(
classes
.
ripplePulsate
,
touchRippleClasses
.
ripplePulsate
),
child
:
clsx
(
classes
.
child
,
touchRippleClasses
.
child
),
childLeaving
:
clsx
(
classes
.
childLeaving
,
touchRippleClasses
.
childLeaving
),
childPulsate
:
clsx
(
classes
.
childPulsate
,
touchRippleClasses
.
childPulsate
)
},
timeout
:
DURATION
,
pulsate
:
pulsate
,
rippleX
:
rippleX
,
rippleY
:
rippleY
,
rippleSize
:
rippleSize
},
nextKey
.
current
)]);
nextKey
.
current
+=
1
;
rippleCallback
.
current
=
cb
;
},
[
classes
]);
const
start
=
React
.
useCallback
((
event
=
{},
options
=
{},
cb
=
()
=>
{})
=>
{
const
{
pulsate
=
false
,
center
=
centerProp
||
options
.
pulsate
,
fakeElement
=
false
// For test purposes
}
=
options
;
if
((
event
==
null
?
void
0
:
event
.
type
)
===
'mousedown'
&&
ignoringMouseDown
.
current
)
{
ignoringMouseDown
.
current
=
false
;
return
;
}
if
((
event
==
null
?
void
0
:
event
.
type
)
===
'touchstart'
)
{
ignoringMouseDown
.
current
=
true
;
}
const
element
=
fakeElement
?
null
:
container
.
current
;
const
rect
=
element
?
element
.
getBoundingClientRect
()
:
{
width
:
0
,
height
:
0
,
left
:
0
,
top
:
0
};
// Get the size of the ripple
let
rippleX
;
let
rippleY
;
let
rippleSize
;
if
(
center
||
event
===
undefined
||
event
.
clientX
===
0
&&
event
.
clientY
===
0
||
!
event
.
clientX
&&
!
event
.
touches
)
{
rippleX
=
Math
.
round
(
rect
.
width
/
2
);
rippleY
=
Math
.
round
(
rect
.
height
/
2
);
}
else
{
const
{
clientX
,
clientY
}
=
event
.
touches
&&
event
.
touches
.
length
>
0
?
event
.
touches
[
0
]
:
event
;
rippleX
=
Math
.
round
(
clientX
-
rect
.
left
);
rippleY
=
Math
.
round
(
clientY
-
rect
.
top
);
}
if
(
center
)
{
rippleSize
=
Math
.
sqrt
((
2
*
rect
.
width
**
2
+
rect
.
height
**
2
)
/
3
);
// For some reason the animation is broken on Mobile Chrome if the size is even.
if
(
rippleSize
%
2
===
0
)
{
rippleSize
+=
1
;
}
}
else
{
const
sizeX
=
Math
.
max
(
Math
.
abs
((
element
?
element
.
clientWidth
:
0
)
-
rippleX
),
rippleX
)
*
2
+
2
;
const
sizeY
=
Math
.
max
(
Math
.
abs
((
element
?
element
.
clientHeight
:
0
)
-
rippleY
),
rippleY
)
*
2
+
2
;
rippleSize
=
Math
.
sqrt
(
sizeX
**
2
+
sizeY
**
2
);
}
// Touche devices
if
(
event
!=
null
&&
event
.
touches
)
{
// check that this isn't another touchstart due to multitouch
// otherwise we will only clear a single timer when unmounting while two
// are running
if
(
startTimerCommit
.
current
===
null
)
{
// Prepare the ripple effect.
startTimerCommit
.
current
=
()
=>
{
startCommit
({
pulsate
,
rippleX
,
rippleY
,
rippleSize
,
cb
});
};
// Delay the execution of the ripple effect.
startTimer
.
current
=
setTimeout
(()
=>
{
if
(
startTimerCommit
.
current
)
{
startTimerCommit
.
current
();
startTimerCommit
.
current
=
null
;
}
},
DELAY_RIPPLE
);
// We have to make a tradeoff with this value.
}
}
else
{
startCommit
({
pulsate
,
rippleX
,
rippleY
,
rippleSize
,
cb
});
}
},
[
centerProp
,
startCommit
]);
const
pulsate
=
React
.
useCallback
(()
=>
{
start
({},
{
pulsate
:
true
});
},
[
start
]);
const
stop
=
React
.
useCallback
((
event
,
cb
)
=>
{
clearTimeout
(
startTimer
.
current
);
// The touch interaction occurs too quickly.
// We still want to show ripple effect.
if
((
event
==
null
?
void
0
:
event
.
type
)
===
'touchend'
&&
startTimerCommit
.
current
)
{
startTimerCommit
.
current
();
startTimerCommit
.
current
=
null
;
startTimer
.
current
=
setTimeout
(()
=>
{
stop
(
event
,
cb
);
});
return
;
}
startTimerCommit
.
current
=
null
;
setRipples
(
oldRipples
=>
{
if
(
oldRipples
.
length
>
0
)
{
return
oldRipples
.
slice
(
1
);
}
return
oldRipples
;
});
rippleCallback
.
current
=
cb
;
},
[]);
React
.
useImperativeHandle
(
ref
,
()
=>
({
pulsate
,
start
,
stop
}),
[
pulsate
,
start
,
stop
]);
return
/*#__PURE__*/
_jsx
(
TouchRippleRoot
,
_extends
({
className
:
clsx
(
touchRippleClasses
.
root
,
classes
.
root
,
className
),
ref
:
container
},
other
,
{
children
:
/*#__PURE__*/
_jsx
(
TransitionGroup
,
{
component
:
null
,
exit
:
true
,
children
:
ripples
})
}));
});
process
.
env
.
NODE_ENV
!==
"production"
?
TouchRipple
.
propTypes
=
{
/**
* If `true`, the ripple starts at the center of the component
* rather than at the point of interaction.
*/
center
:
PropTypes
.
bool
,
/**
* Override or extend the styles applied to the component.
* See [CSS API](#css) below for more details.
*/
classes
:
PropTypes
.
object
,
/**
* @ignore
*/
className
:
PropTypes
.
string
}
:
void
0
;
export
default
TouchRipple
;
Event Timeline
Log In to Comment