1
|
{"version":3,"sources":["webpack:///./src/hooks.ts","webpack:///./src/ui/animation.tsx","webpack:///./src/ui/buttons/Button.tsx","webpack:///./src/events.ts","webpack:///./src/ui/Icon.tsx","webpack:///./src/ui/buttons/DeleteButton.tsx","webpack:///./src/ui/ColorPill.tsx","webpack:///./src/ui/Drawer.tsx","webpack:///./src/ui/inputs.tsx","webpack:///./src/ui/LazyThumbnail.tsx","webpack:///./src/ui/Logo.tsx","webpack:///./src/ui/Main.tsx","webpack:///./src/ui/PageTitle.tsx","webpack:///./src/ui/section.tsx","webpack:///./src/ui/SvgRender.tsx","webpack:///./src/BoardDisplay/display.ts","webpack:///./src/BoardDisplay/PanZoom.tsx","webpack:///./src/BoardDisplay/Controls.tsx","webpack:///./src/BoardDisplay/LayersRender.tsx","webpack:///./src/BoardDisplay/index.tsx","webpack:///./src/layers.ts","webpack:///./src/FileList/VisibilityButton.tsx","webpack:///./src/FileList/FileItem.tsx","webpack:///./src/FileList/SideItem.tsx","webpack:///./src/FileList/SideList.tsx","webpack:///./src/FileList/ShowFilenamesButton.tsx","webpack:///./src/FileList/index.tsx","webpack:///./src/BoardList/ShowButton.tsx","webpack:///./src/BoardList/BoardItem.tsx","webpack:///./src/BoardList/SavedBoardList.tsx","webpack:///./src/BoardList/index.tsx","webpack:///./src/AppSettings/SettingsDrawer.tsx","webpack:///./src/AppSettings/index.tsx","webpack:///./src/BoardSettings/name.tsx","webpack:///./src/BoardSettings/ModeSelect.tsx","webpack:///./src/BoardSettings/values.ts","webpack:///./src/BoardSettings/BoardUrl.tsx","webpack:///./src/BoardSettings/SettingsButtons.tsx","webpack:///./src/BoardSettings/color.tsx","webpack:///./src/BoardSettings/render.tsx","webpack:///./src/BoardSettings/layers.tsx","webpack:///./src/BoardSettings/SettingsForm.tsx","webpack:///./src/BoardSettings/index.tsx","webpack:///./src/Nav/OpenFileDrawer.tsx","webpack:///./src/Nav/FileControls.tsx","webpack:///./src/Nav/Footer.tsx","webpack:///./src/Nav/index.tsx","webpack:///./src/LoadFiles/FileInput.tsx","webpack:///./src/LoadFiles/UrlInput.tsx","webpack:///./src/LoadFiles/index.tsx","webpack:///./src/ErrorToast/Toast.tsx","webpack:///./src/ErrorToast/index.tsx","webpack:///./src/App.tsx","webpack:////home/user/tracespace/packages/whats-that-gerber/index.js","webpack:///./src/state/index.ts","webpack:///./src/state/context.ts","webpack:///./src/state/actions.ts","webpack:///./src/logger.ts","webpack:////home/user/tracespace/packages/whats-that-gerber/lib/constants.js","webpack:////home/user/tracespace/packages/whats-that-gerber/lib/flat-map.js","webpack:////home/user/tracespace/packages/whats-that-gerber/lib/layer-types.js","webpack:////home/user/tracespace/packages/whats-that-gerber/lib/get-common-cad.js","webpack:////home/user/tracespace/packages/whats-that-gerber/lib/get-matches.js","webpack:////home/user/tracespace/packages/whats-that-gerber/lib/matchers.js"],"names":["useTimeout","handler","delay","useEffect","timeout","window","setTimeout","clearTimeout","usePrevious","value","valueRef","useRef","current","useWindowListener","event","addEventListener","removeEventListener","FADE_STYLE","Fade","props","CSSTransition","in","Boolean","classNames","mountOnEnter","unmountOnExit","children","SLIDE_STYLE","Slide","from","BUTTON_CLASSNAME","getButtonStyle","cx","disabled","className","Button","onClick","title","type","suppressHydrationWarning","preventDefault","stopPropagation","select","currentTarget","PREFIX_BY_ICON","check","circle","cog","copy","expand","eye","plus","spinner","square","times","Icon","name","style","faProps","icon","library","add","faCheck","faCheckSquare","faChevronLeft","faChevronRight","faCircle","faCog","faCopy","faDotCircle","faExpand","faEye","faEyeSlash","faFileDownload","faFileUpload","faPlus","faSearchMinus","faSearchPlus","faSlidersH","faSpinner","faSquare","faTimes","faTrashAlt","faQuestionCircle","DELETE_ICON","DELETE_COPY","STYLE","ARMED_STYLE","DISARMED_STYLE","WRAPPER_STYLE","WRAPPER_ARMED_STYLE","WRAPPER_DISARMED_STYLE","COPY_STYLE","DeleteButton","useState","armed","setArmed","ColorPill","color","slice","dark","contrast","backgroundColor","TITLE_BAR_STYLE","TITLE_STYLE","BUTTON_STYLE","Drawer","open","close","LABEL_CLASSNAME","Label","rest","pointer","HiddenInput","Checkbox","inputProps","iconName","LazyThumbnail","imageRef","loaded","setLoaded","handleLoad","complete","url","spinnerColor","background","ref","src","pulse","Logo","width","height","fill","viewBox","xmlns","d","Main","onDragOver","onDrop","PageTitle","subtitle","TitledSection","SectionColumnLeft","SectionColumnRight","SvgRender","React","memo","source","dangerouslySetInnerHTML","__html","SCALE_STEP_COUNT","INITIAL_STATE","x","y","step","SCALE_MIN_LOG","Math","log","SCALE_INITIAL","SCALE_STEP_LOG","SCALE_STEPS","Array","map","_","i","pow","E","zoom","prevState","delta","centerX","centerY","prevX","prevY","prevStep","prevScale","getScale","scale","nextStep","scaleRatio","pan","deltaX","deltaY","round","max","min","WHEEL_THRESHOLD","WHEEL_THRESHOLD_LINE","getEventCenter","pageX","innerWidth","pageY","innerHeight","PanZoom","containerRef","panStart","count","deltaMode","threshhold","DOM_DELTA_LINE","sign","abs","direction","onMouseDown","onMouseUp","onMouseMove","ZOOM_RESET_TOOLTIP","ZOOM_OUT_TOOLTIP","ZOOM_IN_TOOTIP","CONTROLS_STYLE","ZOOM_ICON_STYLE","ZOOM_RESET_STYLE","ZOOM_BAR_CONTAINER_STYLE","ZOOM_BAR_STYLE","ZOOM_SLIDER_STYLE","Controls","grabbing","setGrabbing","reset","zoomIn","zoomOut","sliderLeft","stepToScale","handleGrabMove","getBoundingClientRect","left","clientX","undefined","layerVisibility","layers","filter","ly","converter","layer","length","strokeLinecap","strokeLinejoin","strokeWidth","fillRule","vb","asString","key","id","defs","join","transform","groupProps","stroke","percent","n","getId","b","BoardDisplay","useAppState","mode","board","loading","displayState","setDisplayState","prevBoard","show","controllerProps","args","useLayoutEffect","dn","top","bottom","ALL_TYPES","TYPE_COPPER","TYPE_SOLDERMASK","TYPE_SILKSCREEN","TYPE_SOLDERPASTE","TYPE_DRILL","TYPE_OUTLINE","TYPE_DRAWING","ALL_SIDES","SIDE_TOP","SIDE_BOTTOM","SIDE_INNER","SIDE_ALL","COPPER_TYPES","COPPER_SIDES","VISIBLE_TYPES","VISIBLE_SIDES","MECH_TYPES","MECH_SIDES","typeToValidSides","includes","orderLayers","a","side","OPTIONS","getDefaultLayerOptions","allLayers","reduce","options","forEach","layerValue","initialOptions","isArray","TOP_SIDES","BOTTOM_SIDES","layerVisible","layerTooltip","VisibilityButton","dispatch","visible","tooltip","iconProps","toggleVisibility","shiftKey","TYPE_UNKNOWN","TYPE_STYLE","TYPE_STYLE_EXPANDED","FILENAME_STYLE","VIS_BUTTON_STYLE","FileItem","filename","showFilenames","HEADING_STYLE","SUBLIST_STYLE","SideList","label","SIDES","STYLE_DEFAULT","STYLE_EXPANDED","LIST_WRAPPER_STYLE","LIST_STYLE","onWheel","sideProps","sort","LABEL_STYLE","ShowFilenamesButton","toggle","FileList","setShowFilenames","ShowButton","DEFAULT_COLOR","BoardItem","selected","thumbnail","sm","SavedBoardList","selectedId","boards","onItemClick","BoardList","savedBoards","setShow","setSelected","prevLoading","haveBoards","showList","getBoard","TITLE","FOOTER","pkg","version","DELETE_SAVED_COPY","DELETE_COPY_STYLE","DELETE_BUTTON_STYLE","FOOTER_STYLE","SettingsDrawer","deleteAllBoards","HELP_TOOLTIP","HELP_HREF","SETTINGS_TOOLTIP","AppSettings","setOpen","buttonClassName","toggleOpen","href","target","rel","INPUT_STYLE","BoardName","BoardNameInput","autoComplete","data-lpignore","field","TEXT_STYLE","DESELECTED_STYLE","SELECTED_STYLE","ModeSelect","buttons","setMode","MASK_ALPHA","GAP_FILL_DEFAULT","boardRenderToValues","gerberOptions","layerOptionsToFormValue","drillOptions","result","parseFormBoardOptions","formOptions","outlineGapFill","Number","isFinite","parseFormLayerOptions","coordinateFormat","zeroSuppression","units","parsed","isInteger","warn","SUCCESS_TIMEOUT","PARAM","ICON_STYLE","BoardUrl","success","setSuccess","location","origin","pathname","copyValue","encodeURIComponent","textStyle","iconStyle","onCopy","focus","clipboardData","setData","document","execCommand","onFocus","onBlur","readOnly","CANCEL_TOOLTIP","SAVE_TOOLTIP","SettingsButtons","COLOR_PRESETS","fr4","cf","ss","cu","sp","out","COLOR_IDS","COLOR_NAMES","stripAlpha","c","colorsMatch","ColorInput","colorId","form","onChange","setFieldValue","ColorPresetsField","fieldName","component","ColorPresetInput","ColorFields","preset","ColorPresetOption","checked","every","BoardColorSwatch","boardColor","index","collection","previous","needsBorder","prevHasBorder","bl","USE_OUTLINE_LABEL","GAP_FILL_LABEL","GAP_FILL_UNITS","OVERRIDE_LABEL","COORD_FORMAT_LABEL","ZERO_SUPRESSION_LABEL","UNITS_LABEL","NUMBER_INPUT_STYLE","UseOutlineInput","GapFillInput","values","useOutline","CoordFormatFields","renderName","overridden","defaultValue","OverridableField","placeholder","RadioGroup","opt","ZeroSuppressionFields","UnitsFields","OverrideCheckbox","LayerList","LayerItem","LayerTypeSelect","layerId","validSides","setValues","t","LayerSideSelect","push","LayerColorInput","SettingsForm","sourceUrl","defaultGerberOptions","defaultDrillOptions","handleDelete","deleteBoard","initialValues","onSubmit","updateBoard","formUpdates","Object","keys","update","valuesToBoardUpdate","onReset","formProps","delete","OPEN_BUTTON_TOOLTIP","NAME_STYLE","OPEN_BUTTON_STYLE","MODAL_STYLE","MODAL_CONTENTS_STYLE","FORM_STYLE","BoardSettings","modalContentsRef","$modalContents","shift","clientWidth","updating","UPLOAD_FILES_LABEL","ENTER_URL_LABEL","ENTER_URL_PLACEHOLDER","UPLOAD_FILES_LABEL_STYLE","SEPARATOR_STYLE","ENTER_URL_LABEL_STYLE","URL_INPUT_STYLE","URL_INPUT_WRAPPER_STYLE","OpenFileDrawer","handleFiles","handleUrl","multiple","formikProps","DOWNLOAD_TOOLTIP","UPLOAD_TOOLTIP","FileControls","downloading","toggleUploadOpen","getBoardPackage","REPO_URL_MATCH","repository","match","REPO_URL","author","AUTHOR_NAME","AUTHOR_URL","CONTRIBUTORS_URL","PRIVACY_URL","LINK_STYLE","Footer","toLowerCase","BUTTON_WRAPPER_STYLE","Nav","FileInput","INPUT_ID","defaultUrl","loc","UrlInput","locationRef","enableReinitialize","htmlFor","UPLOAD_MESSAGE","UPLOAD_SUBMESSAGE","URL_MESSAGE","MESSAGE_STYLE","SUBMESSAGE_STYLE","LoadFiles","DISMISS_TIMEOUT","Toast","dismiss","ErrorToast","error","prevError","prevErrorMessage","message","dismissError","App","files","dataTransfer","createBoard","createBoardFromUrl","constants","flatMap","getCommonCad","getMatches","layerTypes","module","exports","filenames","matches","commonCad","cad","filenameMatches","find","_selectMatch","validate","valid","some","getAllLayers","constantName","StateContext","createContext","useContext","CREATE_BOARD","CREATE_BOARD_FROM_URL","GET_BOARD","GET_BOARD_PACKAGE","UPDATE_BOARD","DELETE_BOARD","DELETE_ALL_BOARDS","SET_MODE","TOGGLE_VISIBILITY","BOARD_RENDERED","BOARD_UPDATED","BOARD_DELETED","BOARD_PACKAGED","ALL_BOARDS_DELETED","WORKER_INITIALIZED","WORKER_ERRORED","DISMISS_ERROR","payload","solo","minLevel","STORAGE_KEY","DEFAULT_LEVEL","LEVELS","logger","debug","createLogHandler","info","level","localStorage","maybeLevel","getItem","console","readLogLevel","indexOf","msg","meta","_CAD_KICAD","_CAD_ALTIUM","_CAD_ALLEGRO","_CAD_EAGLE","_CAD_EAGLE_LEGACY","_CAD_EAGLE_OSHPARK","_CAD_EAGLE_PCBNG","_CAD_GEDA_PCB","_CAD_ORCAD","_CAD_DIPTRACE","iterator","element","concat","matchers","ext","cadCount","counts","maxAndName","extend","matcher","test","RegExp"],"mappings":"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","file":"4.c1e3462f6afae971800f.js","sourcesContent":["// reusable utility hooks\nimport {useEffect, useRef} from 'react'\n\nexport function useTimeout(handler: () => unknown, delay: number | null): void {\n useEffect(() => {\n if (delay !== null) {\n const timeout = window.setTimeout(handler, delay)\n return () => window.clearTimeout(timeout)\n }\n }, [delay])\n}\n\nexport function usePrevious<Value>(value: Value): Value | null {\n const valueRef = useRef<Value | null>(null)\n\n useEffect(() => {\n valueRef.current = value\n }, [value])\n\n return valueRef.current\n}\n\nexport function useWindowListener<Event extends keyof WindowEventMap>(\n event: Event,\n handler: (event: WindowEventMap[Event]) => unknown\n): void {\n useEffect(() => {\n window.addEventListener(event, handler)\n return () => window.removeEventListener(event, handler)\n })\n}\n\nexport function useLocation(): Location | null {\n const locationRef = useRef<Location | null>(null)\n\n useEffect(() => {\n locationRef.current = window.location\n }, [])\n\n return locationRef.current\n}\n","import React from 'react'\nimport {CSSTransition} from 'react-transition-group'\n\ntype AnimationProps = {\n in: boolean | string | null | undefined\n children: React.ReactNode\n}\n\nexport type FadeProps = AnimationProps\n\nconst FADE_STYLE = 'fade'\n\nexport function Fade(props: AnimationProps): JSX.Element {\n return (\n <CSSTransition\n in={Boolean(props.in)}\n classNames={FADE_STYLE}\n timeout={500}\n mountOnEnter\n unmountOnExit\n >\n {props.children}\n </CSSTransition>\n )\n}\n\nexport type SlideProps = AnimationProps & {\n from: 'top' | 'bottom' | 'left' | 'right'\n}\n\nconst SLIDE_STYLE = 'slide'\n\nexport function Slide(props: SlideProps): JSX.Element {\n return (\n <CSSTransition\n in={Boolean(props.in)}\n classNames={`${SLIDE_STYLE}-${props.from}`}\n timeout={500}\n mountOnEnter\n unmountOnExit\n >\n {props.children}\n </CSSTransition>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\n\nexport type ButtonProps = {\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n disabled?: boolean\n className?: string\n children?: React.ReactNode\n title?: string\n type?: 'button' | 'submit' | 'reset'\n}\n\nexport const BUTTON_CLASSNAME = 'bn pa0 br2 color-inherit bg-transparent'\n\nexport function getButtonStyle(props: ButtonProps): string {\n return cx(\n {\n 'o-40': props.disabled,\n 'pointer bg-animate hover-bg-black-20': !props.disabled,\n },\n BUTTON_CLASSNAME,\n props.className\n )\n}\n\nexport function Button(props: ButtonProps): JSX.Element {\n const {onClick, title, children} = props\n const type = props.type || 'button'\n const disabled = Boolean(props.disabled)\n const className = getButtonStyle(props)\n\n return (\n <button\n type={type}\n onClick={onClick}\n disabled={disabled}\n className={className}\n title={title}\n suppressHydrationWarning={true}\n >\n {children}\n </button>\n )\n}\n","// event handling helpers\n\nimport {SyntheticEvent} from 'react'\n\nexport function preventDefault(event: SyntheticEvent | Event): void {\n event.preventDefault()\n}\n\nexport function stopPropagation(event: SyntheticEvent | Event): void {\n event.stopPropagation()\n}\n\nexport function select(event: SyntheticEvent<HTMLInputElement>): void {\n event.currentTarget.select()\n}\n","import React from 'react'\nimport cx from 'classnames'\nimport {Omit} from '../types'\n\nimport {\n FontAwesomeIcon as FaIcon,\n Props as FaIconProps,\n} from '@fortawesome/react-fontawesome'\n\nimport {\n library,\n IconPrefix as FaIconPrefix,\n IconProp as FaIconProp,\n} from '@fortawesome/fontawesome-svg-core'\n\nimport {\n faCheckSquare,\n faCircle,\n faCopy,\n faDotCircle,\n faEye,\n faEyeSlash,\n faSquare,\n faTrashAlt,\n} from '@fortawesome/free-regular-svg-icons'\n\nimport {\n faCheck,\n faChevronLeft,\n faChevronRight,\n faCog,\n faExpand,\n faFileDownload,\n faFileUpload,\n faPlus,\n faQuestionCircle,\n faSearchMinus,\n faSearchPlus,\n faSlidersH,\n faSpinner,\n faTimes,\n} from '@fortawesome/free-solid-svg-icons'\n\nconst PREFIX_BY_ICON = {\n check: 'fas',\n 'check-square': 'far',\n 'chevron-left': 'fas',\n 'chevron-right': 'fas',\n circle: 'far',\n cog: 'fas',\n copy: 'far',\n 'dot-circle': 'far',\n expand: 'fas',\n eye: 'far',\n 'eye-slash': 'far',\n 'file-download': 'fas',\n 'file-upload': 'fas',\n plus: 'fas',\n 'question-circle': 'fas',\n 'search-plus': 'fas',\n 'search-minus': 'fas',\n 'sliders-h': 'fas',\n spinner: 'fas',\n square: 'far',\n times: 'fas',\n 'trash-alt': 'far',\n}\n\nexport type IconName = keyof typeof PREFIX_BY_ICON\n\nexport type IconProps = {\n name: IconName\n className?: string\n style?: React.CSSProperties\n faProps?: Omit<FaIconProps, 'icon' | 'className'>\n}\n\nlibrary.add(\n faCheck,\n faCheckSquare,\n faChevronLeft,\n faChevronRight,\n faCircle,\n faCog,\n faCopy,\n faDotCircle,\n faExpand,\n faEye,\n faEyeSlash,\n faFileDownload,\n faFileUpload,\n faPlus,\n faSearchMinus,\n faSearchPlus,\n faSlidersH,\n faSpinner,\n faSquare,\n faTimes,\n faTrashAlt,\n faQuestionCircle\n)\n\nexport function Icon(props: IconProps): JSX.Element {\n const {name, style, faProps} = props\n const icon: FaIconProp = [PREFIX_BY_ICON[name] as FaIconPrefix, name]\n const className = cx(props.className, 'relative w2 h2 pa2')\n\n return (\n <div className={className} style={style}>\n <span className=\"db absolute absolute--center\">\n <FaIcon icon={icon} {...faProps} />\n </span>\n </div>\n )\n}\n","import React, {useState} from 'react'\nimport cx from 'classnames'\n\nimport {useWindowListener} from '../../hooks'\nimport {stopPropagation} from '../../events'\nimport {Icon} from '../Icon'\n\nexport type DeleteButtonProps = {\n className?: string\n onClick: () => void\n}\n\nconst DELETE_ICON = 'trash-alt'\nconst DELETE_COPY = 'delete?'\n\nconst STYLE = 'flex items-center bn pa0 br2 pointer c-animate overflow-hidden'\nconst ARMED_STYLE = 'white bg-red hover-bg-dark-red'\nconst DISARMED_STYLE = 'red bg-white hover-bg-black-20'\n\nconst WRAPPER_STYLE = 'flex-none mw-animate overflow-hidden'\nconst WRAPPER_ARMED_STYLE = 'mw4'\nconst WRAPPER_DISARMED_STYLE = 'mw0'\n\nconst COPY_STYLE = 'dib pl1 pr2'\n\nexport function DeleteButton(props: DeleteButtonProps): JSX.Element {\n const [armed, setArmed] = useState(false)\n const className = cx(\n STYLE,\n armed ? ARMED_STYLE : DISARMED_STYLE,\n props.className\n )\n\n useWindowListener('click', () => armed && setArmed(false))\n\n return (\n <button type=\"button\" onClick={handleClick} className={className}>\n <Icon name={DELETE_ICON} />\n <div\n className={cx(\n WRAPPER_STYLE,\n armed ? WRAPPER_ARMED_STYLE : WRAPPER_DISARMED_STYLE\n )}\n >\n <span className={COPY_STYLE}>{DELETE_COPY}</span>\n </div>\n </button>\n )\n\n function handleClick(event: React.MouseEvent): void {\n stopPropagation(event)\n\n if (armed) {\n setArmed(false)\n props.onClick()\n } else {\n setArmed(true)\n }\n }\n}\n","import React from 'react'\nimport cx from 'classnames'\nimport contrast from 'contrast'\n\nexport type ColorPillProps = {\n color: string\n className?: string\n}\n\nexport function ColorPill(props: ColorPillProps): JSX.Element {\n const color = props.color.slice(0, 7)\n const dark = contrast(color) === 'dark'\n const className = cx(\n 'border-box flex-none pv1 ph2 br-pill code f6',\n dark ? 'white' : 'near-black ba',\n props.className\n )\n const style = {backgroundColor: color}\n\n return (\n <span className={className} style={style}>\n {color}\n </span>\n )\n}\n","import React from 'react'\n\nimport {Slide} from './animation'\nimport {Button} from './buttons'\nimport {Icon} from './Icon'\n\nconst STYLE =\n 'fixed top-1 right-1 z-2 w-25 nt2 nr2 pv2 ph3 br3 near-black bg-white shadow'\nconst TITLE_BAR_STYLE = 'flex items-center mb3'\nconst TITLE_STYLE = 'mr-auto f3 lh-title mv0 normal'\nconst BUTTON_STYLE = 'flex-none nr2 f4'\n\nexport type DrawerProps = {\n title: string\n open: boolean\n children: React.ReactNode\n close: () => unknown\n}\n\nexport function Drawer(props: DrawerProps): JSX.Element {\n const {title, open, children, close} = props\n\n return (\n <Slide in={open} from=\"right\">\n <section className={STYLE}>\n <div className={TITLE_BAR_STYLE}>\n <h2 className={TITLE_STYLE}>{title}</h2>\n <Button onClick={close} className={BUTTON_STYLE}>\n <Icon name=\"times\" />\n </Button>\n </div>\n {children}\n </section>\n </Slide>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\n\nimport {Icon} from './Icon'\n\nexport type LabelProps = {\n className?: string\n disabled?: boolean\n children: React.ReactNode\n} & React.LabelHTMLAttributes<HTMLLabelElement>\n\nexport const LABEL_CLASSNAME = 'flex items-center'\n\nexport function Label(props: LabelProps): JSX.Element {\n const {className, disabled, children, ...rest} = props\n const style = cx(LABEL_CLASSNAME, className, {pointer: !disabled})\n\n return (\n <label className={style} {...rest}>\n {children}\n </label>\n )\n}\n\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>\n\nexport function HiddenInput(props: InputProps): JSX.Element {\n return <input className=\"clip\" {...props} />\n}\n\nexport function Checkbox(props: InputProps): JSX.Element {\n const {className, children, ...inputProps} = props\n const iconName = props.value ? 'check-square' : 'square'\n\n return (\n <Label className={className}>\n <HiddenInput type=\"checkbox\" {...inputProps} />\n <Icon className=\"nl2\" name={iconName} />\n {children}\n </Label>\n )\n}\n","import React, {useState, useRef, useEffect} from 'react'\nimport cx from 'classnames'\n\nimport {Icon} from './Icon'\n\nexport type LazyThumbnailProps = {\n url: string\n spinnerColor: string\n className?: string\n}\n\nconst STYLE = 'flex items-center justify-center'\n\nexport function LazyThumbnail(props: LazyThumbnailProps): JSX.Element {\n const imageRef = useRef<HTMLImageElement>(null)\n const [loaded, setLoaded] = useState(false)\n\n useEffect(() => {\n const handleLoad = (): void => setLoaded(true)\n\n if (imageRef.current) {\n if (!imageRef.current.complete) {\n setLoaded(false)\n imageRef.current.addEventListener('load', handleLoad)\n } else {\n handleLoad()\n }\n }\n\n return () => {\n if (imageRef.current) {\n imageRef.current.removeEventListener('load', handleLoad)\n }\n }\n })\n\n const {url, spinnerColor} = props\n const className = cx(STYLE, props.className)\n const background = loaded\n ? `url(\"${url}\") no-repeat center/contain`\n : 'transparent'\n\n return (\n <div className={className} style={{background}}>\n <img className=\"clip\" ref={imageRef} src={url} />\n {!loaded && (\n <Icon\n name=\"spinner\"\n className=\"f2\"\n style={{color: spinnerColor}}\n faProps={{pulse: true}}\n />\n )}\n </div>\n )\n}\n","// tracespace logo component\nimport React from 'react'\nimport cx from 'classnames'\n\nexport type LogoProps = {\n width?: number | string\n height?: number | string\n color?: string\n className?: string\n}\n\nexport function Logo(props: LogoProps): JSX.Element {\n const width = props.width || props.height || '32px'\n const height = props.height || width || '32px'\n const fill = props.color || 'currentColor'\n\n return (\n <svg\n width={`${width}`}\n height={`${height}`}\n fill={fill}\n viewBox=\"0 0 36 36\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cx('dib', props.className)}\n >\n <path d=\"M22 14H36V0H16L0 16V36H14V22L22 14Z M36 28C36 32.4183 32.4183 36 28 36C23.5817 36 20 32.4183 20 28C20 23.5817 23.5817 20 28 20C32.4183 20 36 23.5817 36 28Z\" />\n </svg>\n )\n}\n","import React from 'react'\n\nexport type MainProps = {\n children: React.ReactNode\n onDragOver: (event: React.DragEvent<HTMLElement>) => void\n onDrop: (event: React.DragEvent<HTMLElement>) => void\n}\n\nconst STYLE = 'sans relative overflow-hidden h-100 pa3 white bg-gradient'\n\nexport function Main(props: MainProps): JSX.Element {\n const {children, onDragOver, onDrop} = props\n\n return (\n <main className={STYLE} onDragOver={onDragOver} onDrop={onDrop}>\n {children}\n </main>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\n\nimport {Logo} from './Logo'\n\nexport type PageTitleProps = {\n subtitle?: string\n className?: string\n}\n\nexport function PageTitle(props: PageTitleProps): JSX.Element {\n const {subtitle, className} = props\n\n return (\n <div className={cx('dib', className)}>\n <Logo className=\"pl1 pr3 v-btm brand\" />\n <h1 className=\"dib mv0 f3 lh-title normal\">\n pogojig\n {subtitle && <span className=\"b\">{` ${subtitle}`}</span>}\n </h1>\n </div>\n )\n}\n","import React from 'react'\n\nexport type TitledSectionProps = {\n title: string\n children: React.ReactNode\n}\n\nexport function TitledSection(props: TitledSectionProps): JSX.Element {\n const {title, children} = props\n\n return (\n <section className=\"tl mb4\">\n <h3 className=\"mt0 mb2 f5 lh-title b\">{title}</h3>\n {children}\n </section>\n )\n}\n\nexport function SectionColumnLeft(props: {\n children: React.ReactNode\n}): JSX.Element {\n return <div className=\"dib w-50 pr3 v-top br\">{props.children}</div>\n}\n\nexport function SectionColumnRight(props: {\n children: React.ReactNode\n}): JSX.Element {\n return <div className=\"dib w-50 pl3 v-top\">{props.children}</div>\n}\n","// tracespace components library\nimport React from 'react'\n\nimport {SvgSource} from '../types'\n\nexport type SvgRenderProps = {\n source: SvgSource\n className?: string\n}\n\nexport const SvgRender = React.memo(_SvgRender)\n\nfunction _SvgRender(props: SvgRenderProps): JSX.Element | null {\n const {source, className} = props\n\n return source ? (\n <div className={className} dangerouslySetInnerHTML={{__html: source}} />\n ) : null\n}\n","// scale constants and utilities\nimport {DisplayState} from './types'\n\nexport const SCALE_INITIAL = 0.5\nexport const SCALE_LIMIT_FACTOR = 40\nexport const SCALE_STEP_COUNT = 16\n\nexport const SCALE_MIN = SCALE_INITIAL / SCALE_LIMIT_FACTOR\nexport const SCALE_MAX = SCALE_INITIAL * SCALE_LIMIT_FACTOR\n\nexport const INITIAL_STATE: DisplayState = {\n x: 0,\n y: 0,\n step: SCALE_STEP_COUNT / 2,\n}\n\nconst SCALE_MIN_LOG = Math.log(SCALE_MIN)\nconst SCALE_MAX_LOG = Math.log(SCALE_MAX)\nconst SCALE_RANGE_LOG = SCALE_MAX_LOG - SCALE_MIN_LOG\nconst SCALE_STEP_LOG = SCALE_RANGE_LOG / SCALE_STEP_COUNT\n\nexport const SCALE_STEPS = new Array(SCALE_STEP_COUNT + 1)\n .fill(0)\n .map((_, i) => Math.pow(Math.E, SCALE_MIN_LOG + SCALE_STEP_LOG * i))\n\n// TODO(mc, 2018-11-20): find the notebook where I did this math and\n// put it in a README in this directory\nexport function zoom(\n prevState: DisplayState,\n delta: number,\n centerX: number = 0.5,\n centerY: number = 0.5\n): DisplayState {\n const {x: prevX, y: prevY, step: prevStep} = prevState\n const {scale: prevScale} = getScale(prevStep)\n const {step: nextStep, scale: nextScale} = getScale(prevStep + delta)\n const scaleRatio = nextScale / prevScale\n\n return {\n step: nextStep,\n x: prevX + (scaleRatio - 1) * (prevX - centerX + 0.5),\n y: prevY + (scaleRatio - 1) * (prevY - centerY + 0.5),\n }\n}\n\nexport function pan(\n prevState: DisplayState,\n deltaX: number,\n deltaY: number\n): DisplayState {\n return {\n ...prevState,\n x: prevState.x + deltaX,\n y: prevState.y + deltaY,\n }\n}\n\nexport function getScale(step: number): {step: number; scale: number} {\n step = Math.round(step)\n step = Math.max(0, step)\n step = Math.min(SCALE_STEP_COUNT, step)\n\n return {step: step, scale: SCALE_STEPS[step]}\n}\n\n// take a logarithmic value and return it on a linear scale where:\n// 0.0 -> scale === SCALE_MIN\n// 0.5 -> scale === SCALE_INITIAL\n// 1.0 -> SCALE === SCALE_MAX\nexport function stepToScale(step: number): number {\n const {step: actualStep} = getScale(step)\n\n return actualStep / SCALE_STEP_COUNT\n}\n\n// reverse of stepToScale\nexport function scaleToStep(scale: number): number {\n return getScale(scale * SCALE_STEP_COUNT).step\n}\n","import React, {useRef} from 'react'\n\nimport {useWindowListener} from '../hooks'\nimport {DisplayControllerProps, Point} from './types'\n\ntype Props = DisplayControllerProps & {\n containerRef: React.RefObject<HTMLDivElement>\n children?: React.ReactNode\n}\n\nconst WHEEL_THRESHOLD = 20\nconst WHEEL_THRESHOLD_LINE = 0\n\nconst getEventCenter = (event: WheelEvent | React.MouseEvent): Point => ({\n x: event.pageX / window.innerWidth,\n y: event.pageY / window.innerHeight,\n})\n\nexport default function PanZoom(props: Props): JSX.Element {\n const {pan, zoom, containerRef, children} = props\n const panStart = useRef<{x: number; y: number} | null>(null)\n const count = useRef(0)\n\n useWindowListener('wheel', function handleWheel(event: WheelEvent): void {\n const {deltaMode, deltaY} = event\n const threshhold =\n deltaMode === event.DOM_DELTA_LINE\n ? WHEEL_THRESHOLD_LINE\n : WHEEL_THRESHOLD\n\n // increment or decrement count based on scroll direction\n // remember that Math.sign(0) === 0\n count.current += Math.sign(deltaY)\n\n if (Math.abs(count.current) > threshhold) {\n const direction = Math.sign(-count.current) || 0\n const {x, y} = getEventCenter(event)\n\n count.current = 0\n zoom(direction, x, y)\n }\n })\n\n return (\n <div\n ref={containerRef}\n className=\"absolute absolute--fill\"\n onMouseDown={event => (panStart.current = getEventCenter(event))}\n onMouseUp={() => (panStart.current = null)}\n onMouseMove={event => {\n if (panStart.current) {\n const {x: prevX, y: prevY} = panStart.current\n const {x, y} = getEventCenter(event)\n\n pan(x - prevX, y - prevY)\n panStart.current = {x, y}\n }\n }}\n >\n <div className=\"absolute top-50 left-50 tf-center w-100\">{children}</div>\n </div>\n )\n}\n","// board display controls for zoom bar and board vs layer render\nimport React, {useState} from 'react'\n\nimport {Button, Icon} from '../ui'\nimport {stepToScale, scaleToStep} from './display'\nimport {DisplayControllerProps} from './types'\n\nconst ZOOM_RESET_TOOLTIP = 'Reset pan and zoom'\nconst ZOOM_OUT_TOOLTIP = 'Zoom out'\nconst ZOOM_IN_TOOTIP = 'Zoom in'\n\nconst CONTROLS_STYLE =\n 'absolute absolute--center-w-third bottom-1 z-1 w-third flex items-center f5'\nconst ZOOM_ICON_STYLE = 'flex-none'\nconst ZOOM_RESET_STYLE = 'absolute bottom-2 left-50 tf-center-x'\n\nconst ZOOM_BAR_CONTAINER_STYLE = 'relative w-100 h2 flex items-center grab'\nconst ZOOM_BAR_STYLE = 'dib pt2 bg-white shadow w-100'\nconst ZOOM_SLIDER_STYLE =\n 'absolute w1 h1 top-50 tf-center bg-brand o-70 left-animate'\n\nexport default function Controls(props: DisplayControllerProps): JSX.Element {\n const [grabbing, setGrabbing] = useState(false)\n const {step, reset, zoom, zoomIn, zoomOut} = props\n const sliderLeft = `${stepToScale(step) * 100}%`\n\n const handleGrabMove = (event: React.MouseEvent): void => {\n const {left, width} = event.currentTarget.getBoundingClientRect()\n const nextStep = scaleToStep((event.clientX - left) / width)\n zoom(nextStep - step)\n }\n\n return (\n <div className={CONTROLS_STYLE}>\n <Button\n className={ZOOM_RESET_STYLE}\n onClick={reset}\n title={ZOOM_RESET_TOOLTIP}\n >\n <Icon name=\"expand\" />\n </Button>\n <Button\n className={ZOOM_ICON_STYLE}\n onClick={zoomOut}\n title={ZOOM_OUT_TOOLTIP}\n >\n <Icon name=\"search-minus\" />\n </Button>\n <span\n className={ZOOM_BAR_CONTAINER_STYLE}\n onMouseDown={event => {\n setGrabbing(true)\n handleGrabMove(event)\n }}\n onMouseUp={() => setGrabbing(false)}\n onMouseMove={grabbing ? handleGrabMove : undefined}\n >\n <span className={ZOOM_BAR_STYLE} />\n <span className={ZOOM_SLIDER_STYLE} style={{left: sliderLeft}} />\n </span>\n <Button\n className={ZOOM_ICON_STYLE}\n onClick={zoomIn}\n title={ZOOM_IN_TOOTIP}\n >\n <Icon name=\"search-plus\" />\n </Button>\n </div>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\nimport vb, {ViewBox} from 'viewbox'\n\nimport {LayerRender, LayerVisibilityMap} from '../types'\n\ntype Props = {\n layers: Array<LayerRender>\n layerVisibility: LayerVisibilityMap\n viewBox: ViewBox\n className?: string\n}\n\nexport function LayersRender(props: Props): JSX.Element {\n const {layerVisibility, viewBox, className} = props\n const layers = props.layers.filter(ly => ly.converter.layer.length > 0)\n\n return (\n <svg\n className={cx(className, 'overflow-visible')}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"0\"\n fillRule=\"evenodd\"\n viewBox={vb.asString(viewBox)}\n >\n {layers.map(ly => (\n <defs\n key={ly.id}\n dangerouslySetInnerHTML={{__html: ly.converter.defs.join('')}}\n />\n ))}\n <g transform={`translate(0,${viewBox[3] + 2 * viewBox[1]}) scale(1, -1)`}>\n {layers.map(ly => {\n const {converter, scale} = ly\n const groupProps: React.SVGProps<SVGGElement> = {\n id: ly.id,\n dangerouslySetInnerHTML: {__html: converter.layer.join('')},\n }\n\n if (scale !== 1) groupProps.transform = `scale(${scale})`\n\n return (\n <g\n key={ly.id}\n fill={ly.color}\n stroke={ly.color}\n className={layerVisibility[ly.id] ? 'o-40' : 'o-0'}\n >\n <g {...groupProps} />\n </g>\n )\n })}\n </g>\n </svg>\n )\n}\n\nexport default React.memo(LayersRender)\n","import React, {useState, useRef, useEffect, useLayoutEffect} from 'react'\nimport cx from 'classnames'\n\nimport {useAppState} from '../state'\nimport {usePrevious} from '../hooks'\nimport {Fade, Slide, SvgRender} from '../ui'\nimport {INITIAL_STATE, pan, zoom, getScale} from './display'\nimport PanZoom from './PanZoom'\nimport Controls from './Controls'\nimport LayersRender from './LayersRender'\nimport {DisplayControllerProps} from './types'\n\nconst percent = (n: number): string => `${n * 100}%`\nconst getId = (b: {id: string} | null): string | null => (b ? b.id : null)\n\nexport default function BoardDisplay(): JSX.Element {\n const {mode, board, loading, layerVisibility} = useAppState()\n const [displayState, setDisplayState] = useState(INITIAL_STATE)\n const prevBoard = usePrevious(board)\n const containerRef = useRef<HTMLDivElement | null>(null)\n const show = !loading && board !== null\n\n const controllerProps: DisplayControllerProps = {\n step: displayState.step,\n reset: () => setDisplayState(INITIAL_STATE),\n pan: (...args) => setDisplayState(pan(displayState, ...args)),\n zoom: (...args) => setDisplayState(zoom(displayState, ...args)),\n zoomIn: () => setDisplayState(zoom(displayState, 1)),\n zoomOut: () => setDisplayState(zoom(displayState, -1)),\n }\n\n useLayoutEffect(() => {\n if (containerRef.current) {\n const {x, y, step} = displayState\n const {scale} = getScale(step)\n const transform = `translate(${percent(x)},${percent(y)}) scale(${scale})`\n\n containerRef.current.style.transform = transform\n }\n })\n\n useEffect(() => {\n if (getId(board) !== getId(prevBoard)) controllerProps.reset()\n }, [board, prevBoard])\n\n return (\n <>\n <Fade in={show}>\n <PanZoom {...controllerProps} containerRef={containerRef}>\n {board && (\n <>\n <SvgRender\n className={cx('w-100', {dn: mode !== 'top'})}\n source={board.top}\n />\n <SvgRender\n className={cx('w-100', {dn: mode !== 'bottom'})}\n source={board.bottom}\n />\n <LayersRender\n className={cx('w-100', {dn: mode !== 'layers'})}\n viewBox={board.viewBox}\n layers={board.layers}\n layerVisibility={layerVisibility}\n />\n </>\n )}\n </PanZoom>\n </Fade>\n <Slide in={show} from=\"bottom\">\n <Controls {...controllerProps} />\n </Slide>\n </>\n )\n}\n","// TODO(mc, 2019-03-01): tree-shake this import somehow or bundle reduction\nimport {\n TYPE_COPPER,\n TYPE_SOLDERMASK,\n TYPE_SILKSCREEN,\n TYPE_SOLDERPASTE,\n TYPE_DRILL,\n TYPE_OUTLINE,\n TYPE_DRAWING,\n SIDE_TOP,\n SIDE_BOTTOM,\n SIDE_INNER,\n SIDE_ALL,\n} from 'whats-that-gerber'\n\nimport {\n Optional,\n GerberType,\n GerberSide,\n LayerRender,\n LayerOptions,\n} from './types'\n\nexport {\n TYPE_COPPER,\n TYPE_SOLDERMASK,\n TYPE_SILKSCREEN,\n TYPE_SOLDERPASTE,\n TYPE_DRILL,\n TYPE_OUTLINE,\n TYPE_DRAWING,\n SIDE_TOP,\n SIDE_BOTTOM,\n SIDE_INNER,\n SIDE_ALL,\n}\n\ntype TypeList = Array<NonNullable<GerberType>>\ntype SideList = Array<NonNullable<GerberSide>>\n\n// all types in priority order\nexport const ALL_TYPES: TypeList = [\n TYPE_COPPER,\n TYPE_SOLDERMASK,\n TYPE_SILKSCREEN,\n TYPE_SOLDERPASTE,\n TYPE_DRILL,\n TYPE_OUTLINE,\n TYPE_DRAWING,\n]\n\n// all side in priority order\nexport const ALL_SIDES: SideList = [SIDE_TOP, SIDE_BOTTOM, SIDE_INNER, SIDE_ALL]\n\n// copper sides/type in priority order\nexport const COPPER_TYPES: TypeList = [TYPE_COPPER]\nexport const COPPER_SIDES: SideList = [SIDE_TOP, SIDE_BOTTOM, SIDE_INNER]\n\n// copper sides in priority order\nexport const VISIBLE_TYPES: TypeList = [\n TYPE_SOLDERMASK,\n TYPE_SILKSCREEN,\n TYPE_SOLDERPASTE,\n]\nexport const VISIBLE_SIDES: SideList = [SIDE_TOP, SIDE_BOTTOM]\n\n// mechanical sides in priority order\nexport const MECH_TYPES: TypeList = [TYPE_DRILL, TYPE_OUTLINE]\nexport const MECH_SIDES: SideList = [SIDE_ALL]\n\n// get list of valid sides based on type\nexport function typeToValidSides(type: unknown): SideList {\n if (COPPER_TYPES.includes(type)) return COPPER_SIDES\n if (VISIBLE_TYPES.includes(type)) return VISIBLE_SIDES\n if (MECH_TYPES.includes(type)) return MECH_SIDES\n return []\n}\n\n// sort by:\n// - top side > bottom side > inner side > all sides > no side\n// - copper > mask > silk > paste > drill > outline > drawing > no type\nexport function orderLayers(a: LayerRender, b: LayerRender): number {\n // place no type and no side at the bottom\n if ((!a.type && b.type) || (!a.side && b.side)) return 1\n if ((a.type && !b.type) || (a.side && !b.side)) return -1\n\n let i\n for (i = 0; i < ALL_SIDES.length; i++) {\n const side = ALL_SIDES[i]\n if (a.side === side && b.side !== side) return -1\n if (a.side !== side && b.side === side) return 1\n }\n\n for (i = 0; i < ALL_TYPES.length; i++) {\n const type = ALL_TYPES[i]\n if (a.type === type && b.type !== type) return -1\n if (a.type !== type && b.type === type) return 1\n }\n\n return 0\n}\n\nconst OPTIONS: Array<keyof LayerOptions> = [\n 'coordinateFormat',\n 'zeroSuppression',\n 'units',\n]\n\nexport function getDefaultLayerOptions(\n allLayers: Array<LayerRender>,\n type: 'gerber' | 'drill'\n): Optional<LayerOptions> {\n const layers = allLayers.filter(\n ly =>\n ly.converter.layer.length !== 0 &&\n ((type === 'gerber' && ly.type && ly.type !== TYPE_DRILL) ||\n (type === 'drill' && ly.type === TYPE_DRILL))\n )\n\n return layers.reduce<Optional<LayerOptions>>((options, ly) => {\n OPTIONS.forEach(name => {\n const layerValue = ly.initialOptions[name]\n let value = options[name]\n\n if (typeof value === 'undefined') {\n // set the option to the layer value if it hasn't been set yet\n value = layerValue\n } else if (value !== null) {\n // if it has been set, check that every layer has the same value, and\n // null out the option if they don't\n if (Array.isArray(value)) {\n if (\n !Array.isArray(layerValue) ||\n value[0] !== layerValue[0] ||\n value[1] !== layerValue[1]\n ) {\n value = null\n }\n } else if (value !== layerValue) {\n value = null\n }\n }\n\n if (value !== options[name]) options = {...options, [name]: value}\n })\n\n return options\n }, {})\n}\n","import React from 'react'\nimport contrast from 'contrast'\nimport {SIDE_TOP, SIDE_BOTTOM, SIDE_ALL, GerberSide} from 'whats-that-gerber'\n\nimport {LayerRender} from '../types'\nimport {useAppState, toggleVisibility, State} from '../state'\nimport {Button, Icon, IconProps} from '../ui'\n\ntype Props = {\n className: string\n id: LayerRender['id']\n side: LayerRender['side']\n type: LayerRender['type']\n converter: LayerRender['converter']\n color: LayerRender['color']\n}\n\nconst TOP_SIDES: Array<GerberSide> = [SIDE_TOP, SIDE_ALL]\nconst BOTTOM_SIDES: Array<GerberSide> = [SIDE_BOTTOM, SIDE_ALL]\nconst TOOLTIP = 'Toggle layer visibility (shift+click to toggle other layers)'\nconst BOARD_MODE_TOOLTIP = 'Cannot change visibility in board mode'\nconst NO_RENDER_TOOLTIP = 'Unable to render file'\n\nconst layerVisible = (\n mode: State['mode'],\n type: LayerRender['type'],\n side: LayerRender['side'],\n converter: LayerRender['converter'],\n layerVisibility: boolean\n): boolean =>\n type !== null &&\n converter.layer.length !== 0 &&\n ((mode === 'layers' && layerVisibility) ||\n (mode === 'top' && TOP_SIDES.includes(side)) ||\n (mode === 'bottom' && BOTTOM_SIDES.includes(side)))\n\nconst layerTooltip = (mode: State['mode'], disabled: boolean): string => {\n if (mode !== 'layers') return BOARD_MODE_TOOLTIP\n if (disabled) return NO_RENDER_TOOLTIP\n return TOOLTIP\n}\n\nexport default function VisibilityButton(props: Props): JSX.Element {\n const {mode, layerVisibility, dispatch} = useAppState()\n const {id, side, type, converter, color, className} = props\n\n const disabled =\n type === null || converter.layer.length === 0 || mode !== 'layers'\n const visible = layerVisible(mode, type, side, converter, layerVisibility[id])\n const tooltip = layerTooltip(mode, disabled)\n const iconProps: IconProps = {name: visible ? 'eye' : 'eye-slash'}\n\n if (mode === 'layers' && visible) {\n iconProps.style = {\n backgroundColor: color,\n color: contrast(color) === 'dark' ? 'white' : 'currentColor',\n }\n }\n\n return (\n <Button\n className={className}\n title={tooltip}\n disabled={disabled}\n onClick={event => dispatch(toggleVisibility(id, event.shiftKey))}\n >\n <Icon {...iconProps} />\n </Button>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\n\nimport {Fade} from '../ui'\nimport {LayerRender} from '../types'\nimport VisibilityButton from './VisibilityButton'\n\ntype Props = LayerRender & {showFilenames: boolean}\n\nconst TYPE_UNKNOWN = 'unknown'\n\nconst STYLE = 'flex items-center h2 mb2 pl3 br3 overflow-hidden bg-white shadow'\nconst TYPE_STYLE = 'f6 lh-title mv0 w-auto mr-auto'\nconst TYPE_STYLE_EXPANDED = 'flex-none'\nconst FILENAME_STYLE = 'f6 lh-title w-60 mv0 ph2 code truncate'\nconst VIS_BUTTON_STYLE = 'dib br0 f5 flex-none'\n\nexport default function FileItem(props: Props): JSX.Element {\n const {id, side, type, converter, filename, color, showFilenames} = props\n\n return (\n <li className={STYLE}>\n <p className={cx(TYPE_STYLE, {[TYPE_STYLE_EXPANDED]: showFilenames})}>\n {type || TYPE_UNKNOWN}\n </p>\n\n <Fade in={showFilenames}>\n <p className={FILENAME_STYLE}>{filename}</p>\n </Fade>\n\n <VisibilityButton\n {...{id, side, type, converter, color}}\n className={VIS_BUTTON_STYLE}\n />\n </li>\n )\n}\n","import React from 'react'\n\nimport {LayerRender} from '../types'\nimport FileItem from './FileItem'\n\ntype Props = {\n label: string\n layers: Array<LayerRender>\n showFilenames: boolean\n}\n\nconst HEADING_STYLE = 'mv2 pl3 lh-title f5 b'\nconst SUBLIST_STYLE = 'list pl0 mv0 near-black'\n\nexport default function SideList(props: Props): JSX.Element | null {\n const {label, layers, showFilenames} = props\n if (layers.length === 0) return null\n\n return (\n <li>\n <h3 className={HEADING_STYLE}>{label}</h3>\n <ul className={SUBLIST_STYLE}>\n {layers.map(layer => (\n <FileItem key={layer.id} {...layer} showFilenames={showFilenames} />\n ))}\n </ul>\n </li>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\nimport {SIDE_TOP, SIDE_BOTTOM, SIDE_INNER, SIDE_ALL} from 'whats-that-gerber'\n\nimport {stopPropagation} from '../events'\nimport {LayerRender} from '../types'\nimport {orderLayers} from '../layers'\nimport SideItem from './SideItem'\n\ntype Props = {\n layers: Array<LayerRender>\n showFilenames: boolean\n}\n\nconst SIDES = [\n {label: 'top', side: SIDE_TOP},\n {label: 'bottom', side: SIDE_BOTTOM},\n {label: 'inner', side: SIDE_INNER},\n {label: 'mechanical', side: SIDE_ALL},\n {label: 'other', side: null},\n]\n\nconst STYLE = 'absolute left-0 top-5 bottom-5 overflow-y-hidden w-animate'\nconst STYLE_DEFAULT = 'w-sixth'\nconst STYLE_EXPANDED = 'w-third'\nconst LIST_WRAPPER_STYLE =\n 'w-100 mxh-100 overflow-y-auto ph3 tf-flip-x scrollbar-white'\nconst LIST_STYLE = 'list mt0 mb3 pl0 tf-flip-x'\n\nexport default function SideList(props: Props): JSX.Element {\n const {layers, showFilenames} = props\n\n return (\n <div className={cx(STYLE, showFilenames ? STYLE_EXPANDED : STYLE_DEFAULT)}>\n <div onWheel={stopPropagation} className={LIST_WRAPPER_STYLE}>\n <ul className={LIST_STYLE}>\n {SIDES.map(sideProps => (\n <SideItem\n key={sideProps.label}\n label={sideProps.label}\n layers={layers\n .filter(ly => ly.side === sideProps.side)\n .sort(orderLayers)}\n showFilenames={showFilenames}\n />\n ))}\n </ul>\n </div>\n </div>\n )\n}\n","import React from 'react'\n\nimport {Button, Icon} from '../ui'\n\ntype Props = {\n showFilenames: boolean\n toggle: () => void\n}\n\nconst STYLE = 'absolute left-1 bottom-2 flex items-center f5'\nconst LABEL_STYLE = 'dib lh-title mv0 ml2 mr3'\n\nexport default function ShowFilenamesButton(props: Props): JSX.Element {\n const {showFilenames, toggle} = props\n\n return (\n <Button className={STYLE} onClick={toggle}>\n <Icon name={showFilenames ? 'chevron-left' : 'chevron-right'} />\n <p className={LABEL_STYLE}>\n {`${showFilenames ? 'Hide' : 'Show'} filenames`}\n </p>\n </Button>\n )\n}\n","import React, {useState} from 'react'\n\nimport {useAppState} from '../state'\nimport {Fade, Slide} from '../ui'\nimport SideList from './SideList'\nimport ShowFilenamesButton from './ShowFilenamesButton'\n\nexport default function FileList(): JSX.Element {\n const {loading, board} = useAppState()\n const [showFilenames, setShowFilenames] = useState(false)\n\n const layers = board ? board.layers : []\n const show = !loading && board !== null\n\n return (\n <>\n <Slide in={show} from=\"left\">\n <SideList layers={layers} showFilenames={showFilenames} />\n </Slide>\n <Fade in={show}>\n <ShowFilenamesButton\n showFilenames={showFilenames}\n toggle={() => setShowFilenames(!showFilenames)}\n />\n </Fade>\n </>\n )\n}\n","import React from 'react'\n\nimport {Button, Icon} from '../ui'\n\ntype Props = {\n show: boolean\n toggle: () => void\n}\n\nexport default function ShowButton(props: Props): JSX.Element {\n const {show, toggle} = props\n\n return (\n <Button\n className=\"absolute top-5 right-1 flex items-center f5\"\n onClick={toggle}\n >\n <p className=\"dib lh-title mv0 ml3 mr2\">\n {`${show ? 'Hide' : 'Show'} saved boards`}\n </p>\n <Icon name={show ? 'chevron-right' : 'chevron-left'} />\n </Button>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\n\nimport {BoardSummary} from '../types'\nimport {LazyThumbnail} from '../ui'\n\nexport type BoardItemProps = BoardSummary & {\n onClick: (id: string) => void\n selected: boolean\n}\n\n// TODO(mc, 2018-12-26): dedupe this logic\nconst DEFAULT_COLOR = 'rgba(00, 66, 00, 0.75)'\n\nexport default function BoardItem(props: BoardItemProps): JSX.Element {\n const {id, name, selected, options, thumbnail} = props\n const color = options.color.sm || DEFAULT_COLOR\n const handleClick = (): unknown => !selected && props.onClick(id)\n\n return (\n <li\n className={cx('dib w-50 pl3 pb3 fr', {pointer: !selected})}\n onClick={handleClick}\n >\n <div className={cx('relative overflow-hidden w-100 h4 br3 shadow')}>\n <div className=\"w-100 h-100 bg-white\">\n <p\n className={cx('f6 lh-title mv0 mh4 pt2 tc truncate', {\n b: selected,\n })}\n >\n {name}\n </p>\n <LazyThumbnail\n url={thumbnail}\n spinnerColor={color}\n className=\"absolute top-2 bottom-1 left-1 right-1\"\n />\n </div>\n </div>\n </li>\n )\n}\n","import React from 'react'\n\nimport {stopPropagation} from '../events'\nimport {BoardSummary} from '../types'\nimport BoardItem from './BoardItem'\n\nconst STYLE = 'absolute right-0 top-7 bottom-5 w-third overflow-hidden'\nconst WRAPPER_STYLE = 'w-100 mxh-100 ph3 overflow-y-auto scrollbar-white'\nconst LIST_STYLE = 'list mt1 mb0 pl0 near-black'\n\ntype Props = {\n selectedId: string | null\n boards: Array<BoardSummary>\n onItemClick: (id: string) => void\n}\n\nexport default function SavedBoardList(props: Props): JSX.Element {\n const {selectedId, boards, onItemClick} = props\n\n return (\n <div className={STYLE}>\n <div onWheel={stopPropagation} className={WRAPPER_STYLE}>\n <ul className={LIST_STYLE}>\n {boards.map(b => (\n <BoardItem\n {...b}\n key={b.id}\n selected={b.id === selectedId}\n onClick={onItemClick}\n />\n ))}\n </ul>\n </div>\n </div>\n )\n}\n","import React, {useState, useEffect} from 'react'\n\nimport {useAppState, getBoard} from '../state'\nimport {usePrevious} from '../hooks'\nimport {Fade, Slide} from '../ui'\nimport ShowButton from './ShowButton'\nimport SavedBoardList from './SavedBoardList'\n\nexport default function BoardList(): JSX.Element {\n const {mode, loading, board, savedBoards, dispatch} = useAppState()\n const [show, setShow] = useState(mode === null)\n const [selected, setSelected] = useState(board ? board.id : null)\n const prevLoading = usePrevious(loading)\n\n useEffect(() => {\n if (prevLoading && !loading && board) {\n setShow(false)\n setSelected(board.id)\n }\n }, [prevLoading, loading, board])\n\n const haveBoards = savedBoards.length > 0\n const showList = haveBoards && show\n\n return (\n <>\n <Fade in={haveBoards}>\n <ShowButton show={showList} toggle={() => setShow(!show)} />\n </Fade>\n <Slide in={showList} from=\"right\">\n <SavedBoardList\n selectedId={selected}\n boards={savedBoards}\n onItemClick={(id: string) => {\n dispatch(getBoard(id))\n setSelected(id)\n }}\n />\n </Slide>\n </>\n )\n}\n","import React from 'react'\n\nimport pkg from '../../package.json'\nimport {useAppState, deleteAllBoards} from '../state'\nimport {DeleteButton, Drawer, Label} from '../ui'\n\nconst TITLE = 'app settings'\nconst FOOTER = `tracespace v${pkg.version}`\n\nconst DELETE_SAVED_COPY = 'delete all saved boards'\n\nconst DELETE_COPY_STYLE = 'mr-auto'\nconst DELETE_BUTTON_STYLE = 'nr2'\nconst FOOTER_STYLE = 'mt3 mb1 f7 lh-copy'\n\ntype Props = {\n open: boolean\n close: () => void\n}\n\nexport default function SettingsDrawer(props: Props): JSX.Element {\n const {dispatch} = useAppState()\n const {open, close} = props\n\n const handleDeleteAllClick = (): void => {\n dispatch(deleteAllBoards())\n close()\n }\n\n return (\n <Drawer title={TITLE} open={open} close={close}>\n <Label>\n <span className={DELETE_COPY_STYLE}>{DELETE_SAVED_COPY}</span>\n <DeleteButton\n className={DELETE_BUTTON_STYLE}\n onClick={handleDeleteAllClick}\n />\n </Label>\n <footer className={FOOTER_STYLE}>{FOOTER}</footer>\n </Drawer>\n )\n}\n","import React, {useState} from 'react'\n\nimport pkg from '../../package.json'\nimport {Button, Icon, getButtonStyle} from '../ui'\nimport SettingsDrawer from './SettingsDrawer'\n\nconst HELP_TOOLTIP = 'Troubleshooting'\nconst HELP_HREF = `https://github.com/tracespace/tracespace/blob/v${pkg.version}/apps/view/HELP.md`\n\nconst SETTINGS_TOOLTIP = 'App settings'\n\nexport type AppSettingsProps = {\n buttonClassName: string\n}\n\nexport default function AppSettings(props: AppSettingsProps): JSX.Element {\n const [open, setOpen] = useState(false)\n const {buttonClassName} = props\n const toggleOpen = (): void => setOpen(!open)\n\n return (\n <>\n <a\n href={HELP_HREF}\n title={HELP_TOOLTIP}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className={getButtonStyle({className: buttonClassName})}\n >\n <Icon name=\"question-circle\" />\n </a>\n <Button\n onClick={toggleOpen}\n title={SETTINGS_TOOLTIP}\n className={buttonClassName}\n >\n <Icon name=\"sliders-h\" />\n </Button>\n <SettingsDrawer open={open} close={toggleOpen} />\n </>\n )\n}\n","import React from 'react'\n\nimport {FieldProps} from './types'\n\nconst BASE_STYLE = 'f3 lh-title normal tc'\nconst STYLE = `${BASE_STYLE} mv0 mh2`\nconst INPUT_STYLE = `${BASE_STYLE} mb3 bb bt-0 br-0 bl-0 b--near-black`\n\nexport function BoardName(props: {children: React.ReactNode}): JSX.Element {\n return <h2 className={STYLE}>{props.children}</h2>\n}\n\nexport function BoardNameInput(props: FieldProps): JSX.Element {\n return (\n <input\n type=\"text\"\n className={INPUT_STYLE}\n autoComplete=\"off\"\n data-lpignore=\"true\"\n {...props.field}\n />\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\n\nimport {useAppState, setMode} from '../state'\nimport {Button} from '../ui'\n\nconst STYLE = 'mt2'\nconst BUTTON_STYLE = 'dib tc'\nconst TEXT_STYLE = 'db w3 mt2 mh2 mb1 bw2 bb'\nconst DESELECTED_STYLE = 'b--transparent'\nconst SELECTED_STYLE = 'b--brand'\n\nexport default function ModeSelect(): JSX.Element | null {\n const {mode, dispatch} = useAppState()\n\n if (!mode) return null\n\n const buttons = [\n {mode: 'layers', onClick: () => dispatch(setMode('layers'))},\n {mode: 'top', onClick: () => dispatch(setMode('top'))},\n {mode: 'bottom', onClick: () => dispatch(setMode('bottom'))},\n ]\n\n return (\n <div className={STYLE}>\n {buttons.map(b => (\n <Button key={b.mode} className={BUTTON_STYLE} onClick={b.onClick}>\n <span\n className={cx(\n TEXT_STYLE,\n mode === b.mode ? SELECTED_STYLE : DESELECTED_STYLE\n )}\n >\n {b.mode}\n </span>\n </Button>\n ))}\n </div>\n )\n}\n","import {\n Optional,\n BoardRender,\n BoardUpdate,\n BoardOptions,\n LayerOptions,\n LayerUpdatesMap,\n Logger,\n} from '../types'\n\nimport {\n Values,\n FormBoardOptions,\n FormLayerOptions,\n FormLayerUpdatesMap,\n} from './types'\n\nexport const MASK_ALPHA = 'bf'\nexport const GAP_FILL_DEFAULT = 0.00011\n\nexport function valuesToBoardUpdate(values: Values, log: Logger): BoardUpdate {\n let outlineGapFill =\n values.options.outlineGapFill !== ''\n ? Number(values.options.outlineGapFill)\n : GAP_FILL_DEFAULT\n\n if (!Number.isFinite(outlineGapFill)) outlineGapFill = GAP_FILL_DEFAULT\n\n return {\n name: values.name,\n options: parseFormBoardOptions(values.options),\n gerberOptions: parseFormLayerOptions(values.gerberOptions, log),\n drillOptions: parseFormLayerOptions(values.drillOptions, log),\n layers: parseFormLayerUpdates(values.layers),\n }\n}\n\nexport function boardRenderToValues(board: BoardRender): Values {\n return {\n name: board.name,\n options: boardOptionsToFormValue(board.options),\n gerberOptions: layerOptionsToFormValue(board.gerberOptions),\n drillOptions: layerOptionsToFormValue(board.drillOptions),\n layers: board.layers.reduce<FormLayerUpdatesMap>(\n (result, ly) => ({\n ...result,\n [ly.id]: {side: ly.side || '', type: ly.type || '', color: ly.color},\n }),\n {}\n ),\n }\n}\n\nfunction parseFormBoardOptions(formOptions: FormBoardOptions): BoardOptions {\n let color = formOptions.color\n let outlineGapFill =\n formOptions.outlineGapFill !== ''\n ? Number(formOptions.outlineGapFill)\n : GAP_FILL_DEFAULT\n\n if (!Number.isFinite(outlineGapFill)) outlineGapFill = GAP_FILL_DEFAULT\n\n color = {...color, sm: `${color.sm.slice(0, 7)}${MASK_ALPHA}`}\n\n return {...formOptions, color, outlineGapFill}\n}\n\nfunction parseFormLayerOptions(\n formOptions: FormLayerOptions,\n log: Logger\n): Optional<LayerOptions> {\n const {coordinateFormat, zeroSuppression, units} = formOptions\n const result: Optional<LayerOptions> = {}\n\n if (Array.isArray(coordinateFormat)) {\n const parsed = coordinateFormat.map(Number)\n if (Number.isInteger(parsed[0]) && Number.isInteger(parsed[1])) {\n result.coordinateFormat = [parsed[0], parsed[1]]\n } else {\n log.warn('Invalid coordinateFormat:', coordinateFormat)\n }\n }\n\n if (zeroSuppression) result.zeroSuppression = zeroSuppression\n if (units) result.units = units\n\n return result\n}\n\nfunction parseFormLayerUpdates(\n formUpdates: FormLayerUpdatesMap\n): LayerUpdatesMap {\n return Object.keys(formUpdates).reduce<LayerUpdatesMap>((result, id) => {\n const update = formUpdates[id]\n\n return {\n ...result,\n [id]: {\n type: update.type || null,\n side: update.side || null,\n color: update.color,\n },\n }\n }, {})\n}\n\nfunction boardOptionsToFormValue(options: BoardOptions): FormBoardOptions {\n return {\n ...options,\n color: {\n ...options.color,\n sm: options.color.sm.slice(0, 7),\n },\n }\n}\n\nfunction layerOptionsToFormValue(\n options: Optional<LayerOptions>\n): FormLayerOptions {\n return {\n coordinateFormat: options.coordinateFormat || '',\n zeroSuppression: options.zeroSuppression || '',\n units: options.units || '',\n }\n}\n","import React, {useState} from 'react'\nimport cx from 'classnames'\n\nimport {useTimeout} from '../hooks'\nimport {preventDefault, select} from '../events'\nimport {Label, Icon} from '../ui'\n\nexport type BoardUrlProps = {\n url: string\n}\n\nconst SUCCESS_TIMEOUT = 1200\n\nconst PARAM = '?boardUrl='\n\nconst STYLE = 'justify-center f6 lh-solid mb3'\nconst TEXT_STYLE =\n 'flex items-center mv0 lh-copy near-black bg-animate near-black'\nconst ICON_STYLE = 'flex-none ml1 nr4 br2 c-animate bg-animate'\n\nexport default function BoardUrl(props: BoardUrlProps): JSX.Element {\n const [selected, setSelected] = useState(false)\n const [success, setSuccess] = useState(false)\n\n useTimeout(() => setSuccess(false), success ? SUCCESS_TIMEOUT : null)\n\n const {url} = props\n const {origin, pathname} = window.location\n const href = `${origin}${pathname}`\n const copyValue = url ? `${href}${PARAM}${encodeURIComponent(url)}` : ''\n const textStyle = cx(TEXT_STYLE, selected ? 'bg-light-blue' : 'bg-white')\n const iconStyle = cx(\n ICON_STYLE,\n success ? 'white bg-brand' : 'near-black bg-white'\n )\n\n return (\n <Label\n className={STYLE}\n onCopy={event => {\n setSuccess(true)\n event.currentTarget.focus()\n event.clipboardData.setData('text/plain', copyValue)\n preventDefault(event)\n }}\n >\n <p className={textStyle}>\n <span className=\"fw3\">\n {href}\n {PARAM}\n </span>\n <span>{url}</span>\n </p>\n <Icon name=\"copy\" className={iconStyle} />\n <input\n type=\"text\"\n value={copyValue}\n className=\"clip\"\n onClick={event => {\n select(event)\n document.execCommand('copy')\n }}\n onFocus={event => {\n select(event)\n setSelected(true)\n }}\n onBlur={() => {\n setSelected(false)\n setSuccess(false)\n }}\n readOnly\n />\n </Label>\n )\n}\n","import React from 'react'\n\nimport {Button, DeleteButton, Icon} from '../ui'\n\nconst CANCEL_TOOLTIP = 'Cancel'\nconst SAVE_TOOLTIP = 'Save changes'\n\nconst STYLE = 'absolute top-1 right-1 nt2 nr2 f4'\nconst BUTTON_STYLE = 'dib pa1'\nconst DELETE_BUTTON_STYLE = `${BUTTON_STYLE} absolute top-1 left-1 nt2 nl2 f4`\n\ntype Props = {\n delete: () => void\n}\n\nexport default function SettingsButtons(props: Props): JSX.Element {\n return (\n <>\n <div className={STYLE}>\n <Button type=\"reset\" className={BUTTON_STYLE} title={CANCEL_TOOLTIP}>\n <Icon name=\"times\" />\n </Button>\n <Button type=\"submit\" className={BUTTON_STYLE} title={SAVE_TOOLTIP}>\n <Icon name=\"check\" className=\"green\" />\n </Button>\n </div>\n <DeleteButton onClick={props.delete} className={DELETE_BUTTON_STYLE} />\n </>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\nimport contrast from 'contrast'\nimport {Field} from 'formik'\n\nimport {BoardOptions} from '../types'\nimport {ColorPill, Icon, Label} from '../ui'\nimport {FieldProps} from './types'\nimport {MASK_ALPHA} from './values'\n\ntype BoardColor = BoardOptions['color']\n\ntype ColorPreset = {\n title: string\n color: BoardColor\n}\n\ntype ColorId = keyof BoardColor\n\nconst DEFAULT_COLOR_PRESET: BoardColor = {\n fr4: '#b7c4c8',\n cf: '#cc9933',\n sm: '#000000',\n ss: '#ff0000',\n cu: '#ffffff',\n sp: '#dddddd',\n out: '#002255',\n}\n\nconst UPSTREAM_COLOR_PRESET: BoardColor = {\n fr4: '#666666',\n cf: '#cc9933',\n sm: '#004200',\n ss: '#ffffff',\n cu: '#cccccc',\n sp: '#999999',\n out: '#000000',\n}\n\nconst OSH_PARK_COLOR_PRESET: BoardColor = {\n fr4: '#666666',\n cf: '#cc9933',\n sm: '#4b0082',\n ss: '#ffffff',\n cu: '#cccccc',\n sp: '#999999',\n out: '#000000',\n}\n\nconst SPARKFUN_COLOR_PRESET: BoardColor = {\n fr4: '#666666',\n cf: '#f5f5f5',\n sm: '#cc0000',\n ss: '#ffffff',\n cu: '#cccccc',\n sp: '#999999',\n out: '#000000',\n}\n\n\nconst COLOR_PRESETS: Array<ColorPreset> = [\n {title: 'default', color: DEFAULT_COLOR_PRESET},\n {title: 'upstream', color: UPSTREAM_COLOR_PRESET},\n {title: 'OSH Park', color: OSH_PARK_COLOR_PRESET},\n {title: 'SparkFun', color: SPARKFUN_COLOR_PRESET},\n]\n\nconst COLOR_IDS: Array<ColorId> = ['sm', 'ss', 'cf', 'cu', 'sp', 'out', 'fr4']\nconst COLOR_NAMES = {sm: 'soldermask', ss: 'silkscreen', cf: 'copper finish', cu: 'copper', sp: 'solder paste', out: 'outline', 'fr4': 'pcb core'}\n\n// TOCO(mc, 2019-03-01): move opacity entirely to pcb-stackup-core\nconst stripAlpha = (c: string): string => c.slice(0, 7)\nconst colorsMatch = (a: string, b: string): boolean =>\n stripAlpha(a) === stripAlpha(b)\n\nfunction ColorInput(props: FieldProps & {colorId: ColorId}): JSX.Element {\n const {colorId, field, form} = props\n const value = stripAlpha(`${field.value}`)\n\n return (\n <Label className=\"h2\">\n <span className=\"mr-auto\">{COLOR_NAMES[colorId]}</span>\n <input\n {...field}\n value={value}\n type=\"color\"\n className=\"clip\"\n onChange={event => {\n let value = stripAlpha(event.target.value)\n if (colorId === 'sm') value += MASK_ALPHA\n form.setFieldValue(field.name, value)\n }}\n />\n <ColorPill color={value} />\n </Label>\n )\n}\n\nexport function ColorPresetsField(props: {fieldName: string}): JSX.Element {\n return <Field name={props.fieldName} component={ColorPresetInput} />\n}\n\nexport function ColorFields(props: {fieldName: string}): JSX.Element {\n return (\n <>\n {COLOR_IDS.map(id => (\n <Field\n key={id}\n name={`${props.fieldName}.${id}`}\n component={ColorInput}\n colorId={id}\n />\n ))}\n </>\n )\n}\n\nfunction ColorPresetInput(props: FieldProps): JSX.Element {\n return (\n <>\n {COLOR_PRESETS.map(preset => (\n <ColorPresetOption key={preset.title} {...preset} {...props} />\n ))}\n </>\n )\n}\n\nfunction ColorPresetOption(props: FieldProps & ColorPreset): JSX.Element {\n const {title, color, field, form} = props\n const value = {...color, sm: `${stripAlpha(color.sm)}${MASK_ALPHA}`}\n const checked = COLOR_IDS.every(i => colorsMatch(color[i], field.value[i]))\n const iconName = checked ? 'dot-circle' : 'circle'\n\n return (\n <Label className=\"h2\">\n <input\n type=\"radio\"\n className=\"clip\"\n checked={checked}\n onChange={() => form.setFieldValue(field.name, value)}\n />\n <Icon name={iconName} className=\"flex-none nl2\" />\n <span className=\"lh-title mr-auto\">{title}</span>\n <BoardColorSwatch boardColor={color} />\n </Label>\n )\n}\n\nfunction BoardColorSwatch(props: {boardColor: BoardColor}): JSX.Element {\n const {boardColor} = props\n\n return (\n <div className=\"flex-none tf-skew-15\">\n {COLOR_IDS.map((id, index, collection) => {\n const color = boardColor[id]\n const previous = boardColor[collection[index - 1]] || null\n const needsBorder = contrast(color) === 'light'\n const prevHasBorder = previous && contrast(previous) === 'light'\n const style = cx('border-box dib w1 h1 v-mid', {\n 'bt bb br b--near-black': needsBorder,\n bl: needsBorder && !prevHasBorder,\n })\n\n return (\n <span key={id} className={style} style={{backgroundColor: color}} />\n )\n })}\n </div>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\nimport {Field} from 'formik'\n\nimport {Checkbox, HiddenInput, Label} from '../ui'\nimport {CoordinateFormat, ZeroSuppression, Units} from '../types'\nimport {FieldProps} from './types'\nimport {GAP_FILL_DEFAULT} from './values'\n\nconst USE_OUTLINE_LABEL = 'use outline layer for board shape'\nconst GAP_FILL_LABEL = 'gap fill limit'\nconst GAP_FILL_UNITS = 'mm'\nconst OVERRIDE_LABEL = 'override'\nconst COORD_FORMAT_LABEL = 'integer/decimal coordinate format'\nconst ZERO_SUPRESSION_LABEL = 'zero suppression'\nconst UNITS_LABEL = 'units'\n\nconst NUMBER_INPUT_STYLE =\n 'bb bt-0 br-0 bl-0 bw1 tc near-black b--near-black bg-transparent code f6'\n\nexport function UseOutlineInput(props: FieldProps): JSX.Element {\n return (\n <Checkbox className=\"inline-flex v-mid\" {...props.field}>\n {USE_OUTLINE_LABEL}\n </Checkbox>\n )\n}\n\nexport function GapFillInput(props: FieldProps): JSX.Element {\n const {field, form} = props\n const value = field.value !== '' ? field.value : GAP_FILL_DEFAULT\n const disabled = !form.values.options.useOutline\n const className = cx('inline-flex items-center pointer h2 v-mid fr', {\n 'o-40': disabled,\n })\n\n return (\n <label className={className}>\n {GAP_FILL_LABEL}\n <input\n {...field}\n type=\"text\"\n className={cx(NUMBER_INPUT_STYLE, 'w3 ml3 mr2')}\n disabled={disabled}\n value={value}\n />\n {GAP_FILL_UNITS}\n </label>\n )\n}\n\ntype RenderSettingProps<Value> = {\n fieldName: string\n renderName: string\n overridden: boolean\n defaultValue: Value | null | undefined\n}\n\nexport function CoordFormatFields(\n props: RenderSettingProps<CoordinateFormat>\n): JSX.Element {\n const {fieldName, renderName, overridden, defaultValue} = props\n\n return (\n <OverridableField\n fieldName={fieldName}\n label={`${OVERRIDE_LABEL} ${renderName} ${COORD_FORMAT_LABEL}`}\n overridden={overridden}\n defaultValue={defaultValue}\n >\n <Field\n name={`${fieldName}[0]`}\n placeholder={defaultValue ? defaultValue[0] : ''}\n type=\"text\"\n className={cx(NUMBER_INPUT_STYLE, 'w2')}\n />\n <span className=\"dib mh2\">.</span>\n <Field\n name={`${fieldName}[1]`}\n placeholder={defaultValue ? defaultValue[1] : ''}\n type=\"text\"\n className={cx(NUMBER_INPUT_STYLE, 'w2')}\n />\n </OverridableField>\n )\n}\n\ntype RadioGroupProps = FieldProps & {\n options: Array<{value: string; label: string}>\n defaultValue: unknown\n}\n\nfunction RadioGroup(props: RadioGroupProps): JSX.Element {\n const {field, options, defaultValue} = props\n\n return (\n <>\n {options.map(opt => {\n const value = field.value || defaultValue\n const checked = value === opt.value\n\n return (\n <Label key={opt.value}>\n <HiddenInput\n {...field}\n type=\"radio\"\n key={opt.value}\n value={opt.value}\n checked={checked}\n />\n <span className={cx('dib ph2 ml2', {'bb bw1 b--brand': checked})}>\n {opt.label}\n </span>\n </Label>\n )\n })}\n </>\n )\n}\n\nexport function ZeroSuppressionFields(\n props: RenderSettingProps<ZeroSuppression>\n): JSX.Element {\n const {fieldName, renderName, overridden, defaultValue} = props\n\n return (\n <OverridableField\n fieldName={fieldName}\n label={`${OVERRIDE_LABEL} ${renderName} ${ZERO_SUPRESSION_LABEL}`}\n overridden={overridden}\n defaultValue={defaultValue}\n >\n <Field\n name={fieldName}\n component={RadioGroup}\n defaultValue={defaultValue}\n options={[\n {value: 'L', label: 'leading'},\n {value: 'T', label: 'trailing'},\n ]}\n />\n </OverridableField>\n )\n}\n\nexport function UnitsFields(props: RenderSettingProps<Units>): JSX.Element {\n const {fieldName, renderName, overridden, defaultValue} = props\n\n return (\n <OverridableField\n fieldName={fieldName}\n label={`${OVERRIDE_LABEL} ${renderName} ${UNITS_LABEL}`}\n overridden={overridden}\n defaultValue={defaultValue}\n >\n <Field\n name={fieldName}\n component={RadioGroup}\n defaultValue={defaultValue}\n options={[\n {value: 'in', label: 'inches'},\n {value: 'mm', label: 'millimeters'},\n ]}\n />\n </OverridableField>\n )\n}\n\ntype OverrideCheckboxProps = FieldProps & {\n label: string\n defaultValue: unknown\n}\n\nfunction OverrideCheckbox(props: OverrideCheckboxProps): JSX.Element {\n const {form, defaultValue, label} = props\n const field = {\n ...props.field,\n checked: !!props.field.value,\n onBlur: () => {},\n onChange: (event: React.ChangeEvent<HTMLInputElement>): void => {\n const value = event.target.checked ? defaultValue : ''\n form.setFieldValue(props.field.name, value)\n },\n }\n\n return <Checkbox {...field}>{label}</Checkbox>\n}\n\ntype OverridableFieldProps = {\n fieldName: string\n label: string\n overridden: boolean\n defaultValue: unknown\n children: React.ReactNode\n}\n\nfunction OverridableField(props: OverridableFieldProps): JSX.Element {\n const {fieldName, label, overridden, defaultValue, children} = props\n\n return (\n <div className=\"flex items-center h2 mt1\">\n <Field\n name={fieldName}\n component={OverrideCheckbox}\n defaultValue={defaultValue}\n label={label}\n className=\"flex\"\n />\n <div className={cx('flex flex-none ml-auto', {'o-40': !overridden})}>\n {children}\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport cx from 'classnames'\n\nimport {ColorPill, HiddenInput, Label} from '../ui'\nimport {SIDE_ALL, ALL_TYPES, typeToValidSides} from '../layers'\nimport {GerberType} from '../types'\nimport {FieldProps} from './types'\n\ntype LayerListProps = {\n children: React.ReactNode\n}\n\nexport function LayerList(props: LayerListProps): JSX.Element {\n return <ul className=\"list pl0 mv0\">{props.children}</ul>\n}\n\ntype LayerItemProps = {\n filename: string\n children: React.ReactNode\n}\n\nexport function LayerItem(props: LayerItemProps): JSX.Element {\n const {filename} = props\n\n return (\n <li className=\"flex items-center mb3\">\n <p className=\"code f5 lh-title mv0 mr-auto\">{filename}</p>\n {props.children}\n </li>\n )\n}\n\ntype LayerFieldProps = FieldProps & {layerId: string}\n\nexport function LayerTypeSelect(props: LayerFieldProps): JSX.Element {\n const {layerId, form, field} = props\n\n return (\n <select\n {...field}\n className=\"dib flex-none f5 w4 mr2\"\n onChange={event => {\n const type = (event.target.value as GerberType) || ''\n const layer = form.values.layers[layerId]\n const validSides = typeToValidSides(type)\n const side = validSides.includes(layer.side)\n ? layer.side\n : validSides[0] || ''\n\n form.setValues({\n ...form.values,\n layers: {...form.values.layers, [layerId]: {...layer, type, side}},\n })\n }}\n >\n {ALL_TYPES.map(t => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n <option value=\"\">n/a</option>\n </select>\n )\n}\n\nexport function LayerSideSelect(props: LayerFieldProps): JSX.Element {\n const {layerId, field, form} = props\n const {type} = form.values.layers[layerId]\n const options: Array<string> = typeToValidSides(type)\n const disabled = options.length < 2\n\n if (options.length < 1) options.push('')\n\n return (\n <select className=\"dib flex-none f5 w4 mr2\" disabled={disabled} {...field}>\n {options.map(opt => (\n <option key={opt} value={opt}>\n {opt === SIDE_ALL || opt === '' ? 'n/a' : opt}\n </option>\n ))}\n </select>\n )\n}\n\nexport function LayerColorInput(props: LayerFieldProps): JSX.Element {\n const {layerId, field, form} = props\n const {type} = form.values.layers[layerId]\n const disabled = type === ''\n\n return (\n <Label className=\"h2\" disabled={disabled}>\n <HiddenInput type=\"color\" disabled={disabled} {...field} />\n <ColorPill color={field.value} className={cx({'o-40': disabled})} />\n </Label>\n )\n}\n","import React from 'react'\nimport {Formik, Form, Field} from 'formik'\n\nimport log from '../logger'\nimport {getDefaultLayerOptions, orderLayers} from '../layers'\nimport {useAppState, updateBoard, deleteBoard} from '../state'\nimport {BoardRender} from '../types'\nimport {TitledSection, SectionColumnLeft, SectionColumnRight} from '../ui'\nimport {Values} from './types'\nimport {boardRenderToValues, valuesToBoardUpdate} from './values'\n\nimport BoardUrl from './BoardUrl'\nimport SettingsButtons from './SettingsButtons'\nimport {BoardNameInput} from './name'\nimport {ColorPresetsField, ColorFields} from './color'\nimport {\n UseOutlineInput,\n GapFillInput,\n CoordFormatFields,\n ZeroSuppressionFields,\n UnitsFields,\n} from './render'\nimport {\n LayerList,\n LayerItem,\n LayerTypeSelect,\n LayerSideSelect,\n LayerColorInput,\n} from './layers'\n\ntype SettingsFormProps = {\n className: string\n board: BoardRender\n close: () => void\n}\n\nexport default function SettingsForm(props: SettingsFormProps): JSX.Element {\n const {dispatch} = useAppState()\n const {board, close, className} = props\n const {id, sourceUrl, layers} = board\n const defaultGerberOptions = getDefaultLayerOptions(layers, 'gerber')\n const defaultDrillOptions = getDefaultLayerOptions(layers, 'drill')\n\n const handleSubmit = (values: Values): void => {\n dispatch(updateBoard(id, valuesToBoardUpdate(values, log)))\n close()\n }\n\n const handleDelete = (): void => {\n dispatch(deleteBoard(id))\n close()\n }\n\n return (\n <Formik\n initialValues={boardRenderToValues(board)}\n onSubmit={handleSubmit}\n onReset={close}\n >\n {formProps => (\n <Form className={className}>\n <SettingsButtons delete={handleDelete} />\n <Field name=\"name\" component={BoardNameInput} />\n {sourceUrl && <BoardUrl url={sourceUrl} />}\n <TitledSection title=\"colors\">\n <SectionColumnLeft>\n <ColorPresetsField fieldName=\"options.color\" />\n </SectionColumnLeft>\n <SectionColumnRight>\n <ColorFields fieldName=\"options.color\" />\n </SectionColumnRight>\n </TitledSection>\n <TitledSection title=\"render options\">\n <div>\n <Field name=\"options.useOutline\" component={UseOutlineInput} />\n <Field name=\"options.outlineGapFill\" component={GapFillInput} />\n </div>\n <CoordFormatFields\n fieldName=\"gerberOptions.coordinateFormat\"\n renderName=\"gerber\"\n defaultValue={defaultGerberOptions.coordinateFormat}\n overridden={!!formProps.values.gerberOptions.coordinateFormat}\n />\n <ZeroSuppressionFields\n fieldName=\"gerberOptions.zeroSuppression\"\n renderName=\"gerber\"\n defaultValue={defaultGerberOptions.zeroSuppression}\n overridden={!!formProps.values.gerberOptions.zeroSuppression}\n />\n <UnitsFields\n fieldName=\"gerberOptions.units\"\n renderName=\"gerber\"\n defaultValue={defaultGerberOptions.units}\n overridden={!!formProps.values.gerberOptions.units}\n />\n <CoordFormatFields\n fieldName=\"drillOptions.coordinateFormat\"\n renderName=\"drill\"\n defaultValue={defaultDrillOptions.coordinateFormat}\n overridden={!!formProps.values.drillOptions.coordinateFormat}\n />\n <ZeroSuppressionFields\n fieldName=\"drillOptions.zeroSuppression\"\n renderName=\"drill\"\n defaultValue={defaultDrillOptions.zeroSuppression}\n overridden={!!formProps.values.drillOptions.zeroSuppression}\n />\n <UnitsFields\n fieldName=\"drillOptions.units\"\n renderName=\"drill\"\n defaultValue={defaultDrillOptions.units}\n overridden={!!formProps.values.drillOptions.units}\n />\n </TitledSection>\n <TitledSection title=\"layers\">\n <LayerList>\n {layers\n .slice(0)\n .sort(orderLayers)\n .map(ly => (\n <LayerItem key={ly.id} filename={ly.filename}>\n <Field\n name={`layers.${ly.id}.type`}\n component={LayerTypeSelect}\n layerId={ly.id}\n />\n <Field\n name={`layers.${ly.id}.side`}\n component={LayerSideSelect}\n layerId={ly.id}\n />\n <Field\n name={`layers.${ly.id}.color`}\n component={LayerColorInput}\n layerId={ly.id}\n />\n </LayerItem>\n ))}\n </LayerList>\n </TitledSection>\n </Form>\n )}\n </Formik>\n )\n}\n","import React, {useState, useRef, useEffect} from 'react'\n\nimport {stopPropagation} from '../events'\nimport {BoardRender} from '../types'\nimport {Button, Icon, Fade} from '../ui'\nimport {BoardName} from './name'\nimport ModeSelect from './ModeSelect'\nimport SettingsForm from './SettingsForm'\n\nexport type BoardSettingsProps = {\n board: BoardRender\n updating: boolean\n}\n\nconst OPEN_BUTTON_TOOLTIP = 'Board settings'\n\nconst STYLE = 'dib ph3 tc v-top w-third'\nconst NAME_STYLE = 'flex items-center justify-center'\nconst OPEN_BUTTON_STYLE = 'nr4'\nconst MODAL_STYLE = 'fixed top-1 left-0 right-0 bottom-1 z-1 nt2'\nconst MODAL_CONTENTS_STYLE =\n 'relative w-50 mxh-100 center pt2 ph4 br3 near-black bg-white shadow overflow-y-auto scrollbar-near-black'\n\nconst FORM_STYLE = 'dib w-100'\n\nexport default function BoardSettings(props: BoardSettingsProps): JSX.Element {\n const [open, setOpen] = useState(false)\n const modalContentsRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const $modalContents = modalContentsRef.current\n\n if ($modalContents) {\n const {width} = $modalContents.getBoundingClientRect()\n const clientWidth = $modalContents.clientWidth\n const shift = (width - clientWidth) / 2\n\n // shift modal contents by scrollbar width if present\n $modalContents.style.transform = `translateX(${shift}px)`\n }\n })\n\n const {board, updating} = props\n const toggleOpen = (): void => setOpen(!open)\n\n return (\n <div className={STYLE}>\n <div className={NAME_STYLE}>\n <BoardName>{board.name}</BoardName>\n <Button\n onClick={toggleOpen}\n disabled={updating}\n className={OPEN_BUTTON_STYLE}\n title={OPEN_BUTTON_TOOLTIP}\n >\n <Icon\n name={updating ? 'spinner' : 'cog'}\n faProps={{pulse: updating}}\n />\n </Button>\n </div>\n <ModeSelect />\n <Fade in={open}>\n <div className={MODAL_STYLE} onWheel={stopPropagation}>\n <div className={MODAL_CONTENTS_STYLE} ref={modalContentsRef}>\n <SettingsForm\n className={FORM_STYLE}\n board={board}\n close={toggleOpen}\n />\n </div>\n </div>\n </Fade>\n </div>\n )\n}\n","import React from 'react'\nimport {Formik, Form, Field} from 'formik'\nimport {Button, Drawer, HiddenInput, Icon, Label, getButtonStyle} from '../ui'\nimport {FileEvent} from '../types'\n\nconst TITLE = 'new board'\n\nconst UPLOAD_FILES_LABEL = 'upload files from your computer'\nconst ENTER_URL_LABEL = 'enter the URL of a ZIP archive'\nconst ENTER_URL_PLACEHOLDER = 'https://tracespace.io/view/arduino-uno.zip'\nconst FOOTER = 'you can also drag-and-drop files into the app at any time'\n\nconst UPLOAD_FILES_LABEL_STYLE = 'mr-auto'\nconst ICON_STYLE = 'flex-none ml2 brand f4'\nconst SEPARATOR_STYLE = 'mv2 fw3 f6 i tc'\nconst ENTER_URL_LABEL_STYLE = 'mt0 mb2 pt2'\nconst URL_INPUT_STYLE = 'w-100 bb bt-0 br-0 bl-0 b--near-black code f7'\nconst URL_INPUT_WRAPPER_STYLE = 'flex items-bottom h2'\nconst FOOTER_STYLE = 'mt4 mb1 f7 lh-copy'\n\nexport type OpenFileDrawerProps = {\n open: boolean\n handleFiles: (event: FileEvent) => void\n handleUrl: (url: string) => void\n close: () => void\n}\n\nfunction OpenFileDrawer(props: OpenFileDrawerProps): JSX.Element {\n const {open, handleFiles, handleUrl, close} = props\n\n return (\n <Drawer title={TITLE} open={open} close={close}>\n <Label>\n <span className={UPLOAD_FILES_LABEL_STYLE}>{UPLOAD_FILES_LABEL}</span>\n <HiddenInput type=\"file\" onChange={handleFiles} multiple />\n <Icon\n name=\"file-upload\"\n className={getButtonStyle({className: ICON_STYLE})}\n />\n </Label>\n <p className={SEPARATOR_STYLE}>or</p>\n <Formik\n initialValues={{url: ''}}\n onSubmit={values => handleUrl(values.url)}\n >\n {formikProps => (\n <Form>\n <p className={ENTER_URL_LABEL_STYLE}>{ENTER_URL_LABEL}</p>\n <span className={URL_INPUT_WRAPPER_STYLE}>\n <Field\n name=\"url\"\n type=\"text\"\n className={URL_INPUT_STYLE}\n placeholder={ENTER_URL_PLACEHOLDER}\n />\n <Button type=\"submit\" disabled={!formikProps.values.url}>\n <Icon name=\"check\" className={ICON_STYLE} />\n </Button>\n </span>\n </Form>\n )}\n </Formik>\n <footer className={FOOTER_STYLE}>{FOOTER}</footer>\n </Drawer>\n )\n}\n\nexport default OpenFileDrawer\n","import React, {useState} from 'react'\n\nimport {useAppState, getBoardPackage} from '../state'\nimport {Button, Icon} from '../ui'\nimport {FileEvent} from '../types'\nimport OpenFileDrawer from './OpenFileDrawer'\n\nconst DOWNLOAD_TOOLTIP = 'Download SVG renders'\nconst UPLOAD_TOOLTIP = 'Upload Gerber/drill files'\n\nexport type FileControlsProps = {\n buttonClassName: string\n handleFiles: (event: FileEvent) => void\n handleUrl: (url: string) => void\n}\n\nexport default function FileControls(props: FileControlsProps): JSX.Element {\n const {board, loading, downloading, dispatch} = useAppState()\n const [open, setOpen] = useState(false)\n const {buttonClassName} = props\n\n const toggleUploadOpen = (): void => setOpen(!open)\n\n const handleFiles = (event: FileEvent): void => {\n setOpen(false)\n props.handleFiles(event)\n }\n\n const handleUrl = (url: string): void => {\n setOpen(false)\n props.handleUrl(url)\n }\n\n const downloadBoard = (): void => {\n if (board) {\n dispatch(getBoardPackage(board.id))\n }\n }\n\n return (\n <>\n <Button\n className={buttonClassName}\n onClick={toggleUploadOpen}\n disabled={loading}\n title={UPLOAD_TOOLTIP}\n >\n <Icon name=\"plus\" />\n </Button>\n <Button\n className={buttonClassName}\n onClick={downloadBoard}\n disabled={!board || downloading}\n title={DOWNLOAD_TOOLTIP}\n >\n <Icon\n name={downloading ? 'spinner' : 'file-download'}\n faProps={{pulse: downloading}}\n />\n </Button>\n <OpenFileDrawer\n open={open}\n handleFiles={handleFiles}\n handleUrl={handleUrl}\n close={toggleUploadOpen}\n />\n </>\n )\n}\n","import React from 'react'\n\nimport pkg from './../../package.json'\n\nconst REPO_URL_MATCH = pkg.repository.url.match(/git\\+(https:\\/\\/.+).git/)\nconst REPO_URL = REPO_URL_MATCH ? REPO_URL_MATCH[1] : '#'\n\nconst {name: AUTHOR_NAME, url: AUTHOR_URL} = pkg.author\nconst CONTRIBUTORS_URL = `${REPO_URL}/graphs/contributors`\nconst PRIVACY_URL = `${REPO_URL}/blob/v${pkg.version}/PRIVACY.md`\n\nconst STYLE = 'fixed right-1 bottom-1 w-third tr'\nconst COPY_STYLE = 'mv0 lh-copy f7 white'\nconst LINK_STYLE = 'link dim fw3 lightest-blue'\n\nexport default function Footer(): JSX.Element {\n return (\n <footer className={STYLE}>\n <p className={COPY_STYLE}>\n {'© 2015 - 2019 by '}\n <a href={AUTHOR_URL} className={LINK_STYLE}>\n {AUTHOR_NAME.toLowerCase()}\n </a>{' '}\n {'and '}\n <a href={CONTRIBUTORS_URL} className={LINK_STYLE}>\n contributors\n </a>\n </p>\n <p className={COPY_STYLE}>\n <a href={PRIVACY_URL} className={LINK_STYLE}>\n privacy policy\n </a>\n {' | '}\n <a href={REPO_URL} className={LINK_STYLE}>\n view source\n </a>\n </p>\n </footer>\n )\n}\n","import React from 'react'\n\nimport {useAppState} from '../state'\nimport {PageTitle, Slide} from '../ui'\nimport {FileEvent} from '../types'\nimport AppSettings from '../AppSettings'\nimport BoardSettings from '../BoardSettings'\nimport FileControls from './FileControls'\n\nimport Footer from './Footer'\n\ntype Props = {\n handleFiles: (event: FileEvent) => void\n handleUrl: (url: string) => void\n}\n\nconst STYLE = 'flex items-start justify-between relative w-100 h3'\nconst TITLE_STYLE = 'w-half flex-none'\nconst BUTTON_WRAPPER_STYLE = 'flex-none flex items-start justify-end w-third'\nconst BUTTON_STYLE = 'ml1 pa1 f3'\n\nexport default function Nav(props: Props): JSX.Element {\n const {board, loading, updating} = useAppState()\n const {handleFiles, handleUrl} = props\n const show = !loading && board !== null\n\n return (\n <nav className={STYLE}>\n <PageTitle subtitle=\"svg template exporter\" className={TITLE_STYLE} />\n {board && (\n <Slide in={show} from=\"top\">\n <BoardSettings board={board} updating={updating} />\n </Slide>\n )}\n <div className={BUTTON_WRAPPER_STYLE}>\n <FileControls\n buttonClassName={BUTTON_STYLE}\n handleFiles={handleFiles}\n handleUrl={handleUrl}\n />\n <AppSettings buttonClassName={BUTTON_STYLE} />\n </div>\n <Footer />\n </nav>\n )\n}\n","import React from 'react'\n\nimport {HiddenInput, Icon} from '../ui'\nimport {FileEvent} from '../types'\n\nexport type FileInputProps = {\n children?: React.ReactNode\n handleFiles: (event: FileEvent) => unknown\n}\n\nexport default function FileInput(props: FileInputProps): JSX.Element {\n const {children, handleFiles} = props\n\n return (\n <label className=\"db pv4 pointer\">\n <HiddenInput type=\"file\" onChange={handleFiles} multiple />\n <Icon name=\"plus\" className=\"dib f1 brand\" />\n {children}\n </label>\n )\n}\n","import React from 'react'\nimport {Formik, Form, Field} from 'formik'\n\nimport {useLocation} from '../hooks'\nimport {Button, Icon} from '../ui'\nimport {select} from '../events'\n\nconst LABEL_STYLE = 'db pointer mb2'\nconst WRAPPER_STYLE = 'flex items-bottom h2'\nconst INPUT_STYLE =\n 'w-100 mh2 bb bt-0 br-0 bl-0 b--near-black code f6 tc bg-transparent'\nconst BUTTON_STYLE = 'flex-none nr4 brand'\n\nconst INPUT_ID = 'load-files_url-input'\n\nconst defaultUrl = (loc: Location | null): string =>\n loc ? `${loc.origin}${loc.pathname}arduino-uno.zip` : ''\n\nexport type UrlInputProps = {\n children?: React.ReactNode\n handleUrl: (url: string) => unknown\n}\n\nexport default function UrlInput(props: UrlInputProps): JSX.Element {\n const {children, handleUrl} = props\n const location = useLocation()\n\n return (\n <Formik\n initialValues={{url: defaultUrl(location)}}\n onSubmit={values => handleUrl(values.url)}\n enableReinitialize\n >\n {formProps => (\n <Form>\n <label htmlFor={INPUT_ID} className={LABEL_STYLE}>\n {children}\n </label>\n <div className={WRAPPER_STYLE}>\n <Field\n id={INPUT_ID}\n name=\"url\"\n type=\"text\"\n className={INPUT_STYLE}\n onClick={select}\n />\n <Button\n type=\"submit\"\n className={BUTTON_STYLE}\n disabled={!formProps.values.url}\n >\n <Icon name=\"check\" />\n </Button>\n </div>\n </Form>\n )}\n </Formik>\n )\n}\n","import React from 'react'\n\nimport {useAppState} from '../state'\nimport {Icon, Fade} from '../ui'\nimport {FileEvent} from '../types'\nimport FileInput from './FileInput'\nimport UrlInput from './UrlInput'\n\nconst UPLOAD_MESSAGE = 'Upload your Gerber and drill files to render your board'\nconst UPLOAD_SUBMESSAGE = 'ZIP files work, too'\nconst URL_MESSAGE = 'or enter the URL of a ZIP archive'\n\nconst WRAPPER_STYLE = 'absolute absolute--center near-black tc'\nconst MESSAGE_STYLE = 'mt3 mb0 f4 lh-copy'\nconst SUBMESSAGE_STYLE = 'f5 fw3'\n\nexport type LoadFilesProps = {\n handleFiles: (event: FileEvent) => void\n handleUrl: (url: string) => void\n}\n\nexport default function LoadFiles(props: LoadFilesProps): JSX.Element {\n const {mode, loading} = useAppState()\n\n return (\n <>\n <Fade in={loading}>\n <Icon\n className={`${WRAPPER_STYLE} f1 brand`}\n name=\"spinner\"\n faProps={{pulse: true}}\n />\n </Fade>\n <Fade in={!mode && !loading}>\n <div className={WRAPPER_STYLE}>\n <FileInput handleFiles={props.handleFiles}>\n <p className={MESSAGE_STYLE}>\n {UPLOAD_MESSAGE}\n <br />\n <span className={SUBMESSAGE_STYLE}>({UPLOAD_SUBMESSAGE})</span>\n </p>\n </FileInput>\n <UrlInput handleUrl={props.handleUrl}>{URL_MESSAGE}</UrlInput>\n </div>\n </Fade>\n </>\n )\n}\n","import React from 'react'\n\nimport {useTimeout} from '../hooks'\nimport {Button, Icon} from '../ui'\n\nconst STYLE = 'dib center fixed top-1 left-0 right-0 tc'\nconst WRAPPER_STYLE =\n 'inline-flex items-center justify-center pl3 pv1 pr1 br2 bg-red white shadow'\nconst MESSAGE_STYLE = 'mv0 mr2'\n\nconst DISMISS_TIMEOUT = 4000\n\nexport type ToastProps = {\n dismiss: () => unknown\n children: React.ReactNode\n}\n\nexport default function Toast(props: ToastProps): JSX.Element {\n const {dismiss, children} = props\n\n useTimeout(dismiss, DISMISS_TIMEOUT)\n\n return (\n <div className={STYLE}>\n <div className={WRAPPER_STYLE}>\n <p className={MESSAGE_STYLE}>\n {'Error: '}\n {children}\n </p>\n <Button onClick={dismiss}>\n <Icon name=\"times\" />\n </Button>\n </div>\n </div>\n )\n}\n","import React from 'react'\n\nimport {useAppState, dismissError} from '../state'\nimport {usePrevious} from '../hooks'\nimport {Slide} from '../ui'\nimport Toast from './Toast'\n\nexport default function ErrorToast(): JSX.Element {\n const {error, dispatch} = useAppState()\n const prevError = usePrevious(error)\n const prevErrorMessage = prevError ? prevError.message : null\n\n return (\n <Slide in={!!error} from=\"top\">\n <Toast dismiss={() => dispatch(dismissError())}>\n {error ? error.message : prevErrorMessage}\n </Toast>\n </Slide>\n )\n}\n","// root component\nimport React from 'react'\nimport {hot} from 'react-hot-loader/root'\n\nimport {useAppState, createBoard, createBoardFromUrl} from './state'\nimport BoardDisplay from './BoardDisplay'\nimport FileList from './FileList'\nimport BoardList from './BoardList'\nimport Nav from './Nav'\nimport LoadFiles from './LoadFiles'\nimport ErrorToast from './ErrorToast'\nimport {preventDefault} from './events'\nimport {Main} from './ui'\nimport {FileEvent} from './types'\n\nfunction App(): JSX.Element {\n const {dispatch} = useAppState()\n\n const handleFiles = (event: FileEvent): void => {\n const files =\n 'dataTransfer' in event\n ? Array.from(event.dataTransfer.files)\n : Array.from(event.target.files || [])\n\n if (files.length > 0) dispatch(createBoard(files))\n if ('value' in event.target) event.target.value = ''\n preventDefault(event)\n }\n\n const handleUrl = (url: string): void => {\n if (url) dispatch(createBoardFromUrl(url))\n }\n\n return (\n <Main onDragOver={preventDefault} onDrop={handleFiles}>\n <BoardDisplay />\n <FileList />\n <BoardList />\n <Nav handleFiles={handleFiles} handleUrl={handleUrl} />\n <LoadFiles handleFiles={handleFiles} handleUrl={handleUrl} />\n <ErrorToast />\n </Main>\n )\n}\n\nexport default hot(App)\n","'use strict'\n\nvar constants = require('./lib/constants')\nvar flatMap = require('./lib/flat-map')\nvar getCommonCad = require('./lib/get-common-cad')\nvar getMatches = require('./lib/get-matches')\nvar layerTypes = require('./lib/layer-types')\n\nmodule.exports = whatsThatGerber\nmodule.exports.validate = validate\nmodule.exports.getAllLayers = getAllLayers\n\nObject.keys(constants).forEach(function(constantName) {\n module.exports[constantName] = constants[constantName]\n})\n\nfunction whatsThatGerber(filenames) {\n if (typeof filenames === 'string') filenames = [filenames]\n\n var matches = flatMap(filenames, getMatches)\n var commonCad = getCommonCad(matches)\n\n return filenames.reduce(function(result, filename) {\n var match = _selectMatch(matches, filename, commonCad)\n\n result[filename] = match\n ? {type: match.type, side: match.side}\n : {type: null, side: null}\n\n return result\n }, {})\n}\n\nfunction getAllLayers() {\n return layerTypes\n .map(function(layer) {\n return {type: layer.type, side: layer.side}\n })\n .filter(function(layer) {\n return layer.type !== null\n })\n}\n\nfunction validate(target) {\n return {\n valid: layerTypes.some(_validateLayer),\n side: layerTypes.some(_validateSide) ? target.side : null,\n type: layerTypes.some(_validateType) ? target.type : null,\n }\n\n function _validateLayer(layer) {\n return layer.side === target.side && layer.type === target.type\n }\n\n function _validateSide(layer) {\n return layer.side === target.side\n }\n\n function _validateType(layer) {\n return layer.type === target.type\n }\n}\n\nfunction _selectMatch(matches, filename, cad) {\n var filenameMatches = matches.filter(function(match) {\n return match.filename === filename\n })\n\n var result = filenameMatches.find(function(match) {\n return match.cad === cad\n })\n\n return result || filenameMatches[0] || null\n}\n","// application state and actions as React context\nexport * from './actions'\nexport * from './context'\nexport * from './types'\n","import React, {useContext} from 'react'\n\nimport {State, ContextProps} from './types'\n\nexport const INITIAL_STATE: State = {\n board: null,\n savedBoards: [],\n mode: null,\n loading: false,\n updating: false,\n downloading: false,\n layerVisibility: {},\n error: null,\n}\n\nexport const StateContext = React.createContext<ContextProps>({\n ...INITIAL_STATE,\n dispatch: () => {},\n})\n\nexport const useAppState = (): ContextProps => useContext(StateContext)\n","import {Board, BoardSummary, BoardUpdate, BoardRender, Mode} from '../types'\nimport {Action} from './types'\n\nexport const CREATE_BOARD = 'CREATE_BOARD'\nexport const CREATE_BOARD_FROM_URL = 'CREATE_BOARD_FROM_URL'\nexport const GET_BOARD = 'GET_BOARD'\nexport const GET_BOARD_PACKAGE = 'GET_BOARD_PACKAGE'\nexport const UPDATE_BOARD = 'UPDATE_BOARD'\nexport const DELETE_BOARD = 'DELETE_BOARD'\nexport const DELETE_ALL_BOARDS = 'DELETE_ALL_BOARDS'\nexport const SET_MODE = 'SET_MODE'\nexport const TOGGLE_VISIBILITY = 'TOGGLE_VISIBILITY'\nexport const BOARD_RENDERED = 'BOARD_RENDERED'\nexport const BOARD_UPDATED = 'BOARD_UPDATED'\nexport const BOARD_DELETED = 'BOARD_DELETED'\nexport const BOARD_PACKAGED = 'BOARD_PACKAGED'\nexport const ALL_BOARDS_DELETED = 'ALL_BOARDS_DELETED'\nexport const WORKER_INITIALIZED = 'WORKER_INITIALIZED'\nexport const WORKER_ERRORED = 'WORKER_ERRORED'\nexport const DISMISS_ERROR = 'DISMISS_ERROR'\n\nexport const createBoard = (files: Array<File>): Action => ({\n type: CREATE_BOARD,\n payload: files,\n})\n\nexport const createBoardFromUrl = (url: string): Action => ({\n type: CREATE_BOARD_FROM_URL,\n payload: url,\n})\n\nexport const getBoard = (id: string): Action => ({\n type: GET_BOARD,\n payload: id,\n})\n\nexport const updateBoard = (id: string, update: BoardUpdate): Action => ({\n type: UPDATE_BOARD,\n payload: {id, update},\n})\n\nexport const deleteBoard = (id: string): Action => ({\n type: DELETE_BOARD,\n payload: id,\n})\n\nexport const deleteAllBoards = (): Action => ({\n type: DELETE_ALL_BOARDS,\n})\n\nexport const getBoardPackage = (id: string): Action => ({\n type: GET_BOARD_PACKAGE,\n payload: id,\n})\n\nexport const setMode = (mode: Mode): Action => ({\n type: SET_MODE,\n payload: mode,\n})\n\nexport const toggleVisibility = (id: string, solo: boolean): Action => ({\n type: TOGGLE_VISIBILITY,\n payload: {id, solo},\n})\n\nexport const boardRendered = (render: BoardRender): Action => ({\n type: BOARD_RENDERED,\n payload: render,\n})\n\nexport const boardUpdated = (board: Board): Action => ({\n type: BOARD_UPDATED,\n payload: board,\n})\n\nexport const boardDeleted = (id: string): Action => ({\n type: BOARD_DELETED,\n payload: id,\n})\n\nexport const boardPackaged = (name: string, file: Blob): Action => ({\n type: BOARD_PACKAGED,\n payload: {name, file},\n})\n\nexport const allBoardsDeleted = (): Action => ({\n type: ALL_BOARDS_DELETED,\n})\n\nexport const workerInitialized = (boards: Array<BoardSummary>): Action => ({\n type: WORKER_INITIALIZED,\n payload: boards,\n})\n\nexport const workerErrored = (request: Action, error: Error): Action => ({\n type: WORKER_ERRORED,\n payload: {\n request,\n error: {name: error.name, message: error.message, error: error.toString()},\n },\n})\n\nexport const dismissError = (): Action => ({\n type: DISMISS_ERROR,\n})\n","import {LogLevel, Logger, LogHandler} from './types'\n\nconst STORAGE_KEY = 'logLevel'\nconst DEFAULT_LEVEL = process.env.NODE_ENV !== 'production' ? 'debug' : 'warn'\nconst LEVELS: Array<LogLevel> = ['debug', 'info', 'warn', 'error']\n\nlet minLevel: LogLevel\n\nconst logger: Logger = {\n debug: createLogHandler('debug'),\n info: createLogHandler('info'),\n warn: createLogHandler('warn'),\n error: createLogHandler('error'),\n}\n\nexport default logger\n\nfunction createLogHandler(level: LogLevel): LogHandler {\n if (!minLevel) minLevel = readLogLevel()\n\n return LEVELS.indexOf(level) >= LEVELS.indexOf(minLevel)\n ? (msg, ...meta) => console[level](`${level}: ${msg}`, ...meta)\n : () => {}\n}\n\nfunction readLogLevel(): LogLevel {\n if (typeof window !== 'undefined' && window.localStorage) {\n try {\n const maybeLevel = window.localStorage.getItem(STORAGE_KEY)\n\n if (\n maybeLevel === 'debug' ||\n maybeLevel === 'info' ||\n maybeLevel === 'warn' ||\n maybeLevel === 'error'\n ) {\n return maybeLevel\n }\n } catch (error) {\n console.error('Could not read logLevel from localStorage', error)\n }\n }\n\n return DEFAULT_LEVEL\n}\n","'use strict'\n\nmodule.exports = {\n // layer types\n TYPE_COPPER: 'copper',\n TYPE_SOLDERMASK: 'soldermask',\n TYPE_SILKSCREEN: 'silkscreen',\n TYPE_SOLDERPASTE: 'solderpaste',\n TYPE_DRILL: 'drill',\n TYPE_OUTLINE: 'outline',\n TYPE_DRAWING: 'drawing',\n\n // board sides\n SIDE_TOP: 'top',\n SIDE_BOTTOM: 'bottom',\n SIDE_INNER: 'inner',\n SIDE_ALL: 'all',\n\n // cad packages\n // internal use only, for now\n _CAD_KICAD: 'kicad',\n _CAD_ALTIUM: 'altium',\n _CAD_ALLEGRO: 'allegro',\n _CAD_EAGLE: 'eagle',\n _CAD_EAGLE_LEGACY: 'eagle-legacy',\n _CAD_EAGLE_OSHPARK: 'eagle-oshpark',\n _CAD_EAGLE_PCBNG: 'eagle-pcbng',\n _CAD_GEDA_PCB: 'geda-pcb',\n _CAD_ORCAD: 'orcad',\n _CAD_DIPTRACE: 'diptrace',\n}\n","'use strict'\n\nmodule.exports = function flatMap(collection, iterator) {\n return collection.reduce(function iterate(result, element) {\n return result.concat(iterator(element))\n }, [])\n}\n","'use strict'\n\nvar c = require('./constants')\n\nmodule.exports = [\n // high-priority blacklist\n {\n type: null,\n side: null,\n matchers: [\n // eagle gerber generation metadata\n {\n ext: 'gpi',\n cad: [\n c._CAD_EAGLE,\n c._CAD_EAGLE_LEGACY,\n c._CAD_EAGLE_OSHPARK,\n c._CAD_EAGLE_PCBNG,\n ],\n },\n // eagle drill generation metadata\n {\n ext: 'dri',\n cad: [\n c._CAD_EAGLE,\n c._CAD_EAGLE_LEGACY,\n c._CAD_EAGLE_OSHPARK,\n c._CAD_EAGLE_PCBNG,\n ],\n },\n // general data/BOM files\n {ext: 'csv', cad: null},\n // pick-n-place BOMs\n {match: /pnp_bom/, cad: c._CAD_EAGLE_PCBNG},\n ],\n },\n {\n type: c.TYPE_COPPER,\n side: c.SIDE_TOP,\n matchers: [\n {ext: 'cmp', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'top', cad: [c._CAD_EAGLE_LEGACY, c._CAD_ORCAD]},\n {ext: 'gtl', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'toplayer\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /top\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /f[._]cu/, cad: c._CAD_KICAD},\n {match: /copper_top/, cad: c._CAD_EAGLE},\n {match: /top_copper/, cad: c._CAD_EAGLE_PCBNG},\n {match: /top copper/, cad: null},\n ],\n },\n {\n type: c.TYPE_SOLDERMASK,\n side: c.SIDE_TOP,\n matchers: [\n {ext: 'stc', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'tsm', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gts', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'smt', cad: c._CAD_ORCAD},\n {ext: 'topsoldermask\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /topmask\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /f[._]mask/, cad: c._CAD_KICAD},\n {match: /soldermask_top/, cad: c._CAD_EAGLE},\n {match: /top_mask/, cad: c._CAD_EAGLE_PCBNG},\n {match: /top solder resist/, cad: null},\n ],\n },\n {\n type: c.TYPE_SILKSCREEN,\n side: c.SIDE_TOP,\n matchers: [\n {ext: 'plc', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'tsk', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gto', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'sst', cad: c._CAD_ORCAD},\n {ext: 'topsilkscreen\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /topsilk\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /f[._]silks/, cad: c._CAD_KICAD},\n {match: /silkscreen_top/, cad: c._CAD_EAGLE},\n {match: /top_silk/, cad: c._CAD_EAGLE_PCBNG},\n {match: /top silk screen/, cad: null},\n ],\n },\n {\n type: c.TYPE_SOLDERPASTE,\n side: c.SIDE_TOP,\n matchers: [\n {ext: 'crc', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'tsp', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gtp', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'spt', cad: c._CAD_ORCAD},\n {ext: 'tcream\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /toppaste\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /f[._]paste/, cad: c._CAD_KICAD},\n {match: /solderpaste_top/, cad: c._CAD_EAGLE},\n {match: /top_paste/, cad: c._CAD_EAGLE_PCBNG},\n ],\n },\n {\n type: c.TYPE_COPPER,\n side: c.SIDE_BOTTOM,\n matchers: [\n {ext: 'sol', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'bot', cad: [c._CAD_EAGLE_LEGACY, c._CAD_ORCAD]},\n {ext: 'gbl', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'bottomlayer\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /bottom\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /b[._]cu/, cad: c._CAD_KICAD},\n {match: /copper_bottom/, cad: c._CAD_EAGLE},\n {match: /bottom_copper/, cad: c._CAD_EAGLE_PCBNG},\n {match: /bottom copper/, cad: null},\n ],\n },\n {\n type: c.TYPE_SOLDERMASK,\n side: c.SIDE_BOTTOM,\n matchers: [\n {ext: 'sts', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'bsm', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gbs', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'smb', cad: c._CAD_ORCAD},\n {ext: 'bottomsoldermask\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /bottommask\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /b[._]mask/, cad: c._CAD_KICAD},\n {match: /soldermask_bottom/, cad: c._CAD_EAGLE},\n {match: /bottom_mask/, cad: c._CAD_EAGLE_PCBNG},\n {match: /bottom solder resist/, cad: null},\n ],\n },\n {\n type: c.TYPE_SILKSCREEN,\n side: c.SIDE_BOTTOM,\n matchers: [\n {ext: 'pls', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'bsk', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gbo', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'ssb', cad: c._CAD_ORCAD},\n {ext: 'bottomsilkscreen\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /bottomsilk\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /b[._]silks/, cad: c._CAD_KICAD},\n {match: /silkscreen_bottom/, cad: c._CAD_EAGLE},\n {match: /bottom_silk/, cad: c._CAD_EAGLE_PCBNG},\n {match: /bottom silk screen/, cad: null},\n ],\n },\n {\n type: c.TYPE_SOLDERPASTE,\n side: c.SIDE_BOTTOM,\n matchers: [\n {ext: 'crs', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'bsp', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gbp', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'spb', cad: c._CAD_ORCAD},\n {ext: 'bcream\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /bottompaste\\.\\w+$/, cad: [c._CAD_GEDA_PCB, c._CAD_DIPTRACE]},\n {match: /b[._]paste/, cad: c._CAD_KICAD},\n {match: /solderpaste_bottom/, cad: c._CAD_EAGLE},\n {match: /bottom_paste/, cad: c._CAD_EAGLE_PCBNG},\n ],\n },\n {\n type: c.TYPE_COPPER,\n side: c.SIDE_INNER,\n matchers: [\n {ext: 'ly\\\\d+', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gp?\\\\d+', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'in\\\\d+', cad: c._CAD_ORCAD},\n {ext: 'internalplane\\\\d+\\\\.ger', cad: c._CAD_EAGLE_OSHPARK},\n {match: /in(?:ner)?\\d+[._]cu/, cad: c._CAD_KICAD},\n {match: /inner/, cad: c._CAD_DIPTRACE},\n ],\n },\n {\n type: c.TYPE_OUTLINE,\n side: c.SIDE_ALL,\n matchers: [\n {ext: 'dim', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'mil', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gml', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'gm\\\\d+', cad: [c._CAD_KICAD, c._CAD_ALTIUM]},\n {ext: 'gko', cad: c._CAD_ALTIUM},\n {ext: 'fab', cad: c._CAD_ORCAD},\n {ext: 'drd', cad: c._CAD_ORCAD},\n {match: /outline/, cad: [c._CAD_GEDA_PCB, c._CAD_EAGLE_PCBNG]},\n {match: /boardoutline/, cad: [c._CAD_EAGLE_OSHPARK, c._CAD_DIPTRACE]},\n {match: /edge[._]cuts/, cad: c._CAD_KICAD},\n {match: /profile/, cad: c._CAD_EAGLE},\n {match: /mechanical \\d+/, cad: null},\n ],\n },\n {\n type: c.TYPE_DRILL,\n side: c.SIDE_ALL,\n matchers: [\n {ext: 'txt', cad: [c._CAD_EAGLE_LEGACY, c._CAD_ALTIUM]},\n {\n ext: 'xln',\n cad: [c._CAD_EAGLE, c._CAD_EAGLE_LEGACY, c._CAD_EAGLE_OSHPARK],\n },\n {ext: 'exc', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'drd', cad: c._CAD_EAGLE_LEGACY},\n {ext: 'drl', cad: [c._CAD_KICAD, c._CAD_DIPTRACE]},\n {ext: 'tap', cad: c._CAD_ORCAD},\n {ext: 'npt', cad: c._CAD_ORCAD},\n {ext: 'plated-drill\\\\.cnc', cad: c._CAD_GEDA_PCB},\n {match: /fab/, cad: c._CAD_GEDA_PCB},\n {match: /npth/, cad: c._CAD_KICAD},\n {match: '/drill/', cad: c._CAD_EAGLE_PCBNG},\n ],\n },\n {\n type: c.TYPE_DRAWING,\n side: null,\n matchers: [\n {ext: 'pos', cad: c._CAD_KICAD},\n {ext: 'art', cad: c._CAD_ALLEGRO},\n {ext: 'gbr', cad: null},\n {ext: 'gbx', cad: null},\n {ext: 'ger', cad: null},\n {ext: 'pho', cad: null},\n ],\n },\n]\n","'use strict'\n\nmodule.exports = function getCommonCad(matches) {\n var cadCount = matches.reduce(function(counts, match) {\n counts[match.cad] = counts[match.cad] + 1 || 1\n return counts\n }, {})\n\n return Object.keys(cadCount).reduce(\n function(maxAndName, name) {\n var count = cadCount[name]\n if (count > maxAndName.max) return {max: count, name: name}\n return maxAndName\n },\n {max: 0, name: null}\n ).name\n}\n","'use strict'\n\nvar extend = require('xtend')\n\nvar matchers = require('./matchers')\n\nmodule.exports = function getMatches(filename) {\n return matchers.map(matcherToFileMatches).filter(Boolean)\n\n function matcherToFileMatches(matcher) {\n if (!matcher.match.test(filename)) return null\n return extend(matcher, {filename: filename})\n }\n}\n","'use strict'\n\nvar flatMap = require('./flat-map')\nvar layerTypes = require('./layer-types')\n\nmodule.exports = flatMap(layerTypes, layerTypeToMatchers)\n\nfunction layerTypeToMatchers(layer) {\n return flatMap(layer.matchers, matcherToCadMatchers)\n\n function matcherToCadMatchers(matcher) {\n var match = matcher.ext\n ? new RegExp('\\\\.' + matcher.ext + '$', 'i')\n : new RegExp(matcher.match, 'i')\n\n return [].concat(matcher.cad).map(mergeLayerWithCad)\n\n function mergeLayerWithCad(cad) {\n return {\n type: layer.type,\n side: layer.side,\n match: match,\n cad: cad,\n }\n }\n }\n}\n"],"sourceRoot":""}
|