a tool for shared writing and social publishing
at feature/recommend 169 lines 6.3 kB view raw
1import { useUIState } from "src/useUIState"; 2import { ToolbarButton } from "."; 3import { useCallback } from "react"; 4import { Fact, useEntity, useReplicache } from "src/replicache"; 5import { Props } from "components/Icons/Props"; 6 7export function TextAlignmentToolbar() { 8 let focusedBlock = useUIState((s) => s.focusedEntity); 9 let { rep } = useReplicache(); 10 let alignment = useEntity( 11 focusedBlock?.entityID || null, 12 "block/text-alignment", 13 )?.data.value; 14 let setAlignment = useCallback( 15 (alignment: Fact<"block/text-alignment">["data"]["value"]) => { 16 let blocks = useUIState.getState().selectedBlocks; 17 if (focusedBlock?.entityType === "page" || !focusedBlock) return null; 18 rep?.mutate.assertFact( 19 blocks.map((b) => ({ 20 entity: b.value, 21 attribute: "block/text-alignment", 22 data: { type: "text-alignment-type-union", value: alignment }, 23 })), 24 ); 25 }, 26 [focusedBlock, rep], 27 ); 28 return ( 29 <> 30 <ToolbarButton 31 onClick={() => setAlignment("left")} 32 tooltipContent="Align Left" 33 active={alignment === "left"} 34 > 35 <AlignLeftSmall /> 36 </ToolbarButton> 37 <ToolbarButton 38 onClick={() => setAlignment("center")} 39 tooltipContent="Align Center" 40 active={alignment === "center"} 41 > 42 <AlignCenterSmall /> 43 </ToolbarButton> 44 <ToolbarButton 45 onClick={() => setAlignment("right")} 46 tooltipContent="Align Right" 47 active={alignment === "right"} 48 > 49 <AlignRightSmall /> 50 </ToolbarButton> 51 52 <ToolbarButton 53 onClick={() => setAlignment("justify")} 54 tooltipContent="Align Justified" 55 active={alignment === "justify"} 56 > 57 <AlignJustifiedSmall /> 58 </ToolbarButton> 59 </> 60 ); 61} 62 63export function TextAlignmentButton(props: { 64 setToolbarState: (s: "text-alignment") => void; 65 className?: string; 66}) { 67 let focusedBlock = useUIState((s) => s.focusedEntity); 68 let alignment = 69 useEntity(focusedBlock?.entityID || null, "block/text-alignment")?.data 70 .value || "left"; 71 return ( 72 <ToolbarButton 73 hiddenOnCanvas 74 tooltipContent={<div>Align</div>} 75 className={`${props.className}`} 76 onClick={() => { 77 props.setToolbarState("text-alignment"); 78 }} 79 > 80 {alignment === "left" ? ( 81 <AlignLeftSmall /> 82 ) : alignment === "center" ? ( 83 <AlignCenterSmall /> 84 ) : alignment === "justify" ? ( 85 <AlignJustifiedSmall /> 86 ) : ( 87 <AlignRightSmall /> 88 )} 89 </ToolbarButton> 90 ); 91} 92 93export const AlignLeftSmall = (props: Props) => { 94 return ( 95 <svg 96 width="24" 97 height="24" 98 viewBox="0 0 24 24" 99 fill="none" 100 xmlns="http://www.w3.org/2000/svg" 101 {...props} 102 > 103 <path 104 fillRule="evenodd" 105 clipRule="evenodd" 106 d="M3.5 6.19983C3.5 5.64754 3.94772 5.19983 4.5 5.19983H19.6547C20.2069 5.19983 20.6547 5.64754 20.6547 6.19983C20.6547 6.75211 20.2069 7.19983 19.6547 7.19983H4.5C3.94772 7.19983 3.5 6.75211 3.5 6.19983ZM3.5 12C3.5 11.4477 3.94772 11 4.5 11H12.8243C13.3766 11 13.8243 11.4477 13.8243 12C13.8243 12.5523 13.3766 13 12.8243 13H4.5C3.94772 13 3.5 12.5523 3.5 12ZM4.5 16.7999C3.94772 16.7999 3.5 17.2476 3.5 17.7999C3.5 18.3522 3.94772 18.7999 4.5 18.7999H16.1426C16.6949 18.7999 17.1426 18.3522 17.1426 17.7999C17.1426 17.2476 16.6949 16.7999 16.1426 16.7999H4.5Z" 107 fill="currentColor" 108 /> 109 </svg> 110 ); 111}; 112export const AlignCenterSmall = (props: Props) => { 113 return ( 114 <svg 115 width="24" 116 height="24" 117 viewBox="0 0 24 24" 118 fill="none" 119 xmlns="http://www.w3.org/2000/svg" 120 {...props} 121 > 122 <path 123 fillRule="evenodd" 124 clipRule="evenodd" 125 d="M3.5 6.19983C3.5 5.64754 3.94772 5.19983 4.5 5.19983H19.6547C20.2069 5.19983 20.6547 5.64754 20.6547 6.19983C20.6547 6.75211 20.2069 7.19983 19.6547 7.19983H4.5C3.94772 7.19983 3.5 6.75211 3.5 6.19983ZM6.91519 12C6.91519 11.4477 7.36291 11 7.91519 11H16.2395C16.7918 11 17.2395 11.4477 17.2395 12C17.2395 12.5523 16.7918 13 16.2395 13H7.91519C7.36291 13 6.91519 12.5523 6.91519 12ZM6.25601 16.7999C5.70373 16.7999 5.25601 17.2476 5.25601 17.7999C5.25601 18.3522 5.70373 18.7999 6.25601 18.7999H17.8987C18.4509 18.7999 18.8987 18.3522 18.8987 17.7999C18.8987 17.2476 18.4509 16.7999 17.8987 16.7999H6.25601Z" 126 fill="currentColor" 127 /> 128 </svg> 129 ); 130}; 131export const AlignRightSmall = (props: Props) => { 132 return ( 133 <svg 134 width="24" 135 height="24" 136 viewBox="0 0 24 24" 137 fill="none" 138 xmlns="http://www.w3.org/2000/svg" 139 {...props} 140 > 141 <path 142 fillRule="evenodd" 143 clipRule="evenodd" 144 d="M3.5 6.19983C3.5 5.64754 3.94772 5.19983 4.5 5.19983H19.6547C20.2069 5.19983 20.6547 5.64754 20.6547 6.19983C20.6547 6.75211 20.2069 7.19983 19.6547 7.19983H4.5C3.94772 7.19983 3.5 6.75211 3.5 6.19983ZM10.3304 12C10.3304 11.4477 10.7781 11 11.3304 11H19.6547C20.2069 11 20.6547 11.4477 20.6547 12C20.6547 12.5523 20.2069 13 19.6547 13H11.3304C10.7781 13 10.3304 12.5523 10.3304 12ZM8.01202 16.7999C7.45974 16.7999 7.01202 17.2476 7.01202 17.7999C7.01202 18.3522 7.45974 18.7999 8.01202 18.7999H19.6547C20.2069 18.7999 20.6547 18.3522 20.6547 17.7999C20.6547 17.2476 20.2069 16.7999 19.6547 16.7999H8.01202Z" 145 fill="currentColor" 146 /> 147 </svg> 148 ); 149}; 150 151export const AlignJustifiedSmall = (props: Props) => { 152 return ( 153 <svg 154 width="24" 155 height="24" 156 viewBox="0 0 24 24" 157 fill="none" 158 xmlns="http://www.w3.org/2000/svg" 159 {...props} 160 > 161 <path 162 fillRule="evenodd" 163 clipRule="evenodd" 164 d="M3.5 6.19983C3.5 5.64754 3.94772 5.19983 4.5 5.19983H19.6547C20.2069 5.19983 20.6547 5.64754 20.6547 6.19983C20.6547 6.75211 20.2069 7.19983 19.6547 7.19983H4.5C3.94772 7.19983 3.5 6.75211 3.5 6.19983ZM3.5 12C3.5 11.4477 3.94772 11 4.5 11H19.6547C20.2069 11 20.6547 11.4477 20.6547 12C20.6547 12.5523 20.2069 13 19.6547 13H4.5C3.94772 13 3.5 12.5523 3.5 12ZM4.5 16.7999C3.94772 16.7999 3.5 17.2476 3.5 17.7999C3.5 18.3522 3.94772 18.7999 4.5 18.7999H19.6547C20.2069 18.7999 20.6547 18.3522 20.6547 17.7999C20.6547 17.2476 20.2069 16.7999 19.6547 16.7999H4.5Z" 165 fill="currentColor" 166 /> 167 </svg> 168 ); 169};