a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

only render datetime blocks on client and fade in on ssr

+65 -36
+65 -36
components/Blocks/DateTimeBlock.tsx
··· 9 9 import { setHours, setMinutes } from "date-fns"; 10 10 import { Separator } from "react-aria-components"; 11 11 import { Checkbox } from "components/Checkbox"; 12 + import { useInitialPageLoad } from "components/InitialPageLoadProvider"; 13 + import { useSpring, animated } from "@react-spring/web"; 12 14 13 15 export function DateTimeBlock(props: BlockProps) { 16 + const [isClient, setIsClient] = useState(false); 17 + let initialPageLoad = useInitialPageLoad(); 18 + 19 + useEffect(() => { 20 + setIsClient(true); 21 + }, []); 22 + 23 + if (!isClient && !initialPageLoad) 24 + return ( 25 + <div 26 + className={`flex flex-row gap-2 group/date w-64 z-[1] border border-transparent`} 27 + > 28 + <BlockCalendarSmall className="text-tertiary" /> 29 + </div> 30 + ); 31 + 32 + return <BaseDateTimeBlock {...props} initalLoad={initialPageLoad} />; 33 + } 34 + 35 + export function BaseDateTimeBlock( 36 + props: BlockProps & { initalLoad?: boolean }, 37 + ) { 14 38 let { rep } = useReplicache(); 15 39 let { permissions } = useEntitySetContext(); 16 40 let dateFact = useEntity(props.entityID, "block/date-time"); 17 41 let selectedDate = useMemo(() => { 18 42 if (!dateFact) return new Date(); 19 - return new Date(dateFact.data.value); 43 + let d = new Date(dateFact.data.value); 44 + return d; 20 45 }, [dateFact]); 21 46 22 47 const [timeValue, setTimeValue] = useState<string>( ··· 24 49 `${selectedDate.getHours().toString().padStart(2, "0")}:${selectedDate.getMinutes().toString().padStart(2, "0")}`, 25 50 ); 26 51 27 - useEffect(() => { 28 - setTimeValue( 29 - `${selectedDate.getHours().toString().padStart(2, "0")}:${selectedDate.getMinutes().toString().padStart(2, "0")}`, 30 - ); 31 - }, [selectedDate]); 32 - 33 52 let isSelected = useUIState((s) => 34 53 s.selectedBlocks.find((b) => b.value === props.entityID), 35 54 ); ··· 38 57 39 58 const handleTimeChange: React.ChangeEventHandler<HTMLInputElement> = (e) => { 40 59 const time = e.target.value; 60 + setTimeValue(time); 41 61 if (!dateFact) { 42 - setTimeValue(time); 43 62 return; 44 63 } 45 64 const [hours, minutes] = time.split(":").map((str) => parseInt(str, 10)); ··· 54 73 }, 55 74 attribute: "block/date-time", 56 75 }); 57 - setTimeValue(time); 58 76 }; 59 77 60 78 const handleDaySelect = (date: Date | undefined) => { ··· 107 125 `} 108 126 > 109 127 <BlockCalendarSmall className="text-tertiary" /> 110 - {dateFact ? ( 111 - <div 112 - suppressHydrationWarning={true} 113 - className={`font-bold 128 + <FadeIn 129 + active={props.initalLoad === undefined ? true : props.initalLoad} 130 + > 131 + {dateFact ? ( 132 + <div 133 + className={`font-bold 114 134 ${!permissions.write || isLocked ? "" : "group-hover/date:underline"} 115 135 `} 116 - > 117 - {selectedDate.toLocaleDateString(undefined, { 118 - month: "short", 119 - year: "numeric", 120 - day: "numeric", 121 - })}{" "} 122 - {!dateFact.data.dateOnly ? ( 123 - <span suppressHydrationWarning={true}> 124 - |{" "} 125 - {selectedDate.toLocaleTimeString(undefined, { 126 - hour: "numeric", 127 - minute: "numeric", 128 - })} 129 - </span> 130 - ) : null} 131 - </div> 132 - ) : ( 133 - <div 134 - className={`italic text-tertiary text-left group-hover/date:underline`} 135 - > 136 - {permissions.write ? "add a date and time..." : "TBD..."} 137 - </div> 138 - )} 136 + > 137 + {selectedDate.toLocaleDateString(undefined, { 138 + month: "short", 139 + year: 140 + new Date().getFullYear() !== selectedDate.getFullYear() 141 + ? "numeric" 142 + : undefined, 143 + day: "numeric", 144 + })}{" "} 145 + {!dateFact.data.dateOnly ? ( 146 + <span> 147 + |{" "} 148 + {selectedDate.toLocaleTimeString([], { 149 + hour: "numeric", 150 + minute: "numeric", 151 + })} 152 + </span> 153 + ) : null} 154 + </div> 155 + ) : ( 156 + <div 157 + className={`italic text-tertiary text-left group-hover/date:underline`} 158 + > 159 + {permissions.write ? "add a date and time..." : "TBD..."} 160 + </div> 161 + )} 162 + </FadeIn> 139 163 </div> 140 164 } 141 165 > ··· 197 221 </Popover> 198 222 ); 199 223 } 224 + 225 + let FadeIn = (props: { children: React.ReactNode; active: boolean }) => { 226 + let spring = useSpring({ opacity: props.active ? 1 : 0 }); 227 + return <animated.div style={spring}>{props.children}</animated.div>; 228 + }; 200 229 201 230 const CustomChevron = (props: ChevronProps) => { 202 231 return (