@persona/design-system 0.10.5 → 0.10.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/Badge-8YzapjWf.mjs.map +1 -1
- package/dist/Breadcrumbs-Dft2TR4v.mjs.map +1 -1
- package/dist/Card-DuQHyroh.mjs.map +1 -1
- package/dist/CardV2-BRJbRSts.mjs.map +1 -1
- package/dist/Checkbox-Dr4LMKHV.mjs.map +1 -1
- package/dist/{CheckboxGroupField-UHpA38U5.d.mts → CheckboxGroupField-CjeEoiPa.d.mts} +2 -2
- package/dist/CheckboxGroupField.d.mts +1 -1
- package/dist/Combobox-DQxaOCLA.mjs.map +1 -1
- package/dist/{Combobox-BXkcQ2aY.d.mts → Combobox-O6LbofT2.d.mts} +3 -3
- package/dist/Combobox.d.mts +2 -2
- package/dist/{ComboboxBase-D2rDQHYZ.d.mts → ComboboxBase-5aSDuY-E.d.mts} +2 -2
- package/dist/ComboboxBase.d.mts +1 -1
- package/dist/{ComboboxMultiSelect-CrvB6ap5.d.mts → ComboboxMultiSelect-D3mX4Dzq.d.mts} +2 -2
- package/dist/ComboboxMultiSelect.d.mts +1 -1
- package/dist/{ComboboxSingleSelect-Dp0iTdDO.d.mts → ComboboxSingleSelect-CfSy6sCU.d.mts} +3 -3
- package/dist/ComboboxSingleSelect.d.mts +1 -1
- package/dist/{DataTable-C000E74h.d.mts → DataTable-BXHmi-SW.d.mts} +7 -6
- package/dist/{DataTable-DEJHWrsy.mjs → DataTable-CAfZNJmb.mjs} +8 -7
- package/dist/DataTable-CAfZNJmb.mjs.map +1 -0
- package/dist/DataTable.d.mts +1 -1
- package/dist/DatePicker-D-_ibUd1.mjs.map +1 -1
- package/dist/DropdownButton-BiFRlSVD.mjs.map +1 -1
- package/dist/DropdownButton.d.mts +1 -1
- package/dist/{DropdownMenu-CQbS7ML5.d.mts → DropdownMenu-CAYVX9Q3.d.mts} +2 -2
- package/dist/DropdownMenu-Q8S-9rXm.mjs.map +1 -1
- package/dist/DropdownMenu.d.mts +1 -1
- package/dist/FormControl-BztNXLn6.mjs.map +1 -1
- package/dist/{FormField-g1zQFM9T.mjs → FormField-BStxmlZT.mjs} +2 -2
- package/dist/FormField-BStxmlZT.mjs.map +1 -0
- package/dist/{FormField-PBo1ctY8.d.mts → FormField-D10LW9-a.d.mts} +2 -2
- package/dist/FormField.d.mts +1 -1
- package/dist/HoverCopyableField-CW7Jxmni.mjs.map +1 -1
- package/dist/{I18nContext-EPmbUprm.d.mts → I18nContext-BBVKF9ui.d.mts} +2 -2
- package/dist/I18nContext.d.mts +1 -1
- package/dist/IconButton-DftINsp7.mjs.map +1 -1
- package/dist/IndexTableLayout.d.mts +3 -3
- package/dist/InlineCombobox.d.mts +1 -1
- package/dist/InlineInput.d.mts +1 -1
- package/dist/Input-DtO3qMnE.mjs.map +1 -1
- package/dist/Link-DKYmdL9t.mjs.map +1 -1
- package/dist/ListBox-CDG0EAPg.mjs.map +1 -1
- package/dist/{ListBox-D9SYTzOd.d.mts → ListBox-CvnFiHK5.d.mts} +2 -2
- package/dist/ListBox.d.mts +1 -1
- package/dist/{ListBoxField-CtPDd_Aw.d.mts → ListBoxField-DuUwx9Cv.d.mts} +4 -4
- package/dist/ListBoxField.d.mts +1 -1
- package/dist/LoadingShimmer-oPIv2ESr.mjs.map +1 -1
- package/dist/{LogicRow-BWIZ7262.d.mts → LogicRow-COvZNiUd.d.mts} +2 -2
- package/dist/LogicRow.d.mts +1 -1
- package/dist/{Menu-DizjcMbO.d.mts → Menu-ByYFNvgS.d.mts} +2 -2
- package/dist/Menu-EIT_MwK6.mjs.map +1 -1
- package/dist/Menu.d.mts +1 -1
- package/dist/{Modal-92O_uW8H.mjs → Modal-ziuzDCPN.mjs} +2 -2
- package/dist/Modal-ziuzDCPN.mjs.map +1 -0
- package/dist/PageHeader-BzvA_NNt.mjs.map +1 -1
- package/dist/PageLayout-DCe3F76N.mjs.map +1 -1
- package/dist/{PageSelector-QaKYtk6y.d.mts → PageSelector-BOe4EzbS.d.mts} +8 -2
- package/dist/PageSelector.d.mts +1 -1
- package/dist/{Pagination-dTsHLVAk.mjs → Pagination-Dpc6TadZ.mjs} +15 -11
- package/dist/Pagination-Dpc6TadZ.mjs.map +1 -0
- package/dist/{Pagination-DeXorbSK.d.mts → Pagination-Dy-OSH0Y.d.mts} +10 -2
- package/dist/Pagination.d.mts +1 -1
- package/dist/Popover-DordjYNM.mjs.map +1 -1
- package/dist/ProgressIndicator-ISARECzW.mjs.map +1 -1
- package/dist/Radio-BlEtetrr.mjs.map +1 -1
- package/dist/RadioGroup-CMrXmmn4.mjs.map +1 -1
- package/dist/SegmentedControl-D_DA-MU1.mjs.map +1 -1
- package/dist/{Select-Chk5WB1F.d.mts → Select-BLqHxJUz.d.mts} +2 -2
- package/dist/Select-DkUMz4LG.mjs.map +1 -1
- package/dist/Select.d.mts +1 -1
- package/dist/SmartTextInputField.d.mts +2 -2
- package/dist/Spacer-C4d9Aho6.mjs.map +1 -1
- package/dist/Spinner-CXb-KUs1.mjs.map +1 -1
- package/dist/StatusIndicator-pWl1-FLb.mjs.map +1 -1
- package/dist/Sticker-Bi_fezCO.mjs.map +1 -1
- package/dist/TabBar-DpXYsWgS.mjs.map +1 -1
- package/dist/Table-DPi4Dt5H.mjs.map +1 -1
- package/dist/TableBox-BfSF36Gy.mjs.map +1 -1
- package/dist/TableBox.d.mts +1 -1
- package/dist/{TableBoxCell-CwroLAWy.d.mts → TableBoxCell-DPXrw63v.d.mts} +4 -4
- package/dist/TableBoxCell.d.mts +1 -1
- package/dist/{TableBoxField-B7bHv7uV.d.mts → TableBoxField-C7MGSie9.d.mts} +5 -5
- package/dist/TableBoxField.d.mts +1 -1
- package/dist/{TableBoxRow-Dke8B99J.d.mts → TableBoxRow-uToXVWvl.d.mts} +2 -2
- package/dist/TableBoxRow.d.mts +1 -1
- package/dist/{TableBoxRowActions-CkUDVERC.d.mts → TableBoxRowActions-Do646IVE.d.mts} +2 -2
- package/dist/TableBoxRowActions.d.mts +1 -1
- package/dist/{TableControls-DAjx1TYG.d.mts → TableControls-BHv-tXA-.d.mts} +4 -3
- package/dist/{TableControls-BDXOQMr7.mjs → TableControls-C-0Dw8vM.mjs} +7 -5
- package/dist/TableControls-C-0Dw8vM.mjs.map +1 -0
- package/dist/TableControls.d.mts +1 -1
- package/dist/{TableControlsContext-BEIvE9qN.d.mts → TableControlsContext-D6rifk-v.d.mts} +2 -2
- package/dist/TableControlsContext.d.mts +1 -1
- package/dist/{TableViewConfigurationDropdown-vYnU0d4k.d.mts → TableViewConfigurationDropdown-C5bjxTGX.d.mts} +2 -2
- package/dist/TableViewConfigurationDropdown.d.mts +1 -1
- package/dist/TechnicalSticker-B_JlBkXZ.mjs.map +1 -1
- package/dist/Text-D0vEReED.mjs.map +1 -1
- package/dist/TextArea-Dro-HH8O.mjs.map +1 -1
- package/dist/Toggle-D9MzTIZs.mjs.map +1 -1
- package/dist/Tooltip-YViXzMdm.mjs.map +1 -1
- package/dist/{clientFilterUtils-DYKgw2Yq.d.mts → clientFilterUtils-DDDG1g7e.d.mts} +2 -2
- package/dist/clientFilterUtils.d.mts +1 -1
- package/dist/components/Accordion/index.mjs.map +1 -1
- package/dist/components/Attribute/index.mjs.map +1 -1
- package/dist/components/Banner/index.mjs.map +1 -1
- package/dist/components/BottomPanel/index.mjs.map +1 -1
- package/dist/components/ButtonGroup/index.mjs.map +1 -1
- package/dist/components/CodeHighlight/index.mjs.map +1 -1
- package/dist/components/Combobox/index.d.mts +2 -2
- package/dist/components/DataTable/TableControls/index.d.mts +6 -6
- package/dist/components/DataTable/TableControls/index.mjs +1 -1
- package/dist/components/DataTable/index.d.mts +5 -5
- package/dist/components/DataTable/index.mjs +1 -1
- package/dist/components/DataTable/types.d.mts +1 -1
- package/dist/components/DropdownMenu/index.d.mts +1 -1
- package/dist/components/FloatingPanel/index.mjs.map +1 -1
- package/dist/components/FormField/index.d.mts +5 -5
- package/dist/components/FormField/index.mjs +1 -1
- package/dist/components/ImageTile/index.mjs.map +1 -1
- package/dist/components/ListBox/index.d.mts +3 -3
- package/dist/components/MaskedInput/index.mjs.map +1 -1
- package/dist/components/MatchHighlight/index.mjs.map +1 -1
- package/dist/components/Menu/index.d.mts +1 -1
- package/dist/components/Modal/index.mjs +1 -1
- package/dist/components/Pagination/index.d.mts +2 -2
- package/dist/components/Pagination/index.mjs +1 -1
- package/dist/components/ProgressBar/index.mjs.map +1 -1
- package/dist/components/RichTextEditor/index.mjs +1 -1
- package/dist/components/RichTextEditor/index.mjs.map +1 -1
- package/dist/components/RightPanel/index.mjs.map +1 -1
- package/dist/components/Select/index.d.mts +1 -1
- package/dist/components/SelectionCard/index.mjs.map +1 -1
- package/dist/components/Slider/index.mjs.map +1 -1
- package/dist/components/SmartTextInput/index.mjs +1 -1
- package/dist/components/SmartTextInput/index.mjs.map +1 -1
- package/dist/components/SwatchPicker/index.mjs.map +1 -1
- package/dist/components/TableBox/index.d.mts +1 -1
- package/dist/components/Tile/index.mjs.map +1 -1
- package/dist/components/Toast/index.mjs.map +1 -1
- package/dist/components/VersionHistory/index.mjs +1 -1
- package/dist/components/VersionHistory/index.mjs.map +1 -1
- package/dist/display.d.mts +1 -1
- package/dist/fieldPickerOptions.d.mts +1 -1
- package/dist/{filters-DjXkx8GJ.d.mts → filters-CkAFU8LV.d.mts} +2 -2
- package/dist/filters.d.mts +1 -1
- package/dist/{helpers-CdxEL7ri.d.mts → helpers-Dvvcz-hL.d.mts} +3 -3
- package/dist/helpers.d.mts +1 -1
- package/dist/{i18n-BLyCaSdJ.mjs → i18n-CKRi992F.mjs} +2 -1
- package/dist/i18n-CKRi992F.mjs.map +1 -0
- package/dist/{index-DX5Zu9JU.d.mts → index-B3A74_ew.d.mts} +3 -3
- package/dist/index6.d.mts +1 -1
- package/dist/{inputFields-CYttsz5M.d.mts → inputFields-Dfpxi68z.d.mts} +5 -5
- package/dist/inputFields.d.mts +1 -1
- package/dist/lib/PDSProvider.d.mts +1 -1
- package/dist/lib/PDSProvider.mjs +1 -1
- package/dist/lib/PDSProvider.mjs.map +1 -1
- package/dist/lib/TruncatedText.mjs.map +1 -1
- package/dist/lib/TruncatedTextWithTooltip.mjs.map +1 -1
- package/dist/lib/color.mjs.map +1 -1
- package/dist/lib/colorMode.mjs.map +1 -1
- package/dist/lib/i18n/index.d.mts +2 -2
- package/dist/lib/i18n/index.mjs +1 -1
- package/dist/lib/pseudoClass.mjs.map +1 -1
- package/dist/lib/semanticColor.mjs.map +1 -1
- package/dist/lib/useEmbeddedSurface.mjs.map +1 -1
- package/dist/mixins/focus.mjs.map +1 -1
- package/dist/mixins/hoverable.mjs.map +1 -1
- package/dist/mixins/input.mjs.map +1 -1
- package/dist/mixins/menuItem.mjs.map +1 -1
- package/dist/mixins/print/index.mjs.map +1 -1
- package/dist/mixins/scrollbar.mjs.map +1 -1
- package/dist/{operators-gCG7uZ6y.d.mts → operators-BrrJKENE.d.mts} +2 -2
- package/dist/operators.d.mts +1 -1
- package/dist/patterns/CardGrouping/index.mjs.map +1 -1
- package/dist/patterns/IndexTableLayout/index.mjs +1 -1
- package/dist/patterns/IndexTableLayout/index.mjs.map +1 -1
- package/dist/patterns/LayoutLoadingShimmer/index.mjs.map +1 -1
- package/dist/patterns/LayoutLoadingSpinner/index.mjs.map +1 -1
- package/dist/patterns/WizardModal/index.mjs +1 -1
- package/dist/patterns/WizardModal/index.mjs.map +1 -1
- package/dist/{strings-CK9n6b65.d.mts → strings-BGXKl_m6.d.mts} +6 -1
- package/dist/strings.d.mts +1 -1
- package/dist/theme.mjs.map +1 -1
- package/dist/{types-DJobO07d.d.mts → types-DoJubhWu.d.mts} +2 -2
- package/dist/{types-CayYd8EX.d.mts → types-sUEmxsGM.d.mts} +2 -2
- package/dist/types5.d.mts +1 -1
- package/dist/useChain-D1aNsdvn.mjs.map +1 -1
- package/dist/useColumnConfiguration.d.mts +2 -2
- package/dist/useComboboxFooterAction.d.mts +1 -1
- package/dist/useFormField-pOVkb5BK.mjs.map +1 -1
- package/dist/{useTableColumns-BK-KYY0L.d.mts → useTableColumns-nPrbDfF_.d.mts} +2 -2
- package/dist/useTableColumns.d.mts +1 -1
- package/dist/useTruncation.d.mts +1 -1
- package/dist/utils/storybook.mjs.map +1 -1
- package/dist/variables/effect.mjs.map +1 -1
- package/package.json +16 -3
- package/dist/DataTable-DEJHWrsy.mjs.map +0 -1
- package/dist/FormField-g1zQFM9T.mjs.map +0 -1
- package/dist/Modal-92O_uW8H.mjs.map +0 -1
- package/dist/Pagination-dTsHLVAk.mjs.map +0 -1
- package/dist/TableControls-BDXOQMr7.mjs.map +0 -1
- package/dist/i18n-BLyCaSdJ.mjs.map +0 -1
package/dist/TableControls.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as TableControlsFiltersV2Props, r as TableControlsProps, t as TableControls } from "./TableControls-
|
|
1
|
+
import { n as TableControlsFiltersV2Props, r as TableControlsProps, t as TableControls } from "./TableControls-BHv-tXA-.mjs";
|
|
2
2
|
export { TableControlsFiltersV2Props, TableControlsProps, TableControls as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as BaseFilterConfig, r as BaseActiveFilter } from "./types-
|
|
1
|
+
import { i as BaseFilterConfig, r as BaseActiveFilter } from "./types-sUEmxsGM.mjs";
|
|
2
2
|
import * as _$react from "react";
|
|
3
3
|
import { Dispatch, ReactNode, SetStateAction } from "react";
|
|
4
4
|
|
|
@@ -18,4 +18,4 @@ declare function TableControlsProvider<TFilter extends BaseFilterConfig = BaseFi
|
|
|
18
18
|
}): _$react.FunctionComponentElement<_$react.ProviderProps<TableControlsContextProps<BaseFilterConfig, BaseActiveFilter<BaseFilterConfig>>>>;
|
|
19
19
|
//#endregion
|
|
20
20
|
export { useTableControls as i, TableControlsContextProps as n, TableControlsProvider as r, TableControlsContext as t };
|
|
21
|
-
//# sourceMappingURL=TableControlsContext-
|
|
21
|
+
//# sourceMappingURL=TableControlsContext-D6rifk-v.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as useTableControls, n as TableControlsContextProps, r as TableControlsProvider, t as TableControlsContext } from "./TableControlsContext-
|
|
1
|
+
import { i as useTableControls, n as TableControlsContextProps, r as TableControlsProvider, t as TableControlsContext } from "./TableControlsContext-D6rifk-v.mjs";
|
|
2
2
|
export { TableControlsContextProps, TableControlsProvider, TableControlsContext as default, useTableControls };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as AttributeColumn } from "./types-
|
|
1
|
+
import { n as AttributeColumn } from "./types-sUEmxsGM.mjs";
|
|
2
2
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/components/DataTable/TableControls/TableViewConfigurationDropdown.d.ts
|
|
@@ -31,4 +31,4 @@ declare const TableViewConfiguration: ({
|
|
|
31
31
|
}: TableViewConfigurationProps) => _$react_jsx_runtime0.JSX.Element;
|
|
32
32
|
//#endregion
|
|
33
33
|
export { TableViewConfigurationProps as i, TableViewConfigurationDropdown as n, TableViewConfigurationDropdownProps as r, TableViewConfiguration as t };
|
|
34
|
-
//# sourceMappingURL=TableViewConfigurationDropdown-
|
|
34
|
+
//# sourceMappingURL=TableViewConfigurationDropdown-C5bjxTGX.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as TableViewConfigurationProps, n as TableViewConfigurationDropdown, r as TableViewConfigurationDropdownProps, t as TableViewConfiguration } from "./TableViewConfigurationDropdown-
|
|
1
|
+
import { i as TableViewConfigurationProps, n as TableViewConfigurationDropdown, r as TableViewConfigurationDropdownProps, t as TableViewConfiguration } from "./TableViewConfigurationDropdown-C5bjxTGX.mjs";
|
|
2
2
|
export { TableViewConfiguration, TableViewConfigurationDropdownProps, TableViewConfigurationProps, TableViewConfigurationDropdown as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TechnicalSticker-B_JlBkXZ.mjs","names":[],"sources":["../src/components/TechnicalSticker/TechnicalSticker.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type MouseEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport styled, { css, useTheme } from 'styled-components';\n\nimport { BorderRadius, Color, Spacing, Typography } from '@persona/design-tokens';\nimport { CopyIcon } from '@persona/icons/12px';\nimport Tooltip from 'design-system/components/Tooltip';\nimport { withAlpha } from 'design-system/lib/color';\nimport copyTextToClipboard from 'design-system/lib/copyTextToClipboard';\nimport MiddleTruncatedText from 'design-system/lib/MiddleTruncatedText';\nimport { isHovered } from 'design-system/lib/pseudoClass';\nimport {\n type MaybeSemanticTheme,\n semanticColor,\n semanticTokens,\n} from 'design-system/lib/semanticColor';\nimport useToggle from 'design-system/lib/useToggle';\nimport type { SemanticTokens } from 'design-system/variables/semantic';\n\nexport type TechnicalStickerVariant = 'grey' | 'white';\n\nconst COPY_CONFIRMATION_TEXT = 'Copied!';\nconst COPY_CONFIRMATION_DURATION_MS = 1200;\nconst DEFAULT_COPY_TOOLTIP_LABEL = 'Copy ID';\nconst HREF_VALIDATION_BASE_URL = 'https://withpersona.com';\nconst TECHNICAL_TEXT_FONT = `${Typography.TextMono.fontWeight} ${Typography.TextExtraSmall.fontSize} ${Typography.TextMono.fontFamily}`;\n\nconst semanticRestFill = (tokens: SemanticTokens, variant: TechnicalStickerVariant) =>\n variant === 'white' ? tokens.FeedbackNeutralInverse : tokens.FeedbackNeutral1;\n\nconst restFill = (theme: MaybeSemanticTheme, variant: TechnicalStickerVariant) => {\n const tokens = semanticTokens(theme);\n if (tokens) {\n return semanticRestFill(tokens, variant);\n }\n return variant === 'white' ? Color.BackgroundLabelWhite : Color.BackgroundLabelGrey;\n};\n\nconst hoverFill = (theme: MaybeSemanticTheme, variant: TechnicalStickerVariant) =>\n variant === 'white'\n ? semanticColor(theme, 'FeedbackNeutral1', Color.BackgroundButtonInverseHover)\n : semanticColor(theme, 'ActionNeutralActive', Color.BackgroundLabelGreyHover);\n\nconst isSafeTechnicalStickerHref = (href: string) => {\n try {\n const url = new URL(href, HREF_VALIDATION_BASE_URL);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n};\n\nconst TechnicalStickerShell = styled.div<{\n variant: TechnicalStickerVariant;\n disabled?: boolean;\n $width?: number | string;\n}>`\n display: inline-flex;\n align-items: center;\n white-space: nowrap;\n\n border-radius: ${BorderRadius.Sm};\n height: 1rem;\n width: ${({ $width }) => (typeof $width === 'number' ? `${$width}px` : ($width ?? 'auto'))};\n max-width: 100%;\n box-sizing: border-box;\n\n color: ${({ theme, disabled }) =>\n disabled\n ? semanticColor(theme, 'FgDisabled', theme.color.text.disabled)\n : semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n background: ${({ theme, variant, disabled }) => {\n const tokens = semanticTokens(theme);\n return tokens && disabled\n ? withAlpha(semanticRestFill(tokens, variant), tokens.Opacity65)\n : restFill(theme, variant);\n }};\n\n position: relative;\n overflow: hidden;\n border: 1px solid ${({ theme }) => semanticColor(theme, 'BorderDefault', Color.BorderInputDefault)};\n\n ${({ theme, variant, disabled }) =>\n !disabled &&\n css`\n &:hover {\n background: ${hoverFill(theme, variant)};\n }\n `}\n`;\n\nconst labelContainerStyles = css`\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1 1 auto;\n min-width: 0;\n padding: 0 ${Spacing[1]};\n`;\n\nconst LabelContainer = styled.div`\n ${labelContainerStyles}\n`;\n\nconst LabelLink = styled.a`\n ${labelContainerStyles}\n color: inherit;\n text-decoration: none;\n`;\n\nconst TechnicalText = styled(MiddleTruncatedText)<{\n $isLinkEnabled: boolean;\n $isTruncated: boolean;\n}>`\n ${Typography.TextMono};\n font-size: ${Typography.TextExtraSmall.fontSize};\n line-height: ${Typography.TextExtraSmall.lineHeight};\n text-align: center;\n\n ${({ $isLinkEnabled, $isTruncated }) =>\n $isTruncated &&\n css`\n cursor: ${$isLinkEnabled ? 'pointer' : 'default'};\n user-select: none;\n\n & > span {\n user-select: none;\n }\n `}\n`;\n\nconst CopyActions = styled.div<{ $visible: boolean }>`\n position: absolute;\n top: 0;\n right: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n height: 16px;\n opacity: ${({ $visible }) => ($visible ? 1 : 0)};\n pointer-events: ${({ $visible }) => ($visible ? 'auto' : 'none')};\n transition: opacity 120ms ease-in-out;\n\n /* Keyboard focus keeps the actions reachable, but a click also focuses the\n button — matching plain :focus-within would leave them visible after the\n pointer moves away. */\n &:has(:focus-visible) {\n opacity: 1;\n pointer-events: auto;\n }\n`;\n\nconst CopyGradient = styled.div<{ $background: string }>`\n width: 8px;\n height: 16px;\n background: linear-gradient(to left, ${({ $background }) => $background}, transparent);\n`;\n\nconst CopyButton = styled.button<{ $background: string }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0 2px 0 0;\n border: none;\n background: ${({ $background }) => $background};\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.BorderIconPrimary)};\n cursor: pointer;\n\n &:disabled {\n cursor: not-allowed;\n }\n\n &${isHovered}:not(:disabled) {\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n }\n`;\n\nexport interface TechnicalStickerProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n /** Full untruncated technical value displayed in the sticker. */\n children: string;\n /** Visual style for the technical sticker. Default: `grey`. */\n variant?: TechnicalStickerVariant;\n /** Renders disabled style and disables copy/link interaction. */\n disabled?: boolean;\n /** Opens in a new tab when the sticker body is clicked. */\n href?: string;\n /**\n * Hover tooltip for the sticker body. Shown when text is truncated or when set explicitly.\n * Defaults to the untruncated `children` string when shown.\n */\n tooltipLabel?: string;\n /**\n * Hover tooltip for the copy icon.\n * Defaults to `Copy ID`.\n */\n copyTooltipLabel?: string;\n /**\n * Confirmation label shown in the copy tooltip after a successful copy.\n * Defaults to `Copied!`.\n */\n copyConfirmationLabel?: string;\n /** Whether to show the hover copy action. Default: true. */\n copyable?: boolean;\n /** Value copied to the clipboard. Defaults to `children`. */\n copyValue?: string;\n /** Width of the sticker. Numbers are interpreted as pixels. */\n width?: number | string;\n /** Max width for middle truncation. Default: '96px'. */\n maxWidth?: number | string;\n}\n\nexport const TechnicalSticker = ({\n variant = 'grey',\n href,\n tooltipLabel: tooltipLabelProp,\n copyTooltipLabel = DEFAULT_COPY_TOOLTIP_LABEL,\n copyConfirmationLabel = COPY_CONFIRMATION_TEXT,\n copyable = true,\n copyValue,\n width,\n maxWidth = '96px',\n children,\n disabled,\n onMouseEnter,\n onMouseLeave,\n ...stickerProps\n}: TechnicalStickerProps) => {\n const [isHoveredState, setIsHoveredState] = useState(false);\n const [isCopyButtonKeyboardFocused, setIsCopyButtonKeyboardFocused] = useState(false);\n const [isTruncated, setIsTruncated] = useState(false);\n const [isCopyTooltipOpen, setIsCopyTooltipOpen] = useState(false);\n const [copyConfirmationOpen, { enable: showCopyConfirmation, disable: hideCopyConfirmation }] =\n useToggle(false);\n const copyConfirmationTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const isPointerFocusRef = useRef(false);\n const copyRequestIdRef = useRef(0);\n\n const tooltipLabel = tooltipLabelProp ?? children;\n const hasCustomTooltipLabel = tooltipLabelProp != null;\n\n const theme = useTheme();\n const hoverBackground = hoverFill(theme, variant);\n const copyActionBackground = isHoveredState ? hoverBackground : restFill(theme, variant);\n const showCopyActions =\n copyable &&\n !disabled &&\n (isHoveredState || isCopyButtonKeyboardFocused || copyConfirmationOpen);\n const showStickerTooltip = tooltipLabel.length > 0 && (isTruncated || hasCustomTooltipLabel);\n const isCopyTooltipVisible = isCopyTooltipOpen || copyConfirmationOpen;\n const isLinkEnabled = href != null && !disabled && isSafeTechnicalStickerHref(href);\n\n const handleCopyTooltipOpenChange = useCallback(\n (open: boolean) => {\n if (copyConfirmationOpen) {\n return;\n }\n\n setIsCopyTooltipOpen(open);\n },\n [copyConfirmationOpen],\n );\n\n const dismissCopyConfirmation = useCallback(() => {\n // Writing to the clipboard is async, so a copy still in flight would\n // otherwise surface its confirmation after the dismissal.\n copyRequestIdRef.current += 1;\n\n if (copyConfirmationTimerRef.current) {\n clearTimeout(copyConfirmationTimerRef.current);\n copyConfirmationTimerRef.current = null;\n }\n\n setIsCopyTooltipOpen(false);\n hideCopyConfirmation();\n }, [hideCopyConfirmation]);\n\n const handleCopy = useCallback(\n async (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (disabled) {\n return;\n }\n\n const requestId = ++copyRequestIdRef.current;\n const copyWasSuccessful = await copyTextToClipboard(copyValue ?? children);\n if (!copyWasSuccessful || requestId !== copyRequestIdRef.current) {\n return;\n }\n\n setIsCopyTooltipOpen(true);\n showCopyConfirmation();\n if (copyConfirmationTimerRef.current) {\n clearTimeout(copyConfirmationTimerRef.current);\n }\n copyConfirmationTimerRef.current = setTimeout(() => {\n setIsCopyTooltipOpen(false);\n hideCopyConfirmation();\n copyConfirmationTimerRef.current = null;\n }, COPY_CONFIRMATION_DURATION_MS);\n },\n [children, copyValue, disabled, hideCopyConfirmation, showCopyConfirmation],\n );\n\n useEffect(\n () => () => {\n if (copyConfirmationTimerRef.current) {\n clearTimeout(copyConfirmationTimerRef.current);\n }\n },\n [],\n );\n\n // Clicking an already keyboard-focused button fires no second focus event, so\n // pointer input has to retire the keyboard state itself.\n const handleCopyButtonMouseDown = () => {\n isPointerFocusRef.current = true;\n setIsCopyButtonKeyboardFocused(false);\n };\n\n // A click focuses the button too, so treating any focus as a reason to keep\n // the actions visible would pin them open once the pointer moves away.\n const handleCopyButtonFocus = () => {\n setIsCopyButtonKeyboardFocused(!isPointerFocusRef.current);\n isPointerFocusRef.current = false;\n };\n\n const handleCopyButtonBlur = () => {\n isPointerFocusRef.current = false;\n setIsCopyButtonKeyboardFocused(false);\n };\n\n const technicalText = (\n <TechnicalText\n value={children}\n maxWidth={width ?? maxWidth}\n font={TECHNICAL_TEXT_FONT}\n onTruncatedChange={setIsTruncated}\n titleBehavior='never'\n $isLinkEnabled={isLinkEnabled}\n $isTruncated={isTruncated}\n />\n );\n\n const labelContent = isLinkEnabled ? (\n <LabelLink href={href} target='_blank' rel='noopener noreferrer'>\n {technicalText}\n </LabelLink>\n ) : (\n <LabelContainer>{technicalText}</LabelContainer>\n );\n\n const labelWithTooltip = showStickerTooltip ? (\n <Tooltip trigger={labelContent} interactive side='top' maxWidth='400px'>\n {tooltipLabel}\n </Tooltip>\n ) : (\n labelContent\n );\n\n return (\n <TechnicalStickerShell\n {...stickerProps}\n variant={variant}\n disabled={disabled}\n $width={width}\n onMouseEnter={(event) => {\n onMouseEnter?.(event);\n setIsHoveredState(true);\n }}\n onMouseLeave={(event) => {\n onMouseLeave?.(event);\n setIsHoveredState(false);\n if (!isCopyButtonKeyboardFocused) {\n // Otherwise a click's focus lingers on a button that is now hidden.\n copyButtonRef.current?.blur();\n dismissCopyConfirmation();\n }\n }}\n >\n {labelWithTooltip}\n {copyable && (\n <CopyActions $visible={showCopyActions}>\n <CopyGradient $background={copyActionBackground} />\n <Tooltip\n open={isCopyTooltipVisible}\n onOpenChange={handleCopyTooltipOpenChange}\n trigger={\n <CopyButton\n ref={copyButtonRef}\n type='button'\n aria-label='Copy'\n disabled={disabled}\n $background={copyActionBackground}\n onClick={handleCopy}\n onMouseDown={handleCopyButtonMouseDown}\n onBlur={handleCopyButtonBlur}\n onFocus={handleCopyButtonFocus}\n >\n <CopyIcon />\n </CopyButton>\n }\n interactive={false}\n side='top'\n >\n {copyConfirmationOpen ? copyConfirmationLabel : copyTooltipLabel}\n </Tooltip>\n </CopyActions>\n )}\n </TechnicalStickerShell>\n );\n};\n\nexport default TechnicalSticker;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TechnicalSticker-B_JlBkXZ.mjs","names":[],"sources":["../src/components/TechnicalSticker/TechnicalSticker.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type MouseEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport styled, { css, useTheme } from 'styled-components';\n\nimport { BorderRadius, Color, Spacing, Typography } from '@persona/design-tokens';\nimport { CopyIcon } from '@persona/icons/12px';\n\nimport Tooltip from '#src/components/Tooltip';\nimport { withAlpha } from '#src/lib/color';\nimport copyTextToClipboard from '#src/lib/copyTextToClipboard';\nimport MiddleTruncatedText from '#src/lib/MiddleTruncatedText';\nimport { isHovered } from '#src/lib/pseudoClass';\nimport { type MaybeSemanticTheme, semanticColor, semanticTokens } from '#src/lib/semanticColor';\nimport useToggle from '#src/lib/useToggle';\nimport type { SemanticTokens } from '#src/variables/semantic';\n\nexport type TechnicalStickerVariant = 'grey' | 'white';\n\nconst COPY_CONFIRMATION_TEXT = 'Copied!';\nconst COPY_CONFIRMATION_DURATION_MS = 1200;\nconst DEFAULT_COPY_TOOLTIP_LABEL = 'Copy ID';\nconst HREF_VALIDATION_BASE_URL = 'https://withpersona.com';\nconst TECHNICAL_TEXT_FONT = `${Typography.TextMono.fontWeight} ${Typography.TextExtraSmall.fontSize} ${Typography.TextMono.fontFamily}`;\n\nconst semanticRestFill = (tokens: SemanticTokens, variant: TechnicalStickerVariant) =>\n variant === 'white' ? tokens.FeedbackNeutralInverse : tokens.FeedbackNeutral1;\n\nconst restFill = (theme: MaybeSemanticTheme, variant: TechnicalStickerVariant) => {\n const tokens = semanticTokens(theme);\n if (tokens) {\n return semanticRestFill(tokens, variant);\n }\n return variant === 'white' ? Color.BackgroundLabelWhite : Color.BackgroundLabelGrey;\n};\n\nconst hoverFill = (theme: MaybeSemanticTheme, variant: TechnicalStickerVariant) =>\n variant === 'white'\n ? semanticColor(theme, 'FeedbackNeutral1', Color.BackgroundButtonInverseHover)\n : semanticColor(theme, 'ActionNeutralActive', Color.BackgroundLabelGreyHover);\n\nconst isSafeTechnicalStickerHref = (href: string) => {\n try {\n const url = new URL(href, HREF_VALIDATION_BASE_URL);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n};\n\nconst TechnicalStickerShell = styled.div<{\n variant: TechnicalStickerVariant;\n disabled?: boolean;\n $width?: number | string;\n}>`\n display: inline-flex;\n align-items: center;\n white-space: nowrap;\n\n border-radius: ${BorderRadius.Sm};\n height: 1rem;\n width: ${({ $width }) => (typeof $width === 'number' ? `${$width}px` : ($width ?? 'auto'))};\n max-width: 100%;\n box-sizing: border-box;\n\n color: ${({ theme, disabled }) =>\n disabled\n ? semanticColor(theme, 'FgDisabled', theme.color.text.disabled)\n : semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n background: ${({ theme, variant, disabled }) => {\n const tokens = semanticTokens(theme);\n return tokens && disabled\n ? withAlpha(semanticRestFill(tokens, variant), tokens.Opacity65)\n : restFill(theme, variant);\n }};\n\n position: relative;\n overflow: hidden;\n border: 1px solid ${({ theme }) => semanticColor(theme, 'BorderDefault', Color.BorderInputDefault)};\n\n ${({ theme, variant, disabled }) =>\n !disabled &&\n css`\n &:hover {\n background: ${hoverFill(theme, variant)};\n }\n `}\n`;\n\nconst labelContainerStyles = css`\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1 1 auto;\n min-width: 0;\n padding: 0 ${Spacing[1]};\n`;\n\nconst LabelContainer = styled.div`\n ${labelContainerStyles}\n`;\n\nconst LabelLink = styled.a`\n ${labelContainerStyles}\n color: inherit;\n text-decoration: none;\n`;\n\nconst TechnicalText = styled(MiddleTruncatedText)<{\n $isLinkEnabled: boolean;\n $isTruncated: boolean;\n}>`\n ${Typography.TextMono};\n font-size: ${Typography.TextExtraSmall.fontSize};\n line-height: ${Typography.TextExtraSmall.lineHeight};\n text-align: center;\n\n ${({ $isLinkEnabled, $isTruncated }) =>\n $isTruncated &&\n css`\n cursor: ${$isLinkEnabled ? 'pointer' : 'default'};\n user-select: none;\n\n & > span {\n user-select: none;\n }\n `}\n`;\n\nconst CopyActions = styled.div<{ $visible: boolean }>`\n position: absolute;\n top: 0;\n right: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n height: 16px;\n opacity: ${({ $visible }) => ($visible ? 1 : 0)};\n pointer-events: ${({ $visible }) => ($visible ? 'auto' : 'none')};\n transition: opacity 120ms ease-in-out;\n\n /* Keyboard focus keeps the actions reachable, but a click also focuses the\n button — matching plain :focus-within would leave them visible after the\n pointer moves away. */\n &:has(:focus-visible) {\n opacity: 1;\n pointer-events: auto;\n }\n`;\n\nconst CopyGradient = styled.div<{ $background: string }>`\n width: 8px;\n height: 16px;\n background: linear-gradient(to left, ${({ $background }) => $background}, transparent);\n`;\n\nconst CopyButton = styled.button<{ $background: string }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0 2px 0 0;\n border: none;\n background: ${({ $background }) => $background};\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.BorderIconPrimary)};\n cursor: pointer;\n\n &:disabled {\n cursor: not-allowed;\n }\n\n &${isHovered}:not(:disabled) {\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n }\n`;\n\nexport interface TechnicalStickerProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n /** Full untruncated technical value displayed in the sticker. */\n children: string;\n /** Visual style for the technical sticker. Default: `grey`. */\n variant?: TechnicalStickerVariant;\n /** Renders disabled style and disables copy/link interaction. */\n disabled?: boolean;\n /** Opens in a new tab when the sticker body is clicked. */\n href?: string;\n /**\n * Hover tooltip for the sticker body. Shown when text is truncated or when set explicitly.\n * Defaults to the untruncated `children` string when shown.\n */\n tooltipLabel?: string;\n /**\n * Hover tooltip for the copy icon.\n * Defaults to `Copy ID`.\n */\n copyTooltipLabel?: string;\n /**\n * Confirmation label shown in the copy tooltip after a successful copy.\n * Defaults to `Copied!`.\n */\n copyConfirmationLabel?: string;\n /** Whether to show the hover copy action. Default: true. */\n copyable?: boolean;\n /** Value copied to the clipboard. Defaults to `children`. */\n copyValue?: string;\n /** Width of the sticker. Numbers are interpreted as pixels. */\n width?: number | string;\n /** Max width for middle truncation. Default: '96px'. */\n maxWidth?: number | string;\n}\n\nexport const TechnicalSticker = ({\n variant = 'grey',\n href,\n tooltipLabel: tooltipLabelProp,\n copyTooltipLabel = DEFAULT_COPY_TOOLTIP_LABEL,\n copyConfirmationLabel = COPY_CONFIRMATION_TEXT,\n copyable = true,\n copyValue,\n width,\n maxWidth = '96px',\n children,\n disabled,\n onMouseEnter,\n onMouseLeave,\n ...stickerProps\n}: TechnicalStickerProps) => {\n const [isHoveredState, setIsHoveredState] = useState(false);\n const [isCopyButtonKeyboardFocused, setIsCopyButtonKeyboardFocused] = useState(false);\n const [isTruncated, setIsTruncated] = useState(false);\n const [isCopyTooltipOpen, setIsCopyTooltipOpen] = useState(false);\n const [copyConfirmationOpen, { enable: showCopyConfirmation, disable: hideCopyConfirmation }] =\n useToggle(false);\n const copyConfirmationTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const isPointerFocusRef = useRef(false);\n const copyRequestIdRef = useRef(0);\n\n const tooltipLabel = tooltipLabelProp ?? children;\n const hasCustomTooltipLabel = tooltipLabelProp != null;\n\n const theme = useTheme();\n const hoverBackground = hoverFill(theme, variant);\n const copyActionBackground = isHoveredState ? hoverBackground : restFill(theme, variant);\n const showCopyActions =\n copyable &&\n !disabled &&\n (isHoveredState || isCopyButtonKeyboardFocused || copyConfirmationOpen);\n const showStickerTooltip = tooltipLabel.length > 0 && (isTruncated || hasCustomTooltipLabel);\n const isCopyTooltipVisible = isCopyTooltipOpen || copyConfirmationOpen;\n const isLinkEnabled = href != null && !disabled && isSafeTechnicalStickerHref(href);\n\n const handleCopyTooltipOpenChange = useCallback(\n (open: boolean) => {\n if (copyConfirmationOpen) {\n return;\n }\n\n setIsCopyTooltipOpen(open);\n },\n [copyConfirmationOpen],\n );\n\n const dismissCopyConfirmation = useCallback(() => {\n // Writing to the clipboard is async, so a copy still in flight would\n // otherwise surface its confirmation after the dismissal.\n copyRequestIdRef.current += 1;\n\n if (copyConfirmationTimerRef.current) {\n clearTimeout(copyConfirmationTimerRef.current);\n copyConfirmationTimerRef.current = null;\n }\n\n setIsCopyTooltipOpen(false);\n hideCopyConfirmation();\n }, [hideCopyConfirmation]);\n\n const handleCopy = useCallback(\n async (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (disabled) {\n return;\n }\n\n const requestId = ++copyRequestIdRef.current;\n const copyWasSuccessful = await copyTextToClipboard(copyValue ?? children);\n if (!copyWasSuccessful || requestId !== copyRequestIdRef.current) {\n return;\n }\n\n setIsCopyTooltipOpen(true);\n showCopyConfirmation();\n if (copyConfirmationTimerRef.current) {\n clearTimeout(copyConfirmationTimerRef.current);\n }\n copyConfirmationTimerRef.current = setTimeout(() => {\n setIsCopyTooltipOpen(false);\n hideCopyConfirmation();\n copyConfirmationTimerRef.current = null;\n }, COPY_CONFIRMATION_DURATION_MS);\n },\n [children, copyValue, disabled, hideCopyConfirmation, showCopyConfirmation],\n );\n\n useEffect(\n () => () => {\n if (copyConfirmationTimerRef.current) {\n clearTimeout(copyConfirmationTimerRef.current);\n }\n },\n [],\n );\n\n // Clicking an already keyboard-focused button fires no second focus event, so\n // pointer input has to retire the keyboard state itself.\n const handleCopyButtonMouseDown = () => {\n isPointerFocusRef.current = true;\n setIsCopyButtonKeyboardFocused(false);\n };\n\n // A click focuses the button too, so treating any focus as a reason to keep\n // the actions visible would pin them open once the pointer moves away.\n const handleCopyButtonFocus = () => {\n setIsCopyButtonKeyboardFocused(!isPointerFocusRef.current);\n isPointerFocusRef.current = false;\n };\n\n const handleCopyButtonBlur = () => {\n isPointerFocusRef.current = false;\n setIsCopyButtonKeyboardFocused(false);\n };\n\n const technicalText = (\n <TechnicalText\n value={children}\n maxWidth={width ?? maxWidth}\n font={TECHNICAL_TEXT_FONT}\n onTruncatedChange={setIsTruncated}\n titleBehavior='never'\n $isLinkEnabled={isLinkEnabled}\n $isTruncated={isTruncated}\n />\n );\n\n const labelContent = isLinkEnabled ? (\n <LabelLink href={href} target='_blank' rel='noopener noreferrer'>\n {technicalText}\n </LabelLink>\n ) : (\n <LabelContainer>{technicalText}</LabelContainer>\n );\n\n const labelWithTooltip = showStickerTooltip ? (\n <Tooltip trigger={labelContent} interactive side='top' maxWidth='400px'>\n {tooltipLabel}\n </Tooltip>\n ) : (\n labelContent\n );\n\n return (\n <TechnicalStickerShell\n {...stickerProps}\n variant={variant}\n disabled={disabled}\n $width={width}\n onMouseEnter={(event) => {\n onMouseEnter?.(event);\n setIsHoveredState(true);\n }}\n onMouseLeave={(event) => {\n onMouseLeave?.(event);\n setIsHoveredState(false);\n if (!isCopyButtonKeyboardFocused) {\n // Otherwise a click's focus lingers on a button that is now hidden.\n copyButtonRef.current?.blur();\n dismissCopyConfirmation();\n }\n }}\n >\n {labelWithTooltip}\n {copyable && (\n <CopyActions $visible={showCopyActions}>\n <CopyGradient $background={copyActionBackground} />\n <Tooltip\n open={isCopyTooltipVisible}\n onOpenChange={handleCopyTooltipOpenChange}\n trigger={\n <CopyButton\n ref={copyButtonRef}\n type='button'\n aria-label='Copy'\n disabled={disabled}\n $background={copyActionBackground}\n onClick={handleCopy}\n onMouseDown={handleCopyButtonMouseDown}\n onBlur={handleCopyButtonBlur}\n onFocus={handleCopyButtonFocus}\n >\n <CopyIcon />\n </CopyButton>\n }\n interactive={false}\n side='top'\n >\n {copyConfirmationOpen ? copyConfirmationLabel : copyTooltipLabel}\n </Tooltip>\n </CopyActions>\n )}\n </TechnicalStickerShell>\n );\n};\n\nexport default TechnicalSticker;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Text-D0vEReED.mjs","names":[],"sources":["../src/components/Text/Text.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ComponentType, FC, PropsWithChildren } from 'react';\nimport styled from 'styled-components';\n\nimport { type MaybeSemanticTheme, semanticColor } from '
|
|
1
|
+
{"version":3,"file":"Text-D0vEReED.mjs","names":[],"sources":["../src/components/Text/Text.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ComponentType, FC, PropsWithChildren } from 'react';\nimport styled from 'styled-components';\n\nimport { type MaybeSemanticTheme, semanticColor } from '#src/lib/semanticColor';\nimport {\n displayMixins,\n type DisplaySize,\n fontFamilyMixin,\n headingMixins,\n type HeadingSize,\n paragraphMixins,\n type ParagraphMixinSize,\n type ParagraphSize,\n} from '#src/mixins/text';\nimport type { PersonaTheme, TextColors } from '#src/theme';\nimport type { SemanticTokens } from '#src/variables/semantic';\n\nexport interface SpanProps {\n id?: string;\n color?: keyof TextColors | null;\n 'data-test'?: string;\n}\n\nconst StyledSpan: FC<PropsWithChildren<SpanProps>> = ({ children, color, ...othersThanColor }) => (\n <span {...othersThanColor}>{children}</span>\n);\n\nconst TEXT_COLOR_TO_SEMANTIC = {\n primary: 'FgPrimary',\n secondary: 'FgSecondary',\n tertiary: 'FgTertiary',\n brand: 'FgAccentStatic',\n inverse: 'FgInverseStatic',\n disabled: 'FgDisabled',\n} as const satisfies Record<keyof TextColors, keyof SemanticTokens>;\n\nconst textColor = (theme: PersonaTheme & MaybeSemanticTheme, color: keyof TextColors | null) =>\n color == null\n ? 'inherit'\n : semanticColor(theme, TEXT_COLOR_TO_SEMANTIC[color], theme.color.text[color]);\n\n/**\n * Base class of all Text components.\n */\nexport const Span = styled(StyledSpan)`\n color: ${({ color = 'primary', theme }) => textColor(theme, color)};\n ${fontFamilyMixin};\n`;\n\nexport interface DisplayProps {\n size: DisplaySize;\n}\n\nexport const Display = styled(Span).attrs(() => ({ as: 'h1' }))<DisplayProps>`\n ${({ size }) => displayMixins[size]}\n`;\n\nexport interface HeadingProps\n extends\n Omit<ComponentPropsWithoutRef<'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'>, 'color'>,\n SpanProps {\n size: HeadingSize;\n as?: string | ComponentType<any>;\n}\n\nconst HeadingComponent = styled(Span)<HeadingProps>`\n ${({ size }) => headingMixins[size]}\n`;\n\n// Needs a wrapper to support chaining .attrs without overwriting `as: size`\n// This is a bug with styled components when chaining .attrs where the inner\n// .attr cannot access values passed by the outer .attr.\nexport const Heading: FC<HeadingProps> = ({ as, size, ...props }) => {\n return <HeadingComponent as={as || 'h3'} size={size} {...props} />;\n};\n\nexport interface ParagraphProps extends Omit<ComponentPropsWithoutRef<'p'>, 'color'>, SpanProps {\n size?: ParagraphSize;\n weight?: 'bold' | 'normal' | 'light';\n as?: string | ComponentType<any>;\n}\n\nexport const Paragraph = styled(Span).attrs<ParagraphProps>(({ as = 'p' }) => ({\n as,\n}))<ParagraphProps>`\n ${({ size = 'md', weight = 'normal' }) => {\n if (weight !== 'normal') {\n if (!['sm', 'md', 'lg'].includes(size) || (size === 'sm' && weight === 'light')) {\n console.error(`Size '${size}' does not exist for weight '${weight}'.`);\n } else {\n return paragraphMixins[\n (size + weight.charAt(0).toUpperCase() + weight.slice(1)) as ParagraphMixinSize\n ];\n }\n }\n\n return paragraphMixins[size];\n }}\n /* Unlike the other text components, Paragraph defaults to the secondary text color. */\n color: ${({ color = 'secondary', theme }) => textColor(theme, color)};\n`;\n\nexport interface LabelProps extends Omit<ComponentPropsWithoutRef<'label'>, 'color'>, SpanProps {\n size?: ParagraphSize;\n weight?: 'bold' | 'normal' | 'light';\n 'data-test'?: string;\n}\n\nexport const Label = styled(Paragraph).attrs<LabelProps>({\n as: 'label',\n})<LabelProps>`\n color: ${({ color = 'primary', theme }) => textColor(theme, color)};\n`;\n\nexport const TabularNumber = styled(Paragraph)`\n font-variant-numeric: tabular-nums;\n color: ${({ color = 'primary', theme }) => textColor(theme, color)};\n`;\n"],"mappings":";;;;;AAuBA,MAAM,cAAgD,EAAE,UAAU,OAAO,GAAG,sBAC1E,oBAAC,QAAD;CAAM,GAAI;CAAkB;CAAgB,CAAA;AAG9C,MAAM,yBAAyB;CAC7B,SAAS;CACT,WAAW;CACX,UAAU;CACV,OAAO;CACP,SAAS;CACT,UAAU;CACX;AAED,MAAM,aAAa,OAA0C,UAC3D,SAAS,OACL,YACA,cAAc,OAAO,uBAAuB,QAAQ,MAAM,MAAM,KAAK,OAAO;;;;AAKlF,MAAa,OAAO,OAAO,WAAW;YAC1B,EAAE,QAAQ,WAAW,YAAY,UAAU,OAAO,MAAM,CAAC;IACjE,gBAAgB;;AAOpB,MAAa,UAAU,OAAO,KAAK,CAAC,aAAa,EAAE,IAAI,MAAM,EAAE;KAC1D,EAAE,WAAW,cAAc,MAAM;;AAWtC,MAAM,mBAAmB,OAAO,KAAK;KAChC,EAAE,WAAW,cAAc,MAAM;;AAMtC,MAAa,WAA6B,EAAE,IAAI,MAAM,GAAG,YAAY;AACnE,QAAO,oBAAC,kBAAD;EAAkB,IAAI,MAAM;EAAY;EAAM,GAAI;EAAS,CAAA;;AASpE,MAAa,YAAY,OAAO,KAAK,CAAC,OAAuB,EAAE,KAAK,WAAW,EAC7E,IACD,EAAE;KACE,EAAE,OAAO,MAAM,SAAS,eAAe;AACxC,KAAI,WAAW,SACb,KAAI,CAAC;EAAC;EAAM;EAAM;EAAK,CAAC,SAAS,KAAK,IAAK,SAAS,QAAQ,WAAW,QACrE,SAAQ,MAAM,SAAS,KAAK,+BAA+B,OAAO,IAAI;KAEtE,QAAO,gBACJ,OAAO,OAAO,OAAO,EAAE,CAAC,aAAa,GAAG,OAAO,MAAM,EAAE;AAK9D,QAAO,gBAAgB;EACvB;;YAEQ,EAAE,QAAQ,aAAa,YAAY,UAAU,OAAO,MAAM,CAAC;;AASvE,MAAa,QAAQ,OAAO,UAAU,CAAC,MAAkB,EACvD,IAAI,SACL,CAAC;YACU,EAAE,QAAQ,WAAW,YAAY,UAAU,OAAO,MAAM,CAAC;;AAGrE,MAAa,gBAAgB,OAAO,UAAU;;YAElC,EAAE,QAAQ,WAAW,YAAY,UAAU,OAAO,MAAM,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextArea-Dro-HH8O.mjs","names":[],"sources":["../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import { type ComponentPropsWithoutRef, forwardRef } from 'react';\nimport styled from 'styled-components';\n\nimport useFormField from '
|
|
1
|
+
{"version":3,"file":"TextArea-Dro-HH8O.mjs","names":[],"sources":["../src/components/TextArea/TextArea.tsx"],"sourcesContent":["import { type ComponentPropsWithoutRef, forwardRef } from 'react';\nimport styled from 'styled-components';\n\nimport useFormField from '#src/components/FormControl/useFormField';\nimport inputMixin, { type InputMixinProps } from '#src/mixins/input';\nimport type { InputProps } from '#src/types/InputProps';\nimport { TransitionDuration } from '#src/variables/transitions';\n\nexport interface TextAreaProps\n extends ComponentPropsWithoutRef<'textarea'>, Omit<InputProps, 'inputSize'> {}\n\nconst TextArea = styled('textarea')<InputMixinProps>`\n ${inputMixin};\n /* Don't cut off overflow text */\n padding-bottom: 0;\n font-family: ${({ theme }) => theme.text.fontFamily.base};\n height: ${({ theme }) => theme.element.height.xl};\n white-space: pre-wrap;\n transition:\n all ${TransitionDuration.Fast},\n height 0s,\n width 0s;\n`;\n\nconst TextAreaWithStyle = forwardRef<HTMLTextAreaElement, TextAreaProps>(function TextAreaWithStyle(\n { size, ...props },\n ref,\n) {\n const { inputId } = useFormField(props);\n\n return (\n <TextArea\n id={inputId}\n aria-invalid={props.hasError === true}\n ref={ref}\n {...props}\n $size={size}\n />\n );\n});\n\nexport { TextAreaWithStyle as TextArea };\nexport default TextAreaWithStyle;\n"],"mappings":";;;;;;;AAWA,MAAM,WAAW,OAAO,WAAW;IAC/B,WAAW;;;kBAGG,EAAE,YAAY,MAAM,KAAK,WAAW,KAAK;aAC9C,EAAE,YAAY,MAAM,QAAQ,OAAO,GAAG;;;kBAGjB;;;;AAKlC,MAAM,oBAAoB,WAA+C,SAAS,kBAChF,EAAE,MAAM,GAAG,SACX,KACA;CACA,MAAM,EAAE,YAAY,aAAa,MAAM;AAEvC,QACE,oBAAC,UAAD;EACE,IAAI;EACJ,gBAAc,MAAM,aAAa;EAC5B;EACL,GAAI;EACJ,OAAO;EACP,CAAA;EAEJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toggle-D9MzTIZs.mjs","names":[],"sources":["../src/components/Toggle/Toggle.tsx"],"sourcesContent":["import { forwardRef, type ReactNode, useCallback, useRef } from 'react';\nimport { useId } from 'react-aria';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport useFormField from 'design-system/components/FormControl/useFormField';\nimport { Label } from 'design-system/components/Text';\nimport { opacityOf } from 'design-system/lib/color';\nimport { isDisabled, isHovered, isNotDisabled } from 'design-system/lib/pseudoClass';\nimport { semanticColor, semanticOnly, semanticTokens } from 'design-system/lib/semanticColor';\nimport useToggle from 'design-system/lib/useToggle';\nimport { focusOutlineControlled } from 'design-system/mixins/focus';\nimport { TransitionDuration } from 'design-system/variables/transitions';\n\ntype ToggleSize = 'md' | 'sm';\n\ninterface SwitchSizes {\n width: number;\n height: number;\n}\n\nconst SWITCH_SIZES: Record<ToggleSize, SwitchSizes> = {\n md: { width: 32, height: 18 },\n sm: { width: 28, height: parseInt(Spacing[4], 10) }, // 16px height from tokens\n};\n\ninterface SliderSizes {\n diameter: number;\n offset: number;\n}\n\nconst SLIDER_SIZES: Record<ToggleSize, SliderSizes> = {\n md: { diameter: 14, offset: 2 },\n sm: { diameter: parseInt(Spacing[3], 10), offset: 2 }, // 12px diameter from tokens\n};\n\nconst Container = styled.div`\n display: inline-flex;\n align-items: center;\n position: relative;\n`;\n\ntype SwitchProps = Pick<ToggleProps, 'disabled'> & {\n checked: boolean;\n focused: boolean;\n size: ToggleSize;\n};\nconst Switch = styled.div<SwitchProps>`\n transition: box-shadow ${TransitionDuration.Fast};\n position: relative;\n display: inline-flex;\n height: ${({ size }) => SWITCH_SIZES[size].height}px;\n width: ${({ size }) => SWITCH_SIZES[size].width}px;\n border-radius: 1000px;\n cursor: pointer;\n &${isDisabled} {\n cursor: not-allowed;\n }\n\n ${focusOutlineControlled}\n\n /* Background */\n &:before {\n position: absolute;\n content: '';\n height: ${({ size }) => SWITCH_SIZES[size].height}px;\n width: ${({ size }) => SWITCH_SIZES[size].width}px;\n top: 0;\n right: 0;\n bottom: 0;\n background-color: ${({ theme, checked, disabled }) => {\n const tokens = semanticTokens(theme);\n if (tokens) {\n if (disabled) {\n return checked ? tokens.InputSurfaceAccentDisabled : tokens.BorderDivider;\n }\n return checked ? tokens.InputSurfaceAccent : tokens.InputBorderStrong;\n }\n if (disabled) {\n return checked ? Color.BackgroundInputActiveDisabled : Color.BackgroundInputDisabled;\n }\n return checked ? Color.BackgroundInputActive : Color.BackgroundInputToggle;\n }};\n\n transition: ${TransitionDuration.Medium};\n border-radius: 1000px;\n\n ${(props) =>\n !props.checked && props.disabled\n ? semanticOnly((tokens) => `opacity: ${opacityOf(tokens.Opacity65)};`)(props)\n : ''}\n }\n\n &${isHovered}${isNotDisabled}:before {\n background-color: ${({ theme, checked }) =>\n checked\n ? semanticColor(theme, 'InputSurfaceAccentHover', Color.BackgroundInputActiveHover)\n : semanticColor(theme, 'InputBorderHoverStrong', Color.BackgroundInputToggleHover)};\n }\n\n /* Slider thumb */\n &:after {\n position: absolute;\n content: '';\n height: ${({ size }) => SLIDER_SIZES[size].diameter}px;\n width: ${({ size }) => SLIDER_SIZES[size].diameter}px;\n bottom: ${({ size }) => SLIDER_SIZES[size].offset}px;\n background-color: ${({ theme }) => semanticColor(theme, 'InputSurfaceInverseStatic', Color.BackgroundInputDefault)};\n transition: ${TransitionDuration.Medium};\n border-radius: 1000px;\n\n right: ${({ size }) => SLIDER_SIZES[size].offset}px;\n\n ${({ checked, size }) =>\n !checked &&\n css`\n transform: translateX(-${getSlideDistance(size)}px);\n `}\n\n ${(props) =>\n props.disabled\n ? semanticOnly((tokens) => `opacity: ${opacityOf(tokens.Opacity65)};`)(props)\n : ''}\n }\n`;\n\nconst ToggleLabel = styled(Label)<Pick<ToggleProps, 'disabled' | 'size'>>`\n cursor: ${({ disabled }) => (disabled ? 'initial' : 'pointer')};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.TextSecondary)};\n\n padding: 0 ${Spacing[2]};\n white-space: nowrap;\n line-height: ${({ size = 'md' }) => `${SWITCH_SIZES[size].height}px`};\n\n ${({ theme, disabled }) =>\n disabled &&\n css`\n color: ${semanticColor(theme, 'FgDisabled', theme.color.text.disabled)};\n `}\n`;\n\nfunction getSlideDistance(size: ToggleSize) {\n const switchSize = SWITCH_SIZES[size];\n const sliderSize = SLIDER_SIZES[size];\n return switchSize.width - sliderSize.diameter - sliderSize.offset * 2;\n}\n\nconst HiddenInput = styled.input`\n height: 0;\n width: 0;\n margin: -1px;\n border: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n position: absolute;\n`;\n\nexport interface ToggleProps {\n className?: string;\n /** Disables interaction and renders the toggle in a muted style. */\n disabled?: boolean;\n /** Marks the switch as required (sets aria-required). */\n required?: boolean;\n /**\n * Tooltip / title shown on the root element when the toggle is off.\n * @defaultValue 'Off'\n */\n titleOff?: string;\n /**\n * Tooltip / title shown on the root element when the toggle is on.\n * @defaultValue 'On'\n */\n titleOn?: string;\n /**\n * Called with the new boolean value when the user clicks the toggle.\n * The component is fully controlled — you must update `value` in response.\n */\n onChange?: (value: boolean) => void;\n /**\n * Current on/off state. Falsy values (`false`, `null`, `undefined`, `''`)\n * are treated as off; `true` is treated as on.\n */\n value: boolean | null | undefined | '';\n /** `id` forwarded to the visible switch element. */\n id?: string;\n /** Label node rendered to the left of the switch when the toggle is on. */\n labelOn?: ReactNode;\n /**\n * Label node rendered to the left of the switch when the toggle is off.\n * Falls back to `labelOn` when not provided.\n */\n labelOff?: ReactNode;\n 'data-test'?: string;\n /**\n * Accessible label for the hidden `<input role=\"switch\">`.\n * Required when no visible label is provided via `labelOn` / `labelOff`.\n */\n 'aria-label'?: string;\n /**\n * Size of the toggle switch.\n * @defaultValue 'md'\n */\n size?: ToggleSize;\n}\n\nexport const Toggle = forwardRef<HTMLDivElement, ToggleProps>(function Toggle(\n {\n className,\n disabled,\n required,\n titleOff = 'Off',\n titleOn = 'On',\n onChange = () => undefined,\n value,\n id,\n labelOn,\n labelOff,\n 'data-test': dataTest,\n 'aria-label': ariaLabel,\n size = 'md',\n },\n ref,\n) {\n const field = useFormField({ disabled });\n const generatedId = useId();\n const label = value ? labelOn : labelOff || labelOn;\n\n const [focused, { enable: setFocus, disable: clearFocus }] = useToggle();\n\n const handleChange = useCallback(() => {\n onChange(!value);\n inputRef.current?.focus();\n }, [onChange, value]);\n\n const inputRef = useRef<HTMLInputElement>();\n\n return (\n <Container\n className={className}\n data-test={dataTest}\n title={value ? titleOn : titleOff}\n ref={ref}\n >\n {label != null && (\n <ToggleLabel htmlFor={generatedId} disabled={field.disabled} size={size}>\n {label}\n </ToggleLabel>\n )}\n <Switch\n id={id}\n checked={!!value}\n disabled={field.disabled}\n focused={focused}\n onClick={field.disabled ? undefined : handleChange}\n size={size}\n />\n <HiddenInput\n id={generatedId}\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n ref={inputRef}\n data-test-toggle-status={value ? 'on' : 'off'}\n disabled={field.disabled}\n type='checkbox'\n checked={!!value}\n readOnly={true}\n onChange={disabled ? undefined : handleChange}\n onFocus={setFocus}\n onBlur={clearFocus}\n aria-checked={!!value}\n role='switch'\n aria-readonly={field.disabled}\n aria-required={required || undefined}\n {...(label\n ? { 'aria-labelledby': generatedId }\n : { 'aria-label': ariaLabel ?? (value ? 'Toggle on' : 'Toggle off') })}\n />\n </Container>\n );\n});\n\nexport default Toggle;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Toggle-D9MzTIZs.mjs","names":[],"sources":["../src/components/Toggle/Toggle.tsx"],"sourcesContent":["import { forwardRef, type ReactNode, useCallback, useRef } from 'react';\nimport { useId } from 'react-aria';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\n\nimport useFormField from '#src/components/FormControl/useFormField';\nimport { Label } from '#src/components/Text';\nimport { opacityOf } from '#src/lib/color';\nimport { isDisabled, isHovered, isNotDisabled } from '#src/lib/pseudoClass';\nimport { semanticColor, semanticOnly, semanticTokens } from '#src/lib/semanticColor';\nimport useToggle from '#src/lib/useToggle';\nimport { focusOutlineControlled } from '#src/mixins/focus';\nimport { TransitionDuration } from '#src/variables/transitions';\n\ntype ToggleSize = 'md' | 'sm';\n\ninterface SwitchSizes {\n width: number;\n height: number;\n}\n\nconst SWITCH_SIZES: Record<ToggleSize, SwitchSizes> = {\n md: { width: 32, height: 18 },\n sm: { width: 28, height: parseInt(Spacing[4], 10) }, // 16px height from tokens\n};\n\ninterface SliderSizes {\n diameter: number;\n offset: number;\n}\n\nconst SLIDER_SIZES: Record<ToggleSize, SliderSizes> = {\n md: { diameter: 14, offset: 2 },\n sm: { diameter: parseInt(Spacing[3], 10), offset: 2 }, // 12px diameter from tokens\n};\n\nconst Container = styled.div`\n display: inline-flex;\n align-items: center;\n position: relative;\n`;\n\ntype SwitchProps = Pick<ToggleProps, 'disabled'> & {\n checked: boolean;\n focused: boolean;\n size: ToggleSize;\n};\nconst Switch = styled.div<SwitchProps>`\n transition: box-shadow ${TransitionDuration.Fast};\n position: relative;\n display: inline-flex;\n height: ${({ size }) => SWITCH_SIZES[size].height}px;\n width: ${({ size }) => SWITCH_SIZES[size].width}px;\n border-radius: 1000px;\n cursor: pointer;\n &${isDisabled} {\n cursor: not-allowed;\n }\n\n ${focusOutlineControlled}\n\n /* Background */\n &:before {\n position: absolute;\n content: '';\n height: ${({ size }) => SWITCH_SIZES[size].height}px;\n width: ${({ size }) => SWITCH_SIZES[size].width}px;\n top: 0;\n right: 0;\n bottom: 0;\n background-color: ${({ theme, checked, disabled }) => {\n const tokens = semanticTokens(theme);\n if (tokens) {\n if (disabled) {\n return checked ? tokens.InputSurfaceAccentDisabled : tokens.BorderDivider;\n }\n return checked ? tokens.InputSurfaceAccent : tokens.InputBorderStrong;\n }\n if (disabled) {\n return checked ? Color.BackgroundInputActiveDisabled : Color.BackgroundInputDisabled;\n }\n return checked ? Color.BackgroundInputActive : Color.BackgroundInputToggle;\n }};\n\n transition: ${TransitionDuration.Medium};\n border-radius: 1000px;\n\n ${(props) =>\n !props.checked && props.disabled\n ? semanticOnly((tokens) => `opacity: ${opacityOf(tokens.Opacity65)};`)(props)\n : ''}\n }\n\n &${isHovered}${isNotDisabled}:before {\n background-color: ${({ theme, checked }) =>\n checked\n ? semanticColor(theme, 'InputSurfaceAccentHover', Color.BackgroundInputActiveHover)\n : semanticColor(theme, 'InputBorderHoverStrong', Color.BackgroundInputToggleHover)};\n }\n\n /* Slider thumb */\n &:after {\n position: absolute;\n content: '';\n height: ${({ size }) => SLIDER_SIZES[size].diameter}px;\n width: ${({ size }) => SLIDER_SIZES[size].diameter}px;\n bottom: ${({ size }) => SLIDER_SIZES[size].offset}px;\n background-color: ${({ theme }) => semanticColor(theme, 'InputSurfaceInverseStatic', Color.BackgroundInputDefault)};\n transition: ${TransitionDuration.Medium};\n border-radius: 1000px;\n\n right: ${({ size }) => SLIDER_SIZES[size].offset}px;\n\n ${({ checked, size }) =>\n !checked &&\n css`\n transform: translateX(-${getSlideDistance(size)}px);\n `}\n\n ${(props) =>\n props.disabled\n ? semanticOnly((tokens) => `opacity: ${opacityOf(tokens.Opacity65)};`)(props)\n : ''}\n }\n`;\n\nconst ToggleLabel = styled(Label)<Pick<ToggleProps, 'disabled' | 'size'>>`\n cursor: ${({ disabled }) => (disabled ? 'initial' : 'pointer')};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.TextSecondary)};\n\n padding: 0 ${Spacing[2]};\n white-space: nowrap;\n line-height: ${({ size = 'md' }) => `${SWITCH_SIZES[size].height}px`};\n\n ${({ theme, disabled }) =>\n disabled &&\n css`\n color: ${semanticColor(theme, 'FgDisabled', theme.color.text.disabled)};\n `}\n`;\n\nfunction getSlideDistance(size: ToggleSize) {\n const switchSize = SWITCH_SIZES[size];\n const sliderSize = SLIDER_SIZES[size];\n return switchSize.width - sliderSize.diameter - sliderSize.offset * 2;\n}\n\nconst HiddenInput = styled.input`\n height: 0;\n width: 0;\n margin: -1px;\n border: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n position: absolute;\n`;\n\nexport interface ToggleProps {\n className?: string;\n /** Disables interaction and renders the toggle in a muted style. */\n disabled?: boolean;\n /** Marks the switch as required (sets aria-required). */\n required?: boolean;\n /**\n * Tooltip / title shown on the root element when the toggle is off.\n * @defaultValue 'Off'\n */\n titleOff?: string;\n /**\n * Tooltip / title shown on the root element when the toggle is on.\n * @defaultValue 'On'\n */\n titleOn?: string;\n /**\n * Called with the new boolean value when the user clicks the toggle.\n * The component is fully controlled — you must update `value` in response.\n */\n onChange?: (value: boolean) => void;\n /**\n * Current on/off state. Falsy values (`false`, `null`, `undefined`, `''`)\n * are treated as off; `true` is treated as on.\n */\n value: boolean | null | undefined | '';\n /** `id` forwarded to the visible switch element. */\n id?: string;\n /** Label node rendered to the left of the switch when the toggle is on. */\n labelOn?: ReactNode;\n /**\n * Label node rendered to the left of the switch when the toggle is off.\n * Falls back to `labelOn` when not provided.\n */\n labelOff?: ReactNode;\n 'data-test'?: string;\n /**\n * Accessible label for the hidden `<input role=\"switch\">`.\n * Required when no visible label is provided via `labelOn` / `labelOff`.\n */\n 'aria-label'?: string;\n /**\n * Size of the toggle switch.\n * @defaultValue 'md'\n */\n size?: ToggleSize;\n}\n\nexport const Toggle = forwardRef<HTMLDivElement, ToggleProps>(function Toggle(\n {\n className,\n disabled,\n required,\n titleOff = 'Off',\n titleOn = 'On',\n onChange = () => undefined,\n value,\n id,\n labelOn,\n labelOff,\n 'data-test': dataTest,\n 'aria-label': ariaLabel,\n size = 'md',\n },\n ref,\n) {\n const field = useFormField({ disabled });\n const generatedId = useId();\n const label = value ? labelOn : labelOff || labelOn;\n\n const [focused, { enable: setFocus, disable: clearFocus }] = useToggle();\n\n const handleChange = useCallback(() => {\n onChange(!value);\n inputRef.current?.focus();\n }, [onChange, value]);\n\n const inputRef = useRef<HTMLInputElement>();\n\n return (\n <Container\n className={className}\n data-test={dataTest}\n title={value ? titleOn : titleOff}\n ref={ref}\n >\n {label != null && (\n <ToggleLabel htmlFor={generatedId} disabled={field.disabled} size={size}>\n {label}\n </ToggleLabel>\n )}\n <Switch\n id={id}\n checked={!!value}\n disabled={field.disabled}\n focused={focused}\n onClick={field.disabled ? undefined : handleChange}\n size={size}\n />\n <HiddenInput\n id={generatedId}\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n ref={inputRef}\n data-test-toggle-status={value ? 'on' : 'off'}\n disabled={field.disabled}\n type='checkbox'\n checked={!!value}\n readOnly={true}\n onChange={disabled ? undefined : handleChange}\n onFocus={setFocus}\n onBlur={clearFocus}\n aria-checked={!!value}\n role='switch'\n aria-readonly={field.disabled}\n aria-required={required || undefined}\n {...(label\n ? { 'aria-labelledby': generatedId }\n : { 'aria-label': ariaLabel ?? (value ? 'Toggle on' : 'Toggle off') })}\n />\n </Container>\n );\n});\n\nexport default Toggle;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip-YViXzMdm.mjs","names":["Card","CircleHelpIconSmall"],"sources":["../src/components/Tooltip/Tooltip.tsx","../src/components/Tooltip/HelperTooltip.tsx","../src/components/Tooltip/TextUnderlineTooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport {\n Children,\n cloneElement,\n type ComponentPropsWithoutRef,\n type ComponentType,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport styled, { type DefaultTheme, type StyledComponent } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport Card, { type CardProps } from 'design-system/components/Card';\nimport { semanticColor, semanticOnly } from 'design-system/lib/semanticColor';\nimport { paragraphMixins } from 'design-system/mixins/text';\nimport { fadeIn } from 'design-system/variables/keyframes';\nimport { TransitionDuration } from 'design-system/variables/transitions';\n\ninterface FloatingTooltipProps extends CardProps {\n zIndex?: number;\n contentAlignment: 'start' | 'center' | 'end';\n maxWidth?: string;\n size?: 'sm' | 'md';\n}\n\nexport const FloatingTooltip: StyledComponent<\n ComponentType<ComponentPropsWithoutRef<typeof Card>>,\n DefaultTheme,\n FloatingTooltipProps\n> = styled(Card)<FloatingTooltipProps>`\n ${({ size = 'md' }) => (size === 'sm' ? paragraphMixins.sm : paragraphMixins.md)};\n line-height: ${({ size = 'md' }) => (size === 'sm' ? '16px' : '20px')};\n box-shadow: 0px 0px 14px 2px rgba(0, 0, 0, 0.12);\n border-radius: 4px;\n display: flex;\n align-items: ${({ contentAlignment }) => contentAlignment || 'center'};\n justify-content: center;\n padding: 6px ${Spacing[2]};\n animation: ${fadeIn} ${TransitionDuration.Fast} ease-in-out;\n z-index: ${({ zIndex }) => zIndex};\n margin: 0;\n max-width: ${({ maxWidth }) => maxWidth || '250px'};\n ${semanticOnly((tokens) => `background-color: ${tokens.SurfaceElevated};`)}\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n`;\n\nconst TooltipArrow = styled.div`\n width: 0;\n height: 0;\n border-color: ${({ theme }) => semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n border-left: 8px solid transparent;\n border-top: 8px solid ${({ theme }) => semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n border-right: 8px solid transparent;\n`;\n\nconst TooltipIcon = styled.div`\n display: inline-flex;\n`;\n\ninterface TooltipBaseProps\n extends\n Omit<TooltipPrimitive.TooltipProps, 'disableHoverableContent'>,\n TooltipPrimitive.TooltipContentProps {\n /**\n * Optionally hide tooltip arrow.\n */\n hideArrow?: boolean;\n\n children?: ReactNode;\n\n /**\n * Disabling will prevent tooltip from rendering on the trigger\n */\n disabled?: boolean;\n\n /**\n * Render in a portal.\n * Disable to render adjacent to trigger for rendering within elements such as modals\n */\n portal?: boolean;\n\n /**\n * Props applied to Radix UI Portal component\n */\n portalProps?: TooltipPrimitive.TooltipPortalProps;\n\n /**\n * Determines if the tooltip closes when the mouse hovers into the tooltip content area\n */\n interactive?: boolean;\n\n /**\n * Override the zIndex in case the tooltip is used in situations where the content is\n * already elevated\n */\n zIndex?: number;\n\n /**\n * Max width of the contents in the tooltip\n */\n maxWidth?: string;\n\n /**\n * Props to apply to Tooltip.Trigger within\n */\n triggerProps?: TooltipPrimitive.TooltipTriggerProps;\n\n /**\n * Size of the tooltip. Defaults to 'md'.\n */\n size?: 'sm' | 'md';\n}\n\nexport interface TooltipStandardProps extends TooltipBaseProps {\n /**\n * Element that will trigger the tooltip. A `ref` will be set.\n */\n trigger: ReactElement;\n\n iconTrigger?: never;\n\n className?: never;\n\n contentAlignment?: 'start' | 'center' | 'end';\n}\n\nexport interface TooltipWithIconProps extends TooltipBaseProps {\n trigger?: never;\n\n /**\n * Icon that will trigger the tooltip. A wrapper div will be set.\n */\n iconTrigger: ReactElement;\n\n className?: string;\n\n contentAlignment?: 'start' | 'center' | 'end';\n}\n\ntype TooltipProps = TooltipStandardProps | TooltipWithIconProps;\n\nexport const Tooltip = ({\n trigger: triggerProp,\n iconTrigger,\n side = 'bottom',\n hideArrow,\n defaultOpen,\n open,\n delayDuration = 300,\n onOpenChange,\n interactive = true,\n children,\n 'aria-label': ariaLabel,\n portal = true,\n disabled = false,\n className,\n maxWidth,\n zIndex = 10,\n triggerProps,\n portalProps,\n contentAlignment,\n size = 'md',\n ...contentProps\n}: TooltipProps) => {\n let trigger;\n\n if (iconTrigger) {\n trigger = (\n <TooltipIcon tabIndex={0} aria-label={ariaLabel} className={className}>\n {cloneElement(iconTrigger, { focusable: false, 'aria-hidden': true })}\n </TooltipIcon>\n );\n } else {\n trigger = triggerProp;\n }\n\n // quick way to check if children are renderable. null, false, and true will be filtered out when converting to an array\n const hasRenderableChildren = Children.toArray(children).length > 0;\n\n const content = (\n <TooltipPrimitive.Content side={side} sideOffset={8} asChild {...contentProps}>\n <FloatingTooltip\n zIndex={zIndex}\n contentAlignment={contentAlignment}\n maxWidth={maxWidth}\n size={size}\n >\n {children}\n {!hideArrow && (\n <TooltipPrimitive.Arrow asChild>\n <TooltipArrow />\n </TooltipPrimitive.Arrow>\n )}\n </FloatingTooltip>\n </TooltipPrimitive.Content>\n );\n\n return (\n <TooltipPrimitive.Provider delayDuration={delayDuration}>\n <TooltipPrimitive.Root\n open={open}\n defaultOpen={defaultOpen}\n disableHoverableContent={!interactive}\n onOpenChange={onOpenChange}\n >\n <TooltipPrimitive.Trigger asChild aria-label={ariaLabel} {...triggerProps}>\n {trigger}\n </TooltipPrimitive.Trigger>\n\n {!disabled &&\n hasRenderableChildren &&\n (portal ? (\n <TooltipPrimitive.Portal {...portalProps}>{content}</TooltipPrimitive.Portal>\n ) : (\n content\n ))}\n </TooltipPrimitive.Root>\n </TooltipPrimitive.Provider>\n );\n};\n\nexport default Tooltip;\n","import type { ReactNode } from 'react';\nimport { useTheme } from 'styled-components';\n\nimport { Color } from '@persona/design-tokens';\nimport { CircleHelpIcon } from '@persona/icons';\nimport { CircleHelpIcon as CircleHelpIconSmall } from '@persona/icons/12px';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\nimport Tooltip, { type TooltipWithIconProps } from './Tooltip';\n\nexport interface HelperTooltipProps extends Omit<TooltipWithIconProps, 'iconTrigger'> {\n children: ReactNode;\n size?: 'md' | 'sm';\n}\n\n/**\n * Helper component for rendering help text via help icons.\n */\nconst HelperTooltip = ({ children, size = 'md', ...props }: HelperTooltipProps) => {\n const theme = useTheme();\n const iconColor = semanticColor(theme, 'FgSecondary', Color.BorderIconSecondary);\n return (\n <Tooltip\n size={size}\n iconTrigger={\n size === 'md' ? (\n <CircleHelpIcon color={iconColor} />\n ) : (\n <CircleHelpIconSmall color={iconColor} />\n )\n }\n {...props}\n >\n {children}\n </Tooltip>\n );\n};\n\nexport default HelperTooltip;\n","import type { ReactNode } from 'react';\nimport styled from 'styled-components';\n\nimport { Color } from '@persona/design-tokens';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\nimport Tooltip, { type TooltipStandardProps } from './Tooltip';\n\nexport const TextWithDashedUnderline = styled.span`\n text-decoration: underline;\n text-decoration-style: dashed;\n text-decoration-color: ${({ theme }) => semanticColor(theme, 'FgTertiary', Color.CoreSlate700)};\n text-underline-offset: 2px;\n text-decoration-thickness: 1px;\n width: fit-content;\n`;\n\ninterface TextUnderlineTooltipProps extends Omit<TooltipStandardProps, 'trigger' | 'iconTrigger'> {\n tooltip: ReactNode;\n}\n\nconst TextUnderlineTooltip = ({ children, tooltip, ...props }: TextUnderlineTooltipProps) => {\n return (\n <Tooltip trigger={<TextWithDashedUnderline>{children}</TextWithDashedUnderline>} {...props}>\n {tooltip}\n </Tooltip>\n );\n};\n\nexport default TextUnderlineTooltip;\n"],"mappings":";;;;;;;;;;;;;AAyBA,MAAa,kBAIT,OAAOA,aAAK;KACX,EAAE,OAAO,WAAY,SAAS,OAAO,gBAAgB,KAAK,gBAAgB,GAAI;kBACjE,EAAE,OAAO,WAAY,SAAS,OAAO,SAAS,OAAQ;;;;kBAItD,EAAE,uBAAuB,oBAAoB,SAAS;;iBAEvD,QAAQ,GAAG;eACb,OAAO,GAAA,QAA2B;cACnC,EAAE,aAAa,OAAO;;gBAEpB,EAAE,eAAe,YAAY,QAAQ;IACjD,cAAc,WAAW,qBAAqB,OAAO,gBAAgB,GAAG,CAAC;YACjE,EAAE,YAAY,cAAc,OAAO,aAAa,MAAM,YAAY,CAAC;;AAG/E,MAAM,eAAe,OAAO,GAAG;;;mBAGZ,EAAE,YAAY,cAAc,OAAO,mBAAmB,MAAM,MAAM,WAAW,QAAQ,CAAC;;2BAE9E,EAAE,YAAY,cAAc,OAAO,mBAAmB,MAAM,MAAM,WAAW,QAAQ,CAAC;;;AAIjH,MAAM,cAAc,OAAO,GAAG;;;AAsF9B,MAAa,WAAW,EACtB,SAAS,aACT,aACA,OAAO,UACP,WACA,aACA,MACA,gBAAgB,KAChB,cACA,cAAc,MACd,UACA,cAAc,WACd,SAAS,MACT,WAAW,OACX,WACA,UACA,SAAS,IACT,cACA,aACA,kBACA,OAAO,MACP,GAAG,mBACe;CAClB,IAAI;AAEJ,KAAI,YACF,WACE,oBAAC,aAAD;EAAa,UAAU;EAAG,cAAY;EAAsB;YACzD,aAAa,aAAa;GAAE,WAAW;GAAO,eAAe;GAAM,CAAC;EACzD,CAAA;KAGhB,WAAU;CAIZ,MAAM,wBAAwB,SAAS,QAAQ,SAAS,CAAC,SAAS;CAElE,MAAM,UACJ,oBAAC,iBAAiB,SAAlB;EAAgC;EAAM,YAAY;EAAG,SAAA;EAAQ,GAAI;YAC/D,qBAAC,iBAAD;GACU;GACU;GACR;GACJ;aAJR,CAMG,UACA,CAAC,aACA,oBAAC,iBAAiB,OAAlB;IAAwB,SAAA;cACtB,oBAAC,cAAD,EAAgB,CAAA;IACO,CAAA,CAEX;;EACO,CAAA;AAG7B,QACE,oBAAC,iBAAiB,UAAlB;EAA0C;YACxC,qBAAC,iBAAiB,MAAlB;GACQ;GACO;GACb,yBAAyB,CAAC;GACZ;aAJhB,CAME,oBAAC,iBAAiB,SAAlB;IAA0B,SAAA;IAAQ,cAAY;IAAW,GAAI;cAC1D;IACwB,CAAA,EAE1B,CAAC,YACA,0BACC,SACC,oBAAC,iBAAiB,QAAlB;IAAyB,GAAI;cAAc;IAAkC,CAAA,GAE7E,SAEkB;;EACE,CAAA;;;;;;;ACvMhC,MAAM,iBAAiB,EAAE,UAAU,OAAO,MAAM,GAAG,YAAgC;CAEjF,MAAM,YAAY,cADJ,UACuB,EAAE,eAAe,MAAM,oBAAoB;AAChF,QACE,oBAAC,SAAD;EACQ;EACN,aACE,SAAS,OACP,oBAAC,gBAAD,EAAgB,OAAO,WAAa,CAAA,GAEpC,oBAACC,kBAAD,EAAqB,OAAO,WAAa,CAAA;EAG7C,GAAI;EAEH;EACO,CAAA;;;;AC1Bd,MAAa,0BAA0B,OAAO,IAAI;;;4BAGtB,EAAE,YAAY,cAAc,OAAO,cAAc,MAAM,aAAa,CAAC;;;;;AAUjG,MAAM,wBAAwB,EAAE,UAAU,SAAS,GAAG,YAAuC;AAC3F,QACE,oBAAC,SAAD;EAAS,SAAS,oBAAC,yBAAD,EAA0B,UAAmC,CAAA;EAAE,GAAI;YAClF;EACO,CAAA"}
|
|
1
|
+
{"version":3,"file":"Tooltip-YViXzMdm.mjs","names":["Card","CircleHelpIconSmall"],"sources":["../src/components/Tooltip/Tooltip.tsx","../src/components/Tooltip/HelperTooltip.tsx","../src/components/Tooltip/TextUnderlineTooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport {\n Children,\n cloneElement,\n type ComponentPropsWithoutRef,\n type ComponentType,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport styled, { type DefaultTheme, type StyledComponent } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\n\nimport Card, { type CardProps } from '#src/components/Card';\nimport { semanticColor, semanticOnly } from '#src/lib/semanticColor';\nimport { paragraphMixins } from '#src/mixins/text';\nimport { fadeIn } from '#src/variables/keyframes';\nimport { TransitionDuration } from '#src/variables/transitions';\n\ninterface FloatingTooltipProps extends CardProps {\n zIndex?: number;\n contentAlignment: 'start' | 'center' | 'end';\n maxWidth?: string;\n size?: 'sm' | 'md';\n}\n\nexport const FloatingTooltip: StyledComponent<\n ComponentType<ComponentPropsWithoutRef<typeof Card>>,\n DefaultTheme,\n FloatingTooltipProps\n> = styled(Card)<FloatingTooltipProps>`\n ${({ size = 'md' }) => (size === 'sm' ? paragraphMixins.sm : paragraphMixins.md)};\n line-height: ${({ size = 'md' }) => (size === 'sm' ? '16px' : '20px')};\n box-shadow: 0px 0px 14px 2px rgba(0, 0, 0, 0.12);\n border-radius: 4px;\n display: flex;\n align-items: ${({ contentAlignment }) => contentAlignment || 'center'};\n justify-content: center;\n padding: 6px ${Spacing[2]};\n animation: ${fadeIn} ${TransitionDuration.Fast} ease-in-out;\n z-index: ${({ zIndex }) => zIndex};\n margin: 0;\n max-width: ${({ maxWidth }) => maxWidth || '250px'};\n ${semanticOnly((tokens) => `background-color: ${tokens.SurfaceElevated};`)}\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n`;\n\nconst TooltipArrow = styled.div`\n width: 0;\n height: 0;\n border-color: ${({ theme }) => semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n border-left: 8px solid transparent;\n border-top: 8px solid ${({ theme }) => semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n border-right: 8px solid transparent;\n`;\n\nconst TooltipIcon = styled.div`\n display: inline-flex;\n`;\n\ninterface TooltipBaseProps\n extends\n Omit<TooltipPrimitive.TooltipProps, 'disableHoverableContent'>,\n TooltipPrimitive.TooltipContentProps {\n /**\n * Optionally hide tooltip arrow.\n */\n hideArrow?: boolean;\n\n children?: ReactNode;\n\n /**\n * Disabling will prevent tooltip from rendering on the trigger\n */\n disabled?: boolean;\n\n /**\n * Render in a portal.\n * Disable to render adjacent to trigger for rendering within elements such as modals\n */\n portal?: boolean;\n\n /**\n * Props applied to Radix UI Portal component\n */\n portalProps?: TooltipPrimitive.TooltipPortalProps;\n\n /**\n * Determines if the tooltip closes when the mouse hovers into the tooltip content area\n */\n interactive?: boolean;\n\n /**\n * Override the zIndex in case the tooltip is used in situations where the content is\n * already elevated\n */\n zIndex?: number;\n\n /**\n * Max width of the contents in the tooltip\n */\n maxWidth?: string;\n\n /**\n * Props to apply to Tooltip.Trigger within\n */\n triggerProps?: TooltipPrimitive.TooltipTriggerProps;\n\n /**\n * Size of the tooltip. Defaults to 'md'.\n */\n size?: 'sm' | 'md';\n}\n\nexport interface TooltipStandardProps extends TooltipBaseProps {\n /**\n * Element that will trigger the tooltip. A `ref` will be set.\n */\n trigger: ReactElement;\n\n iconTrigger?: never;\n\n className?: never;\n\n contentAlignment?: 'start' | 'center' | 'end';\n}\n\nexport interface TooltipWithIconProps extends TooltipBaseProps {\n trigger?: never;\n\n /**\n * Icon that will trigger the tooltip. A wrapper div will be set.\n */\n iconTrigger: ReactElement;\n\n className?: string;\n\n contentAlignment?: 'start' | 'center' | 'end';\n}\n\ntype TooltipProps = TooltipStandardProps | TooltipWithIconProps;\n\nexport const Tooltip = ({\n trigger: triggerProp,\n iconTrigger,\n side = 'bottom',\n hideArrow,\n defaultOpen,\n open,\n delayDuration = 300,\n onOpenChange,\n interactive = true,\n children,\n 'aria-label': ariaLabel,\n portal = true,\n disabled = false,\n className,\n maxWidth,\n zIndex = 10,\n triggerProps,\n portalProps,\n contentAlignment,\n size = 'md',\n ...contentProps\n}: TooltipProps) => {\n let trigger;\n\n if (iconTrigger) {\n trigger = (\n <TooltipIcon tabIndex={0} aria-label={ariaLabel} className={className}>\n {cloneElement(iconTrigger, { focusable: false, 'aria-hidden': true })}\n </TooltipIcon>\n );\n } else {\n trigger = triggerProp;\n }\n\n // quick way to check if children are renderable. null, false, and true will be filtered out when converting to an array\n const hasRenderableChildren = Children.toArray(children).length > 0;\n\n const content = (\n <TooltipPrimitive.Content side={side} sideOffset={8} asChild {...contentProps}>\n <FloatingTooltip\n zIndex={zIndex}\n contentAlignment={contentAlignment}\n maxWidth={maxWidth}\n size={size}\n >\n {children}\n {!hideArrow && (\n <TooltipPrimitive.Arrow asChild>\n <TooltipArrow />\n </TooltipPrimitive.Arrow>\n )}\n </FloatingTooltip>\n </TooltipPrimitive.Content>\n );\n\n return (\n <TooltipPrimitive.Provider delayDuration={delayDuration}>\n <TooltipPrimitive.Root\n open={open}\n defaultOpen={defaultOpen}\n disableHoverableContent={!interactive}\n onOpenChange={onOpenChange}\n >\n <TooltipPrimitive.Trigger asChild aria-label={ariaLabel} {...triggerProps}>\n {trigger}\n </TooltipPrimitive.Trigger>\n\n {!disabled &&\n hasRenderableChildren &&\n (portal ? (\n <TooltipPrimitive.Portal {...portalProps}>{content}</TooltipPrimitive.Portal>\n ) : (\n content\n ))}\n </TooltipPrimitive.Root>\n </TooltipPrimitive.Provider>\n );\n};\n\nexport default Tooltip;\n","import type { ReactNode } from 'react';\nimport { useTheme } from 'styled-components';\n\nimport { Color } from '@persona/design-tokens';\nimport { CircleHelpIcon } from '@persona/icons';\nimport { CircleHelpIcon as CircleHelpIconSmall } from '@persona/icons/12px';\n\nimport { semanticColor } from '#src/lib/semanticColor';\n\nimport Tooltip, { type TooltipWithIconProps } from './Tooltip';\n\nexport interface HelperTooltipProps extends Omit<TooltipWithIconProps, 'iconTrigger'> {\n children: ReactNode;\n size?: 'md' | 'sm';\n}\n\n/**\n * Helper component for rendering help text via help icons.\n */\nconst HelperTooltip = ({ children, size = 'md', ...props }: HelperTooltipProps) => {\n const theme = useTheme();\n const iconColor = semanticColor(theme, 'FgSecondary', Color.BorderIconSecondary);\n return (\n <Tooltip\n size={size}\n iconTrigger={\n size === 'md' ? (\n <CircleHelpIcon color={iconColor} />\n ) : (\n <CircleHelpIconSmall color={iconColor} />\n )\n }\n {...props}\n >\n {children}\n </Tooltip>\n );\n};\n\nexport default HelperTooltip;\n","import type { ReactNode } from 'react';\nimport styled from 'styled-components';\n\nimport { Color } from '@persona/design-tokens';\n\nimport { semanticColor } from '#src/lib/semanticColor';\n\nimport Tooltip, { type TooltipStandardProps } from './Tooltip';\n\nexport const TextWithDashedUnderline = styled.span`\n text-decoration: underline;\n text-decoration-style: dashed;\n text-decoration-color: ${({ theme }) => semanticColor(theme, 'FgTertiary', Color.CoreSlate700)};\n text-underline-offset: 2px;\n text-decoration-thickness: 1px;\n width: fit-content;\n`;\n\ninterface TextUnderlineTooltipProps extends Omit<TooltipStandardProps, 'trigger' | 'iconTrigger'> {\n tooltip: ReactNode;\n}\n\nconst TextUnderlineTooltip = ({ children, tooltip, ...props }: TextUnderlineTooltipProps) => {\n return (\n <Tooltip trigger={<TextWithDashedUnderline>{children}</TextWithDashedUnderline>} {...props}>\n {tooltip}\n </Tooltip>\n );\n};\n\nexport default TextUnderlineTooltip;\n"],"mappings":";;;;;;;;;;;;;AA0BA,MAAa,kBAIT,OAAOA,aAAK;KACX,EAAE,OAAO,WAAY,SAAS,OAAO,gBAAgB,KAAK,gBAAgB,GAAI;kBACjE,EAAE,OAAO,WAAY,SAAS,OAAO,SAAS,OAAQ;;;;kBAItD,EAAE,uBAAuB,oBAAoB,SAAS;;iBAEvD,QAAQ,GAAG;eACb,OAAO,GAAA,QAA2B;cACnC,EAAE,aAAa,OAAO;;gBAEpB,EAAE,eAAe,YAAY,QAAQ;IACjD,cAAc,WAAW,qBAAqB,OAAO,gBAAgB,GAAG,CAAC;YACjE,EAAE,YAAY,cAAc,OAAO,aAAa,MAAM,YAAY,CAAC;;AAG/E,MAAM,eAAe,OAAO,GAAG;;;mBAGZ,EAAE,YAAY,cAAc,OAAO,mBAAmB,MAAM,MAAM,WAAW,QAAQ,CAAC;;2BAE9E,EAAE,YAAY,cAAc,OAAO,mBAAmB,MAAM,MAAM,WAAW,QAAQ,CAAC;;;AAIjH,MAAM,cAAc,OAAO,GAAG;;;AAsF9B,MAAa,WAAW,EACtB,SAAS,aACT,aACA,OAAO,UACP,WACA,aACA,MACA,gBAAgB,KAChB,cACA,cAAc,MACd,UACA,cAAc,WACd,SAAS,MACT,WAAW,OACX,WACA,UACA,SAAS,IACT,cACA,aACA,kBACA,OAAO,MACP,GAAG,mBACe;CAClB,IAAI;AAEJ,KAAI,YACF,WACE,oBAAC,aAAD;EAAa,UAAU;EAAG,cAAY;EAAsB;YACzD,aAAa,aAAa;GAAE,WAAW;GAAO,eAAe;GAAM,CAAC;EACzD,CAAA;KAGhB,WAAU;CAIZ,MAAM,wBAAwB,SAAS,QAAQ,SAAS,CAAC,SAAS;CAElE,MAAM,UACJ,oBAAC,iBAAiB,SAAlB;EAAgC;EAAM,YAAY;EAAG,SAAA;EAAQ,GAAI;YAC/D,qBAAC,iBAAD;GACU;GACU;GACR;GACJ;aAJR,CAMG,UACA,CAAC,aACA,oBAAC,iBAAiB,OAAlB;IAAwB,SAAA;cACtB,oBAAC,cAAD,EAAgB,CAAA;IACO,CAAA,CAEX;;EACO,CAAA;AAG7B,QACE,oBAAC,iBAAiB,UAAlB;EAA0C;YACxC,qBAAC,iBAAiB,MAAlB;GACQ;GACO;GACb,yBAAyB,CAAC;GACZ;aAJhB,CAME,oBAAC,iBAAiB,SAAlB;IAA0B,SAAA;IAAQ,cAAY;IAAW,GAAI;cAC1D;IACwB,CAAA,EAE1B,CAAC,YACA,0BACC,SACC,oBAAC,iBAAiB,QAAlB;IAAyB,GAAI;cAAc;IAAkC,CAAA,GAE7E,SAEkB;;EACE,CAAA;;;;;;;ACvMhC,MAAM,iBAAiB,EAAE,UAAU,OAAO,MAAM,GAAG,YAAgC;CAEjF,MAAM,YAAY,cADJ,UACuB,EAAE,eAAe,MAAM,oBAAoB;AAChF,QACE,oBAAC,SAAD;EACQ;EACN,aACE,SAAS,OACP,oBAAC,gBAAD,EAAgB,OAAO,WAAa,CAAA,GAEpC,oBAACC,kBAAD,EAAqB,OAAO,WAAa,CAAA;EAG7C,GAAI;EAEH;EACO,CAAA;;;;AC1Bd,MAAa,0BAA0B,OAAO,IAAI;;;4BAGtB,EAAE,YAAY,cAAc,OAAO,cAAc,MAAM,aAAa,CAAC;;;;;AAUjG,MAAM,wBAAwB,EAAE,UAAU,SAAS,GAAG,YAAuC;AAC3F,QACE,oBAAC,SAAD;EAAS,SAAS,oBAAC,yBAAD,EAA0B,UAAmC,CAAA;EAAE,GAAI;YAClF;EACO,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as FilterConfig } from "./types-
|
|
1
|
+
import { s as FilterConfig } from "./types-sUEmxsGM.mjs";
|
|
2
2
|
import { Dispatch, SetStateAction } from "react";
|
|
3
3
|
import { Column, ColumnFiltersState, Header, RowData, Table } from "@tanstack/react-table";
|
|
4
4
|
|
|
@@ -17,4 +17,4 @@ declare const generateClientFilters: <TData extends RowData>(columns: Array<{
|
|
|
17
17
|
}>, columnFilters: ColumnFiltersState, setColumnFilters: Dispatch<SetStateAction<ColumnFiltersState>>) => FilterConfig[];
|
|
18
18
|
//#endregion
|
|
19
19
|
export { getFilterFnName as n, generateClientFilters as t };
|
|
20
|
-
//# sourceMappingURL=clientFilterUtils-
|
|
20
|
+
//# sourceMappingURL=clientFilterUtils-DDDG1g7e.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as getFilterFnName, t as generateClientFilters } from "./clientFilterUtils-
|
|
1
|
+
import { n as getFilterFnName, t as generateClientFilters } from "./clientFilterUtils-DDDG1g7e.mjs";
|
|
2
2
|
export { generateClientFilters, getFilterFnName };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["Heading"],"sources":["../../../src/components/Accordion/scrollExpandedItemIntoView.ts","../../../src/components/Accordion/AccordionItem.tsx","../../../src/components/Accordion/accordionTitleTypography.ts","../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["import { TransitionDurationInSeconds } from 'design-system/variables/transitions';\n\nexport type ScrollExpandedItemTarget = {\n itemElement: HTMLElement;\n triggerElement: HTMLElement;\n};\n\nconst SCROLL_ALIGN_THRESHOLD_PX = 4;\n\nconst prefersReducedMotion = () =>\n typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nconst getScrollBehavior = (): ScrollBehavior => (prefersReducedMotion() ? 'auto' : 'smooth');\n\nconst isScrollableOverflow = (overflowY: string) =>\n overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay';\n\nexport const findScrollContainer = (element: HTMLElement): HTMLElement | null => {\n let parent = element.parentElement;\n\n while (parent) {\n const { overflowY } = getComputedStyle(parent);\n if (isScrollableOverflow(overflowY) && parent.scrollHeight > parent.clientHeight) {\n return parent;\n }\n parent = parent.parentElement;\n }\n\n return null;\n};\n\nconst getContainerRect = (container: HTMLElement | null) => {\n if (container) {\n return container.getBoundingClientRect();\n }\n\n return {\n top: 0,\n bottom: window.innerHeight,\n } as Pick<DOMRect, 'top' | 'bottom'>;\n};\n\nconst scrollBy = (container: HTMLElement | null, deltaY: number) => {\n if (Math.abs(deltaY) <= SCROLL_ALIGN_THRESHOLD_PX) {\n return;\n }\n\n const behavior = getScrollBehavior();\n\n if (container) {\n container.scrollTo({ top: container.scrollTop + deltaY, behavior });\n return;\n }\n\n window.scrollBy({ top: deltaY, behavior });\n};\n\nexport const scrollExpandedItemIntoView = (target: ScrollExpandedItemTarget | null) => {\n if (!target) {\n return;\n }\n\n const { itemElement, triggerElement } = target;\n const container = findScrollContainer(itemElement);\n const containerRect = getContainerRect(container);\n const itemRect = itemElement.getBoundingClientRect();\n const triggerRect = triggerElement.getBoundingClientRect();\n const overflowBottom = itemRect.bottom - containerRect.bottom;\n\n if (overflowBottom > SCROLL_ALIGN_THRESHOLD_PX) {\n const maxScrollWithoutHidingTrigger = Math.max(0, triggerRect.top - containerRect.top);\n const deltaY = Math.min(overflowBottom, maxScrollWithoutHidingTrigger);\n scrollBy(container, deltaY);\n }\n};\n\nexport const scrollExpandedItemIntoViewAfterExpand = (target: ScrollExpandedItemTarget | null) => {\n scrollExpandedItemIntoView(target);\n\n if (!target) {\n return undefined;\n }\n\n const cleanups: Array<() => void> = [];\n const resyncScroll = () => scrollExpandedItemIntoView(target);\n\n const timeoutId = window.setTimeout(resyncScroll, TransitionDurationInSeconds.Fast * 1000);\n cleanups.push(() => window.clearTimeout(timeoutId));\n\n const panel = target.itemElement.querySelector<HTMLElement>('[data-accordion-panel]');\n if (panel) {\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target !== panel || event.propertyName !== 'height') {\n return;\n }\n\n resyncScroll();\n };\n\n panel.addEventListener('transitionend', onTransitionEnd);\n cleanups.push(() => panel.removeEventListener('transitionend', onTransitionEnd));\n }\n\n const rafId = window.requestAnimationFrame(() => {\n const innerRafId = window.requestAnimationFrame(resyncScroll);\n cleanups.push(() => window.cancelAnimationFrame(innerRafId));\n });\n cleanups.push(() => window.cancelAnimationFrame(rafId));\n\n return () => {\n cleanups.forEach((cleanup) => cleanup());\n };\n};\n\nexport const resolveAccordionTriggerElement = (itemElement: HTMLElement | null) => {\n if (!itemElement) {\n return null;\n }\n\n return (\n itemElement.querySelector<HTMLElement>('[slot=\"trigger\"]') ??\n itemElement.querySelector<HTMLElement>('button')\n );\n};\n","import type { ReactNode, RefObject } from 'react';\nimport { useLayoutEffect, useRef } from 'react';\nimport { Disclosure, DisclosurePanel } from 'react-aria-components';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport { ChevronDownIcon, ChevronRightIcon } from '@persona/icons/12px';\nimport { HStack } from 'design-system/components/Stack';\nimport { Heading, Paragraph } from 'design-system/components/Text';\nimport { HeadlessAriaButton } from 'design-system/lib/HeadlessAriaButton';\nimport { isFocusedVisible, isNotDisabled } from 'design-system/lib/pseudoClass';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport { TruncatedText } from 'design-system/lib/TruncatedText';\nimport { focusOutlineControlled } from 'design-system/mixins/focus';\nimport { TransitionDuration } from 'design-system/variables/transitions';\n\nimport type { AccordionSize, AccordionTitleTypography } from './accordionTitleTypography';\nimport {\n scrollExpandedItemIntoViewAfterExpand,\n resolveAccordionTriggerElement,\n} from './scrollExpandedItemIntoView';\n\nexport type AccordionTitleHeadingAs = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\nexport type { AccordionSize, AccordionTitleTypography };\n\nconst SIZE_HEIGHT: Record<AccordionSize, string> = {\n sm: Spacing[5],\n md: Spacing[6],\n lg: Spacing[7],\n};\n\nconst ItemContainer = styled(Disclosure)<{ $showDivider: boolean }>`\n display: flex;\n flex-direction: column;\n position: relative;\n\n &:focus-within {\n z-index: 1;\n }\n\n ${({ $showDivider }) =>\n $showDivider &&\n css`\n border-top: 1px solid\n ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n `}\n`;\n\nconst ChevronContainer = styled.span`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: ${Spacing[3]};\n height: ${Spacing[3]};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.BorderIconSecondary)};\n transition: color ${TransitionDuration.Fast} ease;\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n`;\n\nconst TriggerButton = styled(HeadlessAriaButton)<{\n $size: AccordionSize;\n $usesTitleTypographyOverride: boolean;\n}>`\n width: 100%;\n min-height: ${({ $size }) => SIZE_HEIGHT[$size]};\n height: ${({ $size, $usesTitleTypographyOverride }) =>\n $usesTitleTypographyOverride ? 'auto' : SIZE_HEIGHT[$size]};\n display: flex;\n align-items: center;\n text-align: left;\n border-radius: 0;\n background-color: transparent;\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n transition: background-color ${TransitionDuration.Fast} ease-in-out;\n ${focusOutlineControlled}\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n\n &${isFocusedVisible}${isNotDisabled} {\n position: relative;\n z-index: 1;\n }\n\n &:disabled {\n cursor: default;\n color: ${({ theme }) => semanticColor(theme, 'FgDisabled', theme.color.text.disabled)};\n background-color: transparent;\n\n ${ChevronContainer} {\n color: ${({ theme }) => semanticColor(theme, 'FgDisabled', Color.BorderIconDisabled)};\n }\n }\n\n &:hover:not(:disabled) {\n background-color: ${({ theme }) =>\n semanticColor(theme, 'SurfaceHover', Color.BackgroundInteractiveHover)};\n }\n\n &:not(:disabled):hover ${ChevronContainer},\n &${isFocusedVisible}${isNotDisabled} ${ChevronContainer} {\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.BorderIconPrimary)};\n }\n`;\n\nconst CollapseTitle = styled(HStack)`\n width: 100%;\n min-width: 0;\n`;\n\nconst TitleWrapper = styled.span`\n display: flex;\n align-items: center;\n min-width: 0;\n`;\n\nconst Panel = styled(DisclosurePanel)`\n height: var(--disclosure-panel-height);\n overflow: clip;\n transition: height ${TransitionDuration.Fast} ease-out;\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n`;\n\nconst TitleHeading = styled(Heading)`\n margin: 0;\n width: 100%;\n min-width: 0;\n font: inherit;\n font-size: inherit;\n line-height: inherit;\n font-weight: inherit;\n letter-spacing: inherit;\n`;\n\nconst PanelContent = styled.div`\n padding: ${Spacing[3]} ${Spacing[4]};\n`;\n\nconst TitleText = styled.span`\n min-width: 0;\n flex: 1;\n`;\n\nexport type AccordionItemComponentProps = {\n title: string;\n children: ReactNode;\n defaultExpanded?: boolean;\n disabled?: boolean;\n showDivider?: boolean;\n size: AccordionSize;\n titleTypography: AccordionTitleTypography;\n usesTitleTypographyOverride: boolean;\n titleHeadingAs: AccordionTitleHeadingAs;\n};\n\nconst renderTitleLabel = (\n title: string,\n titleTypography: AccordionTitleTypography,\n disabled: boolean,\n) => {\n const content = <TruncatedText>{title}</TruncatedText>;\n const textColor = disabled ? 'disabled' : 'primary';\n\n if (titleTypography.variant === 'heading') {\n return (\n <TitleText>\n <TitleWrapper>\n <Heading as='span' color={textColor} size={titleTypography.size}>\n {content}\n </Heading>\n </TitleWrapper>\n </TitleText>\n );\n }\n\n return (\n <TitleText>\n <TitleWrapper>\n <Paragraph\n as='span'\n color={textColor}\n size={titleTypography.size}\n weight={titleTypography.weight ?? 'normal'}\n >\n {content}\n </Paragraph>\n </TitleWrapper>\n </TitleText>\n );\n};\n\nconst renderChevron = (isExpanded: boolean) =>\n isExpanded ? <ChevronDownIcon /> : <ChevronRightIcon />;\n\nconst ExpandScrollSync = ({\n disabled,\n isExpanded,\n itemRef,\n}: {\n disabled: boolean;\n isExpanded: boolean;\n itemRef: RefObject<HTMLElement | null>;\n}) => {\n const wasExpandedRef = useRef(isExpanded);\n\n useLayoutEffect(() => {\n if (disabled) {\n wasExpandedRef.current = isExpanded;\n return undefined;\n }\n\n const didExpand = isExpanded && !wasExpandedRef.current;\n wasExpandedRef.current = isExpanded;\n\n const itemElement = itemRef.current;\n const triggerElement = resolveAccordionTriggerElement(itemElement);\n\n if (!didExpand || !itemElement || !triggerElement) {\n return undefined;\n }\n\n return scrollExpandedItemIntoViewAfterExpand({\n itemElement,\n triggerElement,\n });\n }, [disabled, isExpanded, itemRef]);\n\n return null;\n};\n\nconst AccordionItem = ({\n title,\n children,\n defaultExpanded = false,\n disabled = false,\n showDivider = false,\n size,\n titleTypography,\n usesTitleTypographyOverride,\n titleHeadingAs,\n}: AccordionItemComponentProps) => {\n const itemRef = useRef<HTMLDivElement>(null);\n\n return (\n <ItemContainer\n ref={itemRef}\n defaultExpanded={disabled ? false : defaultExpanded}\n isDisabled={disabled}\n $showDivider={showDivider}\n >\n {({ isExpanded }) => (\n <>\n <ExpandScrollSync disabled={disabled} isExpanded={isExpanded} itemRef={itemRef} />\n <TitleHeading forwardedAs={titleHeadingAs} size='xsm'>\n <TriggerButton\n slot='trigger'\n $size={size}\n $usesTitleTypographyOverride={usesTitleTypographyOverride}\n isDisabled={disabled}\n >\n <CollapseTitle align='center' spacing={Spacing[1]}>\n <ChevronContainer aria-hidden='true'>{renderChevron(isExpanded)}</ChevronContainer>\n {renderTitleLabel(title, titleTypography, disabled)}\n </CollapseTitle>\n </TriggerButton>\n </TitleHeading>\n <Panel data-accordion-panel>\n <PanelContent>{children}</PanelContent>\n </Panel>\n </>\n )}\n </ItemContainer>\n );\n};\n\nexport default AccordionItem;\n","import type { HeadingSize, ParagraphSize } from 'design-system/mixins/text';\n\nexport type AccordionSize = 'sm' | 'md' | 'lg';\n\nexport type AccordionTitleTypography =\n | { variant: 'heading'; size: HeadingSize }\n | {\n variant: 'paragraph';\n size: Extract<ParagraphSize, 'sm' | 'md' | 'lg'>;\n weight?: 'normal' | 'bold';\n };\n\nexport const getDefaultTitleTypography = (size: AccordionSize): AccordionTitleTypography => {\n if (size === 'lg') {\n return { variant: 'heading', size: 'xsm' };\n }\n\n if (size === 'sm') {\n return { variant: 'paragraph', size: 'sm', weight: 'normal' };\n }\n\n return { variant: 'paragraph', size: 'md', weight: 'bold' };\n};\n\nexport const resolveTitleTypography = (\n size: AccordionSize,\n titleTypography?: AccordionTitleTypography,\n): AccordionTitleTypography => titleTypography ?? getDefaultTitleTypography(size);\n","import type { ReactNode } from 'react';\n\nimport { Spacing } from '@persona/design-tokens';\nimport { Stack } from 'design-system/components/Stack';\n\nimport AccordionItem, {\n type AccordionSize,\n type AccordionTitleHeadingAs,\n type AccordionTitleTypography,\n} from './AccordionItem';\nimport { resolveTitleTypography } from './accordionTitleTypography';\n\nexport type AccordionItemProps = {\n id?: string;\n title: string;\n children: ReactNode;\n defaultExpanded?: boolean;\n disabled?: boolean;\n};\n\nexport type AccordionProps = {\n items: AccordionItemProps[];\n size?: AccordionSize;\n dividers?: boolean;\n titleTypography?: AccordionTitleTypography;\n /**\n * Heading element for each item title (inside the trigger), matching Card section headings.\n * Defaults to `h3`; use a lower level when the page already uses higher headings.\n */\n titleHeadingAs?: AccordionTitleHeadingAs;\n 'aria-label'?: string;\n className?: string;\n};\n\nexport const Accordion = ({\n items,\n size = 'md',\n dividers = false,\n titleTypography,\n titleHeadingAs = 'h3',\n 'aria-label': ariaLabel = 'Accordion',\n className,\n}: AccordionProps) => {\n if (items.length === 0) {\n return null;\n }\n\n const resolvedTitleTypography = resolveTitleTypography(size, titleTypography);\n const usesTitleTypographyOverride = titleTypography != null;\n\n return (\n <Stack aria-label={ariaLabel} className={className} fullWidth role='group' spacing={Spacing[0]}>\n {items.map((item, index) => (\n <AccordionItem\n key={item.id ?? `${item.title}-${index}`}\n defaultExpanded={item.defaultExpanded}\n disabled={item.disabled}\n showDivider={dividers}\n size={size}\n title={item.title}\n titleHeadingAs={titleHeadingAs}\n titleTypography={resolvedTitleTypography}\n usesTitleTypographyOverride={usesTitleTypographyOverride}\n >\n {item.children}\n </AccordionItem>\n ))}\n </Stack>\n );\n};\n\nexport default Accordion;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["Heading"],"sources":["../../../src/components/Accordion/scrollExpandedItemIntoView.ts","../../../src/components/Accordion/AccordionItem.tsx","../../../src/components/Accordion/accordionTitleTypography.ts","../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["import { TransitionDurationInSeconds } from '#src/variables/transitions';\n\nexport type ScrollExpandedItemTarget = {\n itemElement: HTMLElement;\n triggerElement: HTMLElement;\n};\n\nconst SCROLL_ALIGN_THRESHOLD_PX = 4;\n\nconst prefersReducedMotion = () =>\n typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nconst getScrollBehavior = (): ScrollBehavior => (prefersReducedMotion() ? 'auto' : 'smooth');\n\nconst isScrollableOverflow = (overflowY: string) =>\n overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay';\n\nexport const findScrollContainer = (element: HTMLElement): HTMLElement | null => {\n let parent = element.parentElement;\n\n while (parent) {\n const { overflowY } = getComputedStyle(parent);\n if (isScrollableOverflow(overflowY) && parent.scrollHeight > parent.clientHeight) {\n return parent;\n }\n parent = parent.parentElement;\n }\n\n return null;\n};\n\nconst getContainerRect = (container: HTMLElement | null) => {\n if (container) {\n return container.getBoundingClientRect();\n }\n\n return {\n top: 0,\n bottom: window.innerHeight,\n } as Pick<DOMRect, 'top' | 'bottom'>;\n};\n\nconst scrollBy = (container: HTMLElement | null, deltaY: number) => {\n if (Math.abs(deltaY) <= SCROLL_ALIGN_THRESHOLD_PX) {\n return;\n }\n\n const behavior = getScrollBehavior();\n\n if (container) {\n container.scrollTo({ top: container.scrollTop + deltaY, behavior });\n return;\n }\n\n window.scrollBy({ top: deltaY, behavior });\n};\n\nexport const scrollExpandedItemIntoView = (target: ScrollExpandedItemTarget | null) => {\n if (!target) {\n return;\n }\n\n const { itemElement, triggerElement } = target;\n const container = findScrollContainer(itemElement);\n const containerRect = getContainerRect(container);\n const itemRect = itemElement.getBoundingClientRect();\n const triggerRect = triggerElement.getBoundingClientRect();\n const overflowBottom = itemRect.bottom - containerRect.bottom;\n\n if (overflowBottom > SCROLL_ALIGN_THRESHOLD_PX) {\n const maxScrollWithoutHidingTrigger = Math.max(0, triggerRect.top - containerRect.top);\n const deltaY = Math.min(overflowBottom, maxScrollWithoutHidingTrigger);\n scrollBy(container, deltaY);\n }\n};\n\nexport const scrollExpandedItemIntoViewAfterExpand = (target: ScrollExpandedItemTarget | null) => {\n scrollExpandedItemIntoView(target);\n\n if (!target) {\n return undefined;\n }\n\n const cleanups: Array<() => void> = [];\n const resyncScroll = () => scrollExpandedItemIntoView(target);\n\n const timeoutId = window.setTimeout(resyncScroll, TransitionDurationInSeconds.Fast * 1000);\n cleanups.push(() => window.clearTimeout(timeoutId));\n\n const panel = target.itemElement.querySelector<HTMLElement>('[data-accordion-panel]');\n if (panel) {\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target !== panel || event.propertyName !== 'height') {\n return;\n }\n\n resyncScroll();\n };\n\n panel.addEventListener('transitionend', onTransitionEnd);\n cleanups.push(() => panel.removeEventListener('transitionend', onTransitionEnd));\n }\n\n const rafId = window.requestAnimationFrame(() => {\n const innerRafId = window.requestAnimationFrame(resyncScroll);\n cleanups.push(() => window.cancelAnimationFrame(innerRafId));\n });\n cleanups.push(() => window.cancelAnimationFrame(rafId));\n\n return () => {\n cleanups.forEach((cleanup) => cleanup());\n };\n};\n\nexport const resolveAccordionTriggerElement = (itemElement: HTMLElement | null) => {\n if (!itemElement) {\n return null;\n }\n\n return (\n itemElement.querySelector<HTMLElement>('[slot=\"trigger\"]') ??\n itemElement.querySelector<HTMLElement>('button')\n );\n};\n","import type { ReactNode, RefObject } from 'react';\nimport { useLayoutEffect, useRef } from 'react';\nimport { Disclosure, DisclosurePanel } from 'react-aria-components';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport { ChevronDownIcon, ChevronRightIcon } from '@persona/icons/12px';\n\nimport { HStack } from '#src/components/Stack';\nimport { Heading, Paragraph } from '#src/components/Text';\nimport { HeadlessAriaButton } from '#src/lib/HeadlessAriaButton';\nimport { isFocusedVisible, isNotDisabled } from '#src/lib/pseudoClass';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { TruncatedText } from '#src/lib/TruncatedText';\nimport { focusOutlineControlled } from '#src/mixins/focus';\nimport { TransitionDuration } from '#src/variables/transitions';\n\nimport type { AccordionSize, AccordionTitleTypography } from './accordionTitleTypography';\nimport {\n scrollExpandedItemIntoViewAfterExpand,\n resolveAccordionTriggerElement,\n} from './scrollExpandedItemIntoView';\n\nexport type AccordionTitleHeadingAs = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\nexport type { AccordionSize, AccordionTitleTypography };\n\nconst SIZE_HEIGHT: Record<AccordionSize, string> = {\n sm: Spacing[5],\n md: Spacing[6],\n lg: Spacing[7],\n};\n\nconst ItemContainer = styled(Disclosure)<{ $showDivider: boolean }>`\n display: flex;\n flex-direction: column;\n position: relative;\n\n &:focus-within {\n z-index: 1;\n }\n\n ${({ $showDivider }) =>\n $showDivider &&\n css`\n border-top: 1px solid\n ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n `}\n`;\n\nconst ChevronContainer = styled.span`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: ${Spacing[3]};\n height: ${Spacing[3]};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.BorderIconSecondary)};\n transition: color ${TransitionDuration.Fast} ease;\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n`;\n\nconst TriggerButton = styled(HeadlessAriaButton)<{\n $size: AccordionSize;\n $usesTitleTypographyOverride: boolean;\n}>`\n width: 100%;\n min-height: ${({ $size }) => SIZE_HEIGHT[$size]};\n height: ${({ $size, $usesTitleTypographyOverride }) =>\n $usesTitleTypographyOverride ? 'auto' : SIZE_HEIGHT[$size]};\n display: flex;\n align-items: center;\n text-align: left;\n border-radius: 0;\n background-color: transparent;\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n transition: background-color ${TransitionDuration.Fast} ease-in-out;\n ${focusOutlineControlled}\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n\n &${isFocusedVisible}${isNotDisabled} {\n position: relative;\n z-index: 1;\n }\n\n &:disabled {\n cursor: default;\n color: ${({ theme }) => semanticColor(theme, 'FgDisabled', theme.color.text.disabled)};\n background-color: transparent;\n\n ${ChevronContainer} {\n color: ${({ theme }) => semanticColor(theme, 'FgDisabled', Color.BorderIconDisabled)};\n }\n }\n\n &:hover:not(:disabled) {\n background-color: ${({ theme }) =>\n semanticColor(theme, 'SurfaceHover', Color.BackgroundInteractiveHover)};\n }\n\n &:not(:disabled):hover ${ChevronContainer},\n &${isFocusedVisible}${isNotDisabled} ${ChevronContainer} {\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.BorderIconPrimary)};\n }\n`;\n\nconst CollapseTitle = styled(HStack)`\n width: 100%;\n min-width: 0;\n`;\n\nconst TitleWrapper = styled.span`\n display: flex;\n align-items: center;\n min-width: 0;\n`;\n\nconst Panel = styled(DisclosurePanel)`\n height: var(--disclosure-panel-height);\n overflow: clip;\n transition: height ${TransitionDuration.Fast} ease-out;\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n`;\n\nconst TitleHeading = styled(Heading)`\n margin: 0;\n width: 100%;\n min-width: 0;\n font: inherit;\n font-size: inherit;\n line-height: inherit;\n font-weight: inherit;\n letter-spacing: inherit;\n`;\n\nconst PanelContent = styled.div`\n padding: ${Spacing[3]} ${Spacing[4]};\n`;\n\nconst TitleText = styled.span`\n min-width: 0;\n flex: 1;\n`;\n\nexport type AccordionItemComponentProps = {\n title: string;\n children: ReactNode;\n defaultExpanded?: boolean;\n disabled?: boolean;\n showDivider?: boolean;\n size: AccordionSize;\n titleTypography: AccordionTitleTypography;\n usesTitleTypographyOverride: boolean;\n titleHeadingAs: AccordionTitleHeadingAs;\n};\n\nconst renderTitleLabel = (\n title: string,\n titleTypography: AccordionTitleTypography,\n disabled: boolean,\n) => {\n const content = <TruncatedText>{title}</TruncatedText>;\n const textColor = disabled ? 'disabled' : 'primary';\n\n if (titleTypography.variant === 'heading') {\n return (\n <TitleText>\n <TitleWrapper>\n <Heading as='span' color={textColor} size={titleTypography.size}>\n {content}\n </Heading>\n </TitleWrapper>\n </TitleText>\n );\n }\n\n return (\n <TitleText>\n <TitleWrapper>\n <Paragraph\n as='span'\n color={textColor}\n size={titleTypography.size}\n weight={titleTypography.weight ?? 'normal'}\n >\n {content}\n </Paragraph>\n </TitleWrapper>\n </TitleText>\n );\n};\n\nconst renderChevron = (isExpanded: boolean) =>\n isExpanded ? <ChevronDownIcon /> : <ChevronRightIcon />;\n\nconst ExpandScrollSync = ({\n disabled,\n isExpanded,\n itemRef,\n}: {\n disabled: boolean;\n isExpanded: boolean;\n itemRef: RefObject<HTMLElement | null>;\n}) => {\n const wasExpandedRef = useRef(isExpanded);\n\n useLayoutEffect(() => {\n if (disabled) {\n wasExpandedRef.current = isExpanded;\n return undefined;\n }\n\n const didExpand = isExpanded && !wasExpandedRef.current;\n wasExpandedRef.current = isExpanded;\n\n const itemElement = itemRef.current;\n const triggerElement = resolveAccordionTriggerElement(itemElement);\n\n if (!didExpand || !itemElement || !triggerElement) {\n return undefined;\n }\n\n return scrollExpandedItemIntoViewAfterExpand({\n itemElement,\n triggerElement,\n });\n }, [disabled, isExpanded, itemRef]);\n\n return null;\n};\n\nconst AccordionItem = ({\n title,\n children,\n defaultExpanded = false,\n disabled = false,\n showDivider = false,\n size,\n titleTypography,\n usesTitleTypographyOverride,\n titleHeadingAs,\n}: AccordionItemComponentProps) => {\n const itemRef = useRef<HTMLDivElement>(null);\n\n return (\n <ItemContainer\n ref={itemRef}\n defaultExpanded={disabled ? false : defaultExpanded}\n isDisabled={disabled}\n $showDivider={showDivider}\n >\n {({ isExpanded }) => (\n <>\n <ExpandScrollSync disabled={disabled} isExpanded={isExpanded} itemRef={itemRef} />\n <TitleHeading forwardedAs={titleHeadingAs} size='xsm'>\n <TriggerButton\n slot='trigger'\n $size={size}\n $usesTitleTypographyOverride={usesTitleTypographyOverride}\n isDisabled={disabled}\n >\n <CollapseTitle align='center' spacing={Spacing[1]}>\n <ChevronContainer aria-hidden='true'>{renderChevron(isExpanded)}</ChevronContainer>\n {renderTitleLabel(title, titleTypography, disabled)}\n </CollapseTitle>\n </TriggerButton>\n </TitleHeading>\n <Panel data-accordion-panel>\n <PanelContent>{children}</PanelContent>\n </Panel>\n </>\n )}\n </ItemContainer>\n );\n};\n\nexport default AccordionItem;\n","import type { HeadingSize, ParagraphSize } from '#src/mixins/text';\n\nexport type AccordionSize = 'sm' | 'md' | 'lg';\n\nexport type AccordionTitleTypography =\n | { variant: 'heading'; size: HeadingSize }\n | {\n variant: 'paragraph';\n size: Extract<ParagraphSize, 'sm' | 'md' | 'lg'>;\n weight?: 'normal' | 'bold';\n };\n\nexport const getDefaultTitleTypography = (size: AccordionSize): AccordionTitleTypography => {\n if (size === 'lg') {\n return { variant: 'heading', size: 'xsm' };\n }\n\n if (size === 'sm') {\n return { variant: 'paragraph', size: 'sm', weight: 'normal' };\n }\n\n return { variant: 'paragraph', size: 'md', weight: 'bold' };\n};\n\nexport const resolveTitleTypography = (\n size: AccordionSize,\n titleTypography?: AccordionTitleTypography,\n): AccordionTitleTypography => titleTypography ?? getDefaultTitleTypography(size);\n","import type { ReactNode } from 'react';\n\nimport { Spacing } from '@persona/design-tokens';\n\nimport { Stack } from '#src/components/Stack';\n\nimport AccordionItem, {\n type AccordionSize,\n type AccordionTitleHeadingAs,\n type AccordionTitleTypography,\n} from './AccordionItem';\nimport { resolveTitleTypography } from './accordionTitleTypography';\n\nexport type AccordionItemProps = {\n id?: string;\n title: string;\n children: ReactNode;\n defaultExpanded?: boolean;\n disabled?: boolean;\n};\n\nexport type AccordionProps = {\n items: AccordionItemProps[];\n size?: AccordionSize;\n dividers?: boolean;\n titleTypography?: AccordionTitleTypography;\n /**\n * Heading element for each item title (inside the trigger), matching Card section headings.\n * Defaults to `h3`; use a lower level when the page already uses higher headings.\n */\n titleHeadingAs?: AccordionTitleHeadingAs;\n 'aria-label'?: string;\n className?: string;\n};\n\nexport const Accordion = ({\n items,\n size = 'md',\n dividers = false,\n titleTypography,\n titleHeadingAs = 'h3',\n 'aria-label': ariaLabel = 'Accordion',\n className,\n}: AccordionProps) => {\n if (items.length === 0) {\n return null;\n }\n\n const resolvedTitleTypography = resolveTitleTypography(size, titleTypography);\n const usesTitleTypographyOverride = titleTypography != null;\n\n return (\n <Stack aria-label={ariaLabel} className={className} fullWidth role='group' spacing={Spacing[0]}>\n {items.map((item, index) => (\n <AccordionItem\n key={item.id ?? `${item.title}-${index}`}\n defaultExpanded={item.defaultExpanded}\n disabled={item.disabled}\n showDivider={dividers}\n size={size}\n title={item.title}\n titleHeadingAs={titleHeadingAs}\n titleTypography={resolvedTitleTypography}\n usesTitleTypographyOverride={usesTitleTypographyOverride}\n >\n {item.children}\n </AccordionItem>\n ))}\n </Stack>\n );\n};\n\nexport default Accordion;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/components/Attribute/Attribute.tsx","../../../src/components/Attribute/AttributeGrid.tsx"],"sourcesContent":["import { repeat, uniqueId } from 'lodash-es';\nimport {\n type ComponentPropsWithoutRef,\n type ComponentType,\n createContext,\n type FC,\n type PropsWithChildren,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { useToggleButton } from 'react-aria';\nimport { useToggleState } from 'react-stately';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing, Typography } from '@persona/design-tokens';\nimport { EyeIcon, EyeOffIcon } from '@persona/icons';\nimport IconButton from 'design-system/components/Button/IconButton';\nimport Sticker from 'design-system/components/Sticker';\nimport { Paragraph } from 'design-system/components/Text';\nimport { HelperTooltip } from 'design-system/components/Tooltip';\nimport { isHovered, isNotDisabled } from 'design-system/lib/pseudoClass';\nimport { semanticColor, semanticOnly } from 'design-system/lib/semanticColor';\nimport type { ParagraphSize } from 'design-system/mixins/text';\n\nexport type WordBreak = 'break-all' | 'break-word' | 'normal';\nexport type TextTransform = 'capitalize' | 'sentence';\nexport type TableLayoutValue = boolean | 'full-width';\n\nexport type AttributeSize = 'sm' | 'md';\n\nexport const AttributeContext = createContext<{\n table?: TableLayoutValue;\n horizontal?: boolean;\n size?: AttributeSize;\n}>({});\n\n// TODO: Create Toggle Button component\nexport const IconButtonContainer = styled(IconButton)`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n svg {\n transition-duration: 150ms;\n }\n\n :hover {\n svg {\n color: ${({ theme }) => semanticColor(theme, 'FgAccent', Color.CorePurple800)};\n }\n }\n\n ${semanticOnly(\n (tokens) => css`\n background-color: ${tokens.ActionNeutral};\n color: ${tokens.FgPrimary};\n\n svg {\n color: ${tokens.FgPrimary};\n }\n\n svg.pds-icon path[stroke] {\n stroke: currentColor;\n }\n\n &${isHovered}${isNotDisabled} {\n background-color: ${tokens.ActionNeutralHover};\n color: ${tokens.FgAccent};\n\n svg path {\n stroke: currentColor;\n }\n }\n `,\n )}\n`;\n\ninterface AttributeValueProps {\n placeholder: ReactNode;\n show?: boolean;\n redacted?: boolean;\n value?: ReactNode;\n textTransform?: TextTransform;\n wordBreak?: WordBreak;\n size?: AttributeSize;\n 'aria-labelledby': string;\n id: string;\n}\n\ninterface ValueFormatterProps {\n isPlaceholder?: boolean;\n wordBreak?: WordBreak;\n size?: AttributeSize;\n}\n\nconst Value = styled.dd<ValueFormatterProps>`\n ${({ size }) => (size === 'sm' ? Typography.TextSmall : Typography.TextMedium)};\n color: ${({ isPlaceholder, theme }) =>\n isPlaceholder\n ? semanticColor(theme, 'FgSecondary', Color.TextSecondary)\n : semanticColor(theme, 'FgPrimary', Color.CoreSlate1000)};\n margin: 0;\n text-overflow: ellipsis;\n overflow-x: hidden;\n word-break: ${({ wordBreak }) => (wordBreak ? wordBreak : 'normal')};\n\n ul,\n ol {\n list-style-position: inside;\n }\n\n a {\n color: ${({ theme }) => semanticColor(theme, 'FgAccent', theme.color.text.brand)};\n text-decoration: none;\n\n &:visited {\n color: ${({ theme }) => semanticColor(theme, 'FgAccent', theme.color.text.brand)};\n }\n }\n`;\n\nexport const AttributeValue = ({\n placeholder,\n show,\n redacted,\n value,\n wordBreak,\n size,\n id,\n 'aria-labelledby': ariaLabelledBy,\n}: AttributeValueProps) => {\n const isEmpty = value == null || value === '';\n\n const renderedVal = isEmpty ? (\n placeholder\n ) : (\n <>{!show ? repeat('•', typeof value === 'string' ? value.length : 8) : value}</>\n );\n\n return (\n <Value\n isPlaceholder={isEmpty}\n wordBreak={wordBreak}\n size={size}\n title={typeof value === 'string' ? value : undefined}\n aria-labelledby={ariaLabelledBy}\n id={id}\n >\n {redacted ? <Sticker id={id}>Redacted</Sticker> : renderedVal}\n </Value>\n );\n};\n\nexport interface AttributeProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Title of the attribute. Rendered as a <dt>.\n */\n label: ReactNode;\n\n /**\n * Value to display. Rendered as a <dd>.\n */\n value?: ReactNode;\n\n /**\n * Will display a \"Redacted\" sticker if there is a value.\n */\n redacted?: boolean;\n\n /**\n * Renders toggleable eye button to the right of the label\n */\n toggleable?: boolean;\n\n /**\n * Text to display in presence of null value.\n */\n placeholder?: string;\n\n /**\n * Word break styling for value.\n */\n wordBreak?: WordBreak;\n\n /**\n * Render a custom label component\n */\n labelComponent?: FC<PropsWithChildren<{ id: string; size?: ParagraphSize }>>;\n\n /**\n * Render a custom value component\n */\n valueComponent?: ComponentType<AttributeValueProps>;\n\n /**\n * Renders a HelperTooltip to display help text to the right of the label.\n */\n helpText?: ReactNode;\n\n /**\n * Custom adornments to display to the right of the label.\n */\n right?: ReactNode;\n\n /**\n * Renders attributes in a tabular layout.\n */\n table?: TableLayoutValue;\n}\n\ntype AttributeContainerProps = {\n horizontal?: boolean;\n table?: TableLayoutValue;\n size?: AttributeSize;\n};\nconst AttributeContainer = styled('div')<AttributeContainerProps>`\n ${({ table, size }) =>\n table &&\n css`\n display: table-row;\n\n > * {\n display: table-cell;\n }\n\n & > ${AttributeLabel} {\n padding: ${Spacing[1]} 0;\n padding-right: ${size === 'sm' ? Spacing[2] : Spacing[3]};\n }\n & > ${Value} {\n padding: ${size === 'sm' ? Spacing[1] : Spacing[2]} 0;\n }\n `}\n\n ${({ horizontal }) =>\n horizontal &&\n css`\n display: grid;\n gap: ${Spacing[4]};\n grid-template-columns: subgrid;\n grid-column: span 2;\n `}\n`;\n\nexport const AttributeLabel = styled(Paragraph).attrs<{ size?: ParagraphSize }>((props) => ({\n size: props.size ?? 'md',\n color: 'tertiary',\n as: 'dt',\n}))`\n margin: 0;\n overflow-wrap: break-word;\n ${semanticOnly((tokens) => `color: ${tokens.FgSecondary};`)}\n`;\n\nconst RightContainer = styled.span`\n display: inline-block;\n vertical-align: middle;\n margin-left: ${Spacing[2]};\n`;\n\nexport const Attribute = ({\n label,\n value,\n redacted,\n placeholder = '-',\n wordBreak,\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n labelComponent: LabelComponent = AttributeLabel,\n valueComponent: ValueComponent = AttributeValue,\n right,\n helpText,\n toggleable,\n table,\n ...elemProps\n}: AttributeProps) => {\n const attrCtx = useContext(AttributeContext);\n const size = attrCtx?.size ?? 'md';\n const toggleRef = useRef();\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n const valueAsArray = [].concat(value).filter(Boolean);\n const showToggleButton = toggleable && !redacted && valueAsArray.length > 0;\n const state = useToggleState({ defaultSelected: !toggleable });\n const { buttonProps } = useToggleButton(\n {\n 'aria-label': state.isSelected ? `Hide ${label} value` : `Show ${label} value`,\n elementType: 'button',\n },\n state,\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n toggleRef,\n );\n const labelId = useMemo(() => uniqueId('pds_attribute_label__'), []);\n const valueId = useMemo(() => uniqueId('pds_attribute_value__'), []);\n const show = state.isSelected;\n\n useEffect(() => {\n state.setSelected(!toggleable);\n }, [toggleable]);\n\n return (\n <AttributeContainer\n table={table || attrCtx?.table}\n horizontal={attrCtx?.horizontal}\n size={size}\n {...elemProps}\n >\n <LabelComponent id={labelId} aria-details={valueId} size={size}>\n {label}\n {helpText && (\n <RightContainer>\n <HelperTooltip size='sm'>{helpText}</HelperTooltip>\n </RightContainer>\n )}\n {showToggleButton && (\n <RightContainer>\n {/* @ts-expect-error [strict-migration] The following line is not strict; please fix! */}\n <IconButtonContainer {...buttonProps} ref={toggleRef}>\n {show ? <EyeIcon /> : <EyeOffIcon />}\n </IconButtonContainer>\n </RightContainer>\n )}\n {right && <RightContainer>{right}</RightContainer>}\n </LabelComponent>\n <ValueComponent\n id={valueId}\n value={value}\n placeholder={placeholder}\n wordBreak={wordBreak}\n redacted={redacted}\n show={show}\n size={size}\n aria-labelledby={labelId}\n />\n </AttributeContainer>\n );\n};\n\nexport default Attribute;\n","import type { ReactNode } from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\n\nimport { AttributeContext, type AttributeSize, type TableLayoutValue } from './Attribute';\n\ntype AttributeGridProps = {\n children?: ReactNode;\n /**\n * Sets the font size and spacing density for all child Attributes.\n * Defaults to `'md'`.\n */\n size?: AttributeSize;\n} & (\n | {\n /**\n * Set a fixed number of columns for the grid.\n */\n colCount?: number;\n /**\n * Display attributes in a stacked list with label first then value.\n */\n horizontal?: boolean;\n\n table?: never;\n }\n | {\n /**\n * Display attributes in a fixed tabular layout.\n * Set to `full-width` to expand to full width of container.\n */\n table?: TableLayoutValue;\n\n colCount?: never;\n horizontal?: never;\n }\n);\n\ntype AttributeGridComponentProps = {\n colCount?: number;\n horizontal?: boolean;\n table?: TableLayoutValue;\n size?: AttributeSize;\n};\nconst AttributeGridComponent = styled.dl<AttributeGridComponentProps>`\n ${({ colCount, table, horizontal, size }) =>\n table\n ? css`\n display: table;\n ${\n table === 'full-width' &&\n css`\n width: 100%;\n table-layout: fixed;\n border-spacing: 0 ${size === 'sm' ? Spacing[1] : Spacing[2]};\n `\n };\n `\n : css`\n display: grid;\n gap: ${size === 'sm' ? Spacing[2] : Spacing[4]};\n /* If the layout is horizontal we guarentee an even number of columns */\n grid-template-columns: ${\n colCount\n ? `repeat(${colCount}, ${horizontal ? '1fr 2fr' : '1fr'})`\n : `repeat(auto-fit, ${horizontal ? 'minmax(120px, 1fr) minmax(225px, 2fr)' : 'minmax(225px, 1fr)'})`\n };\n `}\n margin: 0;\n\n & + & {\n padding-bottom: ${Spacing[5]};\n }\n`;\n\nconst AttributeGrid = ({ children, horizontal, table, size, ...props }: AttributeGridProps) => {\n return (\n <AttributeGridComponent table={table} horizontal={horizontal} size={size} {...props}>\n <AttributeContext.Provider value={{ horizontal, table, size }}>\n {children}\n </AttributeContext.Provider>\n </AttributeGridComponent>\n );\n};\n\nexport default AttributeGrid;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/components/Attribute/Attribute.tsx","../../../src/components/Attribute/AttributeGrid.tsx"],"sourcesContent":["import { repeat, uniqueId } from 'lodash-es';\nimport {\n type ComponentPropsWithoutRef,\n type ComponentType,\n createContext,\n type FC,\n type PropsWithChildren,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { useToggleButton } from 'react-aria';\nimport { useToggleState } from 'react-stately';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing, Typography } from '@persona/design-tokens';\nimport { EyeIcon, EyeOffIcon } from '@persona/icons';\n\nimport IconButton from '#src/components/Button/IconButton';\nimport Sticker from '#src/components/Sticker';\nimport { Paragraph } from '#src/components/Text';\nimport { HelperTooltip } from '#src/components/Tooltip';\nimport { isHovered, isNotDisabled } from '#src/lib/pseudoClass';\nimport { semanticColor, semanticOnly } from '#src/lib/semanticColor';\nimport type { ParagraphSize } from '#src/mixins/text';\n\nexport type WordBreak = 'break-all' | 'break-word' | 'normal';\nexport type TextTransform = 'capitalize' | 'sentence';\nexport type TableLayoutValue = boolean | 'full-width';\n\nexport type AttributeSize = 'sm' | 'md';\n\nexport const AttributeContext = createContext<{\n table?: TableLayoutValue;\n horizontal?: boolean;\n size?: AttributeSize;\n}>({});\n\n// TODO: Create Toggle Button component\nexport const IconButtonContainer = styled(IconButton)`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n svg {\n transition-duration: 150ms;\n }\n\n :hover {\n svg {\n color: ${({ theme }) => semanticColor(theme, 'FgAccent', Color.CorePurple800)};\n }\n }\n\n ${semanticOnly(\n (tokens) => css`\n background-color: ${tokens.ActionNeutral};\n color: ${tokens.FgPrimary};\n\n svg {\n color: ${tokens.FgPrimary};\n }\n\n svg.pds-icon path[stroke] {\n stroke: currentColor;\n }\n\n &${isHovered}${isNotDisabled} {\n background-color: ${tokens.ActionNeutralHover};\n color: ${tokens.FgAccent};\n\n svg path {\n stroke: currentColor;\n }\n }\n `,\n )}\n`;\n\ninterface AttributeValueProps {\n placeholder: ReactNode;\n show?: boolean;\n redacted?: boolean;\n value?: ReactNode;\n textTransform?: TextTransform;\n wordBreak?: WordBreak;\n size?: AttributeSize;\n 'aria-labelledby': string;\n id: string;\n}\n\ninterface ValueFormatterProps {\n isPlaceholder?: boolean;\n wordBreak?: WordBreak;\n size?: AttributeSize;\n}\n\nconst Value = styled.dd<ValueFormatterProps>`\n ${({ size }) => (size === 'sm' ? Typography.TextSmall : Typography.TextMedium)};\n color: ${({ isPlaceholder, theme }) =>\n isPlaceholder\n ? semanticColor(theme, 'FgSecondary', Color.TextSecondary)\n : semanticColor(theme, 'FgPrimary', Color.CoreSlate1000)};\n margin: 0;\n text-overflow: ellipsis;\n overflow-x: hidden;\n word-break: ${({ wordBreak }) => (wordBreak ? wordBreak : 'normal')};\n\n ul,\n ol {\n list-style-position: inside;\n }\n\n a {\n color: ${({ theme }) => semanticColor(theme, 'FgAccent', theme.color.text.brand)};\n text-decoration: none;\n\n &:visited {\n color: ${({ theme }) => semanticColor(theme, 'FgAccent', theme.color.text.brand)};\n }\n }\n`;\n\nexport const AttributeValue = ({\n placeholder,\n show,\n redacted,\n value,\n wordBreak,\n size,\n id,\n 'aria-labelledby': ariaLabelledBy,\n}: AttributeValueProps) => {\n const isEmpty = value == null || value === '';\n\n const renderedVal = isEmpty ? (\n placeholder\n ) : (\n <>{!show ? repeat('•', typeof value === 'string' ? value.length : 8) : value}</>\n );\n\n return (\n <Value\n isPlaceholder={isEmpty}\n wordBreak={wordBreak}\n size={size}\n title={typeof value === 'string' ? value : undefined}\n aria-labelledby={ariaLabelledBy}\n id={id}\n >\n {redacted ? <Sticker id={id}>Redacted</Sticker> : renderedVal}\n </Value>\n );\n};\n\nexport interface AttributeProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Title of the attribute. Rendered as a <dt>.\n */\n label: ReactNode;\n\n /**\n * Value to display. Rendered as a <dd>.\n */\n value?: ReactNode;\n\n /**\n * Will display a \"Redacted\" sticker if there is a value.\n */\n redacted?: boolean;\n\n /**\n * Renders toggleable eye button to the right of the label\n */\n toggleable?: boolean;\n\n /**\n * Text to display in presence of null value.\n */\n placeholder?: string;\n\n /**\n * Word break styling for value.\n */\n wordBreak?: WordBreak;\n\n /**\n * Render a custom label component\n */\n labelComponent?: FC<PropsWithChildren<{ id: string; size?: ParagraphSize }>>;\n\n /**\n * Render a custom value component\n */\n valueComponent?: ComponentType<AttributeValueProps>;\n\n /**\n * Renders a HelperTooltip to display help text to the right of the label.\n */\n helpText?: ReactNode;\n\n /**\n * Custom adornments to display to the right of the label.\n */\n right?: ReactNode;\n\n /**\n * Renders attributes in a tabular layout.\n */\n table?: TableLayoutValue;\n}\n\ntype AttributeContainerProps = {\n horizontal?: boolean;\n table?: TableLayoutValue;\n size?: AttributeSize;\n};\nconst AttributeContainer = styled('div')<AttributeContainerProps>`\n ${({ table, size }) =>\n table &&\n css`\n display: table-row;\n\n > * {\n display: table-cell;\n }\n\n & > ${AttributeLabel} {\n padding: ${Spacing[1]} 0;\n padding-right: ${size === 'sm' ? Spacing[2] : Spacing[3]};\n }\n & > ${Value} {\n padding: ${size === 'sm' ? Spacing[1] : Spacing[2]} 0;\n }\n `}\n\n ${({ horizontal }) =>\n horizontal &&\n css`\n display: grid;\n gap: ${Spacing[4]};\n grid-template-columns: subgrid;\n grid-column: span 2;\n `}\n`;\n\nexport const AttributeLabel = styled(Paragraph).attrs<{ size?: ParagraphSize }>((props) => ({\n size: props.size ?? 'md',\n color: 'tertiary',\n as: 'dt',\n}))`\n margin: 0;\n overflow-wrap: break-word;\n ${semanticOnly((tokens) => `color: ${tokens.FgSecondary};`)}\n`;\n\nconst RightContainer = styled.span`\n display: inline-block;\n vertical-align: middle;\n margin-left: ${Spacing[2]};\n`;\n\nexport const Attribute = ({\n label,\n value,\n redacted,\n placeholder = '-',\n wordBreak,\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n labelComponent: LabelComponent = AttributeLabel,\n valueComponent: ValueComponent = AttributeValue,\n right,\n helpText,\n toggleable,\n table,\n ...elemProps\n}: AttributeProps) => {\n const attrCtx = useContext(AttributeContext);\n const size = attrCtx?.size ?? 'md';\n const toggleRef = useRef();\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n const valueAsArray = [].concat(value).filter(Boolean);\n const showToggleButton = toggleable && !redacted && valueAsArray.length > 0;\n const state = useToggleState({ defaultSelected: !toggleable });\n const { buttonProps } = useToggleButton(\n {\n 'aria-label': state.isSelected ? `Hide ${label} value` : `Show ${label} value`,\n elementType: 'button',\n },\n state,\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n toggleRef,\n );\n const labelId = useMemo(() => uniqueId('pds_attribute_label__'), []);\n const valueId = useMemo(() => uniqueId('pds_attribute_value__'), []);\n const show = state.isSelected;\n\n useEffect(() => {\n state.setSelected(!toggleable);\n }, [toggleable]);\n\n return (\n <AttributeContainer\n table={table || attrCtx?.table}\n horizontal={attrCtx?.horizontal}\n size={size}\n {...elemProps}\n >\n <LabelComponent id={labelId} aria-details={valueId} size={size}>\n {label}\n {helpText && (\n <RightContainer>\n <HelperTooltip size='sm'>{helpText}</HelperTooltip>\n </RightContainer>\n )}\n {showToggleButton && (\n <RightContainer>\n {/* @ts-expect-error [strict-migration] The following line is not strict; please fix! */}\n <IconButtonContainer {...buttonProps} ref={toggleRef}>\n {show ? <EyeIcon /> : <EyeOffIcon />}\n </IconButtonContainer>\n </RightContainer>\n )}\n {right && <RightContainer>{right}</RightContainer>}\n </LabelComponent>\n <ValueComponent\n id={valueId}\n value={value}\n placeholder={placeholder}\n wordBreak={wordBreak}\n redacted={redacted}\n show={show}\n size={size}\n aria-labelledby={labelId}\n />\n </AttributeContainer>\n );\n};\n\nexport default Attribute;\n","import type { ReactNode } from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\n\nimport { AttributeContext, type AttributeSize, type TableLayoutValue } from './Attribute';\n\ntype AttributeGridProps = {\n children?: ReactNode;\n /**\n * Sets the font size and spacing density for all child Attributes.\n * Defaults to `'md'`.\n */\n size?: AttributeSize;\n} & (\n | {\n /**\n * Set a fixed number of columns for the grid.\n */\n colCount?: number;\n /**\n * Display attributes in a stacked list with label first then value.\n */\n horizontal?: boolean;\n\n table?: never;\n }\n | {\n /**\n * Display attributes in a fixed tabular layout.\n * Set to `full-width` to expand to full width of container.\n */\n table?: TableLayoutValue;\n\n colCount?: never;\n horizontal?: never;\n }\n);\n\ntype AttributeGridComponentProps = {\n colCount?: number;\n horizontal?: boolean;\n table?: TableLayoutValue;\n size?: AttributeSize;\n};\nconst AttributeGridComponent = styled.dl<AttributeGridComponentProps>`\n ${({ colCount, table, horizontal, size }) =>\n table\n ? css`\n display: table;\n ${\n table === 'full-width' &&\n css`\n width: 100%;\n table-layout: fixed;\n border-spacing: 0 ${size === 'sm' ? Spacing[1] : Spacing[2]};\n `\n };\n `\n : css`\n display: grid;\n gap: ${size === 'sm' ? Spacing[2] : Spacing[4]};\n /* If the layout is horizontal we guarentee an even number of columns */\n grid-template-columns: ${\n colCount\n ? `repeat(${colCount}, ${horizontal ? '1fr 2fr' : '1fr'})`\n : `repeat(auto-fit, ${horizontal ? 'minmax(120px, 1fr) minmax(225px, 2fr)' : 'minmax(225px, 1fr)'})`\n };\n `}\n margin: 0;\n\n & + & {\n padding-bottom: ${Spacing[5]};\n }\n`;\n\nconst AttributeGrid = ({ children, horizontal, table, size, ...props }: AttributeGridProps) => {\n return (\n <AttributeGridComponent table={table} horizontal={horizontal} size={size} {...props}>\n <AttributeContext.Provider value={{ horizontal, table, size }}>\n {children}\n </AttributeContext.Provider>\n </AttributeGridComponent>\n );\n};\n\nexport default AttributeGrid;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/components/Banner/Banner.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactElement, ReactNode } from 'react';\nimport { useFocusVisible } from 'react-aria';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport { XIcon } from '@persona/icons';\nimport Button from '
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/components/Banner/Banner.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactElement, ReactNode } from 'react';\nimport { useFocusVisible } from 'react-aria';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport { XIcon } from '@persona/icons';\n\nimport Button from '#src/components/Button';\nimport { withAlpha } from '#src/lib/color';\nimport { isActive, isFocused, isHovered, isNotDisabled } from '#src/lib/pseudoClass';\nimport { semanticOnly, semanticTokens } from '#src/lib/semanticColor';\nimport { paragraphMixins } from '#src/mixins/text';\n\nexport interface BannerProps extends ComponentPropsWithoutRef<'div'> {\n children: ReactNode;\n\n /**\n * Semantic colour theme for the banner background.\n *\n * - `informational` – purple, for general tips or announcements (default).\n * - `success` – green, for confirmations or completed actions.\n * - `warning` – yellow, for non-blocking cautions.\n * - `alert` – red, for errors or destructive warnings.\n *\n * @defaultValue 'informational'\n */\n variant?: 'informational' | 'success' | 'warning' | 'alert';\n\n /**\n * Action affordance rendered to the right of the content.\n *\n * - Pass a `string` together with `onClose` to show a text button that calls `onClose`.\n * - Pass a `ReactElement` to render a fully custom action (e.g. a link or icon button).\n * In this case `onClose` is ignored for the action slot; wire dismissal inside the element.\n */\n action?: string | ReactElement;\n\n /**\n * Called when the user clicks the close (×) button.\n * When provided and `action` is absent, a close icon button is rendered automatically.\n * When `action` is a string, clicking that string-labelled button calls this handler.\n */\n onClose?: VoidFunction;\n\n /**\n * When true, the content area stretches to fill the full banner width.\n * Useful when `children` contains a layout that needs to span the entire space.\n */\n extendContentWidth?: boolean;\n}\n\nconst StyledBanner = styled('div')<BannerProps>`\n ${paragraphMixins.sm};\n display: flex;\n align-items: center;\n justify-content: space-between;\n box-sizing: border-box;\n min-height: 40px;\n padding: ${Spacing[2]};\n border-radius: 4px;\n background: ${({ theme, variant }) => {\n const tokens = semanticTokens(theme);\n switch (variant) {\n case 'success':\n return tokens ? withAlpha(tokens.FeedbackSuccess1, tokens.Opacity15) : Color.CoreGreen100;\n case 'warning':\n return tokens ? withAlpha(tokens.FeedbackWarning1, tokens.Opacity15) : Color.CoreYellow100;\n case 'alert':\n return tokens ? withAlpha(tokens.FeedbackDanger1, tokens.Opacity15) : Color.CoreRed100;\n case 'informational':\n default:\n return tokens ? withAlpha(tokens.FeedbackInfo1, tokens.Opacity25) : Color.CorePurple100;\n }\n }};\n\n ${semanticOnly(\n (tokens) => css`\n color: ${tokens.FgPrimary};\n\n svg {\n color: ${tokens.FgPrimary};\n }\n `,\n )}\n`;\n\nconst BannerContent = styled.div<{ extendContentWidth?: boolean }>`\n display: flex;\n align-items: center;\n\n > svg:first-child {\n margin-right: ${Spacing[2]};\n flex-shrink: 0;\n }\n\n ${({ extendContentWidth }) =>\n extendContentWidth &&\n css`\n width: 100%;\n `}\n`;\n\nconst ActionButton = styled(Button)<{ isFocusVisible?: boolean }>`\n background-color: transparent;\n justify-self: space-between;\n\n &${isActive}${isNotDisabled}, &${isHovered}${isNotDisabled} {\n background-color: unset;\n }\n\n ${({ isFocusVisible }) =>\n !isFocusVisible &&\n css`\n &${isHovered}${isFocused}${isNotDisabled} {\n box-shadow: none;\n }\n &${isFocused}${isNotDisabled} {\n box-shadow: none;\n }\n `}\n`;\n\nexport const Banner = ({\n children,\n variant,\n action,\n onClose,\n extendContentWidth,\n ...elemProps\n}: BannerProps) => {\n const { isFocusVisible } = useFocusVisible();\n\n return (\n <StyledBanner variant={variant} role='alert' {...elemProps}>\n <BannerContent extendContentWidth={extendContentWidth}>{children}</BannerContent>\n {typeof action === 'string'\n ? onClose && (\n <ActionButton variant='basic' width='auto' size='sm' onClick={onClose}>\n {action}\n </ActionButton>\n )\n : action}\n {!action && onClose && (\n <ActionButton\n variant='basic'\n width='icon'\n size='sm'\n aria-label='Close'\n title='Close'\n onClick={onClose}\n isFocusVisible={isFocusVisible}\n >\n <XIcon />\n </ActionButton>\n )}\n </StyledBanner>\n );\n};\n\nexport default Banner;\n"],"mappings":";;;;;;;;;;;AAmDA,MAAM,eAAe,OAAO,MAAM;IAC9B,gBAAgB,GAAG;;;;;;aAMV,QAAQ,GAAG;;iBAEP,EAAE,OAAO,cAAc;CACpC,MAAM,SAAS,eAAe,MAAM;AACpC,SAAQ,SAAR;EACE,KAAK,UACH,QAAO,SAAS,UAAU,OAAO,kBAAkB,OAAO,UAAU,GAAG,MAAM;EAC/E,KAAK,UACH,QAAO,SAAS,UAAU,OAAO,kBAAkB,OAAO,UAAU,GAAG,MAAM;EAC/E,KAAK,QACH,QAAO,SAAS,UAAU,OAAO,iBAAiB,OAAO,UAAU,GAAG,MAAM;EAE9E,QACE,QAAO,SAAS,UAAU,OAAO,eAAe,OAAO,UAAU,GAAG,MAAM;;EAE9E;;IAEA,cACC,WAAW,GAAG;eACJ,OAAO,UAAU;;;iBAGf,OAAO,UAAU;;MAG/B,CAAC;;AAGJ,MAAM,gBAAgB,OAAO,GAAqC;;;;;oBAK9C,QAAQ,GAAG;;;;KAI1B,EAAE,yBACH,sBACA,GAAG;;MAED;;AAGN,MAAM,eAAe,OAAO,OAAO;;;;KAI9B,WAAW,cAAc,KAAK,YAAY,cAAc;;;;KAIxD,EAAE,qBACH,CAAC,kBACD,GAAG;SACE,YAAY,YAAY,cAAc;;;SAGtC,YAAY,cAAc;;;MAG7B;;AAGN,MAAa,UAAU,EACrB,UACA,SACA,QACA,SACA,oBACA,GAAG,gBACc;CACjB,MAAM,EAAE,mBAAmB,iBAAiB;AAE5C,QACE,qBAAC,cAAD;EAAuB;EAAS,MAAK;EAAQ,GAAI;YAAjD;GACE,oBAAC,eAAD;IAAmC;IAAqB;IAAyB,CAAA;GAChF,OAAO,WAAW,WACf,WACE,oBAAC,cAAD;IAAc,SAAQ;IAAQ,OAAM;IAAO,MAAK;IAAK,SAAS;cAC3D;IACY,CAAA,GAEjB;GACH,CAAC,UAAU,WACV,oBAAC,cAAD;IACE,SAAQ;IACR,OAAM;IACN,MAAK;IACL,cAAW;IACX,OAAM;IACN,SAAS;IACO;cAEhB,oBAAC,OAAD,EAAS,CAAA;IACI,CAAA;GAEJ"}
|