import type { Component, JSX } from 'solid-js' import type { IconName } from './mini-components' import { A, useLocation, useSearchParams } from '@solidjs/router' import { Logger } from 'besonders-logger' import { createMemo, For, Show, splitProps } from 'solid-js' import { useSearchContext } from '../data/search' import { useAppSettings } from '../ui/app-settings' import { useFocus } from '../ui/reactive' import { replaceSearchParamsInUrl, useLocationNavigate } from '../ui/utils-ui' import { Iconify } from './mini-components' const { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line unused-imports/no-unused-vars interface Pill { key: string title?: string icon?: IconName link?: string | Record filter?: string isActive?: boolean } const ByTag = { key: 'by-tag', icon: 'tag', title: 'By Tag', filter: 'by-tag' } as const const Timeline = { key: 'timeline', icon: 'clock-light', title: 'Timeline', link: `/timeline` } as const function HomeBlock() { const appSettings = useAppSettings() return { key: 'home', icon: 'house', title: 'Home', link: `/block/${appSettings.homeBlock}` } as const } export const Pills = { ByTag, Timeline, HomeBlock, } as const export const PillFilter: Component< JSX.HTMLAttributes & { leftPills?: Pill[] rightPills?: Pill[] } > = (allProps) => { const [props, restProps] = splitProps(allProps, ['leftPills', 'rightPills']) const { locnav, location, navigate } = useLocationNavigate() const focus = useFocus() const appSettings = useAppSettings() const [search, setSearch] = useSearchContext() const [params, setParams] = useSearchParams() const leftPills = createMemo(() => { const pills = props.leftPills ?? [] const isOnHomeBlock = !!(focus() === appSettings.homeBlock) if (!isOnHomeBlock && focus() || params.preview) return pills // HACK: if params.pub, then too - refactor the responsibility outta here if (!search()) { // TODO refactor to props pills.push(HomeBlock()) pills.push(Timeline) } DEBUG(`leftPills:`, pills) return pills satisfies readonly Pill[] }) const rightPills = createMemo(() => { const pills = props.rightPills ?? [] if (search()) { pills.push(ByTag) } // if (focus()) return pills DEBUG(`rightPills:`, pills) return pills satisfies readonly Pill[] }) return (
{ /* {'Title'} */ }
{pill => }
{pill => }
) } const SinglePill: Component<{ pill: Pill }> = (props) => { const location = useLocation() const [params, setParams] = useSearchParams() const activeFilters = useFilters() const isActive = createMemo(() => props.pill.isActive || (typeof props.pill.link === 'string' && location.pathname.startsWith(props.pill.link)) || activeFilters().includes(props.pill.key), ) const filterAfterToggle = createMemo(() => isActive() ? params.filters?.replace(props.pill.filter ?? props.pill.key, '').trim() : `${params.filters ?? ''} ${props.pill.filter ?? props.pill.key}`.trim(), ) const link = createMemo(() => { if (props.pill.link) { if (typeof props.pill.link === 'string') { return `${props.pill.link}${new URLSearchParams(location.query).size ? '?' : ''}${new URLSearchParams(location.query).toString()}` // (i) keep search, filters, ... } const url = location if (Object.keys(props.pill.link).length !== 1) throw new Error(`TODO: pill link multi param`) for (const [param, val] of Object.entries(props.pill.link)) { return replaceSearchParamsInUrl(location, { [param]: val }) } } return replaceSearchParamsInUrl(location, { filters: filterAfterToggle() }) }) return ( {props.pill.title} ) } export function useFilters() { const [params] = useSearchParams() return createMemo(() => { const filterStrings = (params.filters && !Array.isArray(params.filters)) // params weirdly might be string or array :/ ? [params.filters] as const : params.filters as string[] | null const tokens = filterStrings?.flatMap(f => f.split(/\s+/)) DEBUG(`Search tokens`, { tokens, search: params.filters }) return tokens ?? [] }) }