UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

852 lines (833 loc) • 21.1 kB
import { c } from 'react-compiler-runtime'; import React, { useEffect } from 'react'; import { isResponsiveValue } from '../hooks/useResponsiveValue.js'; import { ArrowLeftIcon } from '@primer/octicons-react'; import { getResponsiveAttributes } from '../internal/utils/getResponsiveAttributes.js'; import { areAllValuesTheSame, haveRegularAndWideSameValue } from '../utils/getBreakpointDeclarations.js'; import { warning } from '../utils/warning.js'; import { clsx } from 'clsx'; import classes from './PageHeader.module.css.js'; import { isSlot } from '../utils/is-slot.js'; import { jsx, Fragment, jsxs } from 'react/jsx-runtime'; import { useProvidedRefOrCreate } from '../hooks/useProvidedRefOrCreate.js'; import Heading from '../Heading/Heading.js'; import Link from '../Link/Link.js'; // Default state for the `visible` prop when a sub component is only visible on narrow viewport const hiddenOnRegularAndWide = { narrow: false, regular: true, wide: true }; // Default state for the `visible` prop when a sub component is visible on regular and wide viewport const hiddenOnNarrow = { narrow: true, regular: false, wide: false }; // Root // ----------------------------------------------------------------------------- const Root = /*#__PURE__*/React.forwardRef((t0, forwardedRef) => { const $ = c(14); const { children, className, as: t1, "aria-label": ariaLabel, role, hasBorder } = t0; const BaseComponent = t1 === undefined ? "div" : t1; const rootRef = useProvidedRefOrCreate(forwardedRef); const isInteractive = _temp; let t2; let t3; if ($[0] !== children || $[1] !== rootRef) { t2 = function validateInteractiveElementsInTitle() { if (!(process.env.NODE_ENV !== "production")) { return; } let hasContextArea = false; let hasLeadingAction = false; if (!rootRef.current || rootRef.current.children.length <= 0) { return; } const titleArea = Array.from(rootRef.current.children).find(_temp2); if (!titleArea) { return; } for (const child_0 of React.Children.toArray(children)) { if (/*#__PURE__*/React.isValidElement(child_0) && (child_0.type === ContextArea || isSlot(child_0, ContextArea))) { hasContextArea = true; } if (/*#__PURE__*/React.isValidElement(child_0) && (child_0.type === LeadingAction || isSlot(child_0, LeadingAction))) { hasLeadingAction = true; } } const hasInteractiveContent = Array.from(titleArea.childNodes).some(child_1 => child_1 instanceof HTMLElement && isInteractive(child_1) || Array.from(child_1.childNodes).some(child_2 => child_2 instanceof HTMLElement && isInteractive(child_2))); process.env.NODE_ENV !== "production" ? warning(hasInteractiveContent && (hasContextArea || hasLeadingAction), "When PageHeader.ContextArea or PageHeader.LeadingAction is present, we recommended not to include any interactive items in the PageHeader.TitleArea to make sure the focus order is logical.") : void 0; }; t3 = [children, rootRef]; $[0] = children; $[1] = rootRef; $[2] = t2; $[3] = t3; } else { t2 = $[2]; t3 = $[3]; } useEffect(t2, t3); let t4; if ($[4] !== className) { t4 = clsx(classes.PageHeader, className); $[4] = className; $[5] = t4; } else { t4 = $[5]; } const t5 = hasBorder ? "true" : undefined; let t6; if ($[6] !== BaseComponent || $[7] !== ariaLabel || $[8] !== children || $[9] !== role || $[10] !== rootRef || $[11] !== t4 || $[12] !== t5) { t6 = /*#__PURE__*/jsx(BaseComponent, { ref: rootRef, className: t4, "data-has-border": t5, "aria-label": ariaLabel, role: role, children: children }); $[6] = BaseComponent; $[7] = ariaLabel; $[8] = children; $[9] = role; $[10] = rootRef; $[11] = t4; $[12] = t5; $[13] = t6; } else { t6 = $[13]; } return t6; }); // PageHeader.ContextArea : Only visible on narrow viewports by default to provide user context of where they are at their journey. `hidden` prop available // to manage their custom visibility but consumers should be careful if they choose to hide this on narrow viewports. // PageHeader.ContextArea Sub Components: PageHeader.ParentLink, PageHeader.ContextBar, PageHeader.ContextAreaActions // --------------------------------------------------------------------- const ContextArea = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? hiddenOnRegularAndWide : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.ContextArea, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; ContextArea.__SLOT__ = Symbol('PageHeader.ContextArea'); // PageHeader.ParentLink : Only visible on narrow viewports by default to let users navigate up in the hierarchy. const ParentLink = /*#__PURE__*/React.forwardRef((t0, ref) => { const $ = c(15); const { children, className, href, "aria-label": ariaLabel, as: t1, hidden: t2 } = t0; const as = t1 === undefined ? "a" : t1; const hidden = t2 === undefined ? hiddenOnRegularAndWide : t2; let t3; if ($[0] !== className) { t3 = clsx(classes.ParentLink, className); $[0] = className; $[1] = t3; } else { t3 = $[1]; } let t4; if ($[2] !== hidden) { t4 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t4; } else { t4 = $[3]; } let t5; if ($[4] === Symbol.for("react.memo_cache_sentinel")) { t5 = /*#__PURE__*/jsx(ArrowLeftIcon, {}); $[4] = t5; } else { t5 = $[4]; } let t6; if ($[5] !== children) { t6 = /*#__PURE__*/jsx("div", { children: children }); $[5] = children; $[6] = t6; } else { t6 = $[6]; } let t7; if ($[7] !== ariaLabel || $[8] !== as || $[9] !== href || $[10] !== ref || $[11] !== t3 || $[12] !== t4 || $[13] !== t6) { t7 = /*#__PURE__*/jsx(Fragment, { children: /*#__PURE__*/jsxs(Link, { ref: ref, as: as, "aria-label": ariaLabel, muted: true, className: t3, ...t4, href: href, children: [t5, t6] }) }); $[7] = ariaLabel; $[8] = as; $[9] = href; $[10] = ref; $[11] = t3; $[12] = t4; $[13] = t6; $[14] = t7; } else { t7 = $[14]; } return t7; }); ParentLink.displayName = 'ParentLink'; // ContextBar // Generic slot for any component above the title region. Use it for custom breadcrumbs and other navigation elements instead of ParentLink. // --------------------------------------------------------------------- const ContextBar = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? hiddenOnRegularAndWide : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.ContextBar, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; // ContextAreaActions // --------------------------------------------------------------------- const ContextAreaActions = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? hiddenOnRegularAndWide : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.ContextAreaActions, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; // PageHeader.TitleArea: The main title area of the page. Visible on all viewports. // PageHeader.TitleArea Sub Components: PageHeader.LeadingVisual, PageHeader.Title, PageTitle.TrailingVisual // --------------------------------------------------------------------- const TitleArea = /*#__PURE__*/React.forwardRef((t0, forwardedRef) => { const $ = c(12); const { children, className, hidden: t1, variant: t2 } = t0; const hidden = t1 === undefined ? false : t1; const variant = t2 === undefined ? "medium" : t2; const titleAreaRef = useProvidedRefOrCreate(forwardedRef); let t3; if ($[0] !== className) { t3 = clsx(classes.TitleArea, className); $[0] = className; $[1] = t3; } else { t3 = $[1]; } let t4; if ($[2] !== variant) { t4 = getResponsiveAttributes("size-variant", variant); $[2] = variant; $[3] = t4; } else { t4 = $[3]; } let t5; if ($[4] !== hidden) { t5 = getHiddenDataAttributes(hidden); $[4] = hidden; $[5] = t5; } else { t5 = $[5]; } let t6; if ($[6] !== children || $[7] !== t3 || $[8] !== t4 || $[9] !== t5 || $[10] !== titleAreaRef) { t6 = /*#__PURE__*/jsx("div", { className: t3, ref: titleAreaRef, "data-component": "TitleArea", ...t4, ...t5, children: children }); $[6] = children; $[7] = t3; $[8] = t4; $[9] = t5; $[10] = titleAreaRef; $[11] = t6; } else { t6 = $[11]; } return t6; }); TitleArea.displayName = 'TitleArea'; // PageHeader.LeadingAction and PageHeader.TrailingAction should only be visible on regular viewports. // So they come as hidden on narrow viewports by default and their visibility can be managed by their `hidden` prop. const LeadingAction = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? hiddenOnNarrow : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.LeadingAction, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, "data-component": "PH_LeadingAction", ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; LeadingAction.__SLOT__ = Symbol('PageHeader.LeadingAction'); // This is reserved for only breadcrumbs. const Breadcrumbs = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? false : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.Breadcrumbs, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, "data-component": "PH_Breadcrumbs", ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; // PageHeader.LeadingVisual and PageHeader.TrailingVisual should remain visible on narrow viewports. const LeadingVisual = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? false : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.LeadingVisual, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, "data-component": "PH_LeadingVisual", ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; const Title = t0 => { const $ = c(10); const { children, className, hidden: t1, as: t2 } = t0; const hidden = t1 === undefined ? false : t1; const as = t2 === undefined ? "h2" : t2; let t3; if ($[0] !== className) { t3 = clsx(classes.Title, className); $[0] = className; $[1] = t3; } else { t3 = $[1]; } let t4; if ($[2] !== hidden) { t4 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t4; } else { t4 = $[3]; } let t5; if ($[4] !== as || $[5] !== children || $[6] !== hidden || $[7] !== t3 || $[8] !== t4) { t5 = /*#__PURE__*/jsx(Heading, { className: t3, "data-component": "PH_Title", "data-hidden": hidden, as: as, ...t4, children: children }); $[4] = as; $[5] = children; $[6] = hidden; $[7] = t3; $[8] = t4; $[9] = t5; } else { t5 = $[9]; } return t5; }; // PageHeader.LeadingVisual and PageHeader.TrailingVisual should remain visible on narrow viewports. const TrailingVisual = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? false : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.TrailingVisual, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, "data-component": "PH_TrailingVisual", ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; const TrailingAction = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? hiddenOnNarrow : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.TrailingAction, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, "data-component": "PH_TrailingAction", ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; const Actions = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? false : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.Actions, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, "data-component": "PH_Actions", ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; // PageHeader.Description: The description area of the header. Visible on all viewports const Description = t0 => { const $ = c(8); const { children, className, hidden: t1 } = t0; const hidden = t1 === undefined ? false : t1; let t2; if ($[0] !== className) { t2 = clsx(classes.Description, className); $[0] = className; $[1] = t2; } else { t2 = $[1]; } let t3; if ($[2] !== hidden) { t3 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t3; } else { t3 = $[3]; } let t4; if ($[4] !== children || $[5] !== t2 || $[6] !== t3) { t4 = /*#__PURE__*/jsx("div", { className: t2, ...t3, children: children }); $[4] = children; $[5] = t2; $[6] = t3; $[7] = t4; } else { t4 = $[7]; } return t4; }; // PageHeader.Navigation: The local navigation area of the header. Visible on all viewports const Navigation = t0 => { const $ = c(11); const { children, className, hidden: t1, as: t2, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy } = t0; const hidden = t1 === undefined ? false : t1; const BaseComponent = t2 === undefined ? "div" : t2; process.env.NODE_ENV !== "production" ? warning(BaseComponent === "nav" && !ariaLabel && !ariaLabelledBy, "Use `aria-label` or `aria-labelledby` prop to provide an accessible label to the `nav` landmark for assistive technology") : void 0; const t3 = BaseComponent === "nav" ? ariaLabel : undefined; const t4 = BaseComponent === "nav" ? ariaLabelledBy : undefined; let t5; if ($[0] !== className) { t5 = clsx(classes.Navigation, className); $[0] = className; $[1] = t5; } else { t5 = $[1]; } let t6; if ($[2] !== hidden) { t6 = getHiddenDataAttributes(hidden); $[2] = hidden; $[3] = t6; } else { t6 = $[3]; } let t7; if ($[4] !== BaseComponent || $[5] !== children || $[6] !== t3 || $[7] !== t4 || $[8] !== t5 || $[9] !== t6) { t7 = /*#__PURE__*/jsx(BaseComponent, { "aria-label": t3, "aria-labelledby": t4, className: t5, "data-component": "PH_Navigation", ...t6, children: children }); $[4] = BaseComponent; $[5] = children; $[6] = t3; $[7] = t4; $[8] = t5; $[9] = t6; $[10] = t7; } else { t7 = $[10]; } return t7; }; // Based on getBreakpointDeclarations, this function will return the // correct data attribute for the given hidden value for CSS modules. function getHiddenDataAttributes(isHidden) { if (isResponsiveValue(isHidden)) { const responsiveValue = isHidden; // Build media queries with the giving cssProperty and mapFn const narrowMediaQuery = 'narrow' in responsiveValue ? { 'data-hidden-narrow': responsiveValue.narrow || undefined } : {}; const regularMediaQuery = 'regular' in responsiveValue ? { 'data-hidden-regular': responsiveValue.regular || undefined } : {}; const wideMediaQuery = 'wide' in responsiveValue ? { 'data-hidden-wide': responsiveValue.wide || undefined } : {}; // check if all values are the same - this is not a recommended practice but we still should check for it if (areAllValuesTheSame(responsiveValue)) { // if all the values are the same, we can just use one of the value to determine the CSS property's value return { 'data-hidden-all': responsiveValue.narrow || undefined }; // check if regular and wide have the same value, if so we can just return the narrow and regular media queries } else if (haveRegularAndWideSameValue(responsiveValue)) { return { ...narrowMediaQuery, ...regularMediaQuery }; } else { return { ...narrowMediaQuery, ...regularMediaQuery, ...wideMediaQuery }; } } else { // If the given value is not a responsive value return { 'data-hidden-all': isHidden || undefined }; } } const PageHeader = Object.assign(Root, { ContextArea, ParentLink, ContextBar, TitleArea, ContextAreaActions, LeadingAction, Breadcrumbs, LeadingVisual, Title, TrailingVisual, TrailingAction, Actions, Description, Navigation }); PageHeader.displayName = 'PageHeader'; function _temp(element) { return ["a", "button"].some(selector => element.matches(selector)) || element.hasAttribute("role") && element.getAttribute("role") === "button" || element.hasAttribute("link") && element.getAttribute("role") === "link" || element.hasAttribute("tabindex"); } function _temp2(child) { return child instanceof HTMLElement && child.getAttribute("data-component") === "TitleArea"; } export { PageHeader };