atmosphere explorer pds.ls
tool typescript atproto

show summary when value collapsed

handle.invalid 4441a51c 67510d74

verified
+37 -15
+37 -15
src/components/json.tsx
··· 167 167 const [show, setShow] = createSignal(true); 168 168 const isBlobContext = props.parentIsBlob ?? ctx.parentIsBlob; 169 169 170 + const isObject = () => props.value === Object(props.value); 171 + const isCollapsible = () => isObject() || typeof props.value === "string"; 172 + const summary = () => { 173 + if (typeof props.value === "string") { 174 + const len = props.value.length; 175 + return `${len.toLocaleString()} ${len === 1 ? "char" : "chars"}`; 176 + } 177 + if (Array.isArray(props.value)) { 178 + const len = (props.value as JSONType[]).length; 179 + return `[ ${len} ${len === 1 ? "item" : "items"} ]`; 180 + } 181 + if (isObject()) { 182 + const len = Object.keys(props.value as object).length; 183 + return `{ ${len} ${len === 1 ? "key" : "keys"} }`; 184 + } 185 + }; 186 + 170 187 return ( 171 188 <span 172 189 classList={{ 173 190 "group/indent flex gap-x-1 w-full": true, 174 - "flex-col": props.value === Object(props.value), 191 + "flex-col": isObject(), 175 192 }} 176 193 > 177 194 <button 178 - class="group/clip relative flex size-fit shrink-0 items-center wrap-anywhere text-neutral-500 hover:text-neutral-700 active:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-300 dark:active:text-neutral-300" 195 + class="group/clip relative flex size-fit shrink-0 items-center gap-x-1 wrap-anywhere text-neutral-500 hover:text-neutral-700 active:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-300 dark:active:text-neutral-300" 179 196 classList={{ 180 197 "max-w-[40%] sm:max-w-[50%]": props.maxWidth !== undefined, 181 198 }} 182 - onclick={() => setShow(!show())} 199 + onclick={() => isCollapsible() && setShow(!show())} 183 200 > 184 - <span 185 - classList={{ 186 - "dark:bg-dark-500 absolute w-4 flex items-center -left-4 bg-neutral-100 text-sm": true, 187 - "hidden group-hover/clip:flex": show(), 188 - }} 189 - > 190 - {show() ? 191 - <span class="iconify lucide--chevron-down"></span> 192 - : <span class="iconify lucide--chevron-right"></span>} 193 - </span> 201 + <Show when={isCollapsible()}> 202 + <span 203 + classList={{ 204 + "dark:bg-dark-500 absolute w-4 flex items-center -left-4 bg-neutral-100 text-sm": true, 205 + "hidden group-hover/clip:flex": show(), 206 + }} 207 + > 208 + {show() ? 209 + <span class="iconify lucide--chevron-down"></span> 210 + : <span class="iconify lucide--chevron-right"></span>} 211 + </span> 212 + </Show> 194 213 {props.label}: 214 + <Show when={!show() && summary()}> 215 + <span class="text-neutral-400 dark:text-neutral-500">{summary()}</span> 216 + </Show> 195 217 </button> 196 218 <span 197 219 classList={{ 198 - "self-center": props.value !== Object(props.value), 220 + "self-center": !isObject(), 199 221 "pl-[calc(2ch-0.5px)] border-l-[0.5px] border-neutral-500/50 dark:border-neutral-400/50 has-hover:group-hover/indent:border-neutral-700 transition-colors dark:has-hover:group-hover/indent:border-neutral-400": 200 - props.value === Object(props.value), 222 + isObject(), 201 223 "invisible h-0 overflow-hidden": !show(), 202 224 }} 203 225 >