antd/lib/select#RefSelectProps TypeScript Examples

The following examples show how to use antd/lib/select#RefSelectProps. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SelectGradientOverflow.tsx    From posthog-foss with MIT License 4 votes vote down vote up
/**
 * Ant Design Select extended with a gradient overlay to indicate a scrollable list.
 */
export function SelectGradientOverflow({
    autoFocus = false,
    defaultOpen = false,
    delayBeforeAutoOpen,
    dropdownMatchSelectWidth = true,
    handleBlur = () => {},
    placement,
    propertyKey,
    ...props
}: SelectGradientOverflowProps): JSX.Element {
    const selectRef: React.RefObject<RefSelectProps> | null = useRef(null)
    const containerRef: React.RefObject<HTMLDivElement> = useRef(null)
    const dropdownRef = useRef<HTMLDivElement>(null)
    const [isOpen, setOpen] = useState(false)
    const { formatForDisplay } = useValues(propertyDefinitionsModel)

    /**
     * Ant Design Tag with custom styling in .scss to match default style
     */
    function CustomTag({ label, onClose, value }: CustomTagProps): JSX.Element {
        // if this component is displaying a list of PropertyFilterValues it needs to format them for display
        if (typeof label === 'string' && propertyKey) {
            label = formatForDisplay(propertyKey, label)
        }
        return (
            <Tooltip title={toString(value)}>
                <Tag>
                    <span className="label">{label}</span>
                    <CloseButton onClick={onClose} />
                </Tag>
            </Tooltip>
        )
    }

    const updateScrollGradient = (): void => {
        const dropdown = dropdownRef.current
        if (!dropdown) {
            return
        }
        const holder: HTMLDivElement | null = dropdown.querySelector('.rc-virtual-list-holder')
        if (!holder) {
            return
        }
        if (holder.scrollTop > 0) {
            dropdown.classList.add('scrollable-above')
        } else {
            dropdown.classList.remove('scrollable-above')
        }
        if (holder.scrollHeight > holder.scrollTop + holder.offsetHeight) {
            holder.classList.add('scrollable-below')
        } else {
            holder.classList.remove('scrollable-below')
        }
    }

    const onFocus: React.FocusEventHandler<HTMLElement> = (e) => {
        props.onFocus?.(e)
        setTimeout(() => setOpen(true), delayBeforeAutoOpen || 0)
    }

    const onBlur: React.FocusEventHandler<HTMLElement> = (e) => {
        props.onBlur?.(e)
        if (isOpen) {
            setOpen(false)
            handleBlur()
        }
    }

    useEffect(() => {
        if (autoFocus || defaultOpen) {
            selectRef.current?.focus()
        }
    }, [autoFocus, defaultOpen])

    const outsideClickListener = (event: any): void => {
        if (!containerRef.current?.contains(event.target) && !dropdownRef.current?.contains(event.target) && isOpen) {
            selectRef.current?.blur()
        }
    }
    document.addEventListener('click', outsideClickListener)

    return (
        <div ref={containerRef} style={{ width: '100%' }}>
            {/*
            This config provider is used to configure the empty data state on the wrapped
            ANT select component
             */}
            <ConfigProvider
                renderEmpty={() => {
                    if (props.loading) {
                        return (
                            <div className="illustration-main" style={{ textAlign: 'center' }}>
                                <LoadingOutlined style={{ fontSize: 20 }} />
                                <div>Loading data</div>
                            </div>
                        )
                    } else {
                        return (
                            <div className="illustration-main">
                                <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="No data" />
                            </div>
                        )
                    }
                }}
            >
                <Select
                    {...props}
                    dropdownAlign={placement ? ANTD_TOOLTIP_PLACEMENTS[placement] : undefined}
                    ref={selectRef}
                    open={isOpen}
                    onFocus={onFocus}
                    onBlur={onBlur}
                    onPopupScroll={() => {
                        updateScrollGradient()
                    }}
                    tagRender={CustomTag}
                    dropdownRender={(menu) => (
                        <DropdownGradientRenderer
                            menu={menu}
                            innerRef={dropdownRef}
                            updateScrollGradient={updateScrollGradient}
                        />
                    )}
                    dropdownMatchSelectWidth={dropdownMatchSelectWidth}
                >
                    {props.children}
                </Select>
            </ConfigProvider>
        </div>
    )
}
Example #2
Source File: FunnelConversionWindowFilter.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function FunnelConversionWindowFilter({ horizontal }: { horizontal?: boolean }): JSX.Element {
    const { insightProps } = useValues(insightLogic)
    const { conversionWindow, aggregationTargetLabel, filters } = useValues(funnelLogic(insightProps))
    const { setFilters } = useActions(funnelLogic(insightProps))
    const [localConversionWindow, setLocalConversionWindow] = useState<FunnelConversionWindow>(conversionWindow)
    const timeUnitRef: React.RefObject<RefSelectProps> | null = useRef(null)

    const options = Object.keys(TIME_INTERVAL_BOUNDS).map((unit) => ({
        label: pluralize(conversionWindow.funnel_window_interval ?? 7, unit, `${unit}s`, false),
        value: unit,
    }))
    const intervalBounds =
        TIME_INTERVAL_BOUNDS[conversionWindow.funnel_window_interval_unit ?? FunnelConversionWindowTimeUnit.Day]

    const setConversionWindow = useDebouncedCallback((): void => {
        if (
            localConversionWindow.funnel_window_interval !== conversionWindow.funnel_window_interval ||
            localConversionWindow.funnel_window_interval_unit !== conversionWindow.funnel_window_interval_unit
        ) {
            setFilters(localConversionWindow)
        }
    }, 200)

    return (
        <div
            className={clsx('funnel-options-container', horizontal && 'flex-center')}
            style={horizontal ? { flexDirection: 'row' } : undefined}
        >
            <span className="funnel-options-label">
                Conversion window limit{' '}
                <Tooltip
                    title={
                        <>
                            <b>Recommended!</b> Limit to {aggregationTargetLabel.plural}{' '}
                            {filters.aggregation_group_type_index != undefined ? 'that' : 'who'} converted within a
                            specific time frame. {capitalizeFirstLetter(aggregationTargetLabel.plural)}{' '}
                            {filters.aggregation_group_type_index != undefined ? 'that' : 'who'} do not convert in this
                            time frame will be considered as drop-offs.
                        </>
                    }
                >
                    <InfoCircleOutlined className="info-indicator" />
                </Tooltip>
            </span>
            <Row className="funnel-options-inputs" style={horizontal ? { paddingLeft: 8 } : undefined}>
                <InputNumber
                    className="time-value-input"
                    min={intervalBounds[0]}
                    max={intervalBounds[1]}
                    defaultValue={conversionWindow.funnel_window_interval}
                    value={localConversionWindow.funnel_window_interval}
                    onChange={(funnel_window_interval) => {
                        setLocalConversionWindow((state) => ({
                            ...state,
                            funnel_window_interval: Number(funnel_window_interval),
                        }))
                        setConversionWindow()
                    }}
                    onBlur={setConversionWindow}
                    onPressEnter={setConversionWindow}
                />
                <Select
                    ref={timeUnitRef}
                    className="time-unit-input"
                    defaultValue={conversionWindow.funnel_window_interval_unit}
                    dropdownMatchSelectWidth={false}
                    value={localConversionWindow.funnel_window_interval_unit}
                    onChange={(funnel_window_interval_unit: FunnelConversionWindowTimeUnit) => {
                        setLocalConversionWindow((state) => ({ ...state, funnel_window_interval_unit }))
                        setConversionWindow()
                    }}
                    onBlur={setConversionWindow}
                >
                    {options.map(({ value, label }) => (
                        <Select.Option value={value} key={value}>
                            {label}
                        </Select.Option>
                    ))}
                </Select>
            </Row>
        </div>
    )
}