import React, { Fragment, useState, useEffect, useRef } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' import { window, document } from 'browser-monads' import Section from './section' import Icon from './icon' import { H2 } from './typography' import { copyToClipboard } from './copy' import classes from '../styles/quickstart.module.sass' function getNewChecked(optionId, checkedForId, multiple) { if (!multiple) return [optionId] if (checkedForId.includes(optionId)) return checkedForId.filter(opt => opt !== optionId) return [...checkedForId, optionId] } const Quickstart = ({ data = [], title, description, copy = true, download, rawContent = null, id = 'quickstart', setters = {}, hidePrompts, small, codeLang, children, }) => { const contentRef = useRef() const copyAreaRef = useRef() const isClient = typeof window !== 'undefined' const supportsCopy = isClient && document.queryCommandSupported('copy') const showCopy = supportsCopy && copy const [styles, setStyles] = useState({}) const [checked, setChecked] = useState({}) const [initialized, setInitialized] = useState(false) const [copySuccess, setCopySuccess] = useState(false) const [otherState, setOtherState] = useState({}) const setOther = (id, value) => setOtherState({ ...otherState, [id]: value }) const getRawContent = ref => { if (rawContent !== null) return rawContent if (ref.current && ref.current.childNodes) { // Select all currently visible nodes (spans and text nodes) const result = [...ref.current.childNodes].filter(el => el.offsetParent !== null) return result.map(el => el.textContent).join('\n') } return '' } const onClickCopy = () => { copyAreaRef.current.value = getRawContent(contentRef) copyToClipboard(copyAreaRef, setCopySuccess) } const getCss = (id, checkedOptions) => { const checkedForId = checkedOptions[id] || [] const exclude = checkedForId .map(value => `:not([data-quickstart-${id}="${value}"])`) .join('') return `[data-quickstart-results]>[data-quickstart-${id}]${exclude} {display: none}` } useEffect(() => { window.dispatchEvent(new Event('resize')) // scroll position for progress if (!initialized) { const initialChecked = Object.assign( {}, ...data.map(({ id, options = [] }) => ({ [id]: options.filter(option => option.checked).map(({ id }) => id), })) ) const initialStyles = Object.assign( {}, ...data.map(({ id }) => ({ [id]: getCss(id, initialChecked) })) ) setChecked(initialChecked) setStyles(initialStyles) setInitialized(true) } }, [data, initialized]) return !data.length ? null : (
{title && (

{title}

)} {description &&

{description}

} {data.map( ({ id, title, options = [], dropdown = [], defaultValue, multiple, other, help, }) => { // Optional function that's called with the value const setterFunc = setters[id] || (() => {}) return (
{title} {help && ( {' '} )}
{!!dropdown.length && ( )} {other && otherState[id] && ( setterFunc(target.value)} /> )} {options.map(option => { const optionType = multiple ? 'checkbox' : 'radio' const checkedForId = checked[id] || [] return ( { const newChecked = { ...checked, [id]: getNewChecked( option.id, checkedForId, multiple ), } setChecked(newChecked) setStyles({ ...styles, [id]: getCss(id, newChecked), }) setterFunc(newChecked[id]) }} type={optionType} className={classNames( classes.input, classes[optionType] )} name={id} id={`quickstart-${option.id}`} value={option.id} checked={checkedForId.includes(option.id)} /> ) })}
) } )}
                    
                        {children}
                    

                    
                        {showCopy && (
                            
                        )}
                        {download && (
                            
                                
                            
                        )}
                    
                
{showCopy &&