{"version":3,"file":"ReleaseAnnouncement.cjs","names":[],"sources":["../../../src/components/ReleaseAnnouncement/ReleaseAnnouncement.tsx"],"sourcesContent":["/*\nCopyright 2024 New Vector Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE files in the repository root for full details.\n*/\n\nimport React, {\n  cloneElement,\n  isValidElement,\n  type JSX,\n  type PropsWithChildren,\n  type Ref,\n} from \"react\";\nimport {\n  FloatingPortal,\n  FloatingFocusManager,\n  type Placement,\n  useMergeRefs,\n  FloatingArrow,\n} from \"@floating-ui/react\";\nimport { Text } from \"../Typography/Text\";\nimport { Button } from \"../Button\";\nimport styles from \"./ReleaseAnnouncement.module.css\";\nimport {\n  useReleaseAnnouncementContext,\n  ReleaseAnnouncementContext,\n} from \"./ReleaseAnnouncementContext\";\nimport { useReleaseAnnouncement } from \"./useReleaseAnnouncement\";\n\ntype UseReleaseAnnouncementParam = Parameters<typeof useReleaseAnnouncement>[0];\n\ninterface ReleaseAnnouncementProps extends Omit<\n  UseReleaseAnnouncementParam,\n  \"placement\" | \"displayArrow\"\n> {\n  /**\n   * The placement of the component\n   * @default \"right\"\n   */\n  placement?: Placement;\n  /**\n   * Whether to display an arrow.\n   * @default true\n   */\n  displayArrow?: boolean;\n}\n\n/**\n * The ReleaseAnnouncement component purpose is to inform the user of a new available feature.\n * This component is a floating component that will appear next to an anchor.\n * @param children - Act as an anchor, the component will be displayed alongside of it.\n * @param placement - The placement of the component\n */\nexport function ReleaseAnnouncement({\n  /**\n   * The children anchor should be a single valid React element.\n   */\n  children,\n  placement = \"right\",\n  displayArrow = true,\n  ...props\n}: PropsWithChildren<ReleaseAnnouncementProps>): JSX.Element {\n  const context = useReleaseAnnouncement({ placement, displayArrow, ...props });\n\n  return (\n    <ReleaseAnnouncementContext.Provider value={context}>\n      <ReleaseAnnouncementAnchor>{children}</ReleaseAnnouncementAnchor>\n      <ReleaseAnnouncementContainer>\n        <ReleaseAnnouncementContent />\n      </ReleaseAnnouncementContainer>\n    </ReleaseAnnouncementContext.Provider>\n  );\n}\n\n/**\n * The anchor for the ReleaseAnnouncement components.\n * The Release Announcement will appear next to this element.\n * @param children - should be a single valid React element\n * @constructor\n */\nfunction ReleaseAnnouncementAnchor({\n  children,\n}: Readonly<PropsWithChildren>): JSX.Element {\n  const context = useReleaseAnnouncementContext();\n\n  // The children can have a ref and we don't want to discard it\n  // Doing a dirty cast to get the optional ref\n  const childrenRef = (children as unknown as { ref?: Ref<HTMLElement> })?.ref;\n  const ref = useMergeRefs([context.refs.setReference, childrenRef]);\n\n  if (!isValidElement(children)) {\n    throw new Error(\n      \"ReleaseAnnouncement anchor must be a single valid React element\",\n    );\n  }\n\n  const referenceProps = context.getReferenceProps({\n    ref,\n    // If the ReleaseAnnouncement is open, we need manually aria-describedby.\n    // The RA has the dialog role and it's not adding automatically the aria-describedby.\n    ...(context.open && {\n      \"aria-describedby\": context.getFloatingProps().id as string,\n    }),\n  });\n\n  // getReferenceProps includes aria-expanded (being true when the popup is shown)\n  // but axe only allows this on certain elements and we use release anncounements on\n  // all sorts of elements. Semantically, I don't think it makes sense because the point\n  // of aria-expanded is a hint to the user that there is something that can be expanded.\n  // The user can't cause a release announcement to be shown, it just appears when it thinks\n  // it's time, so I think adding it here is misleading.\n  delete referenceProps[\"aria-expanded\"];\n\n  return cloneElement(children, referenceProps);\n}\n\n/**\n * The container for the ReleaseAnnouncement components.\n * Manage focus and positioning of the children.\n * @param children\n */\nfunction ReleaseAnnouncementContainer({\n  children,\n}: PropsWithChildren): JSX.Element | null {\n  const {\n    context: floatingContext,\n    arrowRef,\n    displayArrow,\n    ...rest\n  } = useReleaseAnnouncementContext();\n\n  if (!floatingContext.open) return null;\n\n  return (\n    <FloatingPortal>\n      <FloatingFocusManager context={floatingContext} modal={false}>\n        <div\n          ref={rest.refs.setFloating}\n          style={rest.floatingStyles}\n          aria-labelledby={rest.labelId}\n          aria-describedby={rest.descriptionId}\n          {...rest.getFloatingProps()}\n          className={styles.content}\n        >\n          {displayArrow && (\n            <FloatingArrow\n              ref={arrowRef}\n              context={floatingContext}\n              // design absolute value\n              width={20}\n              height={12}\n              className={styles.arrow}\n            />\n          )}\n          {children}\n        </div>\n      </FloatingFocusManager>\n    </FloatingPortal>\n  );\n}\n\n/**\n * The content of the ReleaseAnnouncement component.\n * ---------------------------------------------------------------\n * - The header in a bold text                  -------------    -\n * - A description in a regular text           | Close button |  -\n * - Description can be on multiple lines       -------------    -\n * ---------------------------------------------------------------\n */\nfunction ReleaseAnnouncementContent(): JSX.Element {\n  const { labelId, descriptionId, header, description, closeLabel, onClick } =\n    useReleaseAnnouncementContext();\n\n  return (\n    <>\n      <Text\n        as=\"h3\"\n        id={labelId}\n        className={styles.header}\n        size=\"lg\"\n        weight=\"semibold\"\n      >\n        {header}\n      </Text>\n      <Text\n        as=\"span\"\n        id={descriptionId}\n        className={styles.description}\n        size=\"sm\"\n        weight=\"regular\"\n      >\n        {description}\n      </Text>\n      <Button\n        size=\"sm\"\n        kind=\"secondary\"\n        className={styles.button}\n        onClick={onClick}\n      >\n        {closeLabel}\n      </Button>\n    </>\n  );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAsDA,SAAgB,oBAAoB,EAIlC,UACA,YAAY,SACZ,eAAe,MACf,GAAG,SACwD;CAC3D,MAAM,UAAU,+BAAA,uBAAuB;EAAE;EAAW;EAAc,GAAG;EAAO,CAAC;AAE7E,QACE,iBAAA,GAAA,kBAAA,MAAC,mCAAA,2BAA2B,UAA5B;EAAqC,OAAO;YAA5C,CACE,iBAAA,GAAA,kBAAA,KAAC,2BAAD,EAA4B,UAAqC,CAAA,EACjE,iBAAA,GAAA,kBAAA,KAAC,8BAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,4BAAD,EAA8B,CAAA,EACD,CAAA,CACK;;;;;;;;;AAU1C,SAAS,0BAA0B,EACjC,YAC2C;CAC3C,MAAM,UAAU,mCAAA,+BAA+B;CAI/C,MAAM,cAAe,UAAoD;CACzE,MAAM,OAAA,GAAA,mBAAA,cAAmB,CAAC,QAAQ,KAAK,cAAc,YAAY,CAAC;AAElE,KAAI,EAAA,GAAA,MAAA,gBAAgB,SAAS,CAC3B,OAAM,IAAI,MACR,kEACD;CAGH,MAAM,iBAAiB,QAAQ,kBAAkB;EAC/C;EAGA,GAAI,QAAQ,QAAQ,EAClB,oBAAoB,QAAQ,kBAAkB,CAAC,IAChD;EACF,CAAC;AAQF,QAAO,eAAe;AAEtB,SAAA,GAAA,MAAA,cAAoB,UAAU,eAAe;;;;;;;AAQ/C,SAAS,6BAA6B,EACpC,YACwC;CACxC,MAAM,EACJ,SAAS,iBACT,UACA,cACA,GAAG,SACD,mCAAA,+BAA+B;AAEnC,KAAI,CAAC,gBAAgB,KAAM,QAAO;AAElC,QACE,iBAAA,GAAA,kBAAA,KAAC,mBAAA,gBAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,mBAAA,sBAAD;EAAsB,SAAS;EAAiB,OAAO;YACrD,iBAAA,GAAA,kBAAA,MAAC,OAAD;GACE,KAAK,KAAK,KAAK;GACf,OAAO,KAAK;GACZ,mBAAiB,KAAK;GACtB,oBAAkB,KAAK;GACvB,GAAI,KAAK,kBAAkB;GAC3B,WAAW,mCAAA,QAAO;aANpB,CAQG,gBACC,iBAAA,GAAA,kBAAA,KAAC,mBAAA,eAAD;IACE,KAAK;IACL,SAAS;IAET,OAAO;IACP,QAAQ;IACR,WAAW,mCAAA,QAAO;IAClB,CAAA,EAEH,SACG;;EACe,CAAA,EACR,CAAA;;;;;;;;;;AAYrB,SAAS,6BAA0C;CACjD,MAAM,EAAE,SAAS,eAAe,QAAQ,aAAa,YAAY,YAC/D,mCAAA,+BAA+B;AAEjC,QACE,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,KAAC,aAAA,MAAD;GACE,IAAG;GACH,IAAI;GACJ,WAAW,mCAAA,QAAO;GAClB,MAAK;GACL,QAAO;aAEN;GACI,CAAA;EACP,iBAAA,GAAA,kBAAA,KAAC,aAAA,MAAD;GACE,IAAG;GACH,IAAI;GACJ,WAAW,mCAAA,QAAO;GAClB,MAAK;GACL,QAAO;aAEN;GACI,CAAA;EACP,iBAAA,GAAA,kBAAA,KAAC,eAAA,QAAD;GACE,MAAK;GACL,MAAK;GACL,WAAW,mCAAA,QAAO;GACT;aAER;GACM,CAAA;EACR,EAAA,CAAA"}