clickable-box
Version:
Add `onClick` to HTML elements without sacrificing accessibility.
1 lines • 4.66 kB
Source Map (JSON)
{"version":3,"file":"clickable-box.cjs","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\n\ninterface ClickableBoxProps {\n onClick?(\n event:\n | React.MouseEvent<HTMLElement, MouseEvent>\n | React.KeyboardEvent<HTMLElement>\n ): void;\n is?: keyof JSX.IntrinsicElements | React.ElementType;\n tabIndex?: number;\n onKeyPress?(event: React.KeyboardEvent<HTMLElement>): void;\n disabled?: boolean;\n innerRef?: React.Ref<HTMLElement>;\n // Allow arbitrary props.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\nconst ClickableBox = React.forwardRef<HTMLElement, ClickableBoxProps>(\n (props: ClickableBoxProps, ref) => {\n const {\n is: Component = \"span\",\n onClick,\n disabled,\n tabIndex = 0,\n // Prevent `onKeyPress` from being spread since we will call it in\n // `this.onKeyPress` and we don't want the user function to overwrite our\n // behavior.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onKeyPress,\n ...otherProps\n } = props;\n return (\n <Component\n // Don't set `tabIndex` if `disabled`. We do set it though even if\n // `onClick` is not provided so that it mimics the behavior of a native\n // `button`. We also prevent the user from passing in their own\n // `tabIndex` in the case that it is disabled. This is better than a\n // `-1` because `-1` will make the element focusable but not reachable\n // via keyboard navigation.\n tabIndex={!disabled ? tabIndex : undefined}\n // Always have `role=\"button\"`, even if it is disabled. Combined with\n // `aria-disabled`, screen readers will announce this the same as\n // a native `button` element.\n role=\"button\"\n // Only fire these events if the `disabled` prop is not true.\n onKeyPress={\n !disabled\n ? (event: React.KeyboardEvent<HTMLElement>) => {\n switch (event.key) {\n case \" \":\n case \"Spacebar\": // Support FF <= 37, IE 9-11.\n // Prevent scrolling when pressing `Spacebar`.\n event.preventDefault();\n\n // If space is pressed and both `onKeyPress` and `onClick` exist, only\n // run `onKeyPress`.\n if (onClick && onKeyPress) {\n onKeyPress(event);\n } else if (onKeyPress) {\n onKeyPress(event);\n } else if (onClick) {\n onClick(event);\n }\n break;\n case \"Enter\":\n // `onKeyPress` should run first.\n if (onKeyPress) {\n onKeyPress(event);\n\n // Prevent `onClick` from running in the rare case that the user has\n // a custom `onKeyPress` that contains `event.preventDefault()`.\n if (event.isDefaultPrevented()) {\n return;\n }\n }\n if (onClick) onClick(event);\n break;\n default:\n break;\n }\n }\n : undefined\n }\n onClick={!disabled ? onClick : undefined}\n // Announce to screen readers that the `ClickableBox` is disabled.\n aria-disabled={disabled ? \"true\" : undefined}\n ref={ref}\n {...otherProps}\n />\n );\n }\n);\n\n// This is needed because of the `forwardRef`.\nClickableBox.displayName = \"ClickableBox\";\n\nexport default ClickableBox;\n"],"names":["ClickableBox","React","forwardRef","props","ref","is","Component","_props$is","onClick","disabled","tabIndex","_props$tabIndex","onKeyPress","otherProps","_excluded","_extends","undefined","role","event","key","preventDefault","isDefaultPrevented","displayName"],"mappings":"6YAkBkBA,eAAGC,EAAAA,QAAMC,WACzB,SAACC,EAA0BC,GACzB,MAWID,EAVFE,GAAIC,OAAS,IAAAC,EAAG,OAChBC,EAAAA,EASEL,EATFK,QACAC,EAQEN,EARFM,WAQEN,EAPFO,SAAAA,aAAW,EAACC,EAKZC,EAEET,EAFFS,WACGC,qIACDV,EAAKW,gBACT,OACEb,EAAAA,sBAACK,EAASS,EAAA,CAORL,SAAWD,OAAsBO,EAAXN,EAItBO,KAAK,SAELL,WACGH,OAmCGO,EAlCA,SAACE,GACC,OAAQA,EAAMC,KACZ,IAAK,IACL,IAAK,WAEHD,EAAME,iBAIFZ,GAAWI,GAEJA,EADTA,EAAWM,GAGFV,GACTA,EAAQU,GAEV,MACF,IAAK,QAEH,GAAIN,IACFA,EAAWM,GAIPA,EAAMG,sBACR,OAGAb,GAASA,EAAQU,GAK3B,EAGNV,QAAUC,OAAqBO,EAAVR,EAAmB,gBAEzBC,EAAW,YAASO,EACnCZ,IAAKA,GACDS,GAGV,GAIFb,EAAasB,YAAc"}