check-list.jsx (2630B)
1 /* 2 GoToSocial 3 Copyright (C) GoToSocial Authors admin@gotosocial.org 4 SPDX-License-Identifier: AGPL-3.0-or-later 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 "use strict"; 21 22 const React = require("react"); 23 24 module.exports = function CheckList({ field, header = "All", EntryComponent, getExtraProps }) { 25 return ( 26 <div className="checkbox-list list"> 27 <CheckListHeader toggleAll={field.toggleAll}> {header}</CheckListHeader> 28 <CheckListEntries 29 entries={field.value} 30 updateValue={field.onChange} 31 EntryComponent={EntryComponent} 32 getExtraProps={getExtraProps} 33 /> 34 </div> 35 ); 36 }; 37 38 function CheckListHeader({ toggleAll, children }) { 39 return ( 40 <label className="header entry"> 41 <input 42 ref={toggleAll.ref} 43 type="checkbox" 44 onChange={toggleAll.onChange} 45 /> {children} 46 </label> 47 ); 48 } 49 50 const CheckListEntries = React.memo( 51 function CheckListEntries({ entries, updateValue, EntryComponent, getExtraProps }) { 52 const deferredEntries = React.useDeferredValue(entries); 53 54 return Object.values(deferredEntries).map((entry) => ( 55 <CheckListEntry 56 key={entry.key} 57 entry={entry} 58 updateValue={updateValue} 59 EntryComponent={EntryComponent} 60 getExtraProps={getExtraProps} 61 /> 62 )); 63 } 64 ); 65 66 /* 67 React.memo is a performance optimization that only re-renders a CheckListEntry 68 when it's props actually change, instead of every time anything 69 in the list (CheckListEntries) updates 70 */ 71 const CheckListEntry = React.memo( 72 function CheckListEntry({ entry, updateValue, getExtraProps, EntryComponent }) { 73 const onChange = React.useCallback( 74 (value) => updateValue(entry.key, value), 75 [updateValue, entry.key] 76 ); 77 78 const extraProps = React.useMemo(() => getExtraProps?.(entry), [getExtraProps, entry]); 79 80 return ( 81 <label className="entry"> 82 <input 83 type="checkbox" 84 onChange={(e) => onChange({ checked: e.target.checked })} 85 checked={entry.checked} 86 /> 87 <EntryComponent entry={entry} onChange={onChange} extraProps={extraProps} /> 88 </label> 89 ); 90 } 91 );