@@ -133,35 +133,34 @@ export function useClickAway(cb) {
133
133
return ref ;
134
134
}
135
135
136
- export function useCopyToClipboard ( ) {
137
- const [ state , setState ] = React . useState ( {
138
- error : null ,
139
- text : null ,
140
- } ) ;
141
-
142
- const copyToClipboard = React . useCallback ( async ( value ) => {
143
- if ( ! navigator ?. clipboard ) {
144
- return setState ( {
145
- error : new Error ( "Clipboard not supported" ) ,
146
- text : null ,
147
- } ) ;
148
- }
136
+ function oldSchoolCopy ( text ) {
137
+ const tempTextArea = document . createElement ( "textarea" ) ;
138
+ tempTextArea . value = text ;
139
+ document . body . appendChild ( tempTextArea ) ;
140
+ tempTextArea . select ( ) ;
141
+ document . execCommand ( "copy" ) ;
142
+ document . body . removeChild ( tempTextArea ) ;
143
+ }
149
144
150
- const handleSuccess = ( ) => {
151
- setState ( {
152
- error : null ,
153
- text : value ,
154
- } ) ;
155
- } ;
145
+ export function useCopyToClipboard ( ) {
146
+ const [ state , setState ] = React . useState ( null ) ;
156
147
157
- const handleFailure = ( e ) => {
158
- setState ( {
159
- error : e ,
160
- text : null ,
161
- } ) ;
148
+ const copyToClipboard = React . useCallback ( ( value ) => {
149
+ const handleCopy = async ( ) => {
150
+ try {
151
+ if ( navigator ?. clipboard ?. writeText ) {
152
+ await navigator . clipboard . writeText ( value ) ;
153
+ setState ( value ) ;
154
+ } else {
155
+ throw new Error ( "writeText not supported" ) ;
156
+ }
157
+ } catch ( e ) {
158
+ oldSchoolCopy ( value ) ;
159
+ setState ( value ) ;
160
+ }
162
161
} ;
163
162
164
- navigator . clipboard . writeText ( value ) . then ( handleSuccess , handleFailure ) ;
163
+ handleCopy ( ) ;
165
164
} , [ ] ) ;
166
165
167
166
return [ state , copyToClipboard ] ;
@@ -493,38 +492,38 @@ const initialUseHistoryStateState = {
493
492
494
493
const useHistoryStateReducer = ( state , action ) => {
495
494
const { past, present, future } = state ;
496
- switch ( action . type ) {
497
- case "UNDO" :
498
- return {
499
- past : past . slice ( 0 , past . length - 1 ) ,
500
- present : past [ past . length - 1 ] ,
501
- future : [ present , ...future ] ,
502
- } ;
503
- case "REDO" :
504
- return {
505
- past : [ ...past , present ] ,
506
- present : future [ 0 ] ,
507
- future : future . slice ( 1 ) ,
508
- } ;
509
- case "SET" :
510
- const { newPresent } = action ;
511
495
512
- if ( action . newPresent === present ) {
513
- return state ;
514
- }
496
+ if ( action . type === "UNDO" ) {
497
+ return {
498
+ past : past . slice ( 0 , past . length - 1 ) ,
499
+ present : past [ past . length - 1 ] ,
500
+ future : [ present , ...future ] ,
501
+ } ;
502
+ } else if ( action . type === "REDO" ) {
503
+ return {
504
+ past : [ ...past , present ] ,
505
+ present : future [ 0 ] ,
506
+ future : future . slice ( 1 ) ,
507
+ } ;
508
+ } else if ( action . type === "SET" ) {
509
+ const { newPresent } = action ;
515
510
516
- return {
517
- past : [ ...past , present ] ,
518
- present : newPresent ,
519
- future : [ ] ,
520
- } ;
521
- case "CLEAR" :
522
- return {
523
- ...initialUseHistoryStateState ,
524
- present : action . initialPresent ,
525
- } ;
526
- default :
527
- throw new Error ( "Unsupported action type" ) ;
511
+ if ( action . newPresent === present ) {
512
+ return state ;
513
+ }
514
+
515
+ return {
516
+ past : [ ...past , present ] ,
517
+ present : newPresent ,
518
+ future : [ ] ,
519
+ } ;
520
+ } else if ( action . type === "CLEAR" ) {
521
+ return {
522
+ ...initialState ,
523
+ present : action . initialPresent ,
524
+ } ;
525
+ } else {
526
+ throw new Error ( "Unsupported action type" ) ;
528
527
}
529
528
} ;
530
529
@@ -764,40 +763,29 @@ export function useKeyPress(key, cb, options = {}) {
764
763
export function useList ( defaultList = [ ] ) {
765
764
const [ list , setList ] = React . useState ( defaultList ) ;
766
765
767
- const methods = React . useMemo ( ( ) => {
768
- const set = ( l ) => {
769
- setList ( l ) ;
770
- } ;
771
-
772
- const push = ( element ) => {
773
- setList ( ( l ) => [ ...l , element ] ) ;
774
- } ;
775
-
776
- const removeAt = ( index ) => {
777
- setList ( ( l ) => [ ...l . slice ( 0 , index ) , ...l . slice ( index + 1 ) ] ) ;
778
- } ;
766
+ const set = React . useCallback ( ( l ) => {
767
+ setList ( l ) ;
768
+ } , [ ] ) ;
779
769
780
- const insertAt = ( index , element ) => {
781
- setList ( ( l ) => [ ...l . slice ( 0 , index ) , element , ... l . slice ( index ) ] ) ;
782
- } ;
770
+ const push = React . useCallback ( ( element ) => {
771
+ setList ( ( l ) => [ ...l , element ] ) ;
772
+ } , [ ] ) ;
783
773
784
- const updateAt = ( index , element ) => {
785
- setList ( ( l ) => l . map ( ( e , i ) => ( i === index ? element : e ) ) ) ;
786
- } ;
774
+ const removeAt = React . useCallback ( ( index ) => {
775
+ setList ( ( l ) => [ ... l . slice ( 0 , index ) , ... l . slice ( index + 1 ) ] ) ;
776
+ } , [ ] ) ;
787
777
788
- const clear = ( ) => setList ( [ ] ) ;
778
+ const insertAt = React . useCallback ( ( index , element ) => {
779
+ setList ( ( l ) => [ ...l . slice ( 0 , index ) , element , ...l . slice ( index ) ] ) ;
780
+ } , [ ] ) ;
789
781
790
- return {
791
- set,
792
- push,
793
- removeAt,
794
- insertAt,
795
- updateAt,
796
- clear,
797
- } ;
782
+ const updateAt = React . useCallback ( ( index , element ) => {
783
+ setList ( ( l ) => l . map ( ( e , i ) => ( i === index ? element : e ) ) ) ;
798
784
} , [ ] ) ;
799
785
800
- return [ list , methods ] ;
786
+ const clear = React . useCallback ( ( ) => setList ( [ ] ) , [ ] ) ;
787
+
788
+ return [ list , { set, push, removeAt, insertAt, updateAt, clear } ] ;
801
789
}
802
790
803
791
export function useLocalStorage ( key , initialValue ) {
@@ -1064,8 +1052,6 @@ export function useMouse() {
1064
1052
const elementX = event . pageX - elementPositionX ;
1065
1053
const elementY = event . pageY - elementPositionY ;
1066
1054
1067
- newState . elementX = elementX ;
1068
- newState . elementY = elementY ;
1069
1055
newState . elementX = elementX ;
1070
1056
newState . elementY = elementY ;
1071
1057
newState . elementPositionX = elementPositionX ;
@@ -1090,18 +1076,23 @@ export function useMouse() {
1090
1076
return [ state , ref ] ;
1091
1077
}
1092
1078
1093
- export function useNetworkState ( ) {
1094
- const connection =
1079
+ const getConnection = ( ) => {
1080
+ return (
1095
1081
navigator ?. connection ||
1096
1082
navigator ?. mozConnection ||
1097
- navigator ?. webkitConnection ;
1083
+ navigator ?. webkitConnection
1084
+ ) ;
1085
+ } ;
1098
1086
1087
+ export function useNetworkState ( ) {
1099
1088
const cache = React . useRef ( { } ) ;
1100
1089
1101
1090
const subscribe = React . useCallback ( ( callback ) => {
1102
1091
window . addEventListener ( "online" , callback , { passive : true } ) ;
1103
1092
window . addEventListener ( "offline" , callback , { passive : true } ) ;
1104
1093
1094
+ const connection = getConnection ( ) ;
1095
+
1105
1096
if ( connection ) {
1106
1097
connection . addEventListener ( "change" , callback , { passive : true } ) ;
1107
1098
}
@@ -1118,6 +1109,7 @@ export function useNetworkState() {
1118
1109
1119
1110
const getSnapshot = ( ) => {
1120
1111
const online = navigator . onLine ;
1112
+ const connection = getConnection ( ) ;
1121
1113
1122
1114
const nextState = {
1123
1115
online,
@@ -1491,57 +1483,6 @@ export function useSet(values) {
1491
1483
return setRef . current ;
1492
1484
}
1493
1485
1494
- export function useSpeech ( text , options ) {
1495
- const [ state , setState ] = React . useState ( ( ) => {
1496
- const { lang = "default" , name = "" } = options . voice || { } ;
1497
- return {
1498
- isPlaying : false ,
1499
- status : "init" ,
1500
- lang : options . lang || "default" ,
1501
- voiceInfo : { lang, name } ,
1502
- rate : options . rate || 1 ,
1503
- pitch : options . pitch || 1 ,
1504
- volume : options . volume || 1 ,
1505
- } ;
1506
- } ) ;
1507
-
1508
- const optionsRef = React . useRef ( options ) ;
1509
-
1510
- React . useEffect ( ( ) => {
1511
- const handlePlay = ( ) => {
1512
- setState ( ( s ) => {
1513
- return { ...s , isPlaying : true , status : "play" } ;
1514
- } ) ;
1515
- } ;
1516
-
1517
- const handlePause = ( ) => {
1518
- setState ( ( s ) => {
1519
- return { ...s , isPlaying : false , status : "pause" } ;
1520
- } ) ;
1521
- } ;
1522
-
1523
- const handleEnd = ( ) => {
1524
- setState ( ( s ) => {
1525
- return { ...s , isPlaying : false , status : "end" } ;
1526
- } ) ;
1527
- } ;
1528
-
1529
- const utterance = new SpeechSynthesisUtterance ( text ) ;
1530
- optionsRef . current . lang && ( utterance . lang = optionsRef . current . lang ) ;
1531
- optionsRef . current . voice && ( utterance . voice = optionsRef . current . voice ) ;
1532
- utterance . rate = optionsRef . current . rate || 1 ;
1533
- utterance . pitch = optionsRef . current . pitch || 1 ;
1534
- utterance . volume = optionsRef . current . volume || 1 ;
1535
- utterance . onstart = handlePlay ;
1536
- utterance . onpause = handlePause ;
1537
- utterance . onresume = handlePlay ;
1538
- utterance . onend = handleEnd ;
1539
- window . speechSynthesis . speak ( utterance ) ;
1540
- } , [ text ] ) ;
1541
-
1542
- return state ;
1543
- }
1544
-
1545
1486
export function useThrottle ( value , interval = 500 ) {
1546
1487
const [ throttledValue , setThrottledValue ] = React . useState ( value ) ;
1547
1488
const lastUpdated = React . useRef ( ) ;
@@ -1596,27 +1537,30 @@ export function useToggle(initialValue) {
1596
1537
return [ on , handleToggle ] ;
1597
1538
}
1598
1539
1599
- export function useVisibilityChange ( ) {
1600
- const [ documentVisible , setDocumentVisibility ] = React . useState ( true ) ;
1540
+ const useVisibilityChangeSubscribe = ( callback ) => {
1541
+ document . addEventListener ( "visibilitychange" , callback ) ;
1601
1542
1602
- React . useEffect ( ( ) => {
1603
- const handleChange = ( ) => {
1604
- if ( document . visibilityState !== "visible" ) {
1605
- setDocumentVisibility ( false ) ;
1606
- } else {
1607
- setDocumentVisibility ( true ) ;
1608
- }
1609
- } ;
1610
- handleChange ( ) ;
1543
+ return ( ) => {
1544
+ document . removeEventListener ( "visibilitychange" , callback ) ;
1545
+ } ;
1546
+ } ;
1611
1547
1612
- document . addEventListener ( "visibilitychange" , handleChange ) ;
1548
+ const getVisibilityChangeSnapshot = ( ) => {
1549
+ return document . visibilityState ;
1550
+ } ;
1613
1551
1614
- return ( ) => {
1615
- document . removeEventListener ( "visibilitychange" , handleChange ) ;
1616
- } ;
1617
- } , [ ] ) ;
1552
+ const getVisibilityChangeServerSnapshot = ( ) => {
1553
+ throw Error ( "useVisibilityChange is a client-only hook" ) ;
1554
+ } ;
1555
+
1556
+ export function useVisibilityChange ( ) {
1557
+ const visibilityState = React . useSyncExternalStore (
1558
+ useVisibilityChangeSubscribe ,
1559
+ getVisibilityChangeSnapshot ,
1560
+ getVisibilityChangeServerSnapshot
1561
+ ) ;
1618
1562
1619
- return documentVisible ;
1563
+ return visibilityState === "visible" ;
1620
1564
}
1621
1565
1622
1566
export function useWindowScroll ( ) {
0 commit comments