@persona/design-system 0.10.10 → 0.10.12
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 +48 -0
- package/dist/AdvancedFilterRuleRow.d.mts +5 -2
- package/dist/AdvancedFilterRulesPopover.d.mts +6 -2
- package/dist/ArrayValueControl.d.mts +1 -1
- package/dist/{Badge-BCdsVKuj.mjs → Badge-B2AJMf3d.mjs} +2 -2
- package/dist/{Badge-BCdsVKuj.mjs.map → Badge-B2AJMf3d.mjs.map} +1 -1
- package/dist/BooleanValueControl.d.mts +1 -1
- package/dist/{Breadcrumbs-CMf3Uvow.mjs → Breadcrumbs-DRs9eo1o.mjs} +5 -5
- package/dist/Breadcrumbs-DRs9eo1o.mjs.map +1 -0
- package/dist/{CardV2-CrV6eEQb.mjs → CardV2-DO-8COfu.mjs} +11 -8
- package/dist/CardV2-DO-8COfu.mjs.map +1 -0
- package/dist/ChartFrame.d.mts +61 -0
- package/dist/ChartLegend.d.mts +60 -0
- package/dist/ChartPopover.d.mts +155 -0
- package/dist/{Checkbox-Dr4LMKHV.mjs → Checkbox-BAh-wF_F.mjs} +5 -5
- package/dist/Checkbox-BAh-wF_F.mjs.map +1 -0
- package/dist/{CheckboxGroupField-Bpu2j6G2.d.mts → CheckboxGroupField-XSVAmESI.d.mts} +2 -2
- package/dist/CheckboxGroupField.d.mts +1 -1
- package/dist/ChoicesValueControl.d.mts +1 -1
- package/dist/{Combobox-Gb_j1dg6.mjs → Combobox-BNjYEAmv.mjs} +313 -138
- package/dist/Combobox-BNjYEAmv.mjs.map +1 -0
- package/dist/Combobox-DbcSss15.d.mts +12 -0
- package/dist/Combobox.d.mts +3 -3
- package/dist/{ComboboxBase-BPXqJHaQ.d.mts → ComboboxBase-CrFweFGi.d.mts} +61 -21
- package/dist/ComboboxBase.d.mts +2 -2
- package/dist/{ComboboxMultiSelect-BwkkSymj.d.mts → ComboboxMultiSelect-Cp5GBGQj.d.mts} +10 -6
- package/dist/ComboboxMultiSelect.d.mts +2 -2
- package/dist/{ComboboxSingleSelect-CdNNJNkp.d.mts → ComboboxSingleSelect-u7fK3Yvy.d.mts} +8 -6
- package/dist/ComboboxSingleSelect.d.mts +2 -2
- package/dist/{DataTable-BE9inUi-.d.mts → DataTable-C1mdfmQa.d.mts} +17 -7
- package/dist/{DataTable-CIZJ1vO8.mjs → DataTable-DdSY9mzT.mjs} +36 -23
- package/dist/DataTable-DdSY9mzT.mjs.map +1 -0
- package/dist/DataTable.d.mts +1 -1
- package/dist/{DatePicker-C9redLBr.mjs → DatePicker-DiilpYQg.mjs} +5 -5
- package/dist/{DatePicker-C9redLBr.mjs.map → DatePicker-DiilpYQg.mjs.map} +1 -1
- package/dist/DateRangeValueControl.d.mts +1 -1
- package/dist/DateValueControl.d.mts +1 -1
- package/dist/{DropdownButton-DpLG-cIj.mjs → DropdownButton-BxZ5hn0X.mjs} +3 -3
- package/dist/{DropdownButton-DpLG-cIj.mjs.map → DropdownButton-BxZ5hn0X.mjs.map} +1 -1
- package/dist/DropdownButton.d.mts +1 -1
- package/dist/{DropdownMenu-B6D4stkF.d.mts → DropdownMenu-CQR0U-zM.d.mts} +2 -2
- package/dist/{DropdownMenu-c8XK2Lr4.mjs → DropdownMenu-Ip75l4Th.mjs} +21 -2
- package/dist/DropdownMenu-Ip75l4Th.mjs.map +1 -0
- package/dist/DropdownMenu.d.mts +1 -1
- package/dist/{FieldRegistry-C2NVPhMO.d.mts → FieldRegistry-CJwGpUVK.d.mts} +2 -2
- package/dist/FieldRegistry.d.mts +1 -1
- package/dist/{FilterBar-BE_gBM0H.d.mts → FilterBar-CA4mDAXK.d.mts} +13 -5
- package/dist/FilterBar.d.mts +1 -1
- package/dist/FilterPickerMenu.d.mts +2 -2
- package/dist/FilterPill.d.mts +1 -1
- package/dist/FilterPopover.d.mts +1 -1
- package/dist/FloatValueControl.d.mts +3 -2
- package/dist/{FloatingToolbar-DLRaE0o7.mjs → FloatingToolbar-BA8Fqmrz.mjs} +35 -38
- package/dist/FloatingToolbar-BA8Fqmrz.mjs.map +1 -0
- package/dist/{FormControl-BztNXLn6.mjs → FormControl-BoKGiWdQ.mjs} +2 -2
- package/dist/{FormControl-BztNXLn6.mjs.map → FormControl-BoKGiWdQ.mjs.map} +1 -1
- package/dist/{FormField-Cf1VMvoa.mjs → FormField-yYJFkJ6R.mjs} +13 -13
- package/dist/{FormField-Cf1VMvoa.mjs.map → FormField-yYJFkJ6R.mjs.map} +1 -1
- package/dist/{HoverCopyableField-XHC_n9tp.mjs → HoverCopyableField-X2XfKTTh.mjs} +10 -5
- package/dist/HoverCopyableField-X2XfKTTh.mjs.map +1 -0
- package/dist/{IconButton-DxHB2g80.mjs → IconButton-Bj1fry_K.mjs} +4 -3
- package/dist/IconButton-Bj1fry_K.mjs.map +1 -0
- package/dist/IndexTableLayout.d.mts +11 -3
- package/dist/InlineCombobox.d.mts +1 -1
- package/dist/InlineInput.d.mts +1 -1
- package/dist/{Input-RHXujO9u.mjs → Input-DcbzPaax.mjs} +2 -2
- package/dist/{Input-RHXujO9u.mjs.map → Input-DcbzPaax.mjs.map} +1 -1
- package/dist/IntegerValueControl.d.mts +3 -2
- package/dist/{Link-D_kCyLYX.mjs → Link-B29ZMN6m.mjs} +3 -3
- package/dist/Link-B29ZMN6m.mjs.map +1 -0
- package/dist/{ListBox-BZp6exb8.mjs → ListBox-4rTgr3IJ.mjs} +6 -6
- package/dist/{ListBox-BZp6exb8.mjs.map → ListBox-4rTgr3IJ.mjs.map} +1 -1
- package/dist/{ListBox-DpFcM-dM.d.mts → ListBox-ZDaitaXR.d.mts} +2 -2
- package/dist/ListBox.d.mts +1 -1
- package/dist/{ListBoxField-DL6Zk8TU.d.mts → ListBoxField-CGvVWKyL.d.mts} +4 -4
- package/dist/ListBoxField.d.mts +1 -1
- package/dist/{LoadingShimmer-oPIv2ESr.mjs → LoadingShimmer-BVVdBeN-.mjs} +18 -20
- package/dist/LoadingShimmer-BVVdBeN-.mjs.map +1 -0
- package/dist/{LogicRow-BakOUtzx.d.mts → LogicRow-Bzp5o1sL.d.mts} +2 -2
- package/dist/LogicRow.d.mts +1 -1
- package/dist/{Menu-D6OrKCTC.d.mts → Menu-DviYNrFd.d.mts} +2 -2
- package/dist/Menu.d.mts +1 -1
- package/dist/{Modal-De5_bPJ_.mjs → Modal-CiPFqr0L.mjs} +52 -23
- package/dist/{Modal-De5_bPJ_.mjs.map → Modal-CiPFqr0L.mjs.map} +1 -1
- package/dist/{PageHeader-7_Hf6rHl.mjs → PageHeader-6KvtGED-.mjs} +2 -2
- package/dist/{PageHeader-7_Hf6rHl.mjs.map → PageHeader-6KvtGED-.mjs.map} +1 -1
- package/dist/{PageLayout-DjtGrvJa.mjs → PageLayout-CPiVnS_r.mjs} +3 -1
- package/dist/PageLayout-CPiVnS_r.mjs.map +1 -0
- package/dist/{Pagination-DMH2IaV0.mjs → Pagination-CqFvnlXc.mjs} +4 -4
- package/dist/{Pagination-DMH2IaV0.mjs.map → Pagination-CqFvnlXc.mjs.map} +1 -1
- package/dist/{Pii-24D_nSRQ.mjs → Pii-jSYND7Cn.mjs} +2 -2
- package/dist/{Pii-24D_nSRQ.mjs.map → Pii-jSYND7Cn.mjs.map} +1 -1
- package/dist/{PillShell-B7Bm-dsE.d.mts → PillShell-Bkyu5FXB.d.mts} +2 -2
- package/dist/PillShell.d.mts +1 -1
- package/dist/{Popover-DordjYNM.mjs → Popover-CVX-dfYb.mjs} +48 -18
- package/dist/Popover-CVX-dfYb.mjs.map +1 -0
- package/dist/{Radio-BlEtetrr.mjs → Radio-B1H_S-Qj.mjs} +2 -2
- package/dist/Radio-B1H_S-Qj.mjs.map +1 -0
- package/dist/{RadioGroup-CMrXmmn4.mjs → RadioGroup-7hdcVhsp.mjs} +2 -2
- package/dist/{RadioGroup-CMrXmmn4.mjs.map → RadioGroup-7hdcVhsp.mjs.map} +1 -1
- package/dist/RuleEditorFields.d.mts +2 -2
- package/dist/RulesPill.d.mts +1 -1
- package/dist/{SegmentedControl-D_DA-MU1.mjs → SegmentedControl-BNOJ1FYQ.mjs} +5 -2
- package/dist/SegmentedControl-BNOJ1FYQ.mjs.map +1 -0
- package/dist/{Select-DOlw_LPR.mjs → Select-DbWEgH5c.mjs} +5 -3
- package/dist/Select-DbWEgH5c.mjs.map +1 -0
- package/dist/{Select-CR9TjFfo.d.mts → Select-DsVeAyZy.d.mts} +2 -2
- package/dist/Select.d.mts +1 -1
- package/dist/SmartTextInputField.d.mts +2 -2
- package/dist/{Spinner-CXb-KUs1.mjs → Spinner-k9ZiOdTr.mjs} +1 -1
- package/dist/{Spinner-CXb-KUs1.mjs.map → Spinner-k9ZiOdTr.mjs.map} +1 -1
- package/dist/{Sticker-C1_6I08u.mjs → Sticker-4VdGEFAu.mjs} +2 -2
- package/dist/{Sticker-C1_6I08u.mjs.map → Sticker-4VdGEFAu.mjs.map} +1 -1
- package/dist/StringValueControl.d.mts +2 -1
- package/dist/{TabBar-BCFO38E0.mjs → TabBar-d4sdknti.mjs} +5 -5
- package/dist/TabBar-d4sdknti.mjs.map +1 -0
- package/dist/{Table-DPi4Dt5H.mjs → Table-9mNn8Q-d.mjs} +14 -6
- package/dist/Table-9mNn8Q-d.mjs.map +1 -0
- package/dist/{TableBox-DNQsgQ8x.mjs → TableBox-D9NA-s9l.mjs} +16 -12
- package/dist/TableBox-D9NA-s9l.mjs.map +1 -0
- package/dist/TableBox.d.mts +1 -1
- package/dist/{TableBoxCell-CsRt_5gP.d.mts → TableBoxCell-CQOL30et.d.mts} +4 -4
- package/dist/TableBoxCell.d.mts +1 -1
- package/dist/{TableBoxField-Db0Vjo6Z.d.mts → TableBoxField-z0GIFeQw.d.mts} +5 -5
- package/dist/TableBoxField.d.mts +1 -1
- package/dist/{TableBoxRow-exMlZyc4.d.mts → TableBoxRow-tb9-KMr9.d.mts} +2 -2
- package/dist/TableBoxRow.d.mts +1 -1
- package/dist/{TableBoxRowActions-UO9YN34k.d.mts → TableBoxRowActions-BZwulsFP.d.mts} +2 -2
- package/dist/TableBoxRowActions.d.mts +1 -1
- package/dist/{TableControls-BrP_BqnF.mjs → TableControls-BXykbUBf.mjs} +126 -40
- package/dist/TableControls-BXykbUBf.mjs.map +1 -0
- package/dist/{TableControls-Clo_0Mty.d.mts → TableControls-DE6eHq8h.d.mts} +4 -4
- package/dist/TableControls.d.mts +1 -1
- package/dist/{TableControlsContext-BNd6z9mD.d.mts → TableControlsContext-C2_2EuMh.d.mts} +2 -2
- package/dist/TableControlsContext.d.mts +1 -1
- package/dist/{TableViewConfigurationDropdown-Cp7ausV_.d.mts → TableViewConfigurationDropdown-DE9HFXYY.d.mts} +2 -2
- package/dist/TableViewConfigurationDropdown.d.mts +1 -1
- package/dist/{TechnicalSticker-Cq5jzYKQ.mjs → TechnicalSticker-DtV7Gawf.mjs} +5 -3
- package/dist/TechnicalSticker-DtV7Gawf.mjs.map +1 -0
- package/dist/{TextArea-Dro-HH8O.mjs → TextArea-CQ1YNi2b.mjs} +4 -5
- package/dist/TextArea-CQ1YNi2b.mjs.map +1 -0
- package/dist/{Toggle-D9MzTIZs.mjs → Toggle-CzHoIR-n.mjs} +8 -4
- package/dist/Toggle-CzHoIR-n.mjs.map +1 -0
- package/dist/{Tooltip-YViXzMdm.mjs → Tooltip-CVBxc1yf.mjs} +17 -4
- package/dist/Tooltip-CVBxc1yf.mjs.map +1 -0
- package/dist/chartColors.d.mts +92 -0
- package/dist/chartFrameLayout.d.mts +46 -0
- package/dist/{clientFilterUtils-CGHYF5NE.d.mts → clientFilterUtils-2TBUC31K.d.mts} +2 -2
- package/dist/clientFilterUtils.d.mts +1 -1
- package/dist/components/Accordion/index.mjs +22 -13
- package/dist/components/Accordion/index.mjs.map +1 -1
- package/dist/components/Attribute/index.mjs +6 -4
- package/dist/components/Attribute/index.mjs.map +1 -1
- package/dist/components/Badge/index.mjs +1 -1
- package/dist/components/Banner/index.mjs +1 -1
- package/dist/components/BottomPanel/index.mjs +7 -5
- package/dist/components/BottomPanel/index.mjs.map +1 -1
- package/dist/components/Breadcrumbs/index.mjs +1 -1
- package/dist/components/Button/index.mjs +1 -1
- package/dist/components/ButtonGroup/index.mjs +1 -1
- package/dist/components/CardV2/index.mjs +1 -1
- package/dist/components/Chart/index.d.mts +9 -0
- package/dist/components/Chart/index.mjs +680 -0
- package/dist/components/Chart/index.mjs.map +1 -0
- package/dist/components/Checkbox/index.mjs +1 -1
- package/dist/components/CodeHighlight/index.mjs +1 -1
- package/dist/components/Combobox/index.d.mts +5 -3
- package/dist/components/Combobox/index.mjs +1 -1
- package/dist/components/DataTable/TableControls/index.d.mts +19 -19
- package/dist/components/DataTable/TableControls/index.mjs +2 -2
- 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/DatePicker/index.mjs +1 -1
- package/dist/components/DropdownButton/index.mjs +1 -1
- package/dist/components/DropdownMenu/index.d.mts +1 -1
- package/dist/components/DropdownMenu/index.mjs +1 -1
- package/dist/components/FloatingPanel/index.mjs +16 -14
- package/dist/components/FloatingPanel/index.mjs.map +1 -1
- package/dist/components/FloatingToolbar/index.mjs +1 -1
- package/dist/components/FormControl/index.mjs +1 -1
- package/dist/components/FormField/index.d.mts +4 -4
- package/dist/components/FormField/index.mjs +1 -1
- package/dist/components/HoverCopyableField/index.mjs +1 -1
- package/dist/components/ImageTile/index.mjs +7 -7
- package/dist/components/ImageTile/index.mjs.map +1 -1
- package/dist/components/Input/index.mjs +1 -1
- package/dist/components/Link/index.mjs +1 -1
- package/dist/components/ListBox/index.d.mts +3 -3
- package/dist/components/ListBox/index.mjs +1 -1
- package/dist/components/LoadingShimmer/index.mjs +1 -1
- package/dist/components/MaskedInput/index.mjs +1 -1
- package/dist/components/Menu/index.d.mts +1 -1
- package/dist/components/Modal/index.mjs +1 -1
- package/dist/components/PageHeader/index.mjs +1 -1
- package/dist/components/Pagination/index.mjs +1 -1
- package/dist/components/Pii/index.mjs +1 -1
- package/dist/components/Popover/index.mjs +1 -1
- package/dist/components/ProgressBar/index.mjs +20 -3
- package/dist/components/ProgressBar/index.mjs.map +1 -1
- package/dist/components/Radio/index.mjs +1 -1
- package/dist/components/RadioGroup/index.mjs +1 -1
- package/dist/components/RichTextEditor/index.mjs +5 -5
- package/dist/components/RightPanel/index.mjs +28 -13
- package/dist/components/RightPanel/index.mjs.map +1 -1
- package/dist/components/SegmentedControl/index.mjs +1 -1
- package/dist/components/Select/index.d.mts +1 -1
- package/dist/components/Select/index.mjs +1 -1
- package/dist/components/SelectionCard/index.mjs +2 -2
- package/dist/components/Slider/index.mjs +3 -2
- package/dist/components/Slider/index.mjs.map +1 -1
- package/dist/components/SmartTextInput/index.mjs +9 -78
- package/dist/components/SmartTextInput/index.mjs.map +1 -1
- package/dist/{safe-parse.d.mts → components/SmartTextInput/parser/safe-parse.d.mts} +1 -1
- package/dist/components/SmartTextInput/parser/safe-parse.mjs +30 -0
- package/dist/components/SmartTextInput/parser/safe-parse.mjs.map +1 -0
- package/dist/{tree.d.mts → components/SmartTextInput/parser/tree.d.mts} +1 -1
- package/dist/components/SmartTextInput/parser/tree.mjs +42 -0
- package/dist/components/SmartTextInput/parser/tree.mjs.map +1 -0
- package/dist/components/Spinner/index.mjs +1 -1
- package/dist/components/Sticker/index.mjs +1 -1
- package/dist/components/SwatchPicker/index.mjs +2 -1
- package/dist/components/SwatchPicker/index.mjs.map +1 -1
- package/dist/components/TabBar/index.mjs +1 -1
- package/dist/components/Table/index.mjs +1 -1
- package/dist/components/TableBox/index.d.mts +1 -1
- package/dist/components/TableBox/index.mjs +1 -1
- package/dist/components/TechnicalSticker/index.mjs +1 -1
- package/dist/components/TextArea/index.mjs +1 -1
- package/dist/components/Tile/index.mjs +2 -2
- package/dist/components/Toast/index.mjs +16 -10
- package/dist/components/Toast/index.mjs.map +1 -1
- package/dist/components/Toggle/index.mjs +1 -1
- package/dist/components/Tooltip/index.mjs +1 -1
- package/dist/components/VersionHistory/index.mjs +5 -5
- package/dist/compound-expression.d.mts +1 -1
- package/dist/{date-range-rule-value-ASr06ClE.d.mts → date-range-rule-value-DyLlMtjr.d.mts} +2 -2
- package/dist/date-range-rule-value.d.mts +1 -1
- package/dist/display.d.mts +1 -1
- package/dist/duration-token.d.mts +11 -0
- package/dist/exit-motion.d.mts +7 -0
- package/dist/fieldPickerOptions.d.mts +2 -2
- package/dist/{filter-size-context-CmFyIPCm.d.mts → filter-size-context-DVnjmuhk.d.mts} +2 -2
- package/dist/filter-size-context.d.mts +1 -1
- package/dist/{filters-DTBc0mE7.d.mts → filters-DW7pqWv3.d.mts} +2 -2
- package/dist/filters.d.mts +1 -1
- package/dist/{helpers-CBJ2AqGZ.d.mts → helpers-BTD2kXLs.d.mts} +2 -2
- package/dist/helpers.d.mts +1 -1
- package/dist/{index-OkdnW-u5.d.mts → index-B4tE0RxY.d.mts} +3 -3
- package/dist/{index-kIon1vPp.d.mts → index-DTM_t7OG.d.mts} +2 -2
- package/dist/index4.d.mts +3 -3
- package/dist/index5.d.mts +1 -1
- package/dist/index6.d.mts +14 -14
- package/dist/{inputFields-DpHeZiFX.d.mts → inputFields-DnBb3NhK.d.mts} +4 -4
- package/dist/inputFields.d.mts +1 -1
- package/dist/lib/TruncatedTextWithTooltip.mjs +1 -1
- package/dist/lib/useCloseFocus.d.mts +45 -0
- package/dist/lib/useCloseFocus.mjs +123 -0
- package/dist/lib/useCloseFocus.mjs.map +1 -0
- package/dist/lib/useModalInsetRight.d.mts +4 -3
- package/dist/lib/useModalInsetRight.mjs +7 -5
- package/dist/lib/useModalInsetRight.mjs.map +1 -1
- package/dist/lint/THIRD_PARTY_NOTICES.md +30 -0
- package/dist/lint/index.mjs +696 -11
- package/dist/lint/index.mjs.map +1 -1
- package/dist/lint/recommended.json +7 -1
- package/dist/mixins/hoverable.mjs +1 -1
- package/dist/mixins/hoverable.mjs.map +1 -1
- package/dist/mixins/input.mjs +1 -0
- package/dist/mixins/input.mjs.map +1 -1
- package/dist/mixins/menuItem.mjs +2 -0
- package/dist/mixins/menuItem.mjs.map +1 -1
- package/dist/mixins/motion.d.mts +28 -0
- package/dist/mixins/motion.mjs +66 -0
- package/dist/mixins/motion.mjs.map +1 -0
- package/dist/motion-origin.d.mts +7 -0
- package/dist/motion.d.mts +63 -0
- package/dist/no-layout-motion.d.mts +7 -0
- package/dist/no-transition-all.d.mts +7 -0
- package/dist/{operators-BHxKZcpD.d.mts → operators-B8_k3r69.d.mts} +10 -3
- package/dist/operators.d.mts +2 -2
- package/dist/overlay-motion.d.mts +7 -0
- package/dist/patterns/CardGrouping/index.mjs +6 -6
- package/dist/patterns/CardGrouping/index.mjs.map +1 -1
- package/dist/patterns/IndexTableLayout/index.mjs +23 -16
- package/dist/patterns/IndexTableLayout/index.mjs.map +1 -1
- package/dist/patterns/LayoutLoadingShimmer/index.mjs +4 -4
- package/dist/patterns/LayoutLoadingSpinner/index.mjs +3 -1
- package/dist/patterns/LayoutLoadingSpinner/index.mjs.map +1 -1
- package/dist/patterns/PageLayout/index.mjs +1 -1
- package/dist/patterns/WizardModal/index.mjs +2 -2
- package/dist/relative-date-label.d.mts +1 -1
- package/dist/{types-DLnCkvTt.d.mts → types-BJqmRXFV.d.mts} +15 -1
- package/dist/{types-CqcbWyUY.d.mts → types-BOsCi-kZ.d.mts} +8 -2
- package/dist/{types-BiqzeNsa.d.mts → types-Dws2XDz2.d.mts} +2 -2
- package/dist/{types-BEdERA4v.d.mts → types-NO2GRlM-.d.mts} +2 -2
- package/dist/types4.d.mts +1 -1
- package/dist/types5.d.mts +1 -1
- package/dist/types6.d.mts +1 -1
- package/dist/{url-state-CXUuK3_r.d.mts → url-state-CXPmXzIZ.d.mts} +2 -2
- package/dist/url-state.d.mts +1 -1
- package/dist/useChartColors.d.mts +30 -0
- package/dist/useChartSeriesVisibility.d.mts +22 -0
- package/dist/useChartStyles.d.mts +108 -0
- package/dist/useColumnConfiguration.d.mts +2 -2
- package/dist/useComboboxFooterAction.d.mts +1 -1
- package/dist/{useFilterStateV2-DBpbxAEC.d.mts → useFilterStateV2-DiTS9DTg.d.mts} +3 -3
- package/dist/useFilterStateV2.d.mts +1 -1
- package/dist/{useTableColumns-Xd14vx_h.d.mts → useTableColumns-tITjHasE.d.mts} +2 -2
- package/dist/useTableColumns.d.mts +1 -1
- package/dist/useTruncation.d.mts +1 -1
- package/dist/useValueControlError.d.mts +26 -0
- package/dist/utils.d.mts +1 -1
- package/dist/{validation-Tgg3AhuP.d.mts → validation-BDQdQ1cY.d.mts} +3 -3
- package/dist/validation.d.mts +1 -1
- package/dist/{value-control-resolver-XQbGCdsP.d.mts → value-control-resolver-BFJZEWDn.d.mts} +9 -3
- package/dist/value-control-resolver.d.mts +1 -1
- package/dist/value-labels.d.mts +12 -0
- package/dist/variables/keyframes.d.mts +2 -1
- package/dist/variables/keyframes.mjs +9 -1
- package/dist/variables/keyframes.mjs.map +1 -1
- package/dist/variables/transitions.d.mts +31 -1
- package/dist/variables/transitions.mjs +50 -1
- package/dist/variables/transitions.mjs.map +1 -1
- package/llms.txt +2 -1
- package/package.json +20 -4
- package/skills/new-screen/SKILL.md +33 -0
- package/skills/ui-authoring/COMPONENTS.md +19 -1
- package/skills/ui-authoring/PATTERNS.md +57 -36
- package/skills/ui-authoring/STANDARD.md +78 -4
- package/skills/ui-authoring/TOKENS.md +27 -24
- package/dist/Breadcrumbs-CMf3Uvow.mjs.map +0 -1
- package/dist/CardV2-CrV6eEQb.mjs.map +0 -1
- package/dist/Checkbox-Dr4LMKHV.mjs.map +0 -1
- package/dist/Combobox-CIKqTYZt.d.mts +0 -11
- package/dist/Combobox-Gb_j1dg6.mjs.map +0 -1
- package/dist/DataTable-CIZJ1vO8.mjs.map +0 -1
- package/dist/DropdownMenu-c8XK2Lr4.mjs.map +0 -1
- package/dist/FloatingToolbar-DLRaE0o7.mjs.map +0 -1
- package/dist/HoverCopyableField-XHC_n9tp.mjs.map +0 -1
- package/dist/IconButton-DxHB2g80.mjs.map +0 -1
- package/dist/Link-D_kCyLYX.mjs.map +0 -1
- package/dist/LoadingShimmer-oPIv2ESr.mjs.map +0 -1
- package/dist/PageLayout-DjtGrvJa.mjs.map +0 -1
- package/dist/Popover-DordjYNM.mjs.map +0 -1
- package/dist/Radio-BlEtetrr.mjs.map +0 -1
- package/dist/SegmentedControl-D_DA-MU1.mjs.map +0 -1
- package/dist/Select-DOlw_LPR.mjs.map +0 -1
- package/dist/TabBar-BCFO38E0.mjs.map +0 -1
- package/dist/Table-DPi4Dt5H.mjs.map +0 -1
- package/dist/TableBox-DNQsgQ8x.mjs.map +0 -1
- package/dist/TableControls-BrP_BqnF.mjs.map +0 -1
- package/dist/TechnicalSticker-Cq5jzYKQ.mjs.map +0 -1
- package/dist/TextArea-Dro-HH8O.mjs.map +0 -1
- package/dist/Toggle-D9MzTIZs.mjs.map +0 -1
- package/dist/Tooltip-YViXzMdm.mjs.map +0 -1
|
@@ -17,6 +17,7 @@ exists. If there is no `.mdx`, use the published type declarations
|
|
|
17
17
|
| `Button` | Triggering an action. Use `IconButton` when there is no label | `@persona/design-system/components/Button` |
|
|
18
18
|
| `ButtonGroup` | Choosing among related modes in a compact connected button set (often icons, e.g. alignment). Use `Toggle` for a single on/off setting; `RadioGroup` for a visible list of labeled choices | `@persona/design-system/components/ButtonGroup` |
|
|
19
19
|
| `Card` + `Card.Section` | Grouping related content and actions so they're easier to scan. Collapsible sections on long settings pages | `@persona/design-system/components/CardV2` |
|
|
20
|
+
| `ChartFrame`, `ChartLegend`, `ChartPopover` | Experimental (beta). Charts built on `recharts` (optional peer, 2.x or 3.x): `ChartFrame` lays out legend and plot, `ChartLegend` keys and toggles series, `ChartPopover` is the `<Tooltip>` content. Colour series with `useChartColors` / `resolveSeriesColors`; style hand-built Recharts parts with `useChartStyles`. See Storybook Charts → Design | `@persona/design-system/components/Chart` |
|
|
20
21
|
| `Checkbox` | Selecting one or more options from a visible list | `@persona/design-system/components/Checkbox` |
|
|
21
22
|
| `Combobox` | Picking from a long list that needs search (single or multi). Use `RadioGroup` when every choice should stay visible (one); `Checkbox` when every choice should stay visible (several); `Select` for a short closed list with no search | `@persona/design-system/components/Combobox` |
|
|
22
23
|
| `ConfigFormGroup` | Form fields — spacing a group of config fields and setting `configField` via context. Pair with `TextField` / `TextAreaField` | `@persona/design-system/components/ConfigFormGroup` |
|
|
@@ -25,7 +26,7 @@ exists. If there is no `.mdx`, use the published type declarations
|
|
|
25
26
|
| `SplitColumnLayout` | An 8:4 main and aside page. Same optional regions as `SingleColumnLayout`. Stacks main then aside below 768px | `@persona/design-system/patterns/PageLayout` |
|
|
26
27
|
| `DataTable` | Data table — browsing tabular data with filtering, bulk actions, search, pagination, and sorting | `@persona/design-system/components/DataTable` |
|
|
27
28
|
| `IndexTableLayout` | Standard page shell for a DataTable index; hosts supply controls and own saved-view persistence | `@persona/design-system/patterns/IndexTableLayout` |
|
|
28
|
-
| `FilterBar` | Structured filters with native Rules; opt-in field `condition`, `pickerGroup`, and `disabledReason` support individual host-defined predicates. Hosts own flags and serialization; see DataTable.mdx | `@persona/design-system/components/DataTable/TableControls` |
|
|
29
|
+
| `FilterBar` | Structured filters with native Rules; opt-in field `condition`, `pickerGroup`, and `disabledReason` support individual host-defined predicates. Optional `getValueLabel(fieldId, value)` supplies display-only choice labels for pills/Rules before registry/raw fallbacks. Hosts re-render when names arrive and own fetching, editors, flags and serialization; see DataTable.mdx | `@persona/design-system/components/DataTable/TableControls` |
|
|
29
30
|
| `DatePicker` | Picking a date or date range from a calendar | `@persona/design-system/components/DatePicker` |
|
|
30
31
|
| `DropdownButton` | Opening a menu of related actions from a button | `@persona/design-system/components/DropdownButton` |
|
|
31
32
|
| `DropdownMenu` | Showing a temporary action list on a custom trigger | `@persona/design-system/components/DropdownMenu` |
|
|
@@ -81,6 +82,23 @@ exists. If there is no `.mdx`, use the published type declarations
|
|
|
81
82
|
| `VersionHistory` | Show previous versions of a file and let the user compare or restore one | `@persona/design-system/components/VersionHistory` |
|
|
82
83
|
|
|
83
84
|
|
|
85
|
+
## Server-backed Combobox
|
|
86
|
+
|
|
87
|
+
`filterMode='server'` requires flat `options`, a controlled `query` / `onQueryChange` pair and
|
|
88
|
+
`selectedOptions` for every selected value, including off-page values. Query text is separate from
|
|
89
|
+
the selected label: only native edits call `onQueryChange`; selection and menu transitions do not
|
|
90
|
+
change it. `onInputChange` and grouped/nested browsing stay client-mode only. PDS bypasses Fuse and
|
|
91
|
+
hides built-in Select all in server mode. Missing selection metadata has a `String(value)` safety
|
|
92
|
+
fallback, not a selection cache. Your hook owns debounce, requests, cancellation and accumulated
|
|
93
|
+
pages. Wire `onScrollEnd={loadMore}` for near-end reports and `isLoadingMore` for the optional loading
|
|
94
|
+
row. Calls may repeat; the caller ignores duplicate/loading/exhausted requests. PDS has no
|
|
95
|
+
`hasMore` or request lock and re-checks short lists only on open/count changes, not loading changes.
|
|
96
|
+
Use generic `footerAction` for error retries. Keep `isOptionsLoading={isInitialLoading || isSearching}`
|
|
97
|
+
for initial/replacement searches (`isSearching` includes debounce and page-1 requests); clear stale
|
|
98
|
+
options if a replacement fails. Existing prop
|
|
99
|
+
types and FormField/table wrappers remain client-only; separate `ComboboxServer*Props` types are
|
|
100
|
+
exported for direct server Combobox use. See Combobox.mdx.
|
|
101
|
+
|
|
84
102
|
## Testing
|
|
85
103
|
|
|
86
104
|
```tsx
|
|
@@ -11,7 +11,7 @@ Which pattern to use, and for what. Patterns with a dedicated doc link to
|
|
|
11
11
|
| [Forms](../../patterns/Forms/Forms.mdx) | Labeled fields in a `Modal`, `RightPanel`, or page. Unlabeled controls (search, toolbars) stay as `Input` |
|
|
12
12
|
| Stack / HStack | A heading above content, a cancel/save pair, a title next to an add button, or a wrapping row of tags |
|
|
13
13
|
| EmptyStates | A list, table, or card has no items yet and you want to invite adding one |
|
|
14
|
-
| Charting |
|
|
14
|
+
| Charting | Build charts with `recharts` and the experimental `@persona/design-system/components/Chart` pieces; colour series from the chart palettes, never hex |
|
|
15
15
|
| Indicators | A record’s open, pending, completed, or failed state next to other content. An in-page notice the user shouldn’t miss (success, warning, error). Use `Toast` if it can auto-dismiss |
|
|
16
16
|
| [SingleColumnLayout](../../patterns/PageLayout/SingleColumnLayout.mdx) | One page column under `PageHeader`, with optional tabs and a page notice. `width="wide"` uses the fluid grid |
|
|
17
17
|
| [SplitColumnLayout](../../patterns/PageLayout/SplitColumnLayout.mdx) | An 8:4 main and aside page. Same optional regions. Stacks main then aside below 768px |
|
|
@@ -20,20 +20,24 @@ Which pattern to use, and for what. Patterns with a dedicated doc link to
|
|
|
20
20
|
| LayoutLoadingShimmer | Filling space while content loads |
|
|
21
21
|
| [Panels](../../patterns/Panels/Panels.mdx) | Use `RightPanel` when the page should stay visible. Use `Modal` when the task needs full attention. Never a custom drawer. |
|
|
22
22
|
| [WizardModal](../../patterns/WizardModal/WizardModal.mdx) | A linear multi-step task behind a page overlay. |
|
|
23
|
-
| [Versioned resources: Page header](../../patterns/VersionedResources/VersionedResourcePageHeader.mdx) | Header order for a versioned resource (template,
|
|
23
|
+
| [Versioned resources: Page header](../../patterns/VersionedResources/VersionedResourcePageHeader.mdx) | Header order for a versioned resource (template, policy, workflow): breadcrumbs → object status (icon) → deployment status (no icon) → version status (no icon) → actions (optional Last updated caption, then buttons, one primary rightmost). A code example, not a component: copy the stories and compose `PageHeader` + `StatusIndicator`; there is nothing to import |
|
|
24
24
|
| [CardGrouping](../../patterns/CardGrouping/CardGrouping.mdx) | Distinct records as cards in collapsible groups, for a clean view rather than querying or filtering. Optional controls sit under the list description |
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
## Page layouts
|
|
28
28
|
|
|
29
|
-
Index pages backed by `DataTable` use `IndexTableLayout`, which
|
|
30
|
-
`
|
|
29
|
+
Index pages backed by `DataTable` use `IndexTableLayout`, which composes `PageHeader`,
|
|
30
|
+
`SingleColumnLayout` (wide by default), and `Card`; don't wrap it in `Container` or `Section`.
|
|
31
|
+
Import it from `@persona/design-system/patterns/IndexTableLayout`;
|
|
31
32
|
never copy it, persona-web's `DashboardDataTable` wrapper (PDS does not ship one), or
|
|
32
33
|
`TableControls`/filter panels into an app. Pass app-specific filters through the `controls` prop
|
|
33
34
|
(`controls={{ filters, filterResolver }}` or `controls={{ filterPanel }}`), and if the pattern lacks
|
|
34
35
|
a slot you need, add it here instead of forking the layout. Other pages render `PageHeader`, then `SingleColumnLayout` or
|
|
35
36
|
`SplitColumnLayout`. Do not wrap those templates in `Container` or `Section`.
|
|
36
37
|
|
|
38
|
+
For bulk actions on an index page, always set `floatingBulkActions` with `bulkActions` or
|
|
39
|
+
`getAvailableBulkActions`; inline bulk-action buttons in the table controls are legacy.
|
|
40
|
+
|
|
37
41
|
```tsx
|
|
38
42
|
import Header from '@persona/design-system/components/PageHeader';
|
|
39
43
|
import { SingleColumnLayout, SplitColumnLayout } from '@persona/design-system/patterns/PageLayout';
|
|
@@ -299,44 +303,61 @@ For `Card.Section`, pass `empty={true}` to show the built-in empty state.
|
|
|
299
303
|
|
|
300
304
|
## Charting
|
|
301
305
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
import { ChartingColors } from '@persona/design-tokens';
|
|
306
|
+
Experimental (beta). Build charts with `recharts` (an optional peer, 2.x or 3.x) and the pieces in
|
|
307
|
+
`@persona/design-system/components/Chart`. Full usage guidance comes later; until then see Storybook
|
|
308
|
+
**Charts → Design** (Chart frame, Elements, Themes) and **Charts → Chart types** (Bar chart, Line
|
|
309
|
+
chart).
|
|
307
310
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
+
- `ChartFrame`: legend and plot layout, full width, 300px plot height by default.
|
|
312
|
+
- `ChartLegend`: series key; with `onToggle` (and `useChartSeriesVisibility`) it shows and hides series.
|
|
313
|
+
- `ChartPopover`: the content of a Recharts `<Tooltip>`.
|
|
314
|
+
- `useChartStyles()`: PDS props for Recharts' grid, axes and tooltip cursor in a hand-built chart.
|
|
315
|
+
- `useChartColors()` / `resolveSeriesColors()`: series colours from a chart palette.
|
|
311
316
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
317
|
+
```tsx
|
|
318
|
+
import {
|
|
319
|
+
ChartFrame,
|
|
320
|
+
ChartLegend,
|
|
321
|
+
ChartPopover,
|
|
322
|
+
CHART_PLOT_MARGIN,
|
|
323
|
+
useChartColors,
|
|
324
|
+
useChartStyles,
|
|
325
|
+
} from '@persona/design-system/components/Chart';
|
|
326
|
+
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
|
|
327
|
+
|
|
328
|
+
const colors = useChartColors().resolve(series); // { [series.key]: Color }
|
|
329
|
+
const styles = useChartStyles();
|
|
330
|
+
const items = series.map((s) => ({ ...s, color: colors[s.key] }));
|
|
331
|
+
|
|
332
|
+
<ChartFrame aria-label='Tickets by status' legend={<ChartLegend items={items} />}>
|
|
333
|
+
<ResponsiveContainer width='100%' height='100%'>
|
|
334
|
+
<BarChart data={data} margin={CHART_PLOT_MARGIN}>
|
|
335
|
+
<Tooltip cursor={styles.barCursor} content={<ChartPopover series={items} />} />
|
|
336
|
+
<CartesianGrid {...styles.grid} />
|
|
337
|
+
<XAxis dataKey='month' {...styles.xAxis} />
|
|
338
|
+
<YAxis {...styles.yAxis} />
|
|
339
|
+
{items.map((s) => <Bar key={s.key} dataKey={s.key} name={s.label} fill={s.color} />)}
|
|
340
|
+
</BarChart>
|
|
341
|
+
</ResponsiveContainer>
|
|
342
|
+
</ChartFrame>
|
|
315
343
|
```
|
|
316
344
|
|
|
317
|
-
###
|
|
345
|
+
### Palettes
|
|
318
346
|
|
|
319
|
-
| Data
|
|
320
|
-
|
|
321
|
-
|
|
|
322
|
-
|
|
|
347
|
+
| Data | Palette (`useChartColors(palette)`) | Colours |
|
|
348
|
+
|------|-------------------------------------|---------|
|
|
349
|
+
| Distinct, unordered series (default) | `'qualitative'` | 12 |
|
|
350
|
+
| Ordered magnitude in one hue | `'sequentialMono'` | 8 |
|
|
351
|
+
| Values diverging around a midpoint | `'sequentialDivergent'` | 10 |
|
|
323
352
|
|
|
324
|
-
|
|
353
|
+
Take Qualitative colours in palette order: the order is tuned for readability. Override a series
|
|
354
|
+
only with a Persona token, `chartColor(Color.X)` or a `{ light, dark }` pair of tokens; never hex.
|
|
325
355
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
<PieChart>
|
|
331
|
-
<Pie data={data} dataKey="value">
|
|
332
|
-
{data.map((_, i) => (
|
|
333
|
-
<Cell key={i} fill={ChartingColors.Categorical[i % ChartingColors.Categorical.length]} />
|
|
334
|
-
))}
|
|
335
|
-
</Pie>
|
|
336
|
-
</PieChart>
|
|
337
|
-
```
|
|
356
|
+
**Legacy:** `ChartingColors.Sequential` and `ChartingColors.Categorical` from
|
|
357
|
+
`@persona/design-tokens` are deprecated for new charts. Existing charts may keep them until they
|
|
358
|
+
move to the palettes above.
|
|
338
359
|
|
|
339
360
|
**Anti-patterns:**
|
|
340
|
-
- Hardcoding hex values
|
|
341
|
-
-
|
|
342
|
-
- Using `
|
|
361
|
+
- Hardcoding hex values for series colours
|
|
362
|
+
- Picking Qualitative colours out of order
|
|
363
|
+
- Using `'sequentialMono'` for unordered categories
|
|
@@ -27,7 +27,7 @@ PDH-P1 (honesty) and PDH-P2 (brand) rank first and second. Then:
|
|
|
27
27
|
| PDH-F1 contrast | The core value, WCAG 2.2 AA, in every colour mode the screen ships (light and dark) |
|
|
28
28
|
| PDH-F2 copy | **11 CSS px** for text the user reads, the core web-copy value. 10 px styles are below it (see Checks); use `TextSmall` or `TextSmallMono` (12 px) |
|
|
29
29
|
| PDH-F2 label inside a graphic | **8 CSS px** for a label inside a chart, a diagram or rebuilt product UI, the core value |
|
|
30
|
-
| PDH-F3 reduced motion | Every animation and transition honours `prefers-reduced-motion
|
|
30
|
+
| PDH-F3 reduced motion | Every animation and transition honours `prefers-reduced-motion` with a 150 ms opacity fade and no movement, never an instant change (see [Motion scale](#motion-scale)); flashing follows PDH-F3 |
|
|
31
31
|
| PDH-F4 status | An icon or label as well as colour. `StatusIndicator` and `Sticker` already do this |
|
|
32
32
|
|
|
33
33
|
Product UI shown in a fixed frame (a slide, a video) takes the core's fixed-frame value instead.
|
|
@@ -55,6 +55,9 @@ Record these in the PR body before building, so the source is consulted at intak
|
|
|
55
55
|
- **Source:** the live product, a Figma link, or none. Say so if a source couldn't be reached.
|
|
56
56
|
- **PDS version:** from the app's lockfile.
|
|
57
57
|
- **Brand:** `persona`.
|
|
58
|
+
- **State changes:** one row each, naming a PDS component's motion, a usage row from the
|
|
59
|
+
[motion scale](#motion-scale) or `instant` (the `new-screen` skill's table).
|
|
60
|
+
|
|
58
61
|
## New screens
|
|
59
62
|
|
|
60
63
|
Building one new screen, with no designer (App Builder, internal apps)? Follow the `new-screen`
|
|
@@ -62,6 +65,52 @@ skill (`intent load @persona/design-system#new-screen`): build only from PDS pat
|
|
|
62
65
|
tokens, keep the change to the screen, and don't touch shared components, the theme or code copied
|
|
63
66
|
from PDS. Work that doesn't fit stays out of that change, through normal review.
|
|
64
67
|
|
|
68
|
+
## Motion scale
|
|
69
|
+
|
|
70
|
+
Motion values come from `@persona/design-system/variables/transitions`: `TransitionDuration` in CSS,
|
|
71
|
+
`TransitionDurationInSeconds` in framer-motion, `TransitionEasing` (CSS) or `TransitionEasingCurve`
|
|
72
|
+
(framer-motion), and `ReducedMotionFade`. Pick the row by what the motion is for, not by the
|
|
73
|
+
nearest number.
|
|
74
|
+
|
|
75
|
+
| Usage | Open or in | Close or out | Reduced motion |
|
|
76
|
+
| ----- | ---------- | ------------ | -------------- |
|
|
77
|
+
| Feedback on text or an icon (hover, press) | `ExtraFast`, `Move` | same | same |
|
|
78
|
+
| Feedback on a surface (row, card, menu item, pill hover; selection) | `Fast`, `Move` | same | same |
|
|
79
|
+
| Control state (checkbox, radio, toggle, tab, segmented control, focus ring) | `Fast`, `Move` | same | colour as in full; travel jumps |
|
|
80
|
+
| Hover reveal (row actions, copy button, inserter) | `Fast`, `Enter` | `Faster`, `Exit` | fade |
|
|
81
|
+
| Tooltip | `Fast`, `Enter`, after the 300 ms open delay | `Faster`, `Exit`, no delay | fade |
|
|
82
|
+
| Popover, menu, select or combobox list: fade and scale from 0.96 at the trigger's edge | `Fast`, `Enter` | `Faster`, `Exit`, focus returning when the close starts; `modal` content, Select and Combobox close at once | fade |
|
|
83
|
+
| Modal: overlay fade, card rises 8 px | `Fast`, `Enter` | `Faster`, `Exit`, fade only | fade |
|
|
84
|
+
| Toast: fade, rise and scale from 0.96 | `Medium`, `Enter` | `MediumFast`, `Exit` | fade |
|
|
85
|
+
| Side panel | `Medium`, `Enter` | `MediumFast`, `Exit` | size jumps; content fades |
|
|
86
|
+
| Expand and collapse (accordion height, chevrons) | `Fast`, `Move` | `Fast`, `Move` | height jumps; content fades |
|
|
87
|
+
| Panel resize or full size | `Medium`, `Move` | same | size jumps; content fades |
|
|
88
|
+
| Value change (progress fill) | `MediumFast`, `Move` | same | jumps |
|
|
89
|
+
| Loader reveal, so a fast load doesn't flash a spinner | 500 ms delay, then `Fast`, `Enter` | | same |
|
|
90
|
+
| Loop (spinner, shimmer) | its own period, `Linear` or `Move` | | spinners keep turning; shimmers and skeletons hold still |
|
|
91
|
+
|
|
92
|
+
"Fade" is `ReducedMotionFade`: opacity only, `Faster` (150 ms) on `Move`, at the same cue, with no
|
|
93
|
+
translate, scale or size change. Colour isn't movement, so a colour change keeps its full timing.
|
|
94
|
+
|
|
95
|
+
- **Closes are one step faster than opens** (`Fast` to `Faster`, `Medium` to `MediumFast`). Never delay
|
|
96
|
+
a close or a hover-out; a delay only filters accidental triggers.
|
|
97
|
+
- **Enter on `Enter`, leave on `Exit`, change on `Move`.** None of the curves overshoot.
|
|
98
|
+
- **Nothing over `Medium` (400 ms) is a state change.** `OneSecond` is for loop periods.
|
|
99
|
+
- **Prefer CSS for motion.** Use `transition` or styled-components `keyframes` whenever CSS can
|
|
100
|
+
express the motion, and always for loops (shimmers, pulses, spinners) and simple enter, exit or
|
|
101
|
+
state changes. Use framer-motion only for what CSS can't do: layout or shared-element animation,
|
|
102
|
+
drag and gesture, spring physics, or exit coordination where there is no `[data-exiting]` or
|
|
103
|
+
`[data-state='closed']` hook. A JavaScript animation runs on the main thread every frame, and an
|
|
104
|
+
infinite one can keep an unmounted screen's DOM alive.
|
|
105
|
+
- **Exits are keyframe animations** on `[data-exiting]` (React Aria) or `[data-state='closed']`
|
|
106
|
+
(Radix), because both unmount when the element's animations finish.
|
|
107
|
+
- **Focus leaves when the close starts, not when the exit ends.** Radix returns focus only at
|
|
108
|
+
unmount, so PDS's Popover, DropdownMenu and AdvancedFilterRulesPopover use `useCloseFocus`
|
|
109
|
+
(`@persona/design-system/lib/useCloseFocus`): it runs `onCloseAutoFocus` and focuses the trigger
|
|
110
|
+
at close start, and makes the closing content inert. Raw Radix content with an exit uses it too.
|
|
111
|
+
|
|
112
|
+
persona-motion owns the motion language these rules come from; PDS owns the values.
|
|
113
|
+
|
|
65
114
|
## Checks
|
|
66
115
|
|
|
67
116
|
The automated rows below are lint rules, shipped in this package as an [oxlint](https://oxc.rs) JS
|
|
@@ -71,11 +120,17 @@ the standard it has installed.
|
|
|
71
120
|
|
|
72
121
|
| Rule | Source | Lint rule |
|
|
73
122
|
| ---- | ------ | --------- |
|
|
74
|
-
| Painted colours are semantic: no hex, no `Color.*` outside the `semanticColor` fallback | PDS; keeps PDH-F1 in dark mode | `pds/semantic-color`, error |
|
|
123
|
+
| Painted colours are semantic: no hex, no `Color.*` outside the `semanticColor` fallback or a `chartColor(...)` chart series override | PDS; keeps PDH-F1 in dark mode | `pds/semantic-color`, error |
|
|
75
124
|
| Complete `Typography` styles, never individual font properties or a raw `font-size` | PDS; makes PDH-F2 checkable | `pds/complete-typography`, error |
|
|
76
125
|
| No copy under 11 px. The 10 px routes are `Typography.TextExtraSmall` and `TextExtraSmallMono`, `theme.text.paragraph.xs`, the text mixin's `xs` (`Paragraph` / `Label` `size="xs"`), and the `TextMono` + `TextExtraSmall.fontSize` composite | PDH-F2 | `pds/min-copy-size`, warning: a lint rule can't tell copy from a label inside a graphic |
|
|
77
126
|
| `@keyframes`, `animation` or `transition` only with a `prefers-reduced-motion` block | PDH-F3 | `pds/reduced-motion`, warning |
|
|
78
127
|
| No hand-rolled `<table>`, `<th>` or `<td>` | PDS (Table Guidelines in SKILL.md) | `pds/no-raw-table`, error |
|
|
128
|
+
| What animates in also animates out: a styled overlay (modal, dialog, drawer, sheet, popover, menu, dropdown, tooltip, toast or backdrop) with an enter animation has an exit, and any conditionally rendered `motion.*` element with `initial` has `exit` (a swap between two elements outside `AnimatePresence` is a content change and isn't reported) | PDS motion | `pds/exit-motion`, warning |
|
|
129
|
+
| A hand-rolled overlay (a fixed or absolute styled component named like one, or a fixed backdrop) has a transition or animation | PDS motion | `pds/overlay-motion`, warning |
|
|
130
|
+
| A menu, dropdown or popover that scales up from below 1 sets `transform-origin`, so it grows from its trigger | PDS motion | `pds/motion-origin`, warning |
|
|
131
|
+
| Transitions and keyframes animate `transform` and `opacity`, not layout (`width`, `height`, `top`, `margin`…) | PDS motion | `pds/no-layout-motion`, warning |
|
|
132
|
+
| No `transition: all` (or Tailwind `transition-all`) | PDS motion | `pds/no-transition-all`, warning |
|
|
133
|
+
| Durations come from `TransitionDuration` or `TransitionDurationInSeconds`, not literals (loops excepted) | PDS motion | `pds/duration-token`, warning |
|
|
79
134
|
| Contrast | PDH-F1 | Review |
|
|
80
135
|
| Status not by colour alone | PDH-F4 | Review |
|
|
81
136
|
|
|
@@ -91,7 +146,13 @@ In the app's `.oxlintrc.json` (oxlint 1.72 or later), load the plugin and enable
|
|
|
91
146
|
"pds/complete-typography": "error",
|
|
92
147
|
"pds/no-raw-table": "error",
|
|
93
148
|
"pds/min-copy-size": "warn",
|
|
94
|
-
"pds/reduced-motion": "warn"
|
|
149
|
+
"pds/reduced-motion": "warn",
|
|
150
|
+
"pds/exit-motion": "warn",
|
|
151
|
+
"pds/overlay-motion": "warn",
|
|
152
|
+
"pds/motion-origin": "warn",
|
|
153
|
+
"pds/no-layout-motion": "warn",
|
|
154
|
+
"pds/no-transition-all": "warn",
|
|
155
|
+
"pds/duration-token": "warn"
|
|
95
156
|
}
|
|
96
157
|
}
|
|
97
158
|
```
|
|
@@ -125,6 +186,17 @@ tightening goes in the ledger below, or in the PR's brief when it covers one scr
|
|
|
125
186
|
`pds/reduced-motion` reports once per file, at the first animation or transition, because adding one
|
|
126
187
|
`prefers-reduced-motion` block fixes them all. `pds/min-copy-size` takes `{ "minPx": 11, "rootFontPx": 16 }`.
|
|
127
188
|
|
|
189
|
+
The motion rules adapt the MIT-licensed transitions.dev scanner (notice in
|
|
190
|
+
`dist/lint/THIRD_PARTY_NOTICES.md`). They read one file at a time, so `exit-motion`,
|
|
191
|
+
`overlay-motion` and `motion-origin` find an overlay by its styled-component name (`ModalOverlay`,
|
|
192
|
+
`PopoverContent`, `DropdownMenu`; not parts like `MenuItem` or persistent ones like `SideMenu`) and
|
|
193
|
+
treat anything in the file that animates an exit or sets `transform-origin` as handling it.
|
|
194
|
+
`overlay-motion` also skips a file that uses an animation library (Framer Motion, React Transition
|
|
195
|
+
Group, React Spring) and a style that wraps a component (`styled(Popover)`), since either may bring
|
|
196
|
+
the motion. Using a PDS `<Modal>` or `<Popover>` isn't reported. They stay warnings until a product UI eval
|
|
197
|
+
agrees with them. An accordion animating `height` is the usual `no-layout-motion` exception:
|
|
198
|
+
animate `grid-template-rows` from `0fr` to `1fr`, or suppress it with the reason.
|
|
199
|
+
|
|
128
200
|
## Departure ledger
|
|
129
201
|
|
|
130
202
|
Departures from this file or the core that aren't tightenings, one row each, in the PDH-M3 format:
|
|
@@ -144,7 +216,9 @@ and paints nothing.
|
|
|
144
216
|
|
|
145
217
|
## Citations and tightenings
|
|
146
218
|
|
|
147
|
-
|
|
219
|
+
One tightening: **PDH-F3** asks for a reduced-motion profile; product UI requires that profile to
|
|
220
|
+
keep a 150 ms opacity fade with no movement rather than drop the change to instant (Michael Hu,
|
|
221
|
+
2026-11-04). Every other value above is the core's value.
|
|
148
222
|
|
|
149
223
|
Core rules cited, all at `persona-id/design-harness` `core-v0.3`: PDH-P1, PDH-P2 (ranks 1–2) · PDH-F1 to PDH-F4 ·
|
|
150
224
|
PDH-S1, PDH-S2 · PDH-M1, host side (a screen hosting an illustration, such as an empty state, sets the
|
|
@@ -702,34 +702,37 @@ const Menu = styled.div`
|
|
|
702
702
|
|
|
703
703
|
## Charts
|
|
704
704
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
`
|
|
719
|
-
|
|
720
|
-
| Need | Use | Max series |
|
|
721
|
-
|------|-----|------------|
|
|
722
|
-
| Numeric / ordered | `ChartingColors.Sequential` | 8 |
|
|
723
|
-
| Categorical / unordered | `ChartingColors.Categorical` | 14 |
|
|
705
|
+
Experimental (beta). Colour chart series with the chart palettes from
|
|
706
|
+
`@persona/design-system/components/Chart`: `useChartColors(palette)` (follows the PDS colour mode)
|
|
707
|
+
or `resolveSeriesColors()`. See the Charting section of [PATTERNS.md](PATTERNS.md) and Storybook
|
|
708
|
+
**Charts → Design → Themes**.
|
|
709
|
+
|
|
710
|
+
| Need | Palette | Token palette | Colours |
|
|
711
|
+
|------|---------|---------------|---------|
|
|
712
|
+
| Distinct, unordered series (default) | `'qualitative'` | `ChartingColors.Qualitative` | 12 |
|
|
713
|
+
| Ordered magnitude in one hue | `'sequentialMono'` | `ChartingColors.SequentialMono` | 8 |
|
|
714
|
+
| Values diverging around a midpoint | `'sequentialDivergent'` | `ChartingColors.SequentialDivergent` | 10 |
|
|
715
|
+
|
|
716
|
+
- Take Qualitative colours in order; the order is tuned for readability.
|
|
717
|
+
- Override a series only with a Persona token: `chartColor(Color.X)` or a `{ light, dark }` pair.
|
|
718
|
+
Never hex: `ChartColor` does not accept a hex string, and the `pds/semantic-color` lint rule
|
|
719
|
+
rejects it.
|
|
724
720
|
|
|
725
721
|
```tsx
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
722
|
+
import { useChartColors } from '@persona/design-system/components/Chart';
|
|
723
|
+
|
|
724
|
+
const colors = useChartColors().resolve([
|
|
725
|
+
{ key: 'approved', label: 'Approved' },
|
|
726
|
+
{ key: 'declined', label: 'Declined' },
|
|
727
|
+
]);
|
|
728
|
+
<Bar dataKey='approved' fill={colors.approved} />;
|
|
731
729
|
```
|
|
732
730
|
|
|
731
|
+
**Legacy (deprecated for new charts):** `ChartingColors.Sequential` (8) and
|
|
732
|
+
`ChartingColors.Categorical` (14), also exposed under a colour mode through `chartingColors(theme)`
|
|
733
|
+
from `@persona/design-system/lib/semanticColor`. Existing charts may keep them until they move to
|
|
734
|
+
the palettes above.
|
|
735
|
+
|
|
733
736
|
## Token Verification
|
|
734
737
|
|
|
735
738
|
To explore available tokens in your project:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumbs-CMf3Uvow.mjs","names":["Input"],"sources":["../src/components/Breadcrumbs/Breadcrumb.tsx","../src/components/Breadcrumbs/Breadcrumbs.tsx"],"sourcesContent":["import { type ChangeEvent, useEffect, useRef, useState } from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\nimport { CopyIcon, EditIcon } from '@persona/icons';\n\nimport { IconButton } from '#src/components/Button';\nimport Input from '#src/components/Input';\nimport { HStack } from '#src/components/Stack';\nimport TechnicalSticker from '#src/components/TechnicalSticker';\nimport { Paragraph } from '#src/components/Text';\nimport Tooltip from '#src/components/Tooltip';\nimport { RouterLink } from '#src/lib/router';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport TruncatedTextWithTooltip from '#src/lib/TruncatedTextWithTooltip';\nimport { focusOutline } from '#src/mixins/focus';\nimport { paragraphMixins } from '#src/mixins/text';\nimport { TransitionDuration } from '#src/variables/transitions';\n\nexport type BreadcrumbSize = 'md' | 'lg';\n\nexport type BreadcrumbHeadingAs = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\nconst COPY_TOOLTIP_LABEL = 'Copy ID';\nconst COPIED_TOOLTIP_LABEL = 'Copied!';\nconst DEFAULT_EDIT_MAX_LENGTH = 100;\nconst COPY_TOOLTIP_STICKER_MAX_WIDTH = '96px';\nconst COPY_TOOLTIP_STICKER_TOOLTIP_MAX_WIDTH = '250px';\n\nexport type BreadcrumbProps = {\n label: string;\n size?: BreadcrumbSize;\n current?: boolean;\n /**\n * Overrides the heading element rendered for the current crumb. Defaults to `h1`; use `h2` or\n * lower when the page already has an `h1`.\n */\n headingAs?: BreadcrumbHeadingAs;\n showCopyAction?: boolean;\n copyValue?: string;\n copyTooltipLabel?: string;\n /** Copy tooltip text shown after a successful copy. Defaults to `Copied!`. */\n copiedTooltipLabel?: string;\n /**\n * Appends `copyValue` to both copy tooltip texts as a `TechnicalSticker`, so the tooltip shows\n * which token is being copied.\n */\n showCopyValueInTooltip?: boolean;\n /** Internal path (e.g. `/cases`), rendered as a router-aware link. */\n href?: string;\n /**\n * Activates a non-current crumb without a route change, for trails that navigate in-place (e.g.\n * a control panel drilling into a sub-panel). Ignored when `href` is set.\n */\n onClick?: () => void;\n onEdit?: (newLabel: string) => void;\n editMaxLength?: number;\n onCopy?: () => void;\n};\n\nconst LABEL_ACTION_GAP = Spacing[2];\nconst ACTION_BUTTON_GAP = Spacing[1];\n\nexport const getInlineActionCount = ({\n onEdit,\n showCopyAction,\n copyValue,\n}: Pick<BreadcrumbProps, 'onEdit' | 'showCopyAction' | 'copyValue'>) =>\n Number(onEdit != null) + (showCopyAction && copyValue != null ? 1 : 0);\n\nconst CrumbRow = styled(HStack)`\n align-items: center;\n min-width: 0;\n`;\n\nconst InlineActions = styled(HStack)`\n flex-shrink: 0;\n`;\n\nconst BreadcrumbLabel = styled.span`\n overflow-wrap: anywhere;\n`;\n\nconst TruncatedBreadcrumbLabel = ({ label }: { label: string }) => (\n <TruncatedTextWithTooltip tooltipProps={{ maxWidth: '400px' }}>\n <BreadcrumbLabel>{label}</BreadcrumbLabel>\n </TruncatedTextWithTooltip>\n);\n\nconst crumbLayoutStyles = (size: BreadcrumbSize) => css`\n display: inline-flex;\n align-items: center;\n min-width: 0;\n min-height: ${({ theme }) => theme.element.height.xs};\n ${\n size === 'lg'\n ? css`\n font-size: ${({ theme }) => theme.text.paragraph.lg.fontSize};\n line-height: ${({ theme }) => theme.text.paragraph.lg.lineHeight};\n `\n : css``\n };\n`;\n\nconst editInputTextStyles = (size: BreadcrumbSize, current: boolean) => {\n if (current) {\n return size === 'lg' ? paragraphMixins.lgBold : paragraphMixins.mdBold;\n }\n return size === 'lg' ? paragraphMixins.lg : paragraphMixins.md;\n};\n\nconst ancestorCrumbStyles = css<{ $size: BreadcrumbSize }>`\n ${paragraphMixins.md};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n text-decoration: none;\n transition: color ${TransitionDuration.ExtraFast} ease-out;\n ${focusOutline}\n ${({ $size }) => crumbLayoutStyles($size)}\n\n &:hover {\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n }\n`;\n\nconst AncestorNavLink = styled(RouterLink)<{ $size: BreadcrumbSize }>`\n ${ancestorCrumbStyles}\n`;\n\nconst AncestorNavButton = styled.button<{ $size: BreadcrumbSize }>`\n ${ancestorCrumbStyles}\n padding: 0;\n border: none;\n background: none;\n cursor: pointer;\n`;\n\nconst InlineEditInput = styled(Input)<{\n $size: BreadcrumbSize;\n $current: boolean;\n $editMinWidth?: number;\n}>`\n margin: 0;\n padding: 2px 10px;\n width: auto;\n max-width: 100%;\n min-width: ${({ $editMinWidth }) => ($editMinWidth != null ? `${$editMinWidth}px` : '0')};\n field-sizing: content;\n display: inline-block;\n ${({ $size, $current }) => editInputTextStyles($size, $current)};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n\n &:not(:focus) {\n border-color: transparent;\n }\n\n &:hover:not(:disabled) {\n border-style: solid;\n }\n`;\n\nconst CurrentLabel = styled(Paragraph)<{ $size: BreadcrumbSize }>`\n margin: 0;\n ${({ $size }) => crumbLayoutStyles($size)}\n`;\n\nconst copyToClipboard = async (value: string): Promise<boolean> => {\n try {\n if (navigator.clipboard?.writeText == null) {\n return false;\n }\n\n await navigator.clipboard.writeText(value);\n return true;\n } catch {\n return false;\n }\n};\n\nconst BreadcrumbCopyButton = ({\n copyValue,\n copyTooltipLabel = COPY_TOOLTIP_LABEL,\n copiedTooltipLabel = COPIED_TOOLTIP_LABEL,\n showCopyValueInTooltip = false,\n onCopy,\n}: {\n copyValue: string;\n copyTooltipLabel?: string;\n copiedTooltipLabel?: string;\n showCopyValueInTooltip?: boolean;\n onCopy?: () => void;\n}) => {\n const [tooltipOpen, setTooltipOpen] = useState(false);\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n const success = await copyToClipboard(copyValue);\n if (!success) {\n return;\n }\n\n setCopied(true);\n setTooltipOpen(true);\n onCopy?.();\n\n window.setTimeout(() => {\n setTooltipOpen(false);\n window.setTimeout(() => setCopied(false), 200);\n }, 1000);\n };\n\n const handleMouseEnter = () => {\n if (!copied) {\n setTooltipOpen(true);\n }\n };\n\n const handleMouseLeave = () => {\n if (!copied) {\n setTooltipOpen(false);\n }\n };\n\n const trigger = (\n <span onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>\n <IconButton\n type='button'\n size='sm'\n aria-label={`Copy ${copyValue}`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void handleCopy();\n }}\n >\n <CopyIcon />\n </IconButton>\n </span>\n );\n\n const tooltipLabel = copied ? copiedTooltipLabel : copyTooltipLabel;\n\n return (\n <Tooltip\n trigger={trigger}\n open={tooltipOpen}\n side='top'\n sideOffset={4}\n size='sm'\n contentAlignment='center'\n interactive={false}\n hideArrow\n portal={false}\n maxWidth={showCopyValueInTooltip ? COPY_TOOLTIP_STICKER_TOOLTIP_MAX_WIDTH : undefined}\n >\n {showCopyValueInTooltip ? (\n <HStack spacing={ACTION_BUTTON_GAP} align='center'>\n <span>{tooltipLabel}</span>\n <TechnicalSticker copyable={false} maxWidth={COPY_TOOLTIP_STICKER_MAX_WIDTH}>\n {copyValue}\n </TechnicalSticker>\n </HStack>\n ) : (\n tooltipLabel\n )}\n </Tooltip>\n );\n};\n\nconst Breadcrumb = ({\n label,\n size = 'md',\n current = false,\n headingAs = 'h1',\n showCopyAction = false,\n copyValue,\n copyTooltipLabel,\n copiedTooltipLabel,\n showCopyValueInTooltip,\n href,\n onClick,\n onEdit,\n editMaxLength = DEFAULT_EDIT_MAX_LENGTH,\n onCopy,\n}: BreadcrumbProps) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editValue, setEditValue] = useState(label);\n const [editMinWidth, setEditMinWidth] = useState<number | undefined>();\n const editInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (!isEditing) {\n setEditValue(label);\n }\n }, [isEditing, label]);\n\n useEffect(() => {\n if (!isEditing) {\n setEditMinWidth(undefined);\n return;\n }\n\n const input = editInputRef.current;\n if (input == null) {\n return;\n }\n\n setEditMinWidth(input.offsetWidth);\n input.focus();\n input.select();\n }, [isEditing]);\n\n const commitEdit = () => {\n if (!isEditing) {\n return;\n }\n\n setIsEditing(false);\n if (editValue !== label) {\n onEdit?.(editValue);\n }\n };\n\n const inlineActionCount = getInlineActionCount({ onEdit, showCopyAction, copyValue });\n const inlineActions = !isEditing && inlineActionCount > 0 && (\n <InlineActions spacing={ACTION_BUTTON_GAP} align='center'>\n {onEdit != null && (\n <IconButton\n type='button'\n size='sm'\n aria-label={`Edit ${label}`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n setIsEditing(true);\n }}\n >\n <EditIcon />\n </IconButton>\n )}\n {showCopyAction && copyValue != null && (\n <BreadcrumbCopyButton\n copyValue={copyValue}\n copyTooltipLabel={copyTooltipLabel}\n copiedTooltipLabel={copiedTooltipLabel}\n showCopyValueInTooltip={showCopyValueInTooltip}\n onCopy={onCopy}\n />\n )}\n </InlineActions>\n );\n\n if (isEditing) {\n return (\n <CrumbRow spacing={LABEL_ACTION_GAP}>\n <InlineEditInput\n ref={editInputRef}\n $size={size}\n $current={current}\n $editMinWidth={editMinWidth}\n size='md'\n aria-label={`Edit ${label}`}\n maxLength={editMaxLength}\n value={editValue}\n onChange={(event: ChangeEvent<HTMLInputElement>) => setEditValue(event.target.value)}\n onBlur={commitEdit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n commitEdit();\n }\n if (event.key === 'Escape') {\n setEditValue(label);\n setIsEditing(false);\n }\n }}\n />\n </CrumbRow>\n );\n }\n\n if (current) {\n return (\n <CrumbRow spacing={LABEL_ACTION_GAP}>\n <CurrentLabel\n $size={size}\n size={size === 'lg' ? 'lg' : 'md'}\n weight='bold'\n color='primary'\n as={headingAs}\n >\n <TruncatedBreadcrumbLabel label={label} />\n </CurrentLabel>\n {inlineActions}\n </CrumbRow>\n );\n }\n\n if (href == null && onClick != null) {\n return (\n <CrumbRow spacing={LABEL_ACTION_GAP}>\n <AncestorNavButton type='button' onClick={onClick} $size={size}>\n <TruncatedBreadcrumbLabel label={label} />\n </AncestorNavButton>\n {inlineActions}\n </CrumbRow>\n );\n }\n\n return (\n <CrumbRow spacing={LABEL_ACTION_GAP}>\n <AncestorNavLink to={href ?? ''} $size={size}>\n <TruncatedBreadcrumbLabel label={label} />\n </AncestorNavLink>\n {inlineActions}\n </CrumbRow>\n );\n};\n\nexport default Breadcrumb;\n","import styled from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\n\nimport { intersperse } from '#src/lib/intersperse';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { paragraphMixins } from '#src/mixins/text';\n\nimport Breadcrumb, {\n type BreadcrumbHeadingAs,\n type BreadcrumbProps,\n type BreadcrumbSize,\n getInlineActionCount,\n} from './Breadcrumb';\n\nexport type BreadcrumbsItemProps = Omit<BreadcrumbProps, 'size' | 'current' | 'headingAs'>;\n\nexport type BreadcrumbsProps = {\n items: BreadcrumbsItemProps[];\n size?: BreadcrumbSize;\n /**\n * Overrides the heading element rendered for the current crumb. Defaults to `h1`; use `h2` or\n * lower when the page already has an `h1`.\n */\n headingAs?: BreadcrumbHeadingAs;\n 'aria-label'?: string;\n className?: string;\n};\n\nconst ANCESTOR_MIN_CHARS = 8;\nconst CURRENT_MIN_CHARS = 12;\n\nconst BreadcrumbNav = styled.nav`\n min-width: 0;\n`;\n\nconst BreadcrumbList = styled.ol`\n max-width: 100%;\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n list-style: none;\n margin: 0;\n padding: 0;\n min-width: 0;\n`;\n\nconst BreadcrumbListItem = styled.li<{\n $size: BreadcrumbSize;\n $isCurrent: boolean;\n $isShort: boolean;\n $minWidth?: string;\n}>`\n display: flex;\n align-items: center;\n ${({ $size }) => ($size === 'lg' ? paragraphMixins.lg : paragraphMixins.md)};\n ${({ $isShort, $isCurrent }) =>\n $isShort ? 'flex-shrink: 0;' : $isCurrent ? 'flex: 0 1 auto;' : 'flex: 0 100000 auto;'}\n ${({ $minWidth }) => $minWidth != null && `min-width: ${$minWidth};`}\n\n &:has(input) {\n flex-shrink: 1;\n }\n`;\n\nconst SeparatorListItem = styled.li`\n display: flex;\n align-items: center;\n flex-shrink: 0;\n`;\n\nconst Separator = styled.span<{ $size: BreadcrumbSize }>`\n padding: 0 ${Spacing[2]};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.tertiary)};\n user-select: none;\n ${({ $size }) => ($size === 'lg' ? paragraphMixins.lg : paragraphMixins.md)};\n`;\n\nexport const Breadcrumbs = ({\n items,\n size = 'md',\n headingAs = 'h1',\n 'aria-label': ariaLabel = 'Breadcrumbs',\n className,\n}: BreadcrumbsProps) => {\n if (items.length === 0) {\n return null;\n }\n\n const crumbNodes = items.map((item, index) => {\n const isCurrent = index === items.length - 1;\n const minChars = isCurrent ? CURRENT_MIN_CHARS : ANCESTOR_MIN_CHARS;\n const actionCount = getInlineActionCount(item);\n const actionsWidth =\n actionCount === 0\n ? 0\n : Number.parseFloat(Spacing[2]) +\n actionCount * 24 +\n (actionCount - 1) * Number.parseFloat(Spacing[1]);\n\n return (\n <BreadcrumbListItem\n key={`${item.label}-${index}`}\n aria-current={isCurrent ? 'page' : undefined}\n $size={size}\n $isCurrent={isCurrent}\n $isShort={item.label.length <= minChars}\n $minWidth={\n item.label.length > minChars ? `calc(${minChars}ch + ${actionsWidth}px)` : undefined\n }\n >\n <Breadcrumb {...item} size={size} current={isCurrent} headingAs={headingAs} />\n </BreadcrumbListItem>\n );\n });\n\n const listItems = intersperse(crumbNodes, (separatorIndex: number) => (\n <SeparatorListItem key={`separator-${separatorIndex}`} aria-hidden='true'>\n <Separator $size={size}>/</Separator>\n </SeparatorListItem>\n ));\n\n return (\n <BreadcrumbNav aria-label={ariaLabel} className={className}>\n <BreadcrumbList>{listItems}</BreadcrumbList>\n </BreadcrumbNav>\n );\n};\n\nexport default Breadcrumbs;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CardV2-CrV6eEQb.mjs","names":["CardLoadingShimmer","Heading","Button","DropdownMenu"],"sources":["../src/components/CardV2/SectionHeading.tsx","../src/components/CardV2/Section.tsx","../src/components/CardV2/Card.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, FC, ReactElement, ReactNode } from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing, Typography } from '@persona/design-tokens';\nimport { ChevronDownIcon, MoreIcon } from '@persona/icons';\n\nimport Button, { IconButton } from '#src/components/Button';\nimport DropdownButton from '#src/components/DropdownButton';\nimport DropdownMenu from '#src/components/DropdownMenu';\nimport { LoadingShimmer } from '#src/components/LoadingShimmer';\nimport { HStack } from '#src/components/Stack';\nimport { Heading } from '#src/components/Text';\nimport Tooltip from '#src/components/Tooltip';\nimport { HeadlessAriaButton } from '#src/lib/HeadlessAriaButton';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { TruncatedText } from '#src/lib/TruncatedText';\nimport { focusStyle } from '#src/mixins/focus';\nimport type { HeadingSize } from '#src/mixins/text';\nimport type { IconAction, MenuAction, TextAction } from '#src/types/Action';\nimport { TransitionDuration } from '#src/variables/transitions';\n\n/**\n * Distance from the top of a card to the underside of an expanded top-section heading: the\n * `Spacing[4]` padding above and below a 24px title line, plus the divider. Sticky content inside\n * the card pins here so the heading's divider stays the only line between them.\n */\nexport const CARD_HEADING_STICKY_OFFSET = `calc(${Spacing[9]} + 1px)`;\n\nconst CardLoadingShimmer = styled(LoadingShimmer)`\n border-radius: ${({ theme }) => theme.card.borderRadius};\n`;\n\nconst StickerContainer = styled.div`\n display: flex;\n max-width: 180px;\n`;\n\ntype AccordionContainerProps = {\n $isTopSection: boolean;\n $expanded: boolean;\n};\nconst AccordionContainer = styled.div<AccordionContainerProps>`\n transition: opacity ${TransitionDuration.Faster};\n position: absolute;\n opacity: 0;\n\n height: 12px;\n width: 12px;\n display: flex;\n align-items: center;\n /* Because of padding in the top section heading we need to offset differently. */\n /* We want a 12px icon to be off-center in 24px padding, 4px on the right and 8px on the left */\n left: ${({ $isTopSection }) => ($isTopSection ? '8px' : '-16px')};\n /* center the icon vertically */\n top: calc(50% - 6px);\n\n border-radius: 1px;\n\n & svg {\n transition: transform ${TransitionDuration.Faster} ease-out;\n transform: rotate(${({ $expanded }) => ($expanded ? '0' : '-90deg')});\n }\n`;\n\nconst HeaderButton = styled(HeadlessAriaButton)`\n min-width: 0;\n flex: 1;\n\n &:hover ~ ${AccordionContainer} {\n opacity: 1;\n }\n\n &:focus-visible ~ ${AccordionContainer} {\n opacity: 1;\n ${focusStyle}\n }\n`;\n\ntype HeadingContainerProps = {\n $isTopSection: boolean;\n $divider: boolean;\n $hasFooter: boolean;\n $isExpanded: boolean;\n};\nconst HeadingContainer = styled(HStack)<HeadingContainerProps>`\n position: relative;\n\n ${({ $isTopSection }) =>\n $isTopSection &&\n css`\n padding: ${Spacing[4]} ${Spacing[5]};\n `}\n ${({ $divider }) =>\n $divider &&\n css`\n border-bottom: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n `}\n ${({ $isTopSection, $hasFooter, $isExpanded }) =>\n $isTopSection &&\n !$hasFooter &&\n !$isExpanded &&\n css`\n // We apply 4px of whitespace to the bottom of the card container so that content has a buffer\n // when being scrolled and still appears inside the card. Here we adjust, subtracting\n // 4px from the 16px padding.\n padding-bottom: ${Spacing[3]};\n `}\n`;\n\ntype StyledHeadingProps = {\n $isCollapsible: boolean;\n $isTopSection: boolean;\n size: HeadingSize;\n};\nconst StyledHeading = styled(Heading)<StyledHeadingProps>`\n flex: 1;\n display: flex;\n align-items: center;\n gap: ${Spacing[2]};\n line-height: 24px; // We want an adjusted line-height to hit the target header size.\n overflow: hidden;\n\n ${({ $isCollapsible }) => $isCollapsible && 'cursor: pointer;'}\n ${({ $isTopSection }) =>\n !$isTopSection &&\n css`\n ${Typography.TextLargeBold};\n `}\n`;\n\nconst isIconAction = (action: IconAction | TextAction): action is IconAction => 'icon' in action;\n\nconst ButtonRow: FC<{\n actions: (IconAction | TextAction)[];\n menuActions: MenuAction[];\n}> = ({ actions, menuActions }) => {\n const buttons = actions\n .filter((action) => !action.hidden)\n .map((action, i) => {\n const key = isIconAction(action)\n ? (action.id ?? action.ariaLabel ?? `action-${i}`)\n : (action.id ?? action.label ?? `action-${i}`);\n\n const button = isIconAction(action) ? (\n <IconButton\n id={action.id}\n key={key}\n to={action.to}\n onClick={(e) => {\n e.stopPropagation();\n return action.onClick?.(e);\n }}\n disabled={action.disabled}\n aria-label={action.ariaLabel}\n size='sm'\n >\n {action.icon}\n </IconButton>\n ) : (\n <Button\n id={action.id}\n key={key}\n aria-label={action.ariaLabel}\n to={action.to}\n onClick={(e) => {\n e.stopPropagation();\n return action.onClick?.(e);\n }}\n disabled={action.disabled}\n variant={action.variant ?? 'basic'}\n size='sm'\n width='auto'\n prefixIcon={action.prefixIcon}\n suffixIcon={action.suffixIcon}\n >\n {action.label}\n </Button>\n );\n\n return action.tooltip ? (\n <Tooltip key={key} {...action.tooltipProps} trigger={button}>\n {action.tooltip}\n </Tooltip>\n ) : (\n button\n );\n });\n\n return (\n <HStack>\n {buttons}\n {menuActions.length > 0 && (\n <DropdownButton\n variant='text'\n width='icon'\n size='sm'\n suffixIcon={undefined}\n style={{ justifySelf: 'flex-end' }}\n aria-label='More actions'\n menuProps={{\n portal: true,\n }}\n menuItems={menuActions\n .filter((action) => !action.hidden)\n .map((action) => (\n <DropdownMenu.Item\n id={action.id ?? action.label}\n key={action.id ?? action.label}\n onClick={action.onClick}\n disabled={action.disabled}\n >\n {action.label}\n </DropdownMenu.Item>\n ))}\n >\n <MoreIcon />\n </DropdownButton>\n )}\n </HStack>\n );\n};\n\n/**\n * Private component for rendering the heading of a section, both the primary card heading and\n * section headings.\n */\nexport const SectionHeading: FC<{\n /**\n * Whether this is the top-level section of the card which has different visual treatment.\n */\n isTopSection: boolean;\n\n /**\n * Whether this heading's section has content.\n */\n sectionHasContent: boolean;\n\n /**\n * Whether this heading's section has a footer.\n */\n hasFooter: boolean;\n\n loading: boolean;\n\n /**\n * Title text to render in the heading.\n */\n title: string;\n\n /**\n * Optional sticker to render after the title.\n */\n sticker?: ReactElement;\n\n /**\n * Optional icon to render before the title text.\n *\n * Usage of this icon slot should be avoided if possible to maintain left-text alignement. If\n * using this icon slot for a section heading use it for all sections.\n */\n leftDecorativeIcon?: ReactElement;\n\n /**\n * Optional actions to render in the heading.\n * Only accepts IconButton or Button components with specific prop restrictions.\n */\n actions?: (IconAction | TextAction | undefined)[];\n\n /**\n * Optional actions to render in the heading in a menu.\n */\n menuActions?: (MenuAction | undefined)[];\n\n /**\n * Optional custom content to render in the heading in the button row. Prefer setting `actions` or\n * `menuActions` if possible.\n */\n headerActionsRowContent?: ReactNode;\n\n /**\n * Callback to toggle collapsed state of the section. Omit to disable collapsing.\n */\n toggle?: () => void;\n\n /**\n * Whether the section is currently expanded or collapsed.\n */\n isExpanded: boolean;\n\n /**\n * Optional props to pass to the heading element. Accepts an `as` key to override the\n * rendered heading level. Defaults to `h2` for the top-level card heading and `h3` for\n * section headings so that the document heading hierarchy reflects the visual hierarchy.\n */\n headingProps?: Omit<ComponentPropsWithoutRef<'span'>, 'color'> & {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n };\n}> = ({\n isTopSection,\n sectionHasContent,\n hasFooter,\n loading,\n title,\n actions = [],\n menuActions = [],\n headerActionsRowContent,\n sticker,\n leftDecorativeIcon,\n toggle,\n isExpanded,\n headingProps,\n}) => {\n const renderButtonRow = actions.length > 0 || menuActions.length > 0;\n const { as: headingAs, ...restHeadingProps } = headingProps ?? {};\n\n return (\n <HeadingContainer\n $isTopSection={isTopSection}\n $hasFooter={hasFooter}\n $isExpanded={isExpanded}\n $divider={isTopSection && isExpanded && sectionHasContent}\n align='center'\n justify='space-between'\n spacing={Spacing[2]}\n >\n {loading ? (\n <CardLoadingShimmer height='24px' width='200px' />\n ) : (\n <>\n {/* https://github.com/adobe/react-spectrum/issues/7444 */}\n <HeaderButton slot='trigger' isDisabled={!toggle}>\n <StyledHeading\n forwardedAs={headingAs ?? (isTopSection ? 'h2' : 'h3')}\n size='xsm'\n $isCollapsible={!!toggle}\n $isTopSection={isTopSection}\n aria-label={title}\n {...restHeadingProps}\n >\n {leftDecorativeIcon}\n <TruncatedText>{title}</TruncatedText>\n {sticker && <StickerContainer>{sticker}</StickerContainer>}\n </StyledHeading>\n </HeaderButton>\n {headerActionsRowContent}\n {renderButtonRow && (\n <ButtonRow\n actions={actions.filter((action) => action != null)}\n menuActions={menuActions.filter((action) => action != null)}\n />\n )}\n {toggle && (\n <AccordionContainer $isTopSection={isTopSection} $expanded={isExpanded}>\n <ChevronDownIcon />\n </AccordionContainer>\n )}\n </>\n )}\n </HeadingContainer>\n );\n};\n","import type { ComponentProps, FC, ReactNode } from 'react';\nimport { Disclosure, DisclosurePanel } from 'react-aria-components';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\n\nimport { SectionHeading } from '#src/components/CardV2/SectionHeading';\nimport { LoadingShimmer } from '#src/components/LoadingShimmer';\nimport { HStack } from '#src/components/Stack';\nimport { Paragraph } from '#src/components/Text';\nimport { intersperse } from '#src/lib/intersperse';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { Z_INDICES } from '#src/lib/zindex';\n\nconst FooterParagraph = styled(Paragraph)`\n line-height: 16px;\n`;\n\ntype FooterContainerProps = {\n $divider: boolean;\n};\nconst FooterContainer = styled.div<FooterContainerProps>`\n ${({ $divider }) =>\n $divider &&\n css`\n border-top: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n `}\n padding: ${Spacing[3]} ${Spacing[5]} ${Spacing[2]};\n`;\n\ntype MaybeStickyContainerProps = {\n $enabled: boolean;\n $bottom?: boolean;\n};\nconst MaybeStickyContainer = styled.div<MaybeStickyContainerProps>`\n ${({ $enabled }) =>\n $enabled &&\n css`\n // We are using sticky positioning here to have consistent scrollbar behavior between\n // different card configurations. Usage of sticky allows us to keep the scroll container at\n // the top of the card DOM structure regardless of whether the heading or footer is sticky.\n //\n // This also afaict helps eliminate the need to carry height values through the card DOM\n // structure to the content container (and possibly needing to adjust heights for heading and footer).\n position: sticky;\n top: 0;\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n z-index: ${Z_INDICES.sticky};\n `}\n\n ${({ $bottom = false }) =>\n $bottom &&\n css`\n top: unset;\n bottom: 0;\n `}\n`;\n\ntype StyledDisclosureProps = {\n $fullHeight: boolean;\n};\nconst StyledDisclosure = styled(Disclosure)<StyledDisclosureProps>`\n display: flex;\n flex-direction: column;\n gap: 0;\n ${({ $fullHeight }) =>\n $fullHeight &&\n css`\n height: 100%;\n `}\n`;\n\ntype StyledDisclosurePanelProps = {\n $isTopSection: boolean;\n $fullHeight: boolean;\n};\nconst StyledDisclosurePanel = styled(DisclosurePanel)<StyledDisclosurePanelProps>`\n flex: 1;\n ${({ $fullHeight }) =>\n $fullHeight &&\n css`\n /* Let the panel shrink below min-content so the card doesn't scroll the section. */\n min-height: 0;\n `}\n ${({ $isTopSection }) =>\n $isTopSection &&\n css`\n // Safari does not support hidden='until-found' so react-aria uses display: none instead.\n // Since react-aria is using display to hide content we need to not set display ourselves.\n &:not([aria-hidden='true']) {\n display: flex;\n }\n `}\n`;\n\nconst CardLoadingShimmer = styled(LoadingShimmer)`\n border-radius: ${({ theme }) => theme.card.borderRadius};\n`;\n\ntype SectionContentContainerProps = {\n $isTopSection: boolean;\n $fullHeight: boolean;\n $hasHeading: boolean;\n $hasFooter: boolean;\n};\nconst SectionContentContainer = styled.div<SectionContentContainerProps>`\n ${({ $fullHeight }) =>\n $fullHeight &&\n css`\n /* Let the stretch-clamped container shrink with the panel in fullHeight cards. */\n min-height: 0;\n `}\n ${({ $isTopSection }) =>\n $isTopSection &&\n css`\n padding: ${Spacing[5]};\n display: flex;\n flex-direction: column;\n gap: ${Spacing[5]};\n flex: 1;\n /* Prevent grid blowout https://css-tricks.com/preventing-a-grid-blowout/ */\n min-width: 0;\n `}\n\n ${({ $isTopSection, $hasHeading }) =>\n !$isTopSection &&\n $hasHeading &&\n css`\n padding-top: ${Spacing[3]};\n `}\n\n ${({ $isTopSection, $hasFooter }) =>\n $isTopSection &&\n !$hasFooter &&\n css`\n // We apply 4px of whitespace to the bottom of the card container so that content has a buffer\n // when being scrolled and still appears inside the card. Here we adjust, subtracting\n // 4px from the 24px padding.\n padding-bottom: 20px;\n `}\n`;\n\n/**\n * Private component for rendering sections of the card, both the primary card section and\n * individual sections.\n */\nexport const Section: FC<{\n children?: ReactNode;\n\n /**\n * Whether this is the top-level section of the card which has different visual treatment.\n */\n isTopSection: boolean;\n\n /**\n * Available props for the section's heading.\n */\n heading?: Pick<\n ComponentProps<typeof SectionHeading>,\n | 'title'\n | 'actions'\n | 'menuActions'\n | 'headerActionsRowContent'\n | 'sticker'\n | 'leftDecorativeIcon'\n | 'headingProps'\n >;\n\n /**\n * Optional footer to render at the bottom of the card. Footer content is rendered as a\n * paragraph with the items separated by a dot.\n */\n footer?: ReactNode[];\n\n /**\n * Optional arbitrary footer content to render as-is.\n */\n footerContent?: ReactNode;\n\n /**\n * Whether the section is collapsible.\n */\n collapsible?: boolean;\n\n /**\n * Whether the section heading and footer are sticky.\n */\n sticky?: boolean;\n\n /**\n * Whether the section is initially collapsed.\n */\n defaultCollapsed?: boolean;\n\n /**\n * If true, the section will be rendered in a loading state.\n */\n loading?: boolean;\n\n /**\n * Set height of the loading state.\n */\n loadingProps?: {\n height?: string;\n };\n\n /**\n * Control display of the empty state.\n */\n empty?: boolean;\n\n /**\n * Props for the empty state.\n */\n emptyProps?: {\n /**\n * Empty state message.\n */\n message?: string;\n };\n\n fullHeight?: boolean;\n}> = ({\n children,\n isTopSection,\n heading,\n footer,\n footerContent,\n loading = false,\n loadingProps,\n empty = false,\n emptyProps,\n defaultCollapsed = false,\n collapsible = false,\n sticky = false,\n fullHeight = false,\n}) => {\n let content: ReactNode;\n if (loading) {\n content = <CardLoadingShimmer height={loadingProps?.height ?? '200px'} width='100%' />;\n } else if (empty) {\n content = <Paragraph>{emptyProps?.message ?? 'No data collected'}</Paragraph>;\n } else {\n content = children;\n }\n\n const hasFooter = !!(footer || footerContent);\n const hasContent = !!content;\n\n // Normally we would have `isDisabled` as well but there's a react-aria-components quirk\n // that sets `hidden` on the disclosure panel if both `defaultExpanded` and `isDisabled` are true.\n // https://github.com/adobe/react-spectrum/issues/7444\n return (\n <StyledDisclosure defaultExpanded={!defaultCollapsed} $fullHeight={fullHeight}>\n {({ isExpanded, state }) => (\n <>\n {heading && (\n <MaybeStickyContainer $enabled={sticky}>\n <SectionHeading\n isTopSection={isTopSection}\n hasFooter={hasFooter}\n sectionHasContent={hasContent}\n loading={loading}\n toggle={collapsible ? state.toggle : undefined}\n isExpanded={isExpanded}\n {...heading}\n />\n </MaybeStickyContainer>\n )}\n {hasContent && (\n <StyledDisclosurePanel $isTopSection={isTopSection} $fullHeight={fullHeight}>\n <SectionContentContainer\n $isTopSection={isTopSection}\n $fullHeight={fullHeight}\n $hasHeading={!!heading}\n $hasFooter={hasFooter}\n >\n {content}\n </SectionContentContainer>\n </StyledDisclosurePanel>\n )}\n {hasFooter && (\n <MaybeStickyContainer $enabled={sticky} $bottom>\n <FooterContainer $divider={hasContent}>\n {loading ? (\n <HStack>\n <CardLoadingShimmer height='16px' width='120px' />\n <CardLoadingShimmer height='16px' width='120px' />\n </HStack>\n ) : (\n <>\n {footer && (\n <FooterParagraph size='sm'>\n <HStack spacing={Spacing[1]}>\n {intersperse(\n footer\n .filter((item) => item != null)\n .map((item, i) => <span key={`footer-item-${i}`}>{item}</span>),\n (i) => (\n <span key={i}>•</span>\n ),\n )}\n </HStack>\n </FooterParagraph>\n )}\n {footerContent}\n </>\n )}\n </FooterContainer>\n </MaybeStickyContainer>\n )}\n </>\n )}\n </StyledDisclosure>\n );\n};\n","import { type ComponentProps, createContext, type FC, type ReactNode, useContext } from 'react';\nimport { ErrorBoundary } from 'react-error-boundary';\nimport styled from 'styled-components';\n\nimport { Color } from '@persona/design-tokens';\n\nimport { Section } from '#src/components/CardV2/Section';\nimport { Paragraph } from '#src/components/Text';\nimport ConfigContext from '#src/lib/ConfigContext';\nimport { intersperse } from '#src/lib/intersperse';\nimport { semanticColor } from '#src/lib/semanticColor';\nimport { semanticScrollbar } from '#src/mixins/scrollbar';\n\nconst CardContainer = styled.div`\n border-radius: ${({ theme }) => theme.card.borderRadius};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n // Height has been tricky here.\n // inherit seems to work well for both grid and flexbox layouts. In a grid we want this\n // container to receive the full cell height, In a flexbox we want this container to flex, maintaining\n // the minimum height for it's content.\n height: inherit;\n overflow-y: auto;\n ${semanticScrollbar}\n\n box-sizing: border-box;\n // Small buffer so that content is not scrolling right on the edge of the card.\n border-bottom: 4px solid ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n`;\n\nconst CardContext = createContext<{ isStacked?: boolean }>({});\n\nconst Divider = styled.hr`\n margin: 0;\n border: none;\n border-top: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n`;\n\n/**\n * Renders a card section.\n */\nconst PublicSection: FC<\n Pick<\n ComponentProps<typeof Section>,\n | 'children'\n | 'collapsible'\n | 'defaultCollapsed'\n | 'heading'\n | 'loading'\n | 'loadingProps'\n | 'empty'\n | 'emptyProps'\n >\n> = (props) => {\n return <Section isTopSection={false} {...props} />;\n};\n\n/**\n * Render the card in a \"stacked\" mode. Used for rendering multiple cards on top of each other\n * that appear visually as a single card.\n */\nconst Stacked: FC<{\n children: ReactNode[];\n}> = ({ children }) => {\n return (\n <CardContext.Provider value={{ isStacked: true }}>\n <CardContainer>\n {intersperse(children, (i) => (\n <Divider key={i} />\n ))}\n </CardContainer>\n </CardContext.Provider>\n );\n};\n\nconst DEFAULT_ERROR_MESSAGE = 'Something went wrong loading this card.';\n\n/**\n * Renders a PDS Card.\n *\n * To render sections of the card use `<Card.Section>...</Card.Section>`\n */\nconst Card: FC<\n {\n /**\n * Optional footer to render at the bottom of the card. Footer content is rendered as a\n * paragraph with the items separated by a dot.\n */\n footer?: ReactNode[];\n\n /**\n * Optional arbitrary footer content to render as-is.\n */\n footerContent?: ReactNode;\n\n /**\n * Whether the card heading and footer are sticky.\n */\n sticky?: boolean;\n\n /**\n * Force the card to render in an errored state. Errors bubbling up from children will also\n * render the errored state.\n */\n errored?: boolean;\n\n /**\n * Props for the errored state.\n */\n erroredProps?: {\n /**\n * Message to render in the errored state.\n */\n message?: string;\n /**\n * Callback to handle errors. Note this callback is only called when the error is bubbled up\n * from children, not when `errored` is set to true.\n */\n onError?: (error: Error) => void;\n };\n\n containerProps?: ComponentProps<typeof CardContainer>;\n\n /**\n * Whether the card should render its content with 100% height. This is a bit of a hack for cards\n * that want full control of their content and don't use sections.\n */\n fullHeight?: boolean;\n } & ComponentProps<typeof PublicSection>\n> = ({ children, errored, erroredProps, containerProps, sticky = true, ...sectionProps }) => {\n const { isStacked = false } = useContext(CardContext);\n const { captureException } = useContext(ConfigContext);\n\n const errorFallback = (\n <Section isTopSection {...sectionProps}>\n <Paragraph>{erroredProps?.message ?? DEFAULT_ERROR_MESSAGE}</Paragraph>\n </Section>\n );\n\n const section = (\n <Section isTopSection sticky={sticky} {...sectionProps}>\n {children}\n </Section>\n );\n\n return (\n <ErrorBoundary\n fallback={\n isStacked ? (\n errorFallback\n ) : (\n <CardContainer {...containerProps}>{errorFallback}</CardContainer>\n )\n }\n onError={erroredProps?.onError ?? ((error) => captureException(error))}\n >\n {isStacked ? (\n <>{errored ? <>{errorFallback}</> : <>{section}</>}</>\n ) : (\n <CardContainer {...containerProps}>\n {errored ? <>{errorFallback}</> : <>{section}</>}\n </CardContainer>\n )}\n </ErrorBoundary>\n );\n};\n\nexport default Object.assign(Card, {\n Section: PublicSection,\n Stacked: Stacked,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAa,6BAA6B,QAAQ,QAAQ,GAAG;AAE7D,MAAMA,uBAAqB,OAAO,eAAe;oBAC7B,EAAE,YAAY,MAAM,KAAK,aAAa;;AAG1D,MAAM,mBAAmB,OAAO,GAAG;;;;AASnC,MAAM,qBAAqB,OAAO,GAA4B;gCACZ;;;;;;;;;;WAUvC,EAAE,oBAAqB,gBAAgB,QAAQ,QAAS;;;;;;;oCAOb;yBAC7B,EAAE,gBAAiB,YAAY,MAAM,SAAU;;;AAIxE,MAAM,eAAe,OAAO,mBAAmB;;;;cAIjC,mBAAmB;;;;sBAIX,mBAAmB;;MAEnC,WAAW;;;AAUjB,MAAM,mBAAmB,OAAO,OAAO;;;KAGlC,EAAE,oBACH,iBACA,GAAG;iBACU,QAAQ,GAAG,GAAG,QAAQ,GAAG;MACpC;KACD,EAAE,eACH,YACA,GAAG;kCAC2B,EAAE,YAAY,cAAc,OAAO,gBAAgB,MAAM,cAAc,CAAC;MACpG;KACD,EAAE,eAAe,YAAY,kBAC9B,iBACA,CAAC,cACD,CAAC,eACD,GAAG;;;;wBAIiB,QAAQ,GAAG;MAC7B;;AAQN,MAAM,gBAAgB,OAAOC,UAAQ;;;;SAI5B,QAAQ,GAAG;;;;KAIf,EAAE,qBAAqB,kBAAkB,mBAAmB;KAC5D,EAAE,oBACH,CAAC,iBACD,GAAG;QACC,WAAW,cAAc;MAC3B;;AAGN,MAAM,gBAAgB,WAA0D,UAAU;AAE1F,MAAM,aAGA,EAAE,SAAS,kBAAkB;AAqDjC,QACE,qBAAC,QAAD,EAAA,UAAA,CArDc,QACb,QAAQ,WAAW,CAAC,OAAO,OAAO,CAClC,KAAK,QAAQ,MAAM;EAClB,MAAM,MAAM,aAAa,OAAO,GAC3B,OAAO,MAAM,OAAO,aAAa,UAAU,MAC3C,OAAO,MAAM,OAAO,SAAS,UAAU;EAE5C,MAAM,SAAS,aAAa,OAAO,GACjC,oBAAC,YAAD;GACE,IAAI,OAAO;GAEX,IAAI,OAAO;GACX,UAAU,MAAM;AACd,MAAE,iBAAiB;AACnB,WAAO,OAAO,UAAU,EAAE;;GAE5B,UAAU,OAAO;GACjB,cAAY,OAAO;GACnB,MAAK;aAEJ,OAAO;GACG,EAXN,IAWM,GAEb,oBAACC,UAAD;GACE,IAAI,OAAO;GAEX,cAAY,OAAO;GACnB,IAAI,OAAO;GACX,UAAU,MAAM;AACd,MAAE,iBAAiB;AACnB,WAAO,OAAO,UAAU,EAAE;;GAE5B,UAAU,OAAO;GACjB,SAAS,OAAO,WAAW;GAC3B,MAAK;GACL,OAAM;GACN,YAAY,OAAO;GACnB,YAAY,OAAO;aAElB,OAAO;GACD,EAfF,IAeE;AAGX,SAAO,OAAO,UACZ,oBAAC,SAAD;GAAmB,GAAI,OAAO;GAAc,SAAS;aAClD,OAAO;GACA,EAFI,IAEJ,GAEV;GAMM,EACP,YAAY,SAAS,KACpB,oBAAC,gBAAD;EACE,SAAQ;EACR,OAAM;EACN,MAAK;EACL,YAAY,KAAA;EACZ,OAAO,EAAE,aAAa,YAAY;EAClC,cAAW;EACX,WAAW,EACT,QAAQ,MACT;EACD,WAAW,YACR,QAAQ,WAAW,CAAC,OAAO,OAAO,CAClC,KAAK,WACJ,oBAACC,qBAAa,MAAd;GACE,IAAI,OAAO,MAAM,OAAO;GAExB,SAAS,OAAO;GAChB,UAAU,OAAO;aAEhB,OAAO;GACU,EALb,OAAO,MAAM,OAAO,MAKP,CACpB;YAEJ,oBAAC,UAAD,EAAY,CAAA;EACG,CAAA,CAEZ,EAAA,CAAA;;;;;;AAQb,MAAa,kBAuEP,EACJ,cACA,mBACA,WACA,SACA,OACA,UAAU,EAAE,EACZ,cAAc,EAAE,EAChB,yBACA,SACA,oBACA,QACA,YACA,mBACI;CACJ,MAAM,kBAAkB,QAAQ,SAAS,KAAK,YAAY,SAAS;CACnE,MAAM,EAAE,IAAI,WAAW,GAAG,qBAAqB,gBAAgB,EAAE;AAEjE,QACE,oBAAC,kBAAD;EACE,eAAe;EACf,YAAY;EACZ,aAAa;EACb,UAAU,gBAAgB,cAAc;EACxC,OAAM;EACN,SAAQ;EACR,SAAS,QAAQ;YAEhB,UACC,oBAACH,sBAAD;GAAoB,QAAO;GAAO,OAAM;GAAU,CAAA,GAElD,qBAAA,YAAA,EAAA,UAAA;GAEE,oBAAC,cAAD;IAAc,MAAK;IAAU,YAAY,CAAC;cACxC,qBAAC,eAAD;KACE,aAAa,cAAc,eAAe,OAAO;KACjD,MAAK;KACL,gBAAgB,CAAC,CAAC;KAClB,eAAe;KACf,cAAY;KACZ,GAAI;eANN;MAQG;MACD,oBAAC,eAAD,EAAA,UAAgB,OAAsB,CAAA;MACrC,WAAW,oBAAC,kBAAD,EAAA,UAAmB,SAA2B,CAAA;MAC5C;;IACH,CAAA;GACd;GACA,mBACC,oBAAC,WAAD;IACE,SAAS,QAAQ,QAAQ,WAAW,UAAU,KAAK;IACnD,aAAa,YAAY,QAAQ,WAAW,UAAU,KAAK;IAC3D,CAAA;GAEH,UACC,oBAAC,oBAAD;IAAoB,eAAe;IAAc,WAAW;cAC1D,oBAAC,iBAAD,EAAmB,CAAA;IACA,CAAA;GAEtB,EAAA,CAAA;EAEY,CAAA;;;;ACxVvB,MAAM,kBAAkB,OAAO,UAAU;;;AAOzC,MAAM,kBAAkB,OAAO,GAAyB;KACnD,EAAE,eACH,YACA,GAAG;+BACwB,EAAE,YAAY,cAAc,OAAO,gBAAgB,MAAM,cAAc,CAAC;MACjG;aACO,QAAQ,GAAG,GAAG,QAAQ,GAAG,GAAG,QAAQ,GAAG;;AAOpD,MAAM,uBAAuB,OAAO,GAA8B;KAC7D,EAAE,eACH,YACA,GAAG;;;;;;;;;2BASoB,EAAE,YAAY,cAAc,OAAO,kBAAkB,MAAM,MAAM,WAAW,QAAQ,CAAC;iBAC/F,UAAU,OAAO;MAC5B;;KAED,EAAE,UAAU,YACb,WACA,GAAG;;;MAGD;;AAMN,MAAM,mBAAmB,OAAO,WAAW;;;;KAItC,EAAE,kBACH,eACA,GAAG;;MAED;;AAON,MAAM,wBAAwB,OAAO,gBAAgB;;KAEhD,EAAE,kBACH,eACA,GAAG;;;MAGD;KACD,EAAE,oBACH,iBACA,GAAG;;;;;;MAMD;;AAGN,MAAM,qBAAqB,OAAO,eAAe;oBAC7B,EAAE,YAAY,MAAM,KAAK,aAAa;;AAS1D,MAAM,0BAA0B,OAAO,GAAiC;KACnE,EAAE,kBACH,eACA,GAAG;;;MAGD;KACD,EAAE,oBACH,iBACA,GAAG;iBACU,QAAQ,GAAG;;;aAGf,QAAQ,GAAG;;;;MAIlB;;KAED,EAAE,eAAe,kBAClB,CAAC,iBACD,eACA,GAAG;qBACc,QAAQ,GAAG;MAC1B;;OAEC,EAAE,eAAe,iBAClB,iBACA,CAAC,cACD,GAAG;;;;;MAKH;;;;;;AAON,MAAa,WA4EP,EACJ,UACA,cACA,SACA,QACA,eACA,UAAU,OACV,cACA,QAAQ,OACR,YACA,mBAAmB,OACnB,cAAc,OACd,SAAS,OACT,aAAa,YACT;CACJ,IAAI;AACJ,KAAI,QACF,WAAU,oBAAC,oBAAD;EAAoB,QAAQ,cAAc,UAAU;EAAS,OAAM;EAAS,CAAA;UAC7E,MACT,WAAU,oBAAC,WAAD,EAAA,UAAY,YAAY,WAAW,qBAAgC,CAAA;KAE7E,WAAU;CAGZ,MAAM,YAAY,CAAC,EAAE,UAAU;CAC/B,MAAM,aAAa,CAAC,CAAC;AAKrB,QACE,oBAAC,kBAAD;EAAkB,iBAAiB,CAAC;EAAkB,aAAa;aAC/D,EAAE,YAAY,YACd,qBAAA,YAAA,EAAA,UAAA;GACG,WACC,oBAAC,sBAAD;IAAsB,UAAU;cAC9B,oBAAC,gBAAD;KACgB;KACH;KACX,mBAAmB;KACV;KACT,QAAQ,cAAc,MAAM,SAAS,KAAA;KACzB;KACZ,GAAI;KACJ,CAAA;IACmB,CAAA;GAExB,cACC,oBAAC,uBAAD;IAAuB,eAAe;IAAc,aAAa;cAC/D,oBAAC,yBAAD;KACE,eAAe;KACf,aAAa;KACb,aAAa,CAAC,CAAC;KACf,YAAY;eAEX;KACuB,CAAA;IACJ,CAAA;GAEzB,aACC,oBAAC,sBAAD;IAAsB,UAAU;IAAQ,SAAA;cACtC,oBAAC,iBAAD;KAAiB,UAAU;eACxB,UACC,qBAAC,QAAD,EAAA,UAAA,CACE,oBAAC,oBAAD;MAAoB,QAAO;MAAO,OAAM;MAAU,CAAA,EAClD,oBAAC,oBAAD;MAAoB,QAAO;MAAO,OAAM;MAAU,CAAA,CAC3C,EAAA,CAAA,GAET,qBAAA,YAAA,EAAA,UAAA,CACG,UACC,oBAAC,iBAAD;MAAiB,MAAK;gBACpB,oBAAC,QAAD;OAAQ,SAAS,QAAQ;iBACtB,YACC,OACG,QAAQ,SAAS,QAAQ,KAAK,CAC9B,KAAK,MAAM,MAAM,oBAAC,QAAD,EAAA,UAAgC,MAAY,EAAjC,eAAe,IAAkB,CAAC,GAChE,MACC,oBAAC,QAAD,EAAA,UAAc,KAAQ,EAAX,EAAW,CAEzB;OACM,CAAA;MACO,CAAA,EAEnB,cACA,EAAA,CAAA;KAEW,CAAA;IACG,CAAA;GAExB,EAAA,CAAA;EAEY,CAAA;;;;AC5SvB,MAAM,gBAAgB,OAAO,GAAG;oBACZ,EAAE,YAAY,MAAM,KAAK,aAAa;uBACnC,EAAE,YAAY,cAAc,OAAO,kBAAkB,MAAM,MAAM,WAAW,QAAQ,CAAC;;;;;;;IAOxG,kBAAkB;;;;8BAIQ,EAAE,YAAY,cAAc,OAAO,kBAAkB,MAAM,MAAM,WAAW,QAAQ,CAAC;;AAGnH,MAAM,cAAc,cAAuC,EAAE,CAAC;AAE9D,MAAM,UAAU,OAAO,EAAE;;;2BAGE,EAAE,YAAY,cAAc,OAAO,gBAAgB,MAAM,cAAc,CAAC;;;;;AAMnG,MAAM,iBAYD,UAAU;AACb,QAAO,oBAAC,SAAD;EAAS,cAAc;EAAO,GAAI;EAAS,CAAA;;;;;;AAOpD,MAAM,WAEA,EAAE,eAAe;AACrB,QACE,oBAAC,YAAY,UAAb;EAAsB,OAAO,EAAE,WAAW,MAAM;YAC9C,oBAAC,eAAD,EAAA,UACG,YAAY,WAAW,MACtB,oBAAC,SAAD,EAAmB,EAAL,EAAK,CACnB,EACY,CAAA;EACK,CAAA;;AAI3B,MAAM,wBAAwB;;;;;;AAO9B,MAAM,QA+CD,EAAE,UAAU,SAAS,cAAc,gBAAgB,SAAS,MAAM,GAAG,mBAAmB;CAC3F,MAAM,EAAE,YAAY,UAAU,WAAW,YAAY;CACrD,MAAM,EAAE,qBAAqB,WAAW,cAAc;CAEtD,MAAM,gBACJ,oBAAC,SAAD;EAAS,cAAA;EAAa,GAAI;YACxB,oBAAC,WAAD,EAAA,UAAY,cAAc,WAAW,uBAAkC,CAAA;EAC/D,CAAA;CAGZ,MAAM,UACJ,oBAAC,SAAD;EAAS,cAAA;EAAqB;EAAQ,GAAI;EACvC;EACO,CAAA;AAGZ,QACE,oBAAC,eAAD;EACE,UACE,YACE,gBAEA,oBAAC,eAAD;GAAe,GAAI;aAAiB;GAA8B,CAAA;EAGtE,SAAS,cAAc,aAAa,UAAU,iBAAiB,MAAM;YAEpE,YACC,oBAAA,YAAA,EAAA,UAAG,UAAU,oBAAA,YAAA,EAAA,UAAG,eAAiB,CAAA,GAAG,oBAAA,YAAA,EAAA,UAAG,SAAW,CAAA,EAAI,CAAA,GAEtD,oBAAC,eAAD;GAAe,GAAI;aAChB,UAAU,oBAAA,YAAA,EAAA,UAAG,eAAiB,CAAA,GAAG,oBAAA,YAAA,EAAA,UAAG,SAAW,CAAA;GAClC,CAAA;EAEJ,CAAA;;AAIpB,IAAA,eAAe,OAAO,OAAO,MAAM;CACjC,SAAS;CACA;CACV,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox-Dr4LMKHV.mjs","names":[],"sources":["../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["import { uniqueId } from 'lodash-es';\nimport {\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { Color, Spacing, Typography } from '@persona/design-tokens';\nimport { InputCheckIcon, InputDashIcon } from '@persona/icons';\n\nimport useFormField from '#src/components/FormControl/useFormField';\nimport Stack from '#src/components/Stack/Stack';\nimport Tooltip from '#src/components/Tooltip';\nimport { TextWithDashedUnderline } from '#src/components/Tooltip/TextUnderlineTooltip';\nimport { opacityOf } from '#src/lib/color';\nimport {\n isChecked,\n isDisabled,\n isFocusedVisible,\n isHovered,\n isIndeterminate,\n isNotDisabled,\n} from '#src/lib/pseudoClass';\nimport { semanticColor, semanticOnly } from '#src/lib/semanticColor';\nimport useControlled from '#src/lib/useControlled';\nimport { focusStyle } from '#src/mixins/focus';\nimport { TransitionDuration } from '#src/variables/transitions';\n\nconst Container = styled(Stack)<{ size: 'md' | 'sm'; disabled?: boolean }>`\n position: relative;\n cursor: pointer;\n\n flex-wrap: nowrap;\n\n ${({ size }) =>\n size === 'sm' &&\n css`\n height: 16px;\n `}\n\n &${isDisabled} {\n cursor: default;\n }\n`;\n\nconst CheckboxBox = styled.div<{ disabled?: boolean; checked?: boolean }>`\n cursor: pointer;\n display: flex;\n flex: 0 0 16px;\n justify-content: center;\n align-items: center;\n transition:\n box-shadow ${TransitionDuration.Fast},\n background-color ${TransitionDuration.Fast},\n border-color ${TransitionDuration.Fast};\n border-radius: 3px;\n height: ${Spacing[4]};\n width: ${Spacing[4]};\n box-sizing: border-box;\n border: 1px solid ${({ theme }) => semanticColor(theme, 'InputBorderStrong', Color.BorderInputCheckbox)};\n background: ${({ theme }) => semanticColor(theme, 'InputSurfaceDefault', Color.BackgroundInputDefault)};\n\n svg {\n color: ${({ theme }) => semanticColor(theme, 'FgInverseStatic', Color.BorderIconInverse)};\n }\n\n &${isDisabled} {\n cursor: default;\n background: ${({ theme }) =>\n semanticColor(theme, 'InputSurfaceDisabled', Color.BackgroundInputDisabled)};\n border-color: ${({ theme }) =>\n semanticColor(theme, 'InputBorderDisabled', Color.BorderInputDisabled)};\n ${semanticOnly((tokens) => `opacity: ${opacityOf(tokens.Opacity65)};`)}\n }\n\n ${({ checked, theme }) =>\n checked &&\n css`\n border-color: ${semanticColor(theme, 'InputBorderAccent', Color.BackgroundInputActive)};\n background: ${semanticColor(theme, 'InputSurfaceAccent', Color.BackgroundInputActive)};\n\n &${isDisabled} {\n border-color: ${semanticColor(theme, 'InputSurfaceAccentDisabled', Color.BackgroundInputActiveDisabled)};\n background: ${semanticColor(theme, 'InputSurfaceAccentDisabled', Color.BackgroundInputActiveDisabled)};\n }\n `}\n`;\n\nconst CheckboxInput = styled.input`\n cursor: inherit;\n height: 16px;\n width: 16px;\n margin: 0;\n border: 0;\n opacity: 0;\n overflow: hidden;\n position: absolute;\n\n &${isHovered}${isNotDisabled} ~ ${CheckboxBox} {\n border-color: ${({ theme }) =>\n semanticColor(theme, 'InputBorderHoverStrong', Color.BorderInputCheckboxHover)};\n ${semanticOnly((tokens) => `background: ${tokens.InputSurfaceHover};`)}\n }\n\n &${isChecked}, &${isIndeterminate} {\n &${isHovered}${isNotDisabled} ~ ${CheckboxBox} {\n background: ${({ theme }) => semanticColor(theme, 'InputSurfaceAccentHover', Color.BackgroundInputActiveHover)};\n border-color: ${({ theme }) => semanticColor(theme, 'InputSurfaceAccentHover', Color.BackgroundInputActiveHover)};\n }\n }\n\n &${isFocusedVisible}${isNotDisabled} ~ ${CheckboxBox} {\n ${focusStyle}\n }\n`;\n\nconst Label = styled.label<{ disabled: boolean; size: 'md' | 'sm' }>`\n cursor: inherit;\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n\n ${({ size }) =>\n size === 'sm'\n ? css`\n ${Typography.TextSmall};\n line-height: 16px;\n `\n : css`\n ${Typography.TextMedium};\n\n /** Nudge text for visual alignment */\n position: relative;\n bottom: -1px;\n `}\n\n ${({ theme, disabled }) =>\n disabled &&\n css`\n cursor: default;\n color: ${semanticColor(theme, 'FgDisabled', theme.color.text.disabled)};\n `}\n`;\n\nexport interface CheckboxProps extends Omit<ComponentPropsWithoutRef<'input'>, 'value' | 'size'> {\n /**\n * `id` for the underlying `<input>`. If not provided a unique ID is generated\n * automatically and linked to the label.\n */\n id?: string;\n /** Called whenever the checked state changes. */\n onChange?: (e: ChangeEvent<HTMLInputElement>) => void;\n /** Visible label rendered to the right of the checkbox box. */\n label?: ReactNode;\n /** Disables interaction and renders the checkbox in a muted style. */\n disabled?: boolean;\n /**\n * When true the checkbox displays a dash (−) instead of a tick, indicating a\n * mixed / partially-selected state. Sets `aria-checked=\"mixed\"` for screen readers.\n */\n indeterminate?: boolean;\n /**\n * Controlled checked state. Omit (or pass `undefined`) to let the component\n * manage state internally via `defaultChecked`.\n */\n checked?: boolean;\n /** Value submitted with a form. */\n value?: unknown;\n 'data-test'?: string;\n /** Additional props forwarded to the outer container `<div>`. */\n containerProps?: ComponentPropsWithoutRef<'div'>;\n /**\n * Size of the checkbox and its label text.\n * @defaultValue 'md'\n */\n size?: 'md' | 'sm';\n /**\n * Tooltip content to display when hovering over the label.\n * When provided, the label will be wrapped in a tooltip.\n */\n tooltip?: ReactNode;\n}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n {\n className,\n disabled,\n indeterminate,\n onChange,\n checked: checkedProp,\n defaultChecked,\n id,\n label,\n 'data-test': dataTest,\n containerProps,\n value,\n size = 'md',\n tooltip,\n ...elemProps\n },\n ref,\n) {\n const field = useFormField({ disabled });\n const [checked, setChecked] = useControlled({\n controlledValue: checkedProp,\n default: defaultChecked,\n });\n const generatedId = useMemo(() => uniqueId('pds_checkbox__'), []);\n const inputRef = useRef<HTMLInputElement>();\n\n // Use the inputId from FormControl context if available, otherwise use the provided id or generate one\n const inputId = field.inputId || id || generatedId;\n\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n useImperativeHandle(ref, () => inputRef.current, [inputRef]);\n\n // Re-sync on `checked` changes too: a native click clears the input's\n // `indeterminate` property, so it must be re-applied when the prop stays true.\n useEffect(() => {\n if (inputRef.current) {\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n inputRef.current.indeterminate = indeterminate;\n }\n }, [indeterminate, checked, inputRef]);\n\n return (\n <Container\n direction='horizontal'\n className={className}\n data-test={dataTest}\n disabled={field.disabled}\n align='center'\n size={size}\n {...containerProps}\n >\n <CheckboxInput\n id={inputId}\n /* @ts-expect-error [strict-migration] The following line is not strict; please fix! */\n ref={inputRef}\n data-test={dataTest && `${dataTest}-input`}\n disabled={field.disabled}\n type='checkbox'\n checked={checkedProp == null ? undefined : checked}\n defaultChecked={defaultChecked}\n onChange={(e) => {\n setChecked(e.target.checked);\n if (onChange) {\n onChange(e);\n }\n }}\n aria-checked={indeterminate ? 'mixed' : undefined}\n value={value as unknown as string}\n {...elemProps}\n />\n <CheckboxBox\n aria-hidden='true'\n disabled={field.disabled}\n checked={(checked != null && checked) || indeterminate}\n >\n {indeterminate ? <InputDashIcon /> : checked ? <InputCheckIcon /> : null}\n </CheckboxBox>\n {label &&\n (tooltip ? (\n <Tooltip\n size={size}\n trigger={\n <Label htmlFor={inputId} disabled={!!field.disabled} size={size}>\n <TextWithDashedUnderline>{label}</TextWithDashedUnderline>\n </Label>\n }\n >\n {tooltip}\n </Tooltip>\n ) : (\n <Label htmlFor={inputId} disabled={!!field.disabled} size={size}>\n {label}\n </Label>\n ))}\n </Container>\n );\n});\n\nexport default Checkbox;\n"],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { n as ComboboxMultiSelectProps } from "./ComboboxMultiSelect-BwkkSymj.mjs";
|
|
2
|
-
import { n as ComboboxSingleSelectProps } from "./ComboboxSingleSelect-CdNNJNkp.mjs";
|
|
3
|
-
|
|
4
|
-
//#region src/components/Combobox/Combobox.d.ts
|
|
5
|
-
type ComboboxProps<T = string> = ComboboxSingleSelectProps<T> | ComboboxMultiSelectProps<T>;
|
|
6
|
-
declare const Combobox: <T = string>(props: ComboboxProps<T> & {
|
|
7
|
-
ref?: React.Ref<HTMLInputElement>;
|
|
8
|
-
}) => React.ReactElement;
|
|
9
|
-
//#endregion
|
|
10
|
-
export { ComboboxProps as n, Combobox as t };
|
|
11
|
-
//# sourceMappingURL=Combobox-CIKqTYZt.d.mts.map
|