@persona/design-system 0.10.0 → 0.10.2
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 +25 -0
- package/dist/AdvancedFilterRuleRow.d.mts +2 -2
- package/dist/AdvancedFilterRulesPopover.d.mts +2 -2
- package/dist/ArrayValueControl.d.mts +1 -1
- package/dist/BooleanValueControl.d.mts +1 -1
- package/dist/{Calendar-DAfQCLOJ.d.mts → Calendar-CkjYG7Mj.d.mts} +1 -1
- package/dist/Calendar.d.mts +1 -1
- package/dist/{CheckboxGroupField-BYB4OBlW.d.mts → CheckboxGroupField-BrPGNIyD.d.mts} +2 -2
- package/dist/CheckboxGroupField.d.mts +1 -1
- package/dist/ChoicesValueControl.d.mts +1 -1
- package/dist/{Combobox-CcFJo68g.mjs → Combobox-BXHCfVpE.mjs} +2 -2
- package/dist/{Combobox-CcFJo68g.mjs.map → Combobox-BXHCfVpE.mjs.map} +1 -1
- package/dist/{Combobox-DH5ycYlG.d.mts → Combobox-D0dMN5eY.d.mts} +3 -3
- package/dist/Combobox.d.mts +2 -2
- package/dist/{ComboboxBase-BQQSKUBU.d.mts → ComboboxBase-BlNi9OnF.d.mts} +2 -2
- package/dist/ComboboxBase.d.mts +1 -1
- package/dist/{ComboboxMultiSelect-Da3Gv1k5.d.mts → ComboboxMultiSelect-DbTYO-Yz.d.mts} +2 -2
- package/dist/ComboboxMultiSelect.d.mts +1 -1
- package/dist/{ComboboxSingleSelect-BUDovONU.d.mts → ComboboxSingleSelect-Cd6VYdwr.d.mts} +3 -3
- package/dist/ComboboxSingleSelect.d.mts +1 -1
- package/dist/{CompactBar-D12R7Nm2.d.mts → CompactBar-CfrrZ69k.d.mts} +1 -1
- package/dist/CompactBar.d.mts +1 -1
- package/dist/{ConfigFormGroup-CidT_cE9.mjs → ConfigFormGroup-BE3yR_VU.mjs} +1 -1
- package/dist/{ConfigFormGroup-CidT_cE9.mjs.map → ConfigFormGroup-BE3yR_VU.mjs.map} +1 -1
- package/dist/{DataTable-fZ7SNbIH.d.mts → DataTable-BdKUCgcZ.d.mts} +7 -5
- package/dist/{DataTable-95ZxiPlV.mjs → DataTable-F9R-aQCg.mjs} +8 -8
- package/dist/DataTable-F9R-aQCg.mjs.map +1 -0
- package/dist/DataTable.d.mts +1 -1
- package/dist/{DateField-DLz13Ksl.d.mts → DateField-CwSq77Ri.d.mts} +1 -1
- package/dist/DateField.d.mts +1 -1
- package/dist/{DatePicker-D0cvVbzq.mjs → DatePicker-CkNQjfCN.mjs} +2 -2
- package/dist/{DatePicker-D0cvVbzq.mjs.map → DatePicker-CkNQjfCN.mjs.map} +1 -1
- package/dist/{DatePicker-DYVWmbrb.d.mts → DatePicker-DRhY_0st.d.mts} +1 -1
- package/dist/DatePicker.d.mts +1 -1
- package/dist/{DateRangePicker-Be8TYtjz.d.mts → DateRangePicker-CLuBLF1q.d.mts} +2 -2
- package/dist/DateRangePicker.d.mts +1 -1
- package/dist/DateRangeValueControl.d.mts +2 -2
- package/dist/DateValueControl.d.mts +1 -1
- package/dist/DropdownButton.d.mts +1 -1
- package/dist/{DropdownMenu-DAa2kNrt.d.mts → DropdownMenu-nxFNS1kH.d.mts} +2 -2
- package/dist/DropdownMenu.d.mts +1 -1
- package/dist/{FieldRegistry-d5tGpSch.d.mts → FieldRegistry-B5E-GN91.d.mts} +2 -2
- package/dist/FieldRegistry.d.mts +1 -1
- package/dist/{FilterBar-Bh18VyOK.d.mts → FilterBar-BQWpTi2b.d.mts} +4 -4
- 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 +1 -1
- package/dist/{FormField-cSG93kuo.mjs → FormField-D0y1uRV5.mjs} +9 -9
- package/dist/{FormField-cSG93kuo.mjs.map → FormField-D0y1uRV5.mjs.map} +1 -1
- package/dist/HighlightedText.d.mts +1 -1
- package/dist/{HoverCopyableField-D-BubaRd.mjs → HoverCopyableField-DkOosH8z.mjs} +2 -2
- package/dist/{HoverCopyableField-D-BubaRd.mjs.map → HoverCopyableField-DkOosH8z.mjs.map} +1 -1
- package/dist/ImageThumbnail.d.mts +43 -0
- package/dist/IndexTableLayout.d.mts +3 -3
- package/dist/InlineCombobox.d.mts +1 -1
- package/dist/InlineInput.d.mts +1 -1
- package/dist/IntegerValueControl.d.mts +1 -1
- package/dist/{Link-Cf__H8gD.mjs → Link-BSuXrvTu.mjs} +1 -1
- package/dist/{Link-Cf__H8gD.mjs.map → Link-BSuXrvTu.mjs.map} +1 -1
- package/dist/{ListBox-C80J7DCG.mjs → ListBox-BLoJVezh.mjs} +2 -2
- package/dist/{ListBox-C80J7DCG.mjs.map → ListBox-BLoJVezh.mjs.map} +1 -1
- package/dist/{ListBox-Bj5c626-.d.mts → ListBox-CXFI-0nG.d.mts} +2 -2
- package/dist/ListBox.d.mts +1 -1
- package/dist/{ListBoxField-DsJRabgE.d.mts → ListBoxField-BCOrph2k.d.mts} +4 -4
- package/dist/ListBoxField.d.mts +1 -1
- package/dist/{LogicRow-CcpD-Kk3.d.mts → LogicRow-8oYRkwz5.d.mts} +2 -2
- package/dist/LogicRow.d.mts +1 -1
- package/dist/{Menu-C0FU9WEF.d.mts → Menu-DHnQZ5yN.d.mts} +2 -2
- package/dist/Menu.d.mts +1 -1
- package/dist/{Modal-kjUptzg1.mjs → Modal-IJdbLORi.mjs} +1 -1
- package/dist/{Modal-kjUptzg1.mjs.map → Modal-IJdbLORi.mjs.map} +1 -1
- package/dist/{Pagination-DtK-jbEY.mjs → Pagination-C5ANr9M0.mjs} +2 -2
- package/dist/{Pagination-DtK-jbEY.mjs.map → Pagination-C5ANr9M0.mjs.map} +1 -1
- package/dist/{Pii-DueIK287.mjs → Pii-G16_b7Yk.mjs} +1 -1
- package/dist/{Pii-DueIK287.mjs.map → Pii-G16_b7Yk.mjs.map} +1 -1
- package/dist/{PillShell-CXROf8gO.d.mts → PillShell-DqglbFHe.d.mts} +2 -2
- package/dist/PillShell.d.mts +1 -1
- package/dist/{Popover-BcII7usF.mjs → Popover-532iYFek.mjs} +1 -1
- package/dist/{Popover-BcII7usF.mjs.map → Popover-532iYFek.mjs.map} +1 -1
- package/dist/{Radio-DDT_l8rd.mjs → Radio-BstZg3DI.mjs} +1 -1
- package/dist/{Radio-DDT_l8rd.mjs.map → Radio-BstZg3DI.mjs.map} +1 -1
- package/dist/{RadioGroup-CmD8NFCL.mjs → RadioGroup-erKerwSt.mjs} +2 -2
- package/dist/{RadioGroup-CmD8NFCL.mjs.map → RadioGroup-erKerwSt.mjs.map} +1 -1
- package/dist/{RangeCalendar-cZSYjuOZ.d.mts → RangeCalendar-CK5ArbIQ.d.mts} +2 -2
- package/dist/RangeCalendar.d.mts +1 -1
- package/dist/RangeCalendarPresets.d.mts +1 -1
- package/dist/RuleEditorFields.d.mts +2 -2
- package/dist/RulesPill.d.mts +1 -1
- package/dist/{SegmentedControl-CcKPfxBR.mjs → SegmentedControl-DQjIO6iX.mjs} +1 -1
- package/dist/{SegmentedControl-CcKPfxBR.mjs.map → SegmentedControl-DQjIO6iX.mjs.map} +1 -1
- package/dist/{Select-sBEBrNgo.d.mts → Select-CSbamhJO.d.mts} +2 -2
- package/dist/{Select-BJ9ACmRD.mjs → Select-hnXfPywt.mjs} +1 -1
- package/dist/{Select-BJ9ACmRD.mjs.map → Select-hnXfPywt.mjs.map} +1 -1
- package/dist/Select.d.mts +1 -1
- package/dist/SelectionCard.d.mts +51 -0
- package/dist/SelectionCardGroup.d.mts +37 -0
- package/dist/SmartTextInput.d.mts +22 -5
- package/dist/SmartTextInputField.d.mts +2 -2
- package/dist/SmartTextInputFunctionDialog.d.mts +2 -2
- package/dist/SmartTextInputListbox.d.mts +2 -2
- package/dist/SmartTextInputPopover.d.mts +1 -1
- package/dist/{Spinner-uVZyOh1T.mjs → Spinner-AnIk8d9M.mjs} +1 -1
- package/dist/{Spinner-uVZyOh1T.mjs.map → Spinner-AnIk8d9M.mjs.map} +1 -1
- package/dist/StringValueControl.d.mts +1 -1
- package/dist/{Table--o4ZLRbb.mjs → Table-CmuWqmVN.mjs} +2 -2
- package/dist/{Table--o4ZLRbb.mjs.map → Table-CmuWqmVN.mjs.map} +1 -1
- package/dist/{TableBox-3qunC9Nl.mjs → TableBox-BRJunn09.mjs} +4 -4
- package/dist/{TableBox-3qunC9Nl.mjs.map → TableBox-BRJunn09.mjs.map} +1 -1
- package/dist/TableBox.d.mts +1 -1
- package/dist/{TableBoxCell-BRECnVTs.d.mts → TableBoxCell-Cag3ZYRs.d.mts} +4 -4
- package/dist/TableBoxCell.d.mts +1 -1
- package/dist/{TableBoxField-Lm_tn73M.d.mts → TableBoxField-C3Cg6Lv5.d.mts} +5 -5
- package/dist/TableBoxField.d.mts +1 -1
- package/dist/{TableBoxRow-BS8Dc-zw.d.mts → TableBoxRow-y5ay5lMt.d.mts} +2 -2
- package/dist/TableBoxRow.d.mts +1 -1
- package/dist/{TableBoxRowActions-oLMb8XcM.d.mts → TableBoxRowActions-CDdVjAPQ.d.mts} +2 -2
- package/dist/TableBoxRowActions.d.mts +1 -1
- package/dist/{TableControls-DxSFqRwJ.mjs → TableControls-C5fNNdmT.mjs} +1359 -1308
- package/dist/TableControls-C5fNNdmT.mjs.map +1 -0
- package/dist/{TableControls-UfObf-ZN.d.mts → TableControls-DCtTiWk6.d.mts} +10 -5
- package/dist/TableControls.d.mts +2 -2
- package/dist/{TableControlsContext-Bhtb0cMs.d.mts → TableControlsContext-CzJCMrSe.d.mts} +2 -2
- package/dist/TableControlsContext.d.mts +1 -1
- package/dist/{TableViewConfigurationDropdown-BDXe2Q1Y.d.mts → TableViewConfigurationDropdown-BvOlDkJy.d.mts} +2 -2
- package/dist/TableViewConfigurationDropdown.d.mts +1 -1
- package/dist/{TextArea-CFf0Lspu.mjs → TextArea-CaIEBz8d.mjs} +1 -1
- package/dist/{TextArea-CFf0Lspu.mjs.map → TextArea-CaIEBz8d.mjs.map} +1 -1
- package/dist/{Toggle-BLdemkh_.mjs → Toggle-BsqSNYok.mjs} +1 -1
- package/dist/{Toggle-BLdemkh_.mjs.map → Toggle-BsqSNYok.mjs.map} +1 -1
- package/dist/{chainTypes-BbFZn8a9.d.mts → chainTypes-Cjp0zZ4E.d.mts} +3 -3
- package/dist/{clientFilterUtils-c5xzvoBj.d.mts → clientFilterUtils-BqDn44aM.d.mts} +2 -2
- package/dist/clientFilterUtils.d.mts +1 -1
- package/dist/{codec-DIp7dhcN.d.mts → codec-KAvQRjTW.d.mts} +2 -2
- package/dist/codec.d.mts +1 -1
- package/dist/components/Combobox/index.d.mts +2 -2
- package/dist/components/Combobox/index.mjs +1 -1
- package/dist/components/ConfigFormGroup/index.mjs +1 -1
- package/dist/components/DataTable/TableControls/index.d.mts +21 -21
- package/dist/components/DataTable/TableControls/index.mjs +1 -1
- package/dist/components/DataTable/index.d.mts +5 -5
- package/dist/components/DataTable/index.mjs +1 -1
- package/dist/components/DataTable/types.d.mts +1 -1
- package/dist/components/DatePicker/index.d.mts +5 -5
- package/dist/components/DatePicker/index.mjs +1 -1
- package/dist/components/DropdownMenu/index.d.mts +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 +82 -52
- package/dist/components/ImageTile/index.mjs.map +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/Menu/index.d.mts +1 -1
- package/dist/components/Modal/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/Radio/index.mjs +1 -1
- package/dist/components/RadioGroup/index.mjs +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.d.mts +3 -0
- package/dist/components/SelectionCard/index.mjs +264 -0
- package/dist/components/SelectionCard/index.mjs.map +1 -0
- package/dist/components/SmartTextInput/index.d.mts +2 -2
- package/dist/components/SmartTextInput/index.mjs +12 -3
- package/dist/components/SmartTextInput/index.mjs.map +1 -1
- package/dist/components/Spinner/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/TextArea/index.mjs +1 -1
- package/dist/components/Toggle/index.mjs +1 -1
- package/dist/components/VersionHistory/index.mjs +3 -3
- package/dist/compound-expression.d.mts +1 -1
- package/dist/{date-range-rule-value-D01nn054.d.mts → date-range-rule-value-Dk6pZHnD.d.mts} +2 -2
- package/dist/date-range-rule-value.d.mts +1 -1
- package/dist/{date-rule-intent-B4hQ_APa.d.mts → date-rule-intent-C5C8HB1v.d.mts} +3 -3
- package/dist/date-rule-intent.d.mts +1 -1
- package/dist/display.d.mts +1 -1
- package/dist/fieldPickerOptions.d.mts +2 -2
- package/dist/{filter-size-context-Dj7Idc8j.d.mts → filter-size-context-5xQ3ycnC.d.mts} +2 -2
- package/dist/filter-size-context.d.mts +1 -1
- package/dist/{filters-DDrsgRYy.d.mts → filters-jG9Y3UKb.d.mts} +2 -2
- package/dist/filters.d.mts +1 -1
- package/dist/{helpers-D8_2I4ZX.d.mts → helpers-DCIto6aY.d.mts} +2 -2
- package/dist/helpers.d.mts +1 -1
- package/dist/{index-DsjvDLF8.d.mts → index-C3uFHTo0.d.mts} +3 -3
- package/dist/{index-DkXly4xw.d.mts → index-DTAcGzW4.d.mts} +2 -2
- package/dist/index3.d.mts +3 -3
- package/dist/index4.d.mts +1 -1
- package/dist/index5.d.mts +14 -14
- package/dist/{inputFields-DyOZHse2.d.mts → inputFields-mUsms2tO.d.mts} +4 -4
- package/dist/inputFields.d.mts +1 -1
- package/dist/{jsonSchema-COo0XQLA.d.mts → jsonSchema-DmOA0Lnu.d.mts} +2 -2
- package/dist/lib/PDSProvider.d.mts +8 -0
- package/dist/lib/PDSProvider.mjs +15 -11
- package/dist/lib/PDSProvider.mjs.map +1 -1
- package/dist/lib/chainTypes.d.mts +1 -1
- package/dist/lib/colorMode.d.mts +30 -0
- package/dist/lib/colorMode.mjs +71 -0
- package/dist/lib/colorMode.mjs.map +1 -0
- package/dist/lib/customFunctionSchema.d.mts +1 -1
- package/dist/lib/date-filter/index.d.mts +2 -2
- package/dist/lib/jsonSchema.d.mts +1 -1
- package/dist/lib/jsonSchema.mjs.map +1 -1
- package/dist/lib/jsonSchemaType.d.mts +1 -1
- package/dist/lib/methodChain.d.mts +1 -1
- package/dist/lib/objectSchemaTypes.d.mts +1 -1
- package/dist/lib/platformObject.d.mts +1 -1
- package/dist/lib/schemaOptions.d.mts +2 -2
- package/dist/lib/schemaOptions.mjs +20 -2
- package/dist/lib/schemaOptions.mjs.map +1 -1
- package/dist/lib/useChain.d.mts +1 -1
- package/dist/{listbox-options-D-DyLUdi.d.mts → listbox-options-DCmqWWgy.d.mts} +3 -3
- package/dist/listbox-options.d.mts +1 -1
- package/dist/{methodChain-BAUFBbR9.d.mts → methodChain-DaDvXsHF.d.mts} +2 -2
- package/dist/{operators-DjQXVNVI.d.mts → operators-Seez5p9U.d.mts} +2 -2
- package/dist/operators.d.mts +1 -1
- package/dist/patterns/IndexTableLayout/index.mjs +1 -1
- package/dist/patterns/LayoutLoadingShimmer/index.mjs +1 -1
- package/dist/patterns/WizardModal/index.mjs +1 -1
- package/dist/relative-date-label.d.mts +1 -1
- package/dist/{schemaOptions-D536qhSd.d.mts → schemaOptions-BQgLOgtD.d.mts} +8 -3
- package/dist/{types-DHTFd-5t.d.mts → types-39QvBZuZ.d.mts} +1 -1
- package/dist/{types-Dx8PgO8a.d.mts → types-CrRWZ0Ia.d.mts} +4 -4
- package/dist/{types-DFU6M0OL.d.mts → types-DWU0Dmy9.d.mts} +3 -3
- package/dist/{types-CjQzH0MM.d.mts → types-DxJyE_U8.d.mts} +2 -2
- package/dist/{types-BMpEizJP.d.mts → types-EodOhsjw.d.mts} +2 -2
- package/dist/{types-BhHdS6QP.d.mts → types-SOkNtcBq.d.mts} +2 -2
- package/dist/types3.d.mts +1 -1
- package/dist/types4.d.mts +2 -2
- package/dist/types5.d.mts +2 -2
- package/dist/types6.d.mts +1 -1
- package/dist/types7.d.mts +1 -1
- package/dist/{url-state-D1muieS7.d.mts → url-state-CwaRVyXR.d.mts} +2 -2
- package/dist/url-state.d.mts +1 -1
- package/dist/{useChain-D5LvupTW.d.mts → useChain-DXkKKe-J.d.mts} +4 -4
- package/dist/useChainAtCursor.d.mts +4 -4
- package/dist/useCodeChainFunctionPanel.d.mts +1 -1
- package/dist/useColumnConfiguration.d.mts +2 -2
- package/dist/useComboboxFooterAction.d.mts +1 -1
- package/dist/{useFilterStateV2-MH3zbQFr.d.mts → useFilterStateV2-Bzo27PR-.d.mts} +3 -3
- package/dist/useFilterStateV2.d.mts +1 -1
- package/dist/{useTableColumns-rLskKJhd.d.mts → useTableColumns-DSXRInPb.d.mts} +2 -2
- package/dist/useTableColumns.d.mts +1 -1
- package/dist/useTruncation.d.mts +1 -1
- package/dist/utils.d.mts +1 -1
- package/dist/utils4.d.mts +2 -2
- package/dist/{validation-Csi2SJxm.d.mts → validation-D6NPueNk.d.mts} +3 -3
- package/dist/validation.d.mts +1 -1
- package/dist/validation2.d.mts +3 -3
- package/dist/{value-control-resolver-BoBFvQ_0.d.mts → value-control-resolver-C-UrXVlB.d.mts} +2 -2
- package/dist/value-control-resolver.d.mts +1 -1
- package/llms.txt +9 -1
- package/package.json +5 -1
- package/skills/ui-authoring/COMPONENTS.md +2 -1
- package/skills/ui-authoring/PATTERNS.md +5 -1
- package/skills/ui-authoring/TOKENS.md +10 -0
- package/dist/DataTable-95ZxiPlV.mjs.map +0 -1
- package/dist/TableControls-DxSFqRwJ.mjs.map +0 -1
- /package/dist/{index-BYd3Btr1.d.mts → index-DztUdPP_.d.mts} +0 -0
- /package/dist/{index-IJ_PXwxI2.d.mts → index-uMNhmxEh.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["DropdownMenu"],"sources":["../../../components/ImageTile/ImageTile.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n useCallback,\n useState,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { IconButton } from '@persona/design-system/components/Button';\nimport Checkbox from '@persona/design-system/components/Checkbox';\nimport DropdownMenu from '@persona/design-system/components/DropdownMenu';\nimport { LoadingShimmer } from '@persona/design-system/components/LoadingShimmer';\nimport Stack from '@persona/design-system/components/Stack';\nimport { Paragraph } from '@persona/design-system/components/Text';\nimport { Tooltip } from '@persona/design-system/components/Tooltip';\nimport { focusOutline } from '@persona/design-system/mixins/focus';\nimport { TransitionDuration } from '@persona/design-system/variables/transitions';\nimport { Spacing } from '@persona/design-tokens';\nimport { ImageIcon, LockedIcon, MoreIcon } from '@persona/icons';\nimport { withAlpha } from 'design-system/lib/color';\nimport { semanticColor, semanticTokens } from 'design-system/lib/semanticColor';\nimport type { TextAction } from 'design-system/types/Action';\n\nconst MIN_WIDTH = '180px';\nconst MAX_WIDTH = '420px';\nconst OVERLAY_INSET = Spacing[2];\nconst EMPTY_COPY = 'No available preview';\nconst DEFAULT_SELECTION_LABEL = 'Select image';\n\nexport interface ImageTileProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n /** URL of the thumbnail. While loading shows shimmer; on error shows the empty fallback. */\n src: string | null;\n /** Alt text for the thumbnail. Also seeds the default checkbox label. */\n alt?: string;\n /** How the thumbnail fills its area. `cover` crops overflow; `contain` letterboxes to fit. Defaults to `cover`. */\n objectFit?: 'cover' | 'contain';\n\n /** Enables the selection checkbox (top-left). */\n selectable?: boolean;\n /** Controlled checked state for the selection checkbox. */\n selected?: boolean;\n /** Called with the new checked value when the checkbox is toggled. */\n onSelectedChange?: (selected: boolean) => void;\n /** Accessible label for the checkbox. Defaults to \"Select {alt}\" or \"Select image\". */\n selectionLabel?: string;\n\n /**\n * Action menu items rendered behind a 3-dot IconButton in the top-right.\n * Ignored when `locked` is true. Pass an empty array (or omit) to hide the menu.\n */\n actions?: TextAction[];\n /**\n * Replaces the action menu with a non-interactive lock icon. Indicates the\n * viewer does not have permission to edit. `actions` are ignored.\n */\n locked?: boolean;\n /** Tooltip string shown when hovering the lock icon. */\n lockedTooltip?: string;\n\n /**\n * Metadata rows rendered beneath the thumbnail. Each entry becomes a\n * full-width, left-aligned row in a vertical Stack. Block content fills the\n * row; inline content (e.g. a Sticker) hugs the left. The region is omitted\n * entirely — including while the image is loading — when the array is empty\n * or undefined, so the tile is only the image.\n */\n metadata?: ReactNode[];\n\n /** Optional click handler for the whole tile. When provided, the tile is keyboard-activatable. */\n onClick?: (e: MouseEvent<HTMLDivElement>) => void;\n}\n\nconst ImageContainer = styled.div`\n position: relative;\n aspect-ratio: 200 / 144;\n background-color: ${({ theme }) => semanticColor(theme, 'SurfaceSecondary', theme.color.background.secondary)};\n overflow: hidden;\n`;\n\nconst Thumbnail = styled.img<{ $visible: boolean; $objectFit: 'cover' | 'contain' }>`\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: ${({ $objectFit }) => $objectFit};\n display: block;\n opacity: ${({ $visible }) => ($visible ? 1 : 0)};\n transition: opacity ${TransitionDuration.Fast};\n`;\n\nconst ImageShimmer = styled(LoadingShimmer)`\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n border-radius: 0;\n`;\n\nconst EmptyState = styled.div`\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: ${Spacing[1]};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n padding: ${Spacing[3]};\n text-align: center;\n`;\n\nconst MetadataContainer = styled.div`\n padding: ${Spacing[3]};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n border-top: 1px solid ${({ theme }) => semanticColor(theme, 'BorderDivider', theme.color.border.primary)};\n transition: background-color ${TransitionDuration.Fast};\n`;\n\nconst MetadataRow = styled.div`\n width: 100%;\n // Without these Stickers get bottom aligned\n display: flex;\n align-items: flex-start;\n`;\n\nconst SelectionOverlay = styled.div`\n position: absolute;\n top: ${OVERLAY_INSET};\n left: ${OVERLAY_INSET};\n z-index: 1;\n`;\n\nconst ActionsOverlay = styled.div`\n position: absolute;\n top: ${OVERLAY_INSET};\n right: ${OVERLAY_INSET};\n z-index: 1;\n`;\n\nconst LockedOverlay = styled.div`\n position: absolute;\n top: ${OVERLAY_INSET};\n right: ${OVERLAY_INSET};\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n`;\n\nconst Root = styled.div<{ $clickable: boolean }>`\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: ${MIN_WIDTH};\n max-width: ${MAX_WIDTH};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n border: 1px solid ${({ theme }) => semanticColor(theme, 'BorderDivider', theme.color.border.primary)};\n border-radius: ${({ theme }) => theme.card.borderRadius};\n box-sizing: border-box;\n overflow: hidden;\n ${focusOutline};\n\n ${({ $clickable }) =>\n $clickable &&\n css`\n cursor: pointer;\n `}\n\n &:hover ${MetadataContainer} {\n background-color: ${({ theme }) => {\n const tokens = semanticTokens(theme);\n return tokens\n ? withAlpha(tokens.SurfaceAccent, tokens.Opacity25)\n : theme.color.background.highlight;\n }};\n }\n`;\n\nconst stopPropagation = (e: MouseEvent) => {\n e.stopPropagation();\n};\n\nexport const ImageTile = ({\n src,\n alt = '',\n objectFit = 'cover',\n selectable = false,\n selected = false,\n onSelectedChange,\n selectionLabel,\n actions,\n locked = false,\n lockedTooltip,\n metadata,\n onClick,\n ...props\n}: ImageTileProps) => {\n // Keyed by src so a new image starts loading without an effect that can\n // reset state after a cached image has already decoded.\n const [resolved, setResolved] = useState<{\n src: string;\n status: 'loaded' | 'error';\n } | null>(null);\n\n if (resolved && resolved.src !== src) {\n setResolved(null);\n }\n\n const hasSrc = Boolean(src);\n const loaded = resolved?.src === src && resolved.status === 'loaded';\n const hasError = resolved?.src === src && resolved.status === 'error';\n const isLoading = hasSrc && !loaded && !hasError;\n const showEmpty = !hasSrc || hasError;\n\n const markResolved = (status: 'loaded' | 'error') => {\n if (!src) {\n return;\n }\n setResolved((current) =>\n current?.src === src && current.status === status ? current : { src, status },\n );\n };\n\n const handleImageRef = useCallback(\n (node: HTMLImageElement | null) => {\n // A cached image can finish before React attaches onLoad, which leaves\n // the tile shimmering forever. Adopt an already-decoded image here.\n if (!node || !src || !node.complete || node.naturalWidth === 0) {\n return;\n }\n setResolved((current) =>\n current?.src === src && current.status === 'loaded' ? current : { src, status: 'loaded' },\n );\n },\n [src],\n );\n\n const visibleActions = actions?.filter((action) => !action.hidden) ?? [];\n const renderActions = !locked && visibleActions.length > 0;\n const clickable = Boolean(onClick);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (!onClick) {\n return;\n }\n // Only activate when the key event originates from the tile root itself.\n // Interactive descendants (selection checkbox, action buttons) must keep\n // their own native Space/Enter behavior.\n if (e.target !== e.currentTarget) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.currentTarget.click();\n }\n };\n\n const accessibleSelectionLabel =\n selectionLabel ?? (alt ? `Select ${alt}` : DEFAULT_SELECTION_LABEL);\n\n const hasMetadata = (metadata?.length ?? 0) > 0;\n\n return (\n <Root\n $clickable={clickable}\n onClick={onClick}\n onKeyDown={clickable ? handleKeyDown : undefined}\n role={clickable ? 'button' : undefined}\n tabIndex={clickable ? 0 : undefined}\n {...props}\n >\n <ImageContainer>\n {hasSrc && !hasError && (\n <Thumbnail\n ref={handleImageRef}\n $visible={loaded}\n $objectFit={objectFit}\n src={src ?? undefined}\n alt={alt}\n onLoad={() => markResolved('loaded')}\n onError={() => markResolved('error')}\n />\n )}\n {isLoading && <ImageShimmer />}\n {showEmpty && (\n <EmptyState>\n <ImageIcon size={24} aria-hidden />\n <Paragraph size='sm' color='secondary' as='span'>\n {EMPTY_COPY}\n </Paragraph>\n </EmptyState>\n )}\n\n {selectable && (\n <SelectionOverlay onClick={stopPropagation}>\n <Checkbox\n size='sm'\n checked={selected}\n onChange={(e) => onSelectedChange?.(e.target.checked)}\n aria-label={accessibleSelectionLabel}\n />\n </SelectionOverlay>\n )}\n\n {renderActions && (\n <ActionsOverlay onClick={stopPropagation}>\n <DropdownMenu\n portal\n trigger={\n <IconButton size='sm' aria-label='More actions'>\n <MoreIcon />\n </IconButton>\n }\n >\n {visibleActions.map((action, idx) => (\n <DropdownMenu.Item\n key={action.id ?? `${action.label}-${idx}`}\n prefixIcon={action.prefixIcon}\n suffixIcon={action.suffixIcon}\n disabled={action.disabled}\n variant={action.variant === 'danger' ? 'danger' : 'basic'}\n onClick={(e) => {\n if (action.disabled) {\n return;\n }\n return action.onClick?.(e);\n }}\n >\n {action.label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu>\n </ActionsOverlay>\n )}\n\n {locked && (\n <LockedOverlay onClick={stopPropagation}>\n {lockedTooltip ? (\n <Tooltip iconTrigger={<LockedIcon size={16} />} aria-label={lockedTooltip}>\n {lockedTooltip}\n </Tooltip>\n ) : (\n <LockedIcon size={16} aria-label='Locked' />\n )}\n </LockedOverlay>\n )}\n </ImageContainer>\n\n {hasMetadata && (\n <MetadataContainer>\n {isLoading ? (\n <LoadingShimmer width='60%' height='14px' />\n ) : (\n <Stack spacing={Spacing[2]}>\n {metadata?.map((row, idx) => (\n <MetadataRow key={idx}>{row}</MetadataRow>\n ))}\n </Stack>\n )}\n </MetadataContainer>\n )}\n </Root>\n );\n};\n\nexport default ImageTile;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["DropdownMenu"],"sources":["../../../components/ImageTile/ImageThumbnail.tsx","../../../components/ImageTile/ImageTile.tsx"],"sourcesContent":["import { type Ref, useCallback, useState } from 'react';\nimport styled from 'styled-components';\n\nimport { LoadingShimmer } from '@persona/design-system/components/LoadingShimmer';\nimport { Paragraph } from '@persona/design-system/components/Text';\nimport { TransitionDuration } from '@persona/design-system/variables/transitions';\nimport { Spacing } from '@persona/design-tokens';\nimport { ImageIcon } from '@persona/icons';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\nconst EMPTY_COPY = 'No available preview';\n\nexport interface ImageThumbnailProps {\n /** URL of the thumbnail. While loading shows shimmer; on error shows the empty fallback. */\n src: string | null;\n /** Alt text for the thumbnail. */\n alt?: string;\n /** How the thumbnail fills its area. `cover` crops overflow; `contain` letterboxes to fit. */\n objectFit?: 'cover' | 'contain';\n}\n\ninterface ThumbnailStatus {\n hasSrc: boolean;\n hasError: boolean;\n loaded: boolean;\n isLoading: boolean;\n showEmpty: boolean;\n markResolved: (status: 'loaded' | 'error') => void;\n handleImageRef: Ref<HTMLImageElement>;\n}\n\n/**\n * Tracks decode, error, and src changes for a thumbnail. ImageTile also reads\n * `isLoading` so its metadata row can shimmer in step with the image.\n */\nexport const useThumbnailStatus = (src: string | null): ThumbnailStatus => {\n // Keyed by src so a new image starts loading without an effect that can\n // reset state after a cached image has already decoded.\n const [resolved, setResolved] = useState<{\n src: string;\n status: 'loaded' | 'error';\n } | null>(null);\n\n if (resolved && resolved.src !== src) {\n setResolved(null);\n }\n\n const hasSrc = Boolean(src);\n const loaded = resolved?.src === src && resolved.status === 'loaded';\n const hasError = resolved?.src === src && resolved.status === 'error';\n\n const markResolved = (status: 'loaded' | 'error') => {\n if (!src) {\n return;\n }\n setResolved((current) =>\n current?.src === src && current.status === status ? current : { src, status },\n );\n };\n\n const handleImageRef = useCallback(\n (node: HTMLImageElement | null) => {\n // A cached image can finish before React attaches onLoad, which leaves\n // the tile shimmering forever. Adopt an already-decoded image here.\n if (!node || !src || !node.complete || node.naturalWidth === 0) {\n return;\n }\n setResolved((current) =>\n current?.src === src && current.status === 'loaded' ? current : { src, status: 'loaded' },\n );\n },\n [src],\n );\n\n return {\n hasSrc,\n hasError,\n loaded,\n isLoading: hasSrc && !loaded && !hasError,\n showEmpty: !hasSrc || hasError,\n markResolved,\n handleImageRef,\n };\n};\n\nconst ImageContainer = styled.div`\n position: relative;\n width: 100%;\n aspect-ratio: 200 / 144;\n background-color: ${({ theme }) => semanticColor(theme, 'SurfaceSecondary', theme.color.background.secondary)};\n overflow: hidden;\n`;\n\nconst Thumbnail = styled.img<{ $visible: boolean; $objectFit: 'cover' | 'contain' }>`\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: ${({ $objectFit }) => $objectFit};\n display: block;\n opacity: ${({ $visible }) => ($visible ? 1 : 0)};\n transition: opacity ${TransitionDuration.Fast};\n`;\n\nconst ImageShimmer = styled(LoadingShimmer)`\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n border-radius: 0;\n`;\n\nconst EmptyState = styled.div`\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: ${Spacing[1]};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n padding: ${Spacing[3]};\n text-align: center;\n`;\n\nexport const ThumbnailFrame = ({\n src,\n alt = '',\n objectFit = 'cover',\n status,\n}: ImageThumbnailProps & { status: ThumbnailStatus }) => {\n const { hasSrc, hasError, loaded, isLoading, showEmpty, markResolved, handleImageRef } = status;\n\n return (\n <ImageContainer>\n {hasSrc && !hasError && (\n <Thumbnail\n ref={handleImageRef}\n $visible={loaded}\n $objectFit={objectFit}\n src={src ?? undefined}\n alt={alt}\n onLoad={() => markResolved('loaded')}\n onError={() => markResolved('error')}\n />\n )}\n {isLoading && <ImageShimmer />}\n {showEmpty && (\n <EmptyState>\n <ImageIcon size={24} aria-hidden />\n <Paragraph size='sm' color='secondary' as='span'>\n {EMPTY_COPY}\n </Paragraph>\n </EmptyState>\n )}\n </ImageContainer>\n );\n};\n\n/** Image area used by ImageTile. Not a card chrome. */\nexport const ImageThumbnail = ({ src, alt = '', objectFit = 'cover' }: ImageThumbnailProps) => {\n const status = useThumbnailStatus(src);\n return <ThumbnailFrame src={src} alt={alt} objectFit={objectFit} status={status} />;\n};\n","import type { ComponentPropsWithoutRef, KeyboardEvent, MouseEvent, ReactNode } from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { IconButton } from '@persona/design-system/components/Button';\nimport Checkbox from '@persona/design-system/components/Checkbox';\nimport DropdownMenu from '@persona/design-system/components/DropdownMenu';\nimport { LoadingShimmer } from '@persona/design-system/components/LoadingShimmer';\nimport Stack from '@persona/design-system/components/Stack';\nimport { Tooltip } from '@persona/design-system/components/Tooltip';\nimport { focusOutline } from '@persona/design-system/mixins/focus';\nimport { TransitionDuration } from '@persona/design-system/variables/transitions';\nimport { Spacing } from '@persona/design-tokens';\nimport { LockedIcon, MoreIcon } from '@persona/icons';\nimport { withAlpha } from 'design-system/lib/color';\nimport { semanticColor, semanticTokens } from 'design-system/lib/semanticColor';\nimport type { TextAction } from 'design-system/types/Action';\n\nimport { ThumbnailFrame, useThumbnailStatus } from './ImageThumbnail';\n\nconst MIN_WIDTH = '180px';\nconst MAX_WIDTH = '420px';\nconst OVERLAY_INSET = Spacing[2];\nconst DEFAULT_SELECTION_LABEL = 'Select image';\n\nexport interface ImageTileProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n /** URL of the thumbnail. While loading shows shimmer; on error shows the empty fallback. */\n src: string | null;\n /** Alt text for the thumbnail. Also seeds the default checkbox label. */\n alt?: string;\n /** How the thumbnail fills its area. `cover` crops overflow; `contain` letterboxes to fit. Defaults to `cover`. */\n objectFit?: 'cover' | 'contain';\n\n /** Enables the selection checkbox (top-left). */\n selectable?: boolean;\n /** Controlled checked state for the selection checkbox. */\n selected?: boolean;\n /** Called with the new checked value when the checkbox is toggled. */\n onSelectedChange?: (selected: boolean) => void;\n /** Accessible label for the checkbox. Defaults to \"Select {alt}\" or \"Select image\". */\n selectionLabel?: string;\n\n /**\n * Action menu items rendered behind a 3-dot IconButton in the top-right.\n * Ignored when `locked` is true. Pass an empty array (or omit) to hide the menu.\n */\n actions?: TextAction[];\n /**\n * Replaces the action menu with a non-interactive lock icon. Indicates the\n * viewer does not have permission to edit. `actions` are ignored.\n */\n locked?: boolean;\n /** Tooltip string shown when hovering the lock icon. */\n lockedTooltip?: string;\n\n /**\n * Metadata rows rendered beneath the thumbnail. Each entry becomes a\n * full-width, left-aligned row in a vertical Stack. Block content fills the\n * row; inline content (e.g. a Sticker) hugs the left. The region is omitted\n * entirely — including while the image is loading — when the array is empty\n * or undefined, so the tile is only the image.\n */\n metadata?: ReactNode[];\n\n /** Optional click handler for the whole tile. When provided, the tile is keyboard-activatable. */\n onClick?: (e: MouseEvent<HTMLDivElement>) => void;\n}\n\nconst MetadataContainer = styled.div`\n padding: ${Spacing[3]};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n border-top: 1px solid ${({ theme }) => semanticColor(theme, 'BorderDivider', theme.color.border.primary)};\n transition: background-color ${TransitionDuration.Fast};\n`;\n\nconst MetadataRow = styled.div`\n width: 100%;\n // Without these Stickers get bottom aligned\n display: flex;\n align-items: flex-start;\n`;\n\nconst SelectionOverlay = styled.div`\n position: absolute;\n top: ${OVERLAY_INSET};\n left: ${OVERLAY_INSET};\n z-index: 1;\n`;\n\nconst ActionsOverlay = styled.div`\n position: absolute;\n top: ${OVERLAY_INSET};\n right: ${OVERLAY_INSET};\n z-index: 1;\n`;\n\nconst LockedOverlay = styled.div`\n position: absolute;\n top: ${OVERLAY_INSET};\n right: ${OVERLAY_INSET};\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n`;\n\nconst Root = styled.div<{ $clickable: boolean }>`\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: ${MIN_WIDTH};\n max-width: ${MAX_WIDTH};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.background.primary)};\n border: 1px solid ${({ theme }) => semanticColor(theme, 'BorderDivider', theme.color.border.primary)};\n border-radius: ${({ theme }) => theme.card.borderRadius};\n box-sizing: border-box;\n overflow: hidden;\n ${focusOutline};\n\n ${({ $clickable }) =>\n $clickable &&\n css`\n cursor: pointer;\n `}\n\n &:hover ${MetadataContainer} {\n background-color: ${({ theme }) => {\n const tokens = semanticTokens(theme);\n return tokens\n ? withAlpha(tokens.SurfaceAccent, tokens.Opacity25)\n : theme.color.background.highlight;\n }};\n }\n`;\n\nconst stopPropagation = (e: MouseEvent) => {\n e.stopPropagation();\n};\n\nexport const ImageTile = ({\n src,\n alt = '',\n objectFit = 'cover',\n selectable = false,\n selected = false,\n onSelectedChange,\n selectionLabel,\n actions,\n locked = false,\n lockedTooltip,\n metadata,\n onClick,\n ...props\n}: ImageTileProps) => {\n const thumbnail = useThumbnailStatus(src);\n const { isLoading } = thumbnail;\n\n const visibleActions = actions?.filter((action) => !action.hidden) ?? [];\n const renderActions = !locked && visibleActions.length > 0;\n const clickable = Boolean(onClick);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (!onClick) {\n return;\n }\n // Only activate when the key event originates from the tile root itself.\n // Interactive descendants (selection checkbox, action buttons) must keep\n // their own native Space/Enter behavior.\n if (e.target !== e.currentTarget) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.currentTarget.click();\n }\n };\n\n const accessibleSelectionLabel =\n selectionLabel ?? (alt ? `Select ${alt}` : DEFAULT_SELECTION_LABEL);\n\n const hasMetadata = (metadata?.length ?? 0) > 0;\n\n return (\n <Root\n $clickable={clickable}\n onClick={onClick}\n onKeyDown={clickable ? handleKeyDown : undefined}\n role={clickable ? 'button' : undefined}\n tabIndex={clickable ? 0 : undefined}\n {...props}\n >\n <ThumbnailFrame src={src} alt={alt} objectFit={objectFit} status={thumbnail} />\n\n {selectable && (\n <SelectionOverlay onClick={stopPropagation}>\n <Checkbox\n size='sm'\n checked={selected}\n onChange={(e) => onSelectedChange?.(e.target.checked)}\n aria-label={accessibleSelectionLabel}\n />\n </SelectionOverlay>\n )}\n\n {renderActions && (\n <ActionsOverlay onClick={stopPropagation}>\n <DropdownMenu\n portal\n trigger={\n <IconButton size='sm' aria-label='More actions'>\n <MoreIcon />\n </IconButton>\n }\n >\n {visibleActions.map((action, idx) => (\n <DropdownMenu.Item\n key={action.id ?? `${action.label}-${idx}`}\n prefixIcon={action.prefixIcon}\n suffixIcon={action.suffixIcon}\n disabled={action.disabled}\n variant={action.variant === 'danger' ? 'danger' : 'basic'}\n onClick={(e) => {\n if (action.disabled) {\n return;\n }\n return action.onClick?.(e);\n }}\n >\n {action.label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu>\n </ActionsOverlay>\n )}\n\n {locked && (\n <LockedOverlay onClick={stopPropagation}>\n {lockedTooltip ? (\n <Tooltip iconTrigger={<LockedIcon size={16} />} aria-label={lockedTooltip}>\n {lockedTooltip}\n </Tooltip>\n ) : (\n <LockedIcon size={16} aria-label='Locked' />\n )}\n </LockedOverlay>\n )}\n\n {hasMetadata && (\n <MetadataContainer>\n {isLoading ? (\n <LoadingShimmer width='60%' height='14px' />\n ) : (\n <Stack spacing={Spacing[2]}>\n {metadata?.map((row, idx) => (\n <MetadataRow key={idx}>{row}</MetadataRow>\n ))}\n </Stack>\n )}\n </MetadataContainer>\n )}\n </Root>\n );\n};\n\nexport default ImageTile;\n"],"mappings":";;;;;;;;;;;;;;;;;AAUA,MAAM,aAAa;;;;;AAyBnB,MAAa,sBAAsB,QAAwC;CAGzE,MAAM,CAAC,UAAU,eAAe,SAGtB,KAAK;AAEf,KAAI,YAAY,SAAS,QAAQ,IAC/B,aAAY,KAAK;CAGnB,MAAM,SAAS,QAAQ,IAAI;CAC3B,MAAM,SAAS,UAAU,QAAQ,OAAO,SAAS,WAAW;CAC5D,MAAM,WAAW,UAAU,QAAQ,OAAO,SAAS,WAAW;CAE9D,MAAM,gBAAgB,WAA+B;AACnD,MAAI,CAAC,IACH;AAEF,eAAa,YACX,SAAS,QAAQ,OAAO,QAAQ,WAAW,SAAS,UAAU;GAAE;GAAK;GAAQ,CAC9E;;CAGH,MAAM,iBAAiB,aACpB,SAAkC;AAGjC,MAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,YAAY,KAAK,iBAAiB,EAC3D;AAEF,eAAa,YACX,SAAS,QAAQ,OAAO,QAAQ,WAAW,WAAW,UAAU;GAAE;GAAK,QAAQ;GAAU,CAC1F;IAEH,CAAC,IAAI,CACN;AAED,QAAO;EACL;EACA;EACA;EACA,WAAW,UAAU,CAAC,UAAU,CAAC;EACjC,WAAW,CAAC,UAAU;EACtB;EACA;EACD;;AAGH,MAAM,iBAAiB,OAAO,GAAG;;;;uBAIV,EAAE,YAAY,cAAc,OAAO,oBAAoB,MAAM,MAAM,WAAW,UAAU,CAAC;;;AAIhH,MAAM,YAAY,OAAO,GAA2D;;;;;iBAKnE,EAAE,iBAAiB,WAAW;;cAEjC,EAAE,eAAgB,WAAW,IAAI,EAAG;gCACF;;AAGhD,MAAM,eAAe,OAAO,eAAe;;;;;;;AAQ3C,MAAM,aAAa,OAAO,GAAG;;;;;;;SAOpB,QAAQ,GAAG;YACR,EAAE,YAAY,cAAc,OAAO,eAAe,MAAM,MAAM,KAAK,UAAU,CAAC;aAC7E,QAAQ,GAAG;;;AAIxB,MAAa,kBAAkB,EAC7B,KACA,MAAM,IACN,YAAY,SACZ,aACuD;CACvD,MAAM,EAAE,QAAQ,UAAU,QAAQ,WAAW,WAAW,cAAc,mBAAmB;AAEzF,QACE,qBAAC,gBAAD,EAAA,UAAA;EACG,UAAU,CAAC,YACV,oBAAC,WAAD;GACE,KAAK;GACL,UAAU;GACV,YAAY;GACZ,KAAK,OAAO,KAAA;GACP;GACL,cAAc,aAAa,SAAS;GACpC,eAAe,aAAa,QAAQ;GACpC,CAAA;EAEH,aAAa,oBAAC,cAAD,EAAgB,CAAA;EAC7B,aACC,qBAAC,YAAD,EAAA,UAAA,CACE,oBAAC,WAAD;GAAW,MAAM;GAAI,eAAA;GAAc,CAAA,EACnC,oBAAC,WAAD;GAAW,MAAK;GAAK,OAAM;GAAY,IAAG;aACvC;GACS,CAAA,CACD,EAAA,CAAA;EAEA,EAAA,CAAA;;;;ACxIrB,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,gBAAgB,QAAQ;AAC9B,MAAM,0BAA0B;AA6ChC,MAAM,oBAAoB,OAAO,GAAG;aACvB,QAAQ,GAAG;uBACD,EAAE,YAAY,cAAc,OAAO,kBAAkB,MAAM,MAAM,WAAW,QAAQ,CAAC;2BACjF,EAAE,YAAY,cAAc,OAAO,iBAAiB,MAAM,MAAM,OAAO,QAAQ,CAAC;yCAClD;;AAGzD,MAAM,cAAc,OAAO,GAAG;;;;;;AAO9B,MAAM,mBAAmB,OAAO,GAAG;;SAE1B,cAAc;UACb,cAAc;;;AAIxB,MAAM,iBAAiB,OAAO,GAAG;;SAExB,cAAc;WACZ,cAAc;;;AAIzB,MAAM,gBAAgB,OAAO,GAAG;;SAEvB,cAAc;WACZ,cAAc;;;;;YAKb,EAAE,YAAY,cAAc,OAAO,eAAe,MAAM,MAAM,KAAK,UAAU,CAAC;;AAG1F,MAAM,OAAO,OAAO,GAA4B;;;;;eAKjC,UAAU;eACV,UAAU;uBACF,EAAE,YAAY,cAAc,OAAO,kBAAkB,MAAM,MAAM,WAAW,QAAQ,CAAC;uBACrF,EAAE,YAAY,cAAc,OAAO,iBAAiB,MAAM,MAAM,OAAO,QAAQ,CAAC;oBACnF,EAAE,YAAY,MAAM,KAAK,aAAa;;;IAGtD,aAAa;;KAEZ,EAAE,iBACH,cACA,GAAG;;MAED;;YAEM,kBAAkB;yBACL,EAAE,YAAY;CACjC,MAAM,SAAS,eAAe,MAAM;AACpC,QAAO,SACH,UAAU,OAAO,eAAe,OAAO,UAAU,GACjD,MAAM,MAAM,WAAW;EAC3B;;;AAIN,MAAM,mBAAmB,MAAkB;AACzC,GAAE,iBAAiB;;AAGrB,MAAa,aAAa,EACxB,KACA,MAAM,IACN,YAAY,SACZ,aAAa,OACb,WAAW,OACX,kBACA,gBACA,SACA,SAAS,OACT,eACA,UACA,SACA,GAAG,YACiB;CACpB,MAAM,YAAY,mBAAmB,IAAI;CACzC,MAAM,EAAE,cAAc;CAEtB,MAAM,iBAAiB,SAAS,QAAQ,WAAW,CAAC,OAAO,OAAO,IAAI,EAAE;CACxE,MAAM,gBAAgB,CAAC,UAAU,eAAe,SAAS;CACzD,MAAM,YAAY,QAAQ,QAAQ;CAElC,MAAM,iBAAiB,MAAqC;AAC1D,MAAI,CAAC,QACH;AAKF,MAAI,EAAE,WAAW,EAAE,cACjB;AAEF,MAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,KAAE,gBAAgB;AAClB,KAAE,cAAc,OAAO;;;CAI3B,MAAM,2BACJ,mBAAmB,MAAM,UAAU,QAAQ;CAE7C,MAAM,eAAe,UAAU,UAAU,KAAK;AAE9C,QACE,qBAAC,MAAD;EACE,YAAY;EACH;EACT,WAAW,YAAY,gBAAgB,KAAA;EACvC,MAAM,YAAY,WAAW,KAAA;EAC7B,UAAU,YAAY,IAAI,KAAA;EAC1B,GAAI;YANN;GAQE,oBAAC,gBAAD;IAAqB;IAAU;IAAgB;IAAW,QAAQ;IAAa,CAAA;GAE9E,cACC,oBAAC,kBAAD;IAAkB,SAAS;cACzB,oBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAW,MAAM,mBAAmB,EAAE,OAAO,QAAQ;KACrD,cAAY;KACZ,CAAA;IACe,CAAA;GAGpB,iBACC,oBAAC,gBAAD;IAAgB,SAAS;cACvB,oBAACA,sBAAD;KACE,QAAA;KACA,SACE,oBAAC,YAAD;MAAY,MAAK;MAAK,cAAW;gBAC/B,oBAAC,UAAD,EAAY,CAAA;MACD,CAAA;eAGd,eAAe,KAAK,QAAQ,QAC3B,oBAACA,qBAAa,MAAd;MAEE,YAAY,OAAO;MACnB,YAAY,OAAO;MACnB,UAAU,OAAO;MACjB,SAAS,OAAO,YAAY,WAAW,WAAW;MAClD,UAAU,MAAM;AACd,WAAI,OAAO,SACT;AAEF,cAAO,OAAO,UAAU,EAAE;;gBAG3B,OAAO;MACU,EAbb,OAAO,MAAM,GAAG,OAAO,MAAM,GAAG,MAanB,CACpB;KACW,CAAA;IACA,CAAA;GAGlB,UACC,oBAAC,eAAD;IAAe,SAAS;cACrB,gBACC,oBAAC,SAAD;KAAS,aAAa,oBAAC,YAAD,EAAY,MAAM,IAAM,CAAA;KAAE,cAAY;eACzD;KACO,CAAA,GAEV,oBAAC,YAAD;KAAY,MAAM;KAAI,cAAW;KAAW,CAAA;IAEhC,CAAA;GAGjB,eACC,oBAAC,mBAAD,EAAA,UACG,YACC,oBAAC,gBAAD;IAAgB,OAAM;IAAM,QAAO;IAAS,CAAA,GAE5C,oBAAC,OAAD;IAAO,SAAS,QAAQ;cACrB,UAAU,KAAK,KAAK,QACnB,oBAAC,aAAD,EAAA,UAAwB,KAAkB,EAAxB,IAAwB,CAC1C;IACI,CAAA,EAEQ,CAAA;GAEjB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Link } from "../../Link-
|
|
1
|
+
import { t as Link } from "../../Link-BSuXrvTu.mjs";
|
|
2
2
|
export { Link, Link as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as useListBoxContext, n as ListBoxItemProps, r as ListBoxProps } from "../../ListBox-
|
|
2
|
-
import { n as LogicRowProps } from "../../LogicRow-
|
|
3
|
-
import { t as ListBox } from "../../index-
|
|
1
|
+
import { i as useListBoxContext, n as ListBoxItemProps, r as ListBoxProps } from "../../ListBox-CXFI-0nG.mjs";
|
|
2
|
+
import { n as LogicRowProps } from "../../LogicRow-8oYRkwz5.mjs";
|
|
3
|
+
import { t as ListBox } from "../../index-C3uFHTo0.mjs";
|
|
4
4
|
export { ListBox, ListBox as default, ListBoxItemProps, ListBoxProps, LogicRowProps, useListBoxContext };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as useListBoxContext, t as ListBox } from "../../ListBox-
|
|
1
|
+
import { n as useListBoxContext, t as ListBox } from "../../ListBox-BLoJVezh.mjs";
|
|
2
2
|
export { ListBox, ListBox as default, useListBoxContext };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as MenuDivider, c as MenuItem, d as MenuList, f as MenuProps, i as Menu, l as MenuItemProps, n as IconContainer, o as MenuHeading, r as ListItem, s as MenuHeadingProps, t as FloatingCard, u as MenuItemType } from "../../Menu-
|
|
1
|
+
import { a as MenuDivider, c as MenuItem, d as MenuList, f as MenuProps, i as Menu, l as MenuItemProps, n as IconContainer, o as MenuHeading, r as ListItem, s as MenuHeadingProps, t as FloatingCard, u as MenuItemType } from "../../Menu-DHnQZ5yN.mjs";
|
|
2
2
|
export { FloatingCard, IconContainer, ListItem, Menu, Menu as default, MenuDivider, MenuHeading, MenuHeadingProps, MenuItem, MenuItemProps, MenuItemType, MenuList, MenuProps };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as Modal_default, n as ModalContent, r as ModalTrigger, t as ModalClose } from "../../Modal-
|
|
1
|
+
import { i as Modal_default, n as ModalContent, r as ModalTrigger, t as ModalClose } from "../../Modal-IJdbLORi.mjs";
|
|
2
2
|
export { ModalClose, ModalContent, ModalTrigger, Modal_default as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as MIN_PAGE_SIZE, i as DEFAULT_PAGE_SIZE_OPTIONS, n as PAGE_LIMIT_BEFORE_SCROLL_MODE, r as PageSelector, t as Pagination_default } from "../../Pagination-
|
|
1
|
+
import { a as MIN_PAGE_SIZE, i as DEFAULT_PAGE_SIZE_OPTIONS, n as PAGE_LIMIT_BEFORE_SCROLL_MODE, r as PageSelector, t as Pagination_default } from "../../Pagination-C5ANr9M0.mjs";
|
|
2
2
|
export { DEFAULT_PAGE_SIZE_OPTIONS, MIN_PAGE_SIZE, PAGE_LIMIT_BEFORE_SCROLL_MODE, PageSelector, Pagination_default as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Pii_default } from "../../Pii-
|
|
1
|
+
import { t as Pii_default } from "../../Pii-G16_b7Yk.mjs";
|
|
2
2
|
export { Pii_default as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PopoverPortal, i as PopoverContent, n as PopoverCard, o as PopoverTrigger, r as PopoverClose, s as Popover_default, t as PopoverAnchor } from "../../Popover-
|
|
1
|
+
import { a as PopoverPortal, i as PopoverContent, n as PopoverCard, o as PopoverTrigger, r as PopoverClose, s as Popover_default, t as PopoverAnchor } from "../../Popover-532iYFek.mjs";
|
|
2
2
|
export { PopoverAnchor, PopoverCard, PopoverClose, PopoverContent, PopoverPortal, PopoverTrigger, Popover_default as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Radio } from "../../Radio-
|
|
1
|
+
import { t as Radio } from "../../Radio-BstZg3DI.mjs";
|
|
2
2
|
export { Radio, Radio as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as RadioGroup } from "../../RadioGroup-
|
|
1
|
+
import { t as RadioGroup } from "../../RadioGroup-erKerwSt.mjs";
|
|
2
2
|
export { RadioGroup, RadioGroup as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as SegmentedControlItem, t as SegmentedControl } from "../../SegmentedControl-
|
|
1
|
+
import { n as SegmentedControlItem, t as SegmentedControl } from "../../SegmentedControl-DQjIO6iX.mjs";
|
|
2
2
|
export { SegmentedControl, SegmentedControl as default, SegmentedControlItem };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as SelectProps, n as Select, r as SelectHeader, t as Option } from "../../Select-
|
|
1
|
+
import { i as SelectProps, n as Select, r as SelectHeader, t as Option } from "../../Select-CSbamhJO.mjs";
|
|
2
2
|
export { Option, Select, Select as default, SelectHeader, SelectProps };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as Select, r as SelectHeader, t as Option } from "../../Select-
|
|
1
|
+
import { n as Select, r as SelectHeader, t as Option } from "../../Select-hnXfPywt.mjs";
|
|
2
2
|
export { Option, Select, Select as default, SelectHeader };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { SelectionCard, SelectionCardProps } from "../../SelectionCard.mjs";
|
|
2
|
+
import { SelectionCardGroup, SelectionCardGroupMultipleProps, SelectionCardGroupProps, SelectionCardGroupSingleProps } from "../../SelectionCardGroup.mjs";
|
|
3
|
+
export { SelectionCard, SelectionCard as default, SelectionCardGroup, type SelectionCardGroupMultipleProps, type SelectionCardGroupProps, type SelectionCardGroupSingleProps, type SelectionCardProps };
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { a as styled, r as css } from "../../styledComponentsInterop-NxwFjeA4.mjs";
|
|
2
|
+
import { semanticColor, semanticOnly, semanticTokens } from "../../lib/semanticColor.mjs";
|
|
3
|
+
import { i as Paragraph } from "../../Text-CSwFifQF.mjs";
|
|
4
|
+
import { a as Tooltip } from "../../Tooltip-B-0VRuKT.mjs";
|
|
5
|
+
import { opacityOf, withAlpha } from "../../lib/color.mjs";
|
|
6
|
+
import useControlled from "../../lib/useControlled.mjs";
|
|
7
|
+
import { focusStyle } from "../../mixins/focus.mjs";
|
|
8
|
+
import { n as Stack, t as HStack } from "../../Stack-BkC7FCdF.mjs";
|
|
9
|
+
import { n as useFormField, t as FormControlContext } from "../../useFormField-CbNYbDdp.mjs";
|
|
10
|
+
import { t as Checkbox } from "../../Checkbox-BaJ-dGdX.mjs";
|
|
11
|
+
import { Color, Spacing } from "@persona/design-tokens";
|
|
12
|
+
import { Children, cloneElement, isValidElement, useContext } from "react";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
//#region components/SelectionCard/SelectionCard.tsx
|
|
15
|
+
const CardRoot = styled.label`
|
|
16
|
+
position: relative;
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
flex: 1 1 auto;
|
|
20
|
+
width: 100%;
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
cursor: ${({ $disabled }) => $disabled ? "default" : "pointer"};
|
|
24
|
+
pointer-events: ${({ $disabled }) => $disabled ? "none" : "auto"};
|
|
25
|
+
border-radius: ${({ theme }) => theme.card.borderRadius};
|
|
26
|
+
outline: none;
|
|
27
|
+
|
|
28
|
+
/* Keyboard focus only. A click focuses the input too, and should not draw this ring. */
|
|
29
|
+
&:has(:focus-visible) {
|
|
30
|
+
${focusStyle}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
border: 1px solid
|
|
34
|
+
${({ theme, $selected, $disabled }) => {
|
|
35
|
+
if ($disabled) return semanticColor(theme, "InputBorderDisabled", Color.BorderInputDisabled);
|
|
36
|
+
if ($selected) return semanticColor(theme, "BorderAccent", theme.color.primary.brand);
|
|
37
|
+
return semanticColor(theme, "BorderDefault", theme.color.border.input);
|
|
38
|
+
}};
|
|
39
|
+
|
|
40
|
+
background-color: ${({ theme, $selected, $disabled }) => {
|
|
41
|
+
if ($disabled) return semanticColor(theme, "InputSurfaceDisabled", Color.BackgroundInputDisabled);
|
|
42
|
+
if ($selected) {
|
|
43
|
+
const tokens = semanticTokens(theme);
|
|
44
|
+
return tokens ? withAlpha(tokens.SurfaceAccent, tokens.Opacity25) : theme.color.background.highlight;
|
|
45
|
+
}
|
|
46
|
+
return semanticColor(theme, "SurfacePrimary", theme.color.background.primary);
|
|
47
|
+
}};
|
|
48
|
+
|
|
49
|
+
${({ $disabled, $selected }) => !$disabled && !$selected && css`
|
|
50
|
+
&:hover {
|
|
51
|
+
background-color: ${({ theme }) => semanticColor(theme, "SurfaceHover", Color.BackgroundInteractiveHover)};
|
|
52
|
+
}
|
|
53
|
+
`}
|
|
54
|
+
|
|
55
|
+
${({ $disabled }) => $disabled && css`
|
|
56
|
+
${semanticOnly((tokens) => `opacity: ${opacityOf(tokens.Opacity65)};`)}
|
|
57
|
+
`}
|
|
58
|
+
`;
|
|
59
|
+
const Body = styled.div`
|
|
60
|
+
padding: ${Spacing[4]};
|
|
61
|
+
`;
|
|
62
|
+
const Copy = styled(Stack)`
|
|
63
|
+
flex: 1 1 auto;
|
|
64
|
+
min-width: 0;
|
|
65
|
+
`;
|
|
66
|
+
/** Centers a 16px icon on the label line. `iconBackground` gives it a 32px well. */
|
|
67
|
+
const IconSlot = styled.span`
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
flex: 0 0 auto;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
align-self: flex-start;
|
|
73
|
+
min-height: ${Spacing[5]};
|
|
74
|
+
color: ${({ theme }) => semanticColor(theme, "FgPrimary", theme.color.text.primary)};
|
|
75
|
+
|
|
76
|
+
svg {
|
|
77
|
+
width: 16px;
|
|
78
|
+
height: 16px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
${({ $background, theme }) => $background && css`
|
|
82
|
+
width: ${Spacing[6]};
|
|
83
|
+
height: ${Spacing[6]};
|
|
84
|
+
border-radius: ${theme.card.borderRadius};
|
|
85
|
+
background-color: ${semanticColor(theme, "SurfaceSecondary", theme.color.background.secondary)};
|
|
86
|
+
`}
|
|
87
|
+
`;
|
|
88
|
+
const Marker = styled.span`
|
|
89
|
+
display: inline-flex;
|
|
90
|
+
flex: 0 0 auto;
|
|
91
|
+
align-items: center;
|
|
92
|
+
height: ${Spacing[5]};
|
|
93
|
+
|
|
94
|
+
/* The card draws the only focus ring and the only disabled fade. */
|
|
95
|
+
&& input:focus-visible ~ [aria-hidden] {
|
|
96
|
+
outline: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&& input ~ [aria-hidden] {
|
|
100
|
+
opacity: 1;
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
const NativeRadio = styled.input`
|
|
104
|
+
cursor: inherit;
|
|
105
|
+
position: absolute;
|
|
106
|
+
inset: 0;
|
|
107
|
+
margin: 0;
|
|
108
|
+
opacity: 0;
|
|
109
|
+
border: 0;
|
|
110
|
+
outline: none;
|
|
111
|
+
pointer-events: none;
|
|
112
|
+
`;
|
|
113
|
+
const TooltipTrigger = styled.span`
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
width: 100%;
|
|
117
|
+
align-self: stretch;
|
|
118
|
+
`;
|
|
119
|
+
const SelectionCard = ({ value, label, description, icon, iconBackground = false, disabled: disabledProp, disabledReason, name, checked = false, onChange, multiple = false, className }) => {
|
|
120
|
+
const disabled = !!useFormField({ disabled: disabledProp || void 0 }).disabled;
|
|
121
|
+
const card = /* @__PURE__ */ jsxs(CardRoot, {
|
|
122
|
+
className,
|
|
123
|
+
$selected: checked,
|
|
124
|
+
$disabled: disabled,
|
|
125
|
+
children: [/* @__PURE__ */ jsx(Body, { children: /* @__PURE__ */ jsxs(HStack, {
|
|
126
|
+
align: "flex-start",
|
|
127
|
+
spacing: icon ? Spacing[3] : Spacing[2],
|
|
128
|
+
children: [
|
|
129
|
+
multiple && /* @__PURE__ */ jsx(Marker, { children: /* @__PURE__ */ jsx(Checkbox, {
|
|
130
|
+
name,
|
|
131
|
+
value,
|
|
132
|
+
checked,
|
|
133
|
+
disabled,
|
|
134
|
+
onChange: (event) => onChange?.(event.target.checked)
|
|
135
|
+
}) }),
|
|
136
|
+
icon && /* @__PURE__ */ jsx(IconSlot, {
|
|
137
|
+
$background: iconBackground,
|
|
138
|
+
children: icon
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ jsxs(Copy, {
|
|
141
|
+
spacing: Spacing[1],
|
|
142
|
+
children: [/* @__PURE__ */ jsx(Paragraph, {
|
|
143
|
+
as: "span",
|
|
144
|
+
size: "lg",
|
|
145
|
+
weight: "bold",
|
|
146
|
+
color: disabled ? "disabled" : "primary",
|
|
147
|
+
children: label
|
|
148
|
+
}), description && /* @__PURE__ */ jsx(Paragraph, {
|
|
149
|
+
as: "span",
|
|
150
|
+
size: "md",
|
|
151
|
+
color: disabled ? "disabled" : checked ? "primary" : "secondary",
|
|
152
|
+
children: description
|
|
153
|
+
})]
|
|
154
|
+
})
|
|
155
|
+
]
|
|
156
|
+
}) }), !multiple && /* @__PURE__ */ jsx(NativeRadio, {
|
|
157
|
+
type: "radio",
|
|
158
|
+
name,
|
|
159
|
+
value,
|
|
160
|
+
checked,
|
|
161
|
+
disabled,
|
|
162
|
+
onChange: () => onChange?.(true)
|
|
163
|
+
})]
|
|
164
|
+
});
|
|
165
|
+
if (disabled && disabledReason) return /* @__PURE__ */ jsx(Tooltip, {
|
|
166
|
+
trigger: /* @__PURE__ */ jsx(TooltipTrigger, { children: card }),
|
|
167
|
+
children: disabledReason
|
|
168
|
+
});
|
|
169
|
+
return card;
|
|
170
|
+
};
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region components/SelectionCard/SelectionCardGroup.tsx
|
|
173
|
+
const selectionCards = (children) => Children.toArray(children).filter((child) => isValidElement(child) && child.type === SelectionCard);
|
|
174
|
+
const firstSelectableValue = (children) => selectionCards(children).find((card) => !card.props.disabled)?.props.value;
|
|
175
|
+
const groupLayout = (children, stack) => {
|
|
176
|
+
const inline = selectionCards(children).length === 2 && !stack;
|
|
177
|
+
return {
|
|
178
|
+
$inline: inline,
|
|
179
|
+
direction: inline ? "horizontal" : "vertical",
|
|
180
|
+
equal: inline,
|
|
181
|
+
align: inline ? "stretch" : void 0
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
const Group = styled(Stack)`
|
|
185
|
+
${({ $inline }) => $inline && css`
|
|
186
|
+
> * {
|
|
187
|
+
width: auto;
|
|
188
|
+
min-width: 0;
|
|
189
|
+
align-self: stretch;
|
|
190
|
+
}
|
|
191
|
+
`}
|
|
192
|
+
`;
|
|
193
|
+
const renderCards = (children, getProps) => Children.map(children, (child) => {
|
|
194
|
+
if (!isValidElement(child) || child.type !== SelectionCard) return child;
|
|
195
|
+
const card = child;
|
|
196
|
+
return cloneElement(card, getProps(card.props));
|
|
197
|
+
});
|
|
198
|
+
const SingleGroup = ({ name, className, stack, children, value: valueProp, defaultValue, onChange, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-required": ariaRequired }) => {
|
|
199
|
+
const field = useContext(FormControlContext);
|
|
200
|
+
const [value, setValue] = useControlled({
|
|
201
|
+
controlledValue: valueProp,
|
|
202
|
+
default: defaultValue ?? (field.disabled ? void 0 : firstSelectableValue(children))
|
|
203
|
+
});
|
|
204
|
+
return /* @__PURE__ */ jsx(Group, {
|
|
205
|
+
...groupLayout(children, stack),
|
|
206
|
+
className,
|
|
207
|
+
spacing: Spacing[2],
|
|
208
|
+
role: "radiogroup",
|
|
209
|
+
"aria-label": ariaLabel,
|
|
210
|
+
"aria-labelledby": ariaLabelledby,
|
|
211
|
+
"aria-required": ariaRequired,
|
|
212
|
+
children: renderCards(children, (card) => ({
|
|
213
|
+
name,
|
|
214
|
+
multiple: false,
|
|
215
|
+
checked: card.value === value,
|
|
216
|
+
onChange: () => {
|
|
217
|
+
if (field.disabled || card.disabled) return;
|
|
218
|
+
setValue(card.value);
|
|
219
|
+
onChange?.(card.value);
|
|
220
|
+
}
|
|
221
|
+
}))
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
const MultipleGroup = ({ name, className, stack, children, value: valueProp, defaultValue, onChange, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby }) => {
|
|
225
|
+
const field = useContext(FormControlContext);
|
|
226
|
+
const [value, setValue] = useControlled({
|
|
227
|
+
controlledValue: valueProp,
|
|
228
|
+
default: defaultValue ?? []
|
|
229
|
+
});
|
|
230
|
+
const selected = value ?? [];
|
|
231
|
+
return /* @__PURE__ */ jsx(Group, {
|
|
232
|
+
...groupLayout(children, stack),
|
|
233
|
+
className,
|
|
234
|
+
spacing: Spacing[2],
|
|
235
|
+
role: "group",
|
|
236
|
+
"aria-label": ariaLabel,
|
|
237
|
+
"aria-labelledby": ariaLabelledby,
|
|
238
|
+
children: renderCards(children, (card) => ({
|
|
239
|
+
name,
|
|
240
|
+
multiple: true,
|
|
241
|
+
checked: selected.includes(card.value),
|
|
242
|
+
onChange: (checked) => {
|
|
243
|
+
if (field.disabled || card.disabled) return;
|
|
244
|
+
const next = checked ? selected.includes(card.value) ? selected : [...selected, card.value] : selected.filter((item) => item !== card.value);
|
|
245
|
+
setValue(next);
|
|
246
|
+
onChange?.(next);
|
|
247
|
+
}
|
|
248
|
+
}))
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
const SelectionCardGroup = (props) => {
|
|
252
|
+
const field = useContext(FormControlContext);
|
|
253
|
+
return /* @__PURE__ */ jsx(FormControlContext.Provider, {
|
|
254
|
+
value: {
|
|
255
|
+
...field,
|
|
256
|
+
inputId: void 0
|
|
257
|
+
},
|
|
258
|
+
children: props.multiple ? /* @__PURE__ */ jsx(MultipleGroup, { ...props }) : /* @__PURE__ */ jsx(SingleGroup, { ...props })
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
//#endregion
|
|
262
|
+
export { SelectionCard, SelectionCard as default, SelectionCardGroup };
|
|
263
|
+
|
|
264
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../components/SelectionCard/SelectionCard.tsx","../../../components/SelectionCard/SelectionCardGroup.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport styled, { css } from 'styled-components';\n\nimport Checkbox from '@persona/design-system/components/Checkbox';\nimport { HStack, Stack } from '@persona/design-system/components/Stack';\nimport { Paragraph } from '@persona/design-system/components/Text';\nimport { Tooltip } from '@persona/design-system/components/Tooltip';\nimport { focusStyle } from '@persona/design-system/mixins/focus';\nimport { Color, Spacing } from '@persona/design-tokens';\nimport useFormField from 'design-system/components/FormControl/useFormField';\nimport { opacityOf, withAlpha } from 'design-system/lib/color';\nimport { semanticColor, semanticOnly, semanticTokens } from 'design-system/lib/semanticColor';\n\nexport interface SelectionCardProps {\n /** Value submitted with the group when this card is selected. */\n value: string;\n /** Required visible name. Left-aligned with `description`. */\n label: string;\n /** Optional supporting copy under the label. Omitted when not passed. */\n description?: string;\n /**\n * Optional icon to the left of the label. Leave it off when it does not add\n * meaning, including in multiple mode.\n */\n icon?: ReactElement;\n /**\n * Draw a secondary background behind `icon`. Ignored when `icon` is omitted.\n */\n iconBackground?: boolean;\n disabled?: boolean;\n /** Tooltip shown on hover only while `disabled` is set. */\n disabledReason?: string;\n /** Injected by `SelectionCardGroup`. */\n name?: string;\n /** Injected by `SelectionCardGroup`. */\n checked?: boolean;\n /** Injected by `SelectionCardGroup`. */\n onChange?: (checked: boolean) => void;\n /** Injected by `SelectionCardGroup`. */\n multiple?: boolean;\n /** Layout hook for this card. */\n className?: string;\n}\n\nconst CardRoot = styled.label<{ $selected: boolean; $disabled: boolean }>`\n position: relative;\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n width: 100%;\n box-sizing: border-box;\n overflow: hidden;\n cursor: ${({ $disabled }) => ($disabled ? 'default' : 'pointer')};\n pointer-events: ${({ $disabled }) => ($disabled ? 'none' : 'auto')};\n border-radius: ${({ theme }) => theme.card.borderRadius};\n outline: none;\n\n /* Keyboard focus only. A click focuses the input too, and should not draw this ring. */\n &:has(:focus-visible) {\n ${focusStyle}\n }\n\n border: 1px solid\n ${({ theme, $selected, $disabled }) => {\n if ($disabled) {\n return semanticColor(theme, 'InputBorderDisabled', Color.BorderInputDisabled);\n }\n if ($selected) {\n return semanticColor(theme, 'BorderAccent', theme.color.primary.brand);\n }\n return semanticColor(theme, 'BorderDefault', theme.color.border.input);\n }};\n\n background-color: ${({ theme, $selected, $disabled }) => {\n if ($disabled) {\n return semanticColor(theme, 'InputSurfaceDisabled', Color.BackgroundInputDisabled);\n }\n if ($selected) {\n const tokens = semanticTokens(theme);\n return tokens\n ? withAlpha(tokens.SurfaceAccent, tokens.Opacity25)\n : theme.color.background.highlight;\n }\n return semanticColor(theme, 'SurfacePrimary', theme.color.background.primary);\n }};\n\n ${({ $disabled, $selected }) =>\n !$disabled &&\n !$selected &&\n css`\n &:hover {\n background-color: ${({ theme }) =>\n semanticColor(theme, 'SurfaceHover', Color.BackgroundInteractiveHover)};\n }\n `}\n\n ${({ $disabled }) =>\n $disabled &&\n css`\n ${semanticOnly((tokens) => `opacity: ${opacityOf(tokens.Opacity65)};`)}\n `}\n`;\n\nconst Body = styled.div`\n padding: ${Spacing[4]};\n`;\n\nconst Copy = styled(Stack)`\n flex: 1 1 auto;\n min-width: 0;\n`;\n\n/** Centers a 16px icon on the label line. `iconBackground` gives it a 32px well. */\nconst IconSlot = styled.span<{ $background: boolean }>`\n display: inline-flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: center;\n align-self: flex-start;\n min-height: ${Spacing[5]};\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n\n svg {\n width: 16px;\n height: 16px;\n }\n\n ${({ $background, theme }) =>\n $background &&\n css`\n width: ${Spacing[6]};\n height: ${Spacing[6]};\n border-radius: ${theme.card.borderRadius};\n background-color: ${semanticColor(theme, 'SurfaceSecondary', theme.color.background.secondary)};\n `}\n`;\nconst Marker = styled.span`\n display: inline-flex;\n flex: 0 0 auto;\n align-items: center;\n height: ${Spacing[5]};\n\n /* The card draws the only focus ring and the only disabled fade. */\n && input:focus-visible ~ [aria-hidden] {\n outline: none;\n }\n\n && input ~ [aria-hidden] {\n opacity: 1;\n }\n`;\n\nconst NativeRadio = styled.input`\n cursor: inherit;\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n border: 0;\n outline: none;\n pointer-events: none;\n`;\n\nconst TooltipTrigger = styled.span`\n display: flex;\n flex-direction: column;\n width: 100%;\n align-self: stretch;\n`;\n\nexport const SelectionCard = ({\n value,\n label,\n description,\n icon,\n iconBackground = false,\n disabled: disabledProp,\n disabledReason,\n name,\n checked = false,\n onChange,\n multiple = false,\n className,\n}: SelectionCardProps) => {\n const field = useFormField({ disabled: disabledProp || undefined });\n const disabled = !!field.disabled;\n const card = (\n <CardRoot className={className} $selected={checked} $disabled={disabled}>\n <Body>\n <HStack align='flex-start' spacing={icon ? Spacing[3] : Spacing[2]}>\n {multiple && (\n <Marker>\n <Checkbox\n name={name}\n value={value}\n checked={checked}\n disabled={disabled}\n onChange={(event) => onChange?.(event.target.checked)}\n />\n </Marker>\n )}\n {icon && <IconSlot $background={iconBackground}>{icon}</IconSlot>}\n <Copy spacing={Spacing[1]}>\n <Paragraph as='span' size='lg' weight='bold' color={disabled ? 'disabled' : 'primary'}>\n {label}\n </Paragraph>\n {description && (\n <Paragraph\n as='span'\n size='md'\n color={disabled ? 'disabled' : checked ? 'primary' : 'secondary'}\n >\n {description}\n </Paragraph>\n )}\n </Copy>\n </HStack>\n </Body>\n {!multiple && (\n <NativeRadio\n type='radio'\n name={name}\n value={value}\n checked={checked}\n disabled={disabled}\n onChange={() => onChange?.(true)}\n />\n )}\n </CardRoot>\n );\n\n if (disabled && disabledReason) {\n return <Tooltip trigger={<TooltipTrigger>{card}</TooltipTrigger>}>{disabledReason}</Tooltip>;\n }\n\n return card;\n};\n\nexport default SelectionCard;\n","import {\n Children,\n cloneElement,\n isValidElement,\n type ReactElement,\n type ReactNode,\n useContext,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\nimport Stack from '@persona/design-system/components/Stack';\nimport { Spacing } from '@persona/design-tokens';\nimport { FormControlContext } from 'design-system/components/FormControl/useFormField';\nimport useControlled from 'design-system/lib/useControlled';\n\nimport SelectionCard, { type SelectionCardProps } from './SelectionCard';\n\ninterface SelectionCardGroupBaseProps {\n /** Shared input name. Radios in a single group arrow-key together. */\n name?: string;\n /** Layout hook for the group. Not forwarded onto each card. */\n className?: string;\n /** Place two cards in a column. Two cards sit side by side when this is omitted. Three or more always stack. */\n stack?: boolean;\n /** Accessible name for the group. */\n 'aria-label'?: string;\n /** Id of the element that names the group, such as a field label. */\n 'aria-labelledby'?: string;\n children: ReactNode;\n}\n\nexport interface SelectionCardGroupSingleProps extends SelectionCardGroupBaseProps {\n /** One card may be selected. Cards render no radio mark. */\n multiple?: false;\n 'aria-required'?: boolean;\n value?: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n}\n\nexport interface SelectionCardGroupMultipleProps extends SelectionCardGroupBaseProps {\n /** Several cards may be selected. Each card shows a checkbox. */\n multiple: true;\n value?: string[];\n defaultValue?: string[];\n onChange?: (value: string[]) => void;\n}\n\nexport type SelectionCardGroupProps =\n | SelectionCardGroupSingleProps\n | SelectionCardGroupMultipleProps;\n\nconst selectionCards = (children: ReactNode) =>\n Children.toArray(children).filter(\n (child): child is ReactElement<SelectionCardProps> =>\n isValidElement(child) && child.type === SelectionCard,\n );\n\nconst firstSelectableValue = (children: ReactNode) =>\n selectionCards(children).find((card) => !card.props.disabled)?.props.value;\n\nconst groupLayout = (children: ReactNode, stack?: boolean) => {\n const inline = selectionCards(children).length === 2 && !stack;\n return {\n $inline: inline,\n direction: inline ? ('horizontal' as const) : ('vertical' as const),\n equal: inline,\n align: inline ? ('stretch' as const) : undefined,\n };\n};\n\nconst Group = styled(Stack)<{ $inline: boolean }>`\n ${({ $inline }) =>\n $inline &&\n css`\n > * {\n width: auto;\n min-width: 0;\n align-self: stretch;\n }\n `}\n`;\nconst renderCards = (\n children: ReactNode,\n getProps: (card: SelectionCardProps) => Partial<SelectionCardProps>,\n) =>\n Children.map(children, (child) => {\n if (!isValidElement(child) || child.type !== SelectionCard) {\n return child;\n }\n const card = child as ReactElement<SelectionCardProps>;\n return cloneElement(card, getProps(card.props));\n });\n\nconst SingleGroup = ({\n name,\n className,\n stack,\n children,\n value: valueProp,\n defaultValue,\n onChange,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-required': ariaRequired,\n}: SelectionCardGroupSingleProps) => {\n const field = useContext(FormControlContext);\n const [value, setValue] = useControlled({\n controlledValue: valueProp,\n default: defaultValue ?? (field.disabled ? undefined : firstSelectableValue(children)),\n });\n\n return (\n <Group\n {...groupLayout(children, stack)}\n className={className}\n spacing={Spacing[2]}\n role='radiogroup'\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-required={ariaRequired}\n >\n {renderCards(children, (card) => ({\n name,\n multiple: false,\n checked: card.value === value,\n onChange: () => {\n if (field.disabled || card.disabled) {\n return;\n }\n setValue(card.value);\n onChange?.(card.value);\n },\n }))}\n </Group>\n );\n};\n\nconst MultipleGroup = ({\n name,\n className,\n stack,\n children,\n value: valueProp,\n defaultValue,\n onChange,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n}: SelectionCardGroupMultipleProps) => {\n const field = useContext(FormControlContext);\n const [value, setValue] = useControlled({\n controlledValue: valueProp,\n default: defaultValue ?? [],\n });\n const selected = value ?? [];\n\n return (\n <Group\n {...groupLayout(children, stack)}\n className={className}\n spacing={Spacing[2]}\n role='group'\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n >\n {renderCards(children, (card) => ({\n name,\n multiple: true,\n checked: selected.includes(card.value),\n onChange: (checked: boolean) => {\n if (field.disabled || card.disabled) {\n return;\n }\n const next = checked\n ? selected.includes(card.value)\n ? selected\n : [...selected, card.value]\n : selected.filter((item) => item !== card.value);\n setValue(next);\n onChange?.(next);\n },\n }))}\n </Group>\n );\n};\n\nexport const SelectionCardGroup = (props: SelectionCardGroupProps) => {\n const field = useContext(FormControlContext);\n /* Each card's checkbox would otherwise take the enclosing field's shared input id. */\n return (\n <FormControlContext.Provider value={{ ...field, inputId: undefined }}>\n {props.multiple ? <MultipleGroup {...props} /> : <SingleGroup {...props} />}\n </FormControlContext.Provider>\n );\n};\n\nexport default SelectionCardGroup;\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as Mode, i as FunctionFormRenderProps, n as CustomFunctionDetailRenderProps, o as OpenCodeChainFunctionPanel, s as PopoverFooterRenderer, t as CodeChainFunctionPanelRenderProps, u as ValueType } from "../../types-
|
|
2
|
-
import { t as ContextMenuExamples } from "../../listbox-options-
|
|
1
|
+
import { a as Mode, i as FunctionFormRenderProps, n as CustomFunctionDetailRenderProps, o as OpenCodeChainFunctionPanel, s as PopoverFooterRenderer, t as CodeChainFunctionPanelRenderProps, u as ValueType } from "../../types-DWU0Dmy9.mjs";
|
|
2
|
+
import { t as ContextMenuExamples } from "../../listbox-options-DCmqWWgy.mjs";
|
|
3
3
|
import SmartTextInput, { SmartTextInputProps } from "../../SmartTextInput.mjs";
|
|
4
4
|
import SmartTextInputField, { SmartTextInputFieldProps } from "../../SmartTextInputField.mjs";
|
|
5
5
|
export { type CodeChainFunctionPanelRenderProps, type ContextMenuExamples, type CustomFunctionDetailRenderProps, type FunctionFormRenderProps, Mode, type OpenCodeChainFunctionPanel, type PopoverFooterRenderer, SmartTextInputField, type SmartTextInputFieldProps, type SmartTextInputProps, ValueType, SmartTextInput as default };
|
|
@@ -6,7 +6,7 @@ import { isCreatableReceiverSchema, isNoArgCodeChainFunction } from "../../lib/c
|
|
|
6
6
|
import { isASTCustomFunctionNode, isAnyASTFunctionNode, isRealASTFunctionParamType } from "./parser/method-chain/types.mjs";
|
|
7
7
|
import { _ as methodChainToString, l as isEmpty, n as MethodChainNodeTypes, w as assertNever } from "../../methodChain-xZ1_vhbz.mjs";
|
|
8
8
|
import { normalizeChain, normalizeFunctionParam } from "../../lib/methodChainNormalize.mjs";
|
|
9
|
-
import { getFunctionSchemaForNode, getSchemaForFieldPath } from "../../lib/schemaOptions.mjs";
|
|
9
|
+
import { UNTYPED_ADDITIONAL_PROPERTY_SCHEMA, getFunctionSchemaForNode, getSchemaForFieldPath } from "../../lib/schemaOptions.mjs";
|
|
10
10
|
import { n as useChain, r as useChainSchema } from "../../useChain-Cu4KDfFk.mjs";
|
|
11
11
|
import { Z_INDICES } from "../../lib/zindex.mjs";
|
|
12
12
|
import { focusStyle } from "../../mixins/focus.mjs";
|
|
@@ -16,7 +16,7 @@ import { n as Button } from "../../IconButton-HWx5Hlmi.mjs";
|
|
|
16
16
|
import { n as useFormField } from "../../useFormField-CbNYbDdp.mjs";
|
|
17
17
|
import Input_default from "../Input/index.mjs";
|
|
18
18
|
import { n as ErrorText } from "../../FormControl-C4CiA0H-.mjs";
|
|
19
|
-
import { m as FormField, n as TableBoxField, p as splitOutFormFieldProps } from "../../FormField-
|
|
19
|
+
import { m as FormField, n as TableBoxField, p as splitOutFormFieldProps } from "../../FormField-D0y1uRV5.mjs";
|
|
20
20
|
import PillType from "./PillType.mjs";
|
|
21
21
|
import { ErrorMessageByKind, NodeType, isASTChainNode, isASTContainerNode, isMethodChainNode } from "./parser/smart-text/types.mjs";
|
|
22
22
|
import { parse as peg$parse } from "./parser/smart-text/parser.mjs";
|
|
@@ -771,6 +771,15 @@ const SmartTextInputFunctionDialog = ({ id, inputRef, functionAtCursor, nextPoss
|
|
|
771
771
|
};
|
|
772
772
|
}
|
|
773
773
|
}, [functionAtCursor, nextPossibleChains]);
|
|
774
|
+
const rendersCustomFunctionDetail = functionAtCursor.custom && functionSchema?.ccfToken != null;
|
|
775
|
+
const isMissingFunctionForm = functionSchema != null && !rendersCustomFunctionDetail && renderFunctionForm == null;
|
|
776
|
+
const warnedMissingFunctionFormRef = useRef(false);
|
|
777
|
+
useEffect(() => {
|
|
778
|
+
if (process.env.NODE_ENV !== "production" && isMissingFunctionForm && !warnedMissingFunctionFormRef.current) {
|
|
779
|
+
warnedMissingFunctionFormRef.current = true;
|
|
780
|
+
console.warn(`SmartTextInput: the function dialog for "${functionAtCursor.functionName}" opened without a \`renderFunctionForm\` prop, so its body is empty. Method-chain consumers must pass \`renderFunctionForm\` (in persona-web, use \`useDashboardSmartTextInputProps\`).`);
|
|
781
|
+
}
|
|
782
|
+
}, [isMissingFunctionForm, functionAtCursor.functionName]);
|
|
774
783
|
return /* @__PURE__ */ jsxs(StyledDialog, {
|
|
775
784
|
ref,
|
|
776
785
|
...restDialogProps,
|
|
@@ -1344,7 +1353,7 @@ function findSchemaErrors(tree, rootSchema, platformObjectJsonSchema, primitiveU
|
|
|
1344
1353
|
const enclosing = enclosingExpr(tree, chainNode);
|
|
1345
1354
|
const inClosedHandlebars = enclosing?.type === NodeType.Handlebars && !enclosing.children?.some((c) => c.type === NodeType.Error && c.kind === "unclosedHandlebars");
|
|
1346
1355
|
if (!hasIncomplete && identifierLinks.length > 0 && inClosedHandlebars) {
|
|
1347
|
-
if (!isSchemaTypeAllowed(prevSchema, JsonSchemaStringifiableTypes)) {
|
|
1356
|
+
if (!(prevSchema === UNTYPED_ADDITIONAL_PROPERTY_SCHEMA || isSchemaTypeAllowed(prevSchema, JsonSchemaStringifiableTypes))) {
|
|
1348
1357
|
const lastLink = identifierLinks[identifierLinks.length - 1];
|
|
1349
1358
|
return {
|
|
1350
1359
|
start: lastLink.start,
|