pne-ui 4.3.0-rc.4 → 4.3.0-rc.41
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/README.md +649 -128
- package/cjs/common/paynet/dropdown.d.ts +24 -5
- package/cjs/common/paynet/dropdown.js +38 -37
- package/cjs/common/paynet/dropdown.js.map +1 -1
- package/cjs/component/PneBreadcrumbs.d.ts +43 -0
- package/cjs/component/PneBreadcrumbs.js +269 -0
- package/cjs/component/PneBreadcrumbs.js.map +1 -0
- package/cjs/component/PneButton.d.ts +24 -6
- package/cjs/component/PneButton.js +30 -31
- package/cjs/component/PneButton.js.map +1 -1
- package/cjs/component/PneCheckbox.d.ts +4 -1
- package/cjs/component/PneCheckbox.js +78 -2
- package/cjs/component/PneCheckbox.js.map +1 -1
- package/cjs/component/PneCoachmark.d.ts +63 -0
- package/cjs/component/PneCoachmark.js +194 -0
- package/cjs/component/PneCoachmark.js.map +1 -0
- package/cjs/component/PneField.d.ts +49 -9
- package/cjs/component/PneField.js +109 -23
- package/cjs/component/PneField.js.map +1 -1
- package/cjs/component/PneFieldContext.d.ts +31 -8
- package/cjs/component/PneFieldContext.js +35 -12
- package/cjs/component/PneFieldContext.js.map +1 -1
- package/cjs/component/PneLabeledCheckbox.d.ts +4 -4
- package/cjs/component/PneLabeledCheckbox.js +9 -3
- package/cjs/component/PneLabeledCheckbox.js.map +1 -1
- package/cjs/component/PneModal.d.ts +65 -22
- package/cjs/component/PneModal.js +298 -62
- package/cjs/component/PneModal.js.map +1 -1
- package/cjs/component/PneModalActions.d.ts +16 -3
- package/cjs/component/PneModalActions.js +83 -33
- package/cjs/component/PneModalActions.js.map +1 -1
- package/cjs/component/PneOrdersIcon.d.ts +3 -0
- package/cjs/component/PneOrdersIcon.js +12 -0
- package/cjs/component/PneOrdersIcon.js.map +1 -0
- package/cjs/component/PneSwitch.d.ts +13 -2
- package/cjs/component/PneSwitch.js +287 -2
- package/cjs/component/PneSwitch.js.map +1 -1
- package/cjs/component/PneTextField.d.ts +2 -0
- package/cjs/component/PneTextField.js +288 -32
- package/cjs/component/PneTextField.js.map +1 -1
- package/cjs/component/PneToggleInput.d.ts +26 -0
- package/cjs/component/PneToggleInput.js +138 -0
- package/cjs/component/PneToggleInput.js.map +1 -0
- package/cjs/component/confirm/PneConfirmProvider.d.ts +14 -4
- package/cjs/component/confirm/PneConfirmProvider.js +35 -14
- package/cjs/component/confirm/PneConfirmProvider.js.map +1 -1
- package/cjs/component/dropdown/PneAsyncAutocomplete.d.ts +42 -17
- package/cjs/component/dropdown/PneAsyncAutocomplete.js +324 -51
- package/cjs/component/dropdown/PneAsyncAutocomplete.js.map +1 -1
- package/cjs/component/dropdown/PneAutocomplete.d.ts +39 -10
- package/cjs/component/dropdown/PneAutocomplete.js +33 -17
- package/cjs/component/dropdown/PneAutocomplete.js.map +1 -1
- package/cjs/component/dropdown/PneAutocompleteShared.d.ts +30 -0
- package/cjs/component/dropdown/PneAutocompleteShared.js +122 -0
- package/cjs/component/dropdown/PneAutocompleteShared.js.map +1 -0
- package/cjs/component/dropdown/PneSelect.d.ts +78 -12
- package/cjs/component/dropdown/PneSelect.js +296 -61
- package/cjs/component/dropdown/PneSelect.js.map +1 -1
- package/cjs/component/internal/PneSurface.d.ts +9 -0
- package/cjs/component/internal/PneSurface.js +57 -0
- package/cjs/component/internal/PneSurface.js.map +1 -0
- package/cjs/component/non-abstract-entity-selector/AbstractEntitySelectModal.d.ts +1 -0
- package/cjs/component/non-abstract-entity-selector/AbstractEntitySelectModal.js +6 -3
- package/cjs/component/non-abstract-entity-selector/AbstractEntitySelectModal.js.map +1 -1
- package/cjs/component/non-abstract-entity-selector/AbstractEntitySelector.js +2 -2
- package/cjs/component/non-abstract-entity-selector/AbstractEntitySelector.js.map +1 -1
- package/cjs/component/non-abstract-entity-selector/styled.d.ts +1 -1
- package/cjs/component/overlay/OverlayHost.d.ts +41 -2
- package/cjs/component/overlay/OverlayHost.js +190 -26
- package/cjs/component/overlay/OverlayHost.js.map +1 -1
- package/cjs/component/overlay/OverlayPortalContainerContext.d.ts +3 -0
- package/cjs/component/overlay/OverlayPortalContainerContext.js +8 -0
- package/cjs/component/overlay/OverlayPortalContainerContext.js.map +1 -0
- package/cjs/component/overlay/PaynetErrorContent.d.ts +8 -0
- package/cjs/component/overlay/PaynetErrorContent.js +255 -0
- package/cjs/component/overlay/PaynetErrorContent.js.map +1 -0
- package/cjs/component/overlay/overlayStore.d.ts +4 -2
- package/cjs/component/overlay/overlayStore.js +55 -13
- package/cjs/component/overlay/overlayStore.js.map +1 -1
- package/cjs/component/overlay/paynetError.d.ts +7 -0
- package/cjs/component/overlay/paynetError.js +209 -0
- package/cjs/component/overlay/paynetError.js.map +1 -0
- package/cjs/component/overlay/types.d.ts +36 -0
- package/cjs/component/search-ui/SearchUI.d.ts +23 -15
- package/cjs/component/search-ui/SearchUI.js +223 -9
- package/cjs/component/search-ui/SearchUI.js.map +1 -1
- package/cjs/component/search-ui/SearchUITableSelection.d.ts +70 -0
- package/cjs/component/search-ui/SearchUITableSelection.js +30 -0
- package/cjs/component/search-ui/SearchUITableSelection.js.map +1 -0
- package/cjs/component/search-ui/filters/SearchUIFilters.js +2 -2
- package/cjs/component/search-ui/filters/SearchUIFilters.js.map +1 -1
- package/cjs/component/search-ui/filters/component/criterion/ErrorCodeCriterion.js +1 -1
- package/cjs/component/search-ui/filters/component/criterion/ErrorCodeCriterion.js.map +1 -1
- package/cjs/component/search-ui/filters/component/criterion/GroupingCriterion.js +1 -6
- package/cjs/component/search-ui/filters/component/criterion/GroupingCriterion.js.map +1 -1
- package/cjs/component/search-ui/filters/component/criterion/MultigetCriterionPanel.js +6 -9
- package/cjs/component/search-ui/filters/component/criterion/MultigetCriterionPanel.js.map +1 -1
- package/cjs/component/search-ui/filters/component/criterion/ProjectCurrencyCriterion.js +1 -1
- package/cjs/component/search-ui/filters/component/criterion/ProjectCurrencyCriterion.js.map +1 -1
- package/cjs/component/search-ui/filters/component/criterion/TransactionSessionStatusCriterion.js +8 -11
- package/cjs/component/search-ui/filters/component/criterion/TransactionSessionStatusCriterion.js.map +1 -1
- package/cjs/component/search-ui/filters/component/criterion/orders-search/OrdersSearchCountrySelect.js +3 -3
- package/cjs/component/search-ui/filters/component/criterion/orders-search/OrdersSearchCountrySelect.js.map +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIAbstractEntityChipSelect.js +2 -2
- package/cjs/component/search-ui/filters/component/select/SearchUIAbstractEntityChipSelect.js.map +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIAddFilter.js +2 -2
- package/cjs/component/search-ui/filters/component/select/SearchUIAddFilter.js.map +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIDateRangeSpecTypeSelect.js +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIDateRangeSpecTypeSelect.js.map +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIExactSearchLabelSelect.js +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIExactSearchLabelSelect.js.map +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIGroupingDateTypeSelect.js +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIGroupingDateTypeSelect.js.map +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIOrderDateTypeSelect.js +1 -1
- package/cjs/component/search-ui/filters/component/select/SearchUIOrderDateTypeSelect.js.map +1 -1
- package/cjs/component/search-ui/filters/component/template/SearchUITemplatePanel.js +6 -9
- package/cjs/component/search-ui/filters/component/template/SearchUITemplatePanel.js.map +1 -1
- package/cjs/component/search-ui/filters/component/template/SearchUITemplatesMenu.js +1 -1
- package/cjs/component/search-ui/filters/component/template/SearchUITemplatesMenu.js.map +1 -1
- package/cjs/component/table/AbstractTable.d.ts +2 -0
- package/cjs/component/table/AbstractTable.js +40 -15
- package/cjs/component/table/AbstractTable.js.map +1 -1
- package/cjs/component/table/AbstractTableCell.d.ts +2 -1
- package/cjs/component/table/AbstractTableCell.js +5 -4
- package/cjs/component/table/AbstractTableCell.js.map +1 -1
- package/cjs/component/table/PneTableCell.d.ts +5 -2
- package/cjs/component/table/PneTableCell.js +7 -6
- package/cjs/component/table/PneTableCell.js.map +1 -1
- package/cjs/component/table/PneTableControlCell.d.ts +5 -2
- package/cjs/component/table/PneTableControlCell.js +5 -4
- package/cjs/component/table/PneTableControlCell.js.map +1 -1
- package/cjs/component/table/PneTablePagination.d.ts +1 -1
- package/cjs/component/table/PneTablePaginationActions.d.ts +15 -0
- package/cjs/component/table/PneTablePaginationActions.js +225 -31
- package/cjs/component/table/PneTablePaginationActions.js.map +1 -1
- package/cjs/component/table/PneTableSelectionCell.d.ts +21 -0
- package/cjs/component/table/PneTableSelectionCell.js +46 -0
- package/cjs/component/table/PneTableSelectionCell.js.map +1 -0
- package/cjs/component/table/PneTableSelectionControls.d.ts +10 -0
- package/cjs/component/table/PneTableSelectionControls.js +40 -0
- package/cjs/component/table/PneTableSelectionControls.js.map +1 -0
- package/cjs/component/table/PneTableSelectionHeaderCell.d.ts +15 -0
- package/cjs/component/table/PneTableSelectionHeaderCell.js +48 -0
- package/cjs/component/table/PneTableSelectionHeaderCell.js.map +1 -0
- package/cjs/component/table/PneTableSwitchCell.d.ts +37 -0
- package/cjs/component/table/PneTableSwitchCell.js +62 -0
- package/cjs/component/table/PneTableSwitchCell.js.map +1 -0
- package/cjs/component/table/PneTableToolbar.d.ts +26 -0
- package/cjs/component/table/PneTableToolbar.js +126 -0
- package/cjs/component/table/PneTableToolbar.js.map +1 -0
- package/cjs/component/table/PneTableViewSelector.js +20 -11
- package/cjs/component/table/PneTableViewSelector.js.map +1 -1
- package/cjs/component/table/tableSelection.d.ts +26 -0
- package/cjs/component/table/tableSelection.js +173 -0
- package/cjs/component/table/tableSelection.js.map +1 -0
- package/cjs/component/table/useTableSelection.d.ts +46 -0
- package/cjs/component/table/useTableSelection.js +178 -0
- package/cjs/component/table/useTableSelection.js.map +1 -0
- package/cjs/exports/buttons.d.ts +1 -1
- package/cjs/exports/buttons.js +1 -3
- package/cjs/exports/buttons.js.map +1 -1
- package/cjs/exports/confirm.d.ts +1 -1
- package/cjs/exports/confirm.js.map +1 -1
- package/cjs/exports/inputs.d.ts +11 -6
- package/cjs/exports/inputs.js +3 -3
- package/cjs/exports/inputs.js.map +1 -1
- package/cjs/exports/modals.d.ts +3 -1
- package/cjs/exports/modals.js +3 -1
- package/cjs/exports/modals.js.map +1 -1
- package/cjs/exports/navigation.d.ts +2 -0
- package/cjs/exports/navigation.js +8 -0
- package/cjs/exports/navigation.js.map +1 -0
- package/cjs/exports/overlay.d.ts +5 -1
- package/cjs/exports/overlay.js +6 -1
- package/cjs/exports/overlay.js.map +1 -1
- package/cjs/exports/search.d.ts +2 -1
- package/cjs/exports/search.js.map +1 -1
- package/cjs/exports/table.d.ts +15 -0
- package/cjs/exports/table.js +22 -1
- package/cjs/exports/table.js.map +1 -1
- package/cjs/index.d.ts +1 -1
- package/cjs/index.js +1 -1
- package/cjs/index.js.map +1 -1
- package/esm/common/paynet/dropdown.d.ts +24 -5
- package/esm/common/paynet/dropdown.js +37 -36
- package/esm/common/paynet/dropdown.js.map +1 -1
- package/esm/component/PneBreadcrumbs.d.ts +43 -0
- package/esm/component/PneBreadcrumbs.js +264 -0
- package/esm/component/PneBreadcrumbs.js.map +1 -0
- package/esm/component/PneButton.d.ts +24 -6
- package/esm/component/PneButton.js +30 -31
- package/esm/component/PneButton.js.map +1 -1
- package/esm/component/PneCheckbox.d.ts +4 -1
- package/esm/component/PneCheckbox.js +79 -3
- package/esm/component/PneCheckbox.js.map +1 -1
- package/esm/component/PneCoachmark.d.ts +63 -0
- package/esm/component/PneCoachmark.js +191 -0
- package/esm/component/PneCoachmark.js.map +1 -0
- package/esm/component/PneField.d.ts +49 -9
- package/esm/component/PneField.js +110 -24
- package/esm/component/PneField.js.map +1 -1
- package/esm/component/PneFieldContext.d.ts +31 -8
- package/esm/component/PneFieldContext.js +32 -9
- package/esm/component/PneFieldContext.js.map +1 -1
- package/esm/component/PneLabeledCheckbox.d.ts +4 -4
- package/esm/component/PneLabeledCheckbox.js +10 -4
- package/esm/component/PneLabeledCheckbox.js.map +1 -1
- package/esm/component/PneModal.d.ts +65 -22
- package/esm/component/PneModal.js +300 -64
- package/esm/component/PneModal.js.map +1 -1
- package/esm/component/PneModalActions.d.ts +16 -3
- package/esm/component/PneModalActions.js +83 -33
- package/esm/component/PneModalActions.js.map +1 -1
- package/esm/component/PneOrdersIcon.d.ts +3 -0
- package/esm/component/PneOrdersIcon.js +7 -0
- package/esm/component/PneOrdersIcon.js.map +1 -0
- package/esm/component/PneSwitch.d.ts +13 -2
- package/esm/component/PneSwitch.js +289 -4
- package/esm/component/PneSwitch.js.map +1 -1
- package/esm/component/PneTextField.d.ts +2 -0
- package/esm/component/PneTextField.js +289 -33
- package/esm/component/PneTextField.js.map +1 -1
- package/esm/component/PneToggleInput.d.ts +26 -0
- package/esm/component/PneToggleInput.js +133 -0
- package/esm/component/PneToggleInput.js.map +1 -0
- package/esm/component/confirm/PneConfirmProvider.d.ts +14 -4
- package/esm/component/confirm/PneConfirmProvider.js +35 -14
- package/esm/component/confirm/PneConfirmProvider.js.map +1 -1
- package/esm/component/dropdown/PneAsyncAutocomplete.d.ts +42 -17
- package/esm/component/dropdown/PneAsyncAutocomplete.js +328 -55
- package/esm/component/dropdown/PneAsyncAutocomplete.js.map +1 -1
- package/esm/component/dropdown/PneAutocomplete.d.ts +39 -10
- package/esm/component/dropdown/PneAutocomplete.js +34 -18
- package/esm/component/dropdown/PneAutocomplete.js.map +1 -1
- package/esm/component/dropdown/PneAutocompleteShared.d.ts +30 -0
- package/esm/component/dropdown/PneAutocompleteShared.js +112 -0
- package/esm/component/dropdown/PneAutocompleteShared.js.map +1 -0
- package/esm/component/dropdown/PneSelect.d.ts +78 -12
- package/esm/component/dropdown/PneSelect.js +299 -64
- package/esm/component/dropdown/PneSelect.js.map +1 -1
- package/esm/component/internal/PneSurface.d.ts +9 -0
- package/esm/component/internal/PneSurface.js +53 -0
- package/esm/component/internal/PneSurface.js.map +1 -0
- package/esm/component/non-abstract-entity-selector/AbstractEntitySelectModal.d.ts +1 -0
- package/esm/component/non-abstract-entity-selector/AbstractEntitySelectModal.js +6 -3
- package/esm/component/non-abstract-entity-selector/AbstractEntitySelectModal.js.map +1 -1
- package/esm/component/non-abstract-entity-selector/AbstractEntitySelector.js +2 -2
- package/esm/component/non-abstract-entity-selector/AbstractEntitySelector.js.map +1 -1
- package/esm/component/non-abstract-entity-selector/styled.d.ts +1 -1
- package/esm/component/overlay/OverlayHost.d.ts +41 -2
- package/esm/component/overlay/OverlayHost.js +189 -27
- package/esm/component/overlay/OverlayHost.js.map +1 -1
- package/esm/component/overlay/OverlayPortalContainerContext.d.ts +3 -0
- package/esm/component/overlay/OverlayPortalContainerContext.js +4 -0
- package/esm/component/overlay/OverlayPortalContainerContext.js.map +1 -0
- package/esm/component/overlay/PaynetErrorContent.d.ts +8 -0
- package/esm/component/overlay/PaynetErrorContent.js +250 -0
- package/esm/component/overlay/PaynetErrorContent.js.map +1 -0
- package/esm/component/overlay/overlayStore.d.ts +4 -2
- package/esm/component/overlay/overlayStore.js +55 -13
- package/esm/component/overlay/overlayStore.js.map +1 -1
- package/esm/component/overlay/paynetError.d.ts +7 -0
- package/esm/component/overlay/paynetError.js +205 -0
- package/esm/component/overlay/paynetError.js.map +1 -0
- package/esm/component/overlay/types.d.ts +36 -0
- package/esm/component/search-ui/SearchUI.d.ts +23 -15
- package/esm/component/search-ui/SearchUI.js +225 -11
- package/esm/component/search-ui/SearchUI.js.map +1 -1
- package/esm/component/search-ui/SearchUITableSelection.d.ts +70 -0
- package/esm/component/search-ui/SearchUITableSelection.js +26 -0
- package/esm/component/search-ui/SearchUITableSelection.js.map +1 -0
- package/esm/component/search-ui/filters/SearchUIFilters.js +2 -2
- package/esm/component/search-ui/filters/SearchUIFilters.js.map +1 -1
- package/esm/component/search-ui/filters/component/criterion/ErrorCodeCriterion.js +1 -1
- package/esm/component/search-ui/filters/component/criterion/ErrorCodeCriterion.js.map +1 -1
- package/esm/component/search-ui/filters/component/criterion/GroupingCriterion.js +1 -6
- package/esm/component/search-ui/filters/component/criterion/GroupingCriterion.js.map +1 -1
- package/esm/component/search-ui/filters/component/criterion/MultigetCriterionPanel.js +6 -9
- package/esm/component/search-ui/filters/component/criterion/MultigetCriterionPanel.js.map +1 -1
- package/esm/component/search-ui/filters/component/criterion/ProjectCurrencyCriterion.js +1 -1
- package/esm/component/search-ui/filters/component/criterion/ProjectCurrencyCriterion.js.map +1 -1
- package/esm/component/search-ui/filters/component/criterion/TransactionSessionStatusCriterion.js +8 -11
- package/esm/component/search-ui/filters/component/criterion/TransactionSessionStatusCriterion.js.map +1 -1
- package/esm/component/search-ui/filters/component/criterion/orders-search/OrdersSearchCountrySelect.js +3 -3
- package/esm/component/search-ui/filters/component/criterion/orders-search/OrdersSearchCountrySelect.js.map +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIAbstractEntityChipSelect.js +2 -2
- package/esm/component/search-ui/filters/component/select/SearchUIAbstractEntityChipSelect.js.map +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIAddFilter.js +2 -2
- package/esm/component/search-ui/filters/component/select/SearchUIAddFilter.js.map +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIDateRangeSpecTypeSelect.js +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIDateRangeSpecTypeSelect.js.map +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIExactSearchLabelSelect.js +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIExactSearchLabelSelect.js.map +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIGroupingDateTypeSelect.js +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIGroupingDateTypeSelect.js.map +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIOrderDateTypeSelect.js +1 -1
- package/esm/component/search-ui/filters/component/select/SearchUIOrderDateTypeSelect.js.map +1 -1
- package/esm/component/search-ui/filters/component/template/SearchUITemplatePanel.js +6 -9
- package/esm/component/search-ui/filters/component/template/SearchUITemplatePanel.js.map +1 -1
- package/esm/component/search-ui/filters/component/template/SearchUITemplatesMenu.js +1 -1
- package/esm/component/search-ui/filters/component/template/SearchUITemplatesMenu.js.map +1 -1
- package/esm/component/table/AbstractTable.d.ts +2 -0
- package/esm/component/table/AbstractTable.js +40 -15
- package/esm/component/table/AbstractTable.js.map +1 -1
- package/esm/component/table/AbstractTableCell.d.ts +2 -1
- package/esm/component/table/AbstractTableCell.js +5 -4
- package/esm/component/table/AbstractTableCell.js.map +1 -1
- package/esm/component/table/PneTableCell.d.ts +5 -2
- package/esm/component/table/PneTableCell.js +7 -6
- package/esm/component/table/PneTableCell.js.map +1 -1
- package/esm/component/table/PneTableControlCell.d.ts +5 -2
- package/esm/component/table/PneTableControlCell.js +5 -4
- package/esm/component/table/PneTableControlCell.js.map +1 -1
- package/esm/component/table/PneTablePagination.d.ts +1 -1
- package/esm/component/table/PneTablePaginationActions.d.ts +15 -0
- package/esm/component/table/PneTablePaginationActions.js +223 -31
- package/esm/component/table/PneTablePaginationActions.js.map +1 -1
- package/esm/component/table/PneTableSelectionCell.d.ts +21 -0
- package/esm/component/table/PneTableSelectionCell.js +42 -0
- package/esm/component/table/PneTableSelectionCell.js.map +1 -0
- package/esm/component/table/PneTableSelectionControls.d.ts +10 -0
- package/esm/component/table/PneTableSelectionControls.js +37 -0
- package/esm/component/table/PneTableSelectionControls.js.map +1 -0
- package/esm/component/table/PneTableSelectionHeaderCell.d.ts +15 -0
- package/esm/component/table/PneTableSelectionHeaderCell.js +45 -0
- package/esm/component/table/PneTableSelectionHeaderCell.js.map +1 -0
- package/esm/component/table/PneTableSwitchCell.d.ts +37 -0
- package/esm/component/table/PneTableSwitchCell.js +59 -0
- package/esm/component/table/PneTableSwitchCell.js.map +1 -0
- package/esm/component/table/PneTableToolbar.d.ts +26 -0
- package/esm/component/table/PneTableToolbar.js +121 -0
- package/esm/component/table/PneTableToolbar.js.map +1 -0
- package/esm/component/table/PneTableViewSelector.js +21 -12
- package/esm/component/table/PneTableViewSelector.js.map +1 -1
- package/esm/component/table/tableSelection.d.ts +26 -0
- package/esm/component/table/tableSelection.js +162 -0
- package/esm/component/table/tableSelection.js.map +1 -0
- package/esm/component/table/useTableSelection.d.ts +46 -0
- package/esm/component/table/useTableSelection.js +176 -0
- package/esm/component/table/useTableSelection.js.map +1 -0
- package/esm/exports/buttons.d.ts +1 -1
- package/esm/exports/buttons.js +0 -1
- package/esm/exports/buttons.js.map +1 -1
- package/esm/exports/confirm.d.ts +1 -1
- package/esm/exports/confirm.js.map +1 -1
- package/esm/exports/inputs.d.ts +11 -6
- package/esm/exports/inputs.js +1 -1
- package/esm/exports/inputs.js.map +1 -1
- package/esm/exports/modals.d.ts +3 -1
- package/esm/exports/modals.js +1 -0
- package/esm/exports/modals.js.map +1 -1
- package/esm/exports/navigation.d.ts +2 -0
- package/esm/exports/navigation.js +3 -0
- package/esm/exports/navigation.js.map +1 -0
- package/esm/exports/overlay.d.ts +5 -1
- package/esm/exports/overlay.js +3 -1
- package/esm/exports/overlay.js.map +1 -1
- package/esm/exports/search.d.ts +2 -1
- package/esm/exports/search.js.map +1 -1
- package/esm/exports/table.d.ts +15 -0
- package/esm/exports/table.js +7 -0
- package/esm/exports/table.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/package.json +13 -19
- package/cjs/component/PneButtonGroup.d.ts +0 -3
- package/cjs/component/PneButtonGroup.js +0 -20
- package/cjs/component/PneButtonGroup.js.map +0 -1
- package/cjs/component/PneHighContrastLabeledCheckbox.d.ts +0 -3
- package/cjs/component/PneHighContrastLabeledCheckbox.js +0 -203
- package/cjs/component/PneHighContrastLabeledCheckbox.js.map +0 -1
- package/cjs/component/cloudscape/CloudscapeBoardStyles.d.ts +0 -10
- package/cjs/component/cloudscape/CloudscapeBoardStyles.js +0 -92
- package/cjs/component/cloudscape/CloudscapeBoardStyles.js.map +0 -1
- package/cjs/component/cloudscape/CloudscapeThemeProvider.d.ts +0 -8
- package/cjs/component/cloudscape/CloudscapeThemeProvider.js +0 -19
- package/cjs/component/cloudscape/CloudscapeThemeProvider.js.map +0 -1
- package/cjs/component/cloudscape/boardI18n.d.ts +0 -10
- package/cjs/component/cloudscape/boardI18n.js +0 -51
- package/cjs/component/cloudscape/boardI18n.js.map +0 -1
- package/cjs/component/cloudscape/cloudscapeTheme.d.ts +0 -6
- package/cjs/component/cloudscape/cloudscapeTheme.js +0 -14
- package/cjs/component/cloudscape/cloudscapeTheme.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoard.d.ts +0 -13
- package/cjs/component/widget-board/WidgetBoard.js +0 -342
- package/cjs/component/widget-board/WidgetBoard.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardCloudscapeEngine.d.ts +0 -15
- package/cjs/component/widget-board/WidgetBoardCloudscapeEngine.js +0 -24
- package/cjs/component/widget-board/WidgetBoardCloudscapeEngine.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardFab.d.ts +0 -6
- package/cjs/component/widget-board/WidgetBoardFab.js +0 -28
- package/cjs/component/widget-board/WidgetBoardFab.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardHeaderControls.d.ts +0 -11
- package/cjs/component/widget-board/WidgetBoardHeaderControls.js +0 -155
- package/cjs/component/widget-board/WidgetBoardHeaderControls.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardItem.d.ts +0 -17
- package/cjs/component/widget-board/WidgetBoardItem.js +0 -56
- package/cjs/component/widget-board/WidgetBoardItem.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardReactGridLayoutEngine.d.ts +0 -30
- package/cjs/component/widget-board/WidgetBoardReactGridLayoutEngine.js +0 -239
- package/cjs/component/widget-board/WidgetBoardReactGridLayoutEngine.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardScope.d.ts +0 -7
- package/cjs/component/widget-board/WidgetBoardScope.js +0 -23
- package/cjs/component/widget-board/WidgetBoardScope.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardSkeleton.d.ts +0 -2
- package/cjs/component/widget-board/WidgetBoardSkeleton.js +0 -65
- package/cjs/component/widget-board/WidgetBoardSkeleton.js.map +0 -1
- package/cjs/component/widget-board/WidgetBoardVisibilityModal.d.ts +0 -10
- package/cjs/component/widget-board/WidgetBoardVisibilityModal.js +0 -45
- package/cjs/component/widget-board/WidgetBoardVisibilityModal.js.map +0 -1
- package/cjs/component/widget-board/WidgetLayoutsPanel.d.ts +0 -21
- package/cjs/component/widget-board/WidgetLayoutsPanel.js +0 -127
- package/cjs/component/widget-board/WidgetLayoutsPanel.js.map +0 -1
- package/cjs/component/widget-board/index.d.ts +0 -9
- package/cjs/component/widget-board/index.js +0 -13
- package/cjs/component/widget-board/index.js.map +0 -1
- package/cjs/component/widget-board/layoutPersistence.d.ts +0 -2
- package/cjs/component/widget-board/layoutPersistence.js +0 -78
- package/cjs/component/widget-board/layoutPersistence.js.map +0 -1
- package/cjs/component/widget-board/types.d.ts +0 -95
- package/cjs/component/widget-board/types.js +0 -3
- package/cjs/component/widget-board/types.js.map +0 -1
- package/cjs/component/widget-board/useWidgetBoardAutosize.d.ts +0 -19
- package/cjs/component/widget-board/useWidgetBoardAutosize.js +0 -220
- package/cjs/component/widget-board/useWidgetBoardAutosize.js.map +0 -1
- package/cjs/component/widget-board/useWidgetBoardFabActions.d.ts +0 -11
- package/cjs/component/widget-board/useWidgetBoardFabActions.js +0 -104
- package/cjs/component/widget-board/useWidgetBoardFabActions.js.map +0 -1
- package/cjs/component/widget-board/useWidgetBoardInteractionLock.d.ts +0 -1
- package/cjs/component/widget-board/useWidgetBoardInteractionLock.js +0 -29
- package/cjs/component/widget-board/useWidgetBoardInteractionLock.js.map +0 -1
- package/cjs/component/widget-board/useWidgetBoardLayoutActions.d.ts +0 -28
- package/cjs/component/widget-board/useWidgetBoardLayoutActions.js +0 -144
- package/cjs/component/widget-board/useWidgetBoardLayoutActions.js.map +0 -1
- package/cjs/component/widget-board/useWidgetBoardLayoutSource.d.ts +0 -29
- package/cjs/component/widget-board/useWidgetBoardLayoutSource.js +0 -72
- package/cjs/component/widget-board/useWidgetBoardLayoutSource.js.map +0 -1
- package/cjs/component/widget-board/useWidgetBoardStateActions.d.ts +0 -24
- package/cjs/component/widget-board/useWidgetBoardStateActions.js +0 -249
- package/cjs/component/widget-board/useWidgetBoardStateActions.js.map +0 -1
- package/cjs/component/widget-board/widgetBoardFabStore.d.ts +0 -27
- package/cjs/component/widget-board/widgetBoardFabStore.js +0 -16
- package/cjs/component/widget-board/widgetBoardFabStore.js.map +0 -1
- package/cjs/component/widget-board/widgetBoardLayoutUtils.d.ts +0 -21
- package/cjs/component/widget-board/widgetBoardLayoutUtils.js +0 -125
- package/cjs/component/widget-board/widgetBoardLayoutUtils.js.map +0 -1
- package/cjs/exports/cloudscape.d.ts +0 -5
- package/cjs/exports/cloudscape.js +0 -15
- package/cjs/exports/cloudscape.js.map +0 -1
- package/esm/component/PneButtonGroup.d.ts +0 -3
- package/esm/component/PneButtonGroup.js +0 -15
- package/esm/component/PneButtonGroup.js.map +0 -1
- package/esm/component/PneHighContrastLabeledCheckbox.d.ts +0 -3
- package/esm/component/PneHighContrastLabeledCheckbox.js +0 -199
- package/esm/component/PneHighContrastLabeledCheckbox.js.map +0 -1
- package/esm/component/cloudscape/CloudscapeBoardStyles.d.ts +0 -10
- package/esm/component/cloudscape/CloudscapeBoardStyles.js +0 -88
- package/esm/component/cloudscape/CloudscapeBoardStyles.js.map +0 -1
- package/esm/component/cloudscape/CloudscapeThemeProvider.d.ts +0 -8
- package/esm/component/cloudscape/CloudscapeThemeProvider.js +0 -15
- package/esm/component/cloudscape/CloudscapeThemeProvider.js.map +0 -1
- package/esm/component/cloudscape/boardI18n.d.ts +0 -10
- package/esm/component/cloudscape/boardI18n.js +0 -47
- package/esm/component/cloudscape/boardI18n.js.map +0 -1
- package/esm/component/cloudscape/cloudscapeTheme.d.ts +0 -6
- package/esm/component/cloudscape/cloudscapeTheme.js +0 -11
- package/esm/component/cloudscape/cloudscapeTheme.js.map +0 -1
- package/esm/component/widget-board/WidgetBoard.d.ts +0 -13
- package/esm/component/widget-board/WidgetBoard.js +0 -337
- package/esm/component/widget-board/WidgetBoard.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardCloudscapeEngine.d.ts +0 -15
- package/esm/component/widget-board/WidgetBoardCloudscapeEngine.js +0 -19
- package/esm/component/widget-board/WidgetBoardCloudscapeEngine.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardFab.d.ts +0 -6
- package/esm/component/widget-board/WidgetBoardFab.js +0 -23
- package/esm/component/widget-board/WidgetBoardFab.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardHeaderControls.d.ts +0 -11
- package/esm/component/widget-board/WidgetBoardHeaderControls.js +0 -150
- package/esm/component/widget-board/WidgetBoardHeaderControls.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardItem.d.ts +0 -17
- package/esm/component/widget-board/WidgetBoardItem.js +0 -51
- package/esm/component/widget-board/WidgetBoardItem.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardReactGridLayoutEngine.d.ts +0 -30
- package/esm/component/widget-board/WidgetBoardReactGridLayoutEngine.js +0 -233
- package/esm/component/widget-board/WidgetBoardReactGridLayoutEngine.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardScope.d.ts +0 -7
- package/esm/component/widget-board/WidgetBoardScope.js +0 -17
- package/esm/component/widget-board/WidgetBoardScope.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardSkeleton.d.ts +0 -2
- package/esm/component/widget-board/WidgetBoardSkeleton.js +0 -60
- package/esm/component/widget-board/WidgetBoardSkeleton.js.map +0 -1
- package/esm/component/widget-board/WidgetBoardVisibilityModal.d.ts +0 -10
- package/esm/component/widget-board/WidgetBoardVisibilityModal.js +0 -40
- package/esm/component/widget-board/WidgetBoardVisibilityModal.js.map +0 -1
- package/esm/component/widget-board/WidgetLayoutsPanel.d.ts +0 -21
- package/esm/component/widget-board/WidgetLayoutsPanel.js +0 -122
- package/esm/component/widget-board/WidgetLayoutsPanel.js.map +0 -1
- package/esm/component/widget-board/index.d.ts +0 -9
- package/esm/component/widget-board/index.js +0 -10
- package/esm/component/widget-board/index.js.map +0 -1
- package/esm/component/widget-board/layoutPersistence.d.ts +0 -2
- package/esm/component/widget-board/layoutPersistence.js +0 -74
- package/esm/component/widget-board/layoutPersistence.js.map +0 -1
- package/esm/component/widget-board/types.d.ts +0 -95
- package/esm/component/widget-board/types.js +0 -2
- package/esm/component/widget-board/types.js.map +0 -1
- package/esm/component/widget-board/useWidgetBoardAutosize.d.ts +0 -19
- package/esm/component/widget-board/useWidgetBoardAutosize.js +0 -216
- package/esm/component/widget-board/useWidgetBoardAutosize.js.map +0 -1
- package/esm/component/widget-board/useWidgetBoardFabActions.d.ts +0 -11
- package/esm/component/widget-board/useWidgetBoardFabActions.js +0 -99
- package/esm/component/widget-board/useWidgetBoardFabActions.js.map +0 -1
- package/esm/component/widget-board/useWidgetBoardInteractionLock.d.ts +0 -1
- package/esm/component/widget-board/useWidgetBoardInteractionLock.js +0 -25
- package/esm/component/widget-board/useWidgetBoardInteractionLock.js.map +0 -1
- package/esm/component/widget-board/useWidgetBoardLayoutActions.d.ts +0 -28
- package/esm/component/widget-board/useWidgetBoardLayoutActions.js +0 -140
- package/esm/component/widget-board/useWidgetBoardLayoutActions.js.map +0 -1
- package/esm/component/widget-board/useWidgetBoardLayoutSource.d.ts +0 -29
- package/esm/component/widget-board/useWidgetBoardLayoutSource.js +0 -68
- package/esm/component/widget-board/useWidgetBoardLayoutSource.js.map +0 -1
- package/esm/component/widget-board/useWidgetBoardStateActions.d.ts +0 -24
- package/esm/component/widget-board/useWidgetBoardStateActions.js +0 -245
- package/esm/component/widget-board/useWidgetBoardStateActions.js.map +0 -1
- package/esm/component/widget-board/widgetBoardFabStore.d.ts +0 -27
- package/esm/component/widget-board/widgetBoardFabStore.js +0 -12
- package/esm/component/widget-board/widgetBoardFabStore.js.map +0 -1
- package/esm/component/widget-board/widgetBoardLayoutUtils.d.ts +0 -21
- package/esm/component/widget-board/widgetBoardLayoutUtils.js +0 -113
- package/esm/component/widget-board/widgetBoardLayoutUtils.js.map +0 -1
- package/esm/exports/cloudscape.d.ts +0 -5
- package/esm/exports/cloudscape.js +0 -6
- package/esm/exports/cloudscape.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,25 +10,450 @@
|
|
|
10
10
|
Установите `pne-ui` вместе с peer-зависимостями:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
yarn add pne-ui @emotion/react@^11 @emotion/styled@^11 @mui/material@^
|
|
13
|
+
yarn add pne-ui @emotion/react@^11 @emotion/styled@^11 @mui/material@^9.0.1 @mui/system@^9.0.1 @mui/x-date-pickers-pro@^9 @mui/icons-material@^9.0.1 i18next@^23 react@^19 react-dom@^19 react-i18next@^11
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
`pne-ui` требует React 19 и MUI 9.0.1 или новее в пределах major 9. React 18, MUI 9.0.0 и предыдущие
|
|
17
|
+
major-версии MUI не входят в поддерживаемый peer contract.
|
|
18
18
|
|
|
19
19
|
Необходимые peer-зависимости и минимальные версии:
|
|
20
20
|
|
|
21
21
|
- `@emotion/react@^11`
|
|
22
22
|
- `@emotion/styled@^11`
|
|
23
|
-
- `@mui/material
|
|
24
|
-
- `@mui/system
|
|
25
|
-
- `@mui/x-date-pickers-pro@^
|
|
26
|
-
- `@mui/icons-material
|
|
23
|
+
- `@mui/material@>=9.0.1 <10`
|
|
24
|
+
- `@mui/system@>=9.0.1 <10`
|
|
25
|
+
- `@mui/x-date-pickers-pro@^9`
|
|
26
|
+
- `@mui/icons-material@>=9.0.1 <10`
|
|
27
27
|
- `i18next@^23`
|
|
28
|
-
- `react@^
|
|
29
|
-
- `react-dom@^
|
|
28
|
+
- `react@^19`
|
|
29
|
+
- `react-dom@^19`
|
|
30
30
|
- `react-i18next@^11`
|
|
31
31
|
|
|
32
|
+
## PneBreadcrumbs
|
|
33
|
+
|
|
34
|
+
`PneBreadcrumbs` — общий визуальный компонент хлебных крошек для host-приложения и микрофронтов. Он не
|
|
35
|
+
зависит от роутера, i18next, меню или permissions: consumer передаёт уже локализованные `label`, формирует
|
|
36
|
+
доступные ему элементы и при необходимости подключает bridge-aware ссылку через `linkComponent`.
|
|
37
|
+
Такой link adapter должен принимать `href`, передавать `className` и прочие DOM props и через `forwardRef`
|
|
38
|
+
возвращать ref фактического `<a>` — это нужно для клавиатурного фокуса в overflow-меню.
|
|
39
|
+
|
|
40
|
+
Элементы имеют стабильный `id` и один из трёх взаимоисключающих типов: `link` с `href`, `action` с `onClick`
|
|
41
|
+
или неинтерактивный `text`. Последний `text` автоматически получает `aria-current="page"`. При нехватке места
|
|
42
|
+
середина цепочки сворачивается в доступное меню, а `ResizeObserver` следит только за собственным контейнером
|
|
43
|
+
компонента. Для корректного измерения родитель должен разрешать сжатие через `min-width: 0`.
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<PneBreadcrumbs
|
|
47
|
+
ariaLabel={t("navigation.breadcrumbs")}
|
|
48
|
+
moreLabel={t("navigation.more")}
|
|
49
|
+
linkComponent={PneLink}
|
|
50
|
+
items={[
|
|
51
|
+
{
|
|
52
|
+
id: "orders",
|
|
53
|
+
label: t("main.nav.orders"),
|
|
54
|
+
icon: <PneOrdersIcon/>,
|
|
55
|
+
type: "text",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "orders-search",
|
|
59
|
+
label: t("sidebar.menu.orders"),
|
|
60
|
+
href: "/paynet-ui/react-orders",
|
|
61
|
+
type: "link",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: `order-${orderId}`,
|
|
65
|
+
label: `${t("orders.order.history.order")} ${orderId}`,
|
|
66
|
+
type: "text",
|
|
67
|
+
},
|
|
68
|
+
]}
|
|
69
|
+
/>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## PneButton
|
|
73
|
+
|
|
74
|
+
`pneStyle` — единственный публичный способ выбрать PNE-вариант кнопки. Низкоуровневые MUI props `variant` и
|
|
75
|
+
`color` намеренно исключены из TypeScript API, чтобы они не конфликтовали с design-system preset.
|
|
76
|
+
|
|
77
|
+
| `pneStyle` | Эквивалент прежнего MUI API |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `contained` или prop не задан | `variant="contained" color="primary"` |
|
|
80
|
+
| `outlined` | `variant="outlined" color="primary"` |
|
|
81
|
+
| `error` | `variant="outlined" color="error"` |
|
|
82
|
+
| `text` | `variant="text" color="primary"` |
|
|
83
|
+
| `neutral` | `variant="contained" color="pneNeutral"` |
|
|
84
|
+
| `neutralText` | `variant="text" color="pneNeutral"` |
|
|
85
|
+
| `primaryLight` | `variant="contained" color="pnePrimaryLight"` |
|
|
86
|
+
| `warning` | `variant="contained" color="pneWarningLight"` |
|
|
87
|
+
| `white` | `variant="contained" color="pneWhite"` |
|
|
88
|
+
|
|
89
|
+
Компонент сохраняет polymorphic MUI-контракт для `component` и `href`; типы DOM props, событий и `ref`
|
|
90
|
+
выводятся из фактического root element. Это поведение рассчитано на React 19 ref-as-prop.
|
|
91
|
+
|
|
92
|
+
`PneButtonGroup` удалён из публичного API. Для группировки используйте `ButtonGroup` напрямую из
|
|
93
|
+
`@mui/material`; расстояние между независимыми действиями задавайте на layout-контейнере.
|
|
94
|
+
|
|
95
|
+
## PneField
|
|
96
|
+
|
|
97
|
+
`PneField` задаёт общий семантический контракт для одного поля: label, helper text, error/disabled/required state и
|
|
98
|
+
их ARIA-связи с единственным логическим control или control group. `PneTextField`, `PneSelect`,
|
|
99
|
+
`PneAutocomplete`, `PneAsyncAutocomplete`, `PneCheckbox` и `PneSwitch` читают этот контракт автоматически.
|
|
100
|
+
Внутри `PneField` должен быть ровно один логический control; для группы передавайте один group component, а не
|
|
101
|
+
несколько соседних controls. `PneField` не принимает ID произвольной layout-обёртки за ID самого control.
|
|
102
|
+
|
|
103
|
+
`id` принадлежит root `FormControl` и служит namespace для сгенерированных ID. `controlId` принадлежит самому
|
|
104
|
+
интерактивному control и используется в `label[for]`; эти ID должны различаться. Указанный на child `id` не
|
|
105
|
+
переопределяет field-owned ID, поэтому при миграции переносите его в `controlId`. Prop `htmlFor` оставлен только
|
|
106
|
+
как deprecated alias `controlId` и не должен использоваться в новом коде. ID обрезаются по краям; пустые ID и
|
|
107
|
+
ID с внутренними пробельными символами считаются невалидными, игнорируются и заменяются сгенерированными.
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<PneField
|
|
111
|
+
id="delivery-field"
|
|
112
|
+
controlId="delivery-control"
|
|
113
|
+
label="Delivery server"
|
|
114
|
+
helperText="Select one server"
|
|
115
|
+
slotProps={{
|
|
116
|
+
label: {id: "delivery-label", "data-autotest": "delivery-label"},
|
|
117
|
+
helperText: {id: "delivery-help", "data-autotest": "delivery-help"},
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
<PneSelect options={servers} value={server} onChange={setServer}/>
|
|
121
|
+
</PneField>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Для произвольного control используйте render prop и передайте результат `getControlProps` на фактический
|
|
125
|
+
focusable control или group root. Adapter сохраняет дополнительные props, объединяет consumer
|
|
126
|
+
`aria-labelledby`/`aria-describedby` с ID label/helper text и дедуплицирует ссылки. Явный `aria-label`
|
|
127
|
+
остаётся самостоятельным naming override и не смешивается с `aria-labelledby`. При disabled field adapter
|
|
128
|
+
возвращает одновременно `disabled` и `aria-disabled`; это сохраняет нативную/MUI блокировку и корректно
|
|
129
|
+
описывает composite control с group-role.
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
<PneField label="Period" helperText="Choose a unit" error={Boolean(error)} required>
|
|
133
|
+
{({getControlProps, fullWidth}) => (
|
|
134
|
+
<ToggleButtonGroup
|
|
135
|
+
{...getControlProps({"aria-describedby": "period-format"})}
|
|
136
|
+
exclusive
|
|
137
|
+
sx={{width: fullWidth ? "100%" : "auto"}}
|
|
138
|
+
value={period}
|
|
139
|
+
onChange={(_event, value) => setPeriod(value)}
|
|
140
|
+
>
|
|
141
|
+
<ToggleButton value="day">Day</ToggleButton>
|
|
142
|
+
<ToggleButton value="week">Week</ToggleButton>
|
|
143
|
+
</ToggleButtonGroup>
|
|
144
|
+
)}
|
|
145
|
+
</PneField>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Если adapter нужен внутри отдельного descendant component, вызовите `usePneFieldControl()` там; вне
|
|
149
|
+
`PneField` hook возвращает `undefined`. Render prop предпочтительнее для прямой композиции, потому что явно
|
|
150
|
+
показывает место применения DOM-контракта.
|
|
151
|
+
|
|
152
|
+
`PneField` владеет ID и связями label/helper text. Значения `true` у field-level `disabled`, `error` и
|
|
153
|
+
`required` нельзя ослабить props дочернего control; его дополнительные ARIA ID при этом не теряются. Явный
|
|
154
|
+
`fullWidth` у встроенного PNE control может переопределить field default. `required` на `PneField` добавляет
|
|
155
|
+
asterisk и `aria-required`, но намеренно не устанавливает нативный `required`: browser constraint validation
|
|
156
|
+
включается только `required` на самом input/select/checkbox/switch.
|
|
157
|
+
|
|
158
|
+
`slotProps.label` и `slotProps.helperText` предназначены для `id`, `className`, `sx`, `ref`, ARIA и `data-*`
|
|
159
|
+
соответствующих slots. Старые `labelSx` и `helperTextSx` deprecated. Split-state props MUI FormControl
|
|
160
|
+
(`color`, `focused`, `hiddenLabel`, `size`, `variant`) не входят в публичный API `PneField`; внешний вид control
|
|
161
|
+
настраивается на самом control, а label/helper — через `slotProps`. Root остаётся polymorphic через `component`,
|
|
162
|
+
и тип `ref` выводится из выбранного root element. `margin` остаётся исключительно layout-prop root
|
|
163
|
+
`FormControl` и не передаётся дочернему control.
|
|
164
|
+
|
|
165
|
+
## PneTextField
|
|
166
|
+
|
|
167
|
+
`PneTextField` сохраняет API MUI `TextField` и по умолчанию использует `size="small"`. Его `ref` указывает на
|
|
168
|
+
root `HTMLDivElement`; в text/multiline-режимах для focus, selection и интеграции с form-библиотеками передавайте
|
|
169
|
+
`inputRef`, который получает нативный `input` или `textarea`. В режиме `select` и при custom input slots семантика
|
|
170
|
+
`inputRef` остаётся контрактом MUI. В text/multiline-режимах нативные атрибуты (`maxLength`, `min`, `inputMode`) и
|
|
171
|
+
привязанные к input test/ARIA anchors передавайте через object или functional `slotProps.htmlInput`; для
|
|
172
|
+
интерактивного combobox в режиме `select` используйте `slotProps.select.SelectDisplayProps`. Обычные `data-*`
|
|
173
|
+
props самого `PneTextField` остаются на root. Компонент сохраняет результат slot callback и объединяет consumer
|
|
174
|
+
`aria-describedby` со связью собственного или внешнего helper text.
|
|
175
|
+
|
|
176
|
+
В композиции с `PneField` текстовое поле получает control ID, `disabled`, `error`, `fullWidth`, helper-связь и
|
|
177
|
+
`aria-required`. `required` внешнего `PneField` намеренно не включает нативный атрибут `required`: если нужна
|
|
178
|
+
browser constraint validation, передайте `required` непосредственно в `PneTextField`.
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
const { ref, ...field } = controllerField
|
|
182
|
+
|
|
183
|
+
<PneField label="Customer reference" required helperText={error?.message}>
|
|
184
|
+
<PneTextField
|
|
185
|
+
{...field}
|
|
186
|
+
inputRef={ref}
|
|
187
|
+
slotProps={{htmlInput: {maxLength: 64}}}
|
|
188
|
+
/>
|
|
189
|
+
</PneField>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## PneCheckbox, PneSwitch и PneLabeledCheckbox
|
|
193
|
+
|
|
194
|
+
`PneCheckbox` и `PneSwitch` сохраняют MUI-контракт `checked` / `defaultChecked` / `onChange`, а также нативные
|
|
195
|
+
`name`, `value`, `required` и `disabled`. Основной `ref` указывает на фактический root `HTMLSpanElement`; для
|
|
196
|
+
focus, form-библиотек и доступа к нативным свойствам используйте `inputRef: Ref<HTMLInputElement>`. Верхнеуровневые
|
|
197
|
+
`aria-*` применяются к нативному input, а `data-*`, включая существующие `data-autotest`, остаются на root.
|
|
198
|
+
Object и functional `slotProps.input` сохраняются и объединяются с обоими refs и управляемой семантикой.
|
|
199
|
+
Это же объединение применяется к `MuiCheckbox` / `MuiSwitch` theme `defaultProps`, включая их input slots.
|
|
200
|
+
|
|
201
|
+
`PneSwitch` всегда сохраняет `role="switch"`. `PneCheckbox indeterminate` синхронизирует одновременно
|
|
202
|
+
`input.indeterminate` и mixed accessibility state. `readOnly` у обоих компонентов действительно блокирует
|
|
203
|
+
pointer, label и keyboard activation, но не делает input disabled: он остаётся focusable и участвует в
|
|
204
|
+
`FormData`; состояние также объявляется через `aria-readonly`.
|
|
205
|
+
|
|
206
|
+
Если `PneSwitch.onChange` возвращает Promise/thenable, компонент автоматически включает optimistic lifecycle
|
|
207
|
+
без отдельного `pending` prop: сразу показывает запрошенное состояние, помечает input через `aria-busy` и
|
|
208
|
+
`aria-disabled`, показывает progress-индикатор и игнорирует повторную активацию до settlement. При reject
|
|
209
|
+
переключатель откатывается, при resolve сохраняет подтверждённое состояние. Синхронные callbacks работают как
|
|
210
|
+
раньше. Для controlled usage возвращаемый Promise должен завершаться после обновления внешнего `checked`;
|
|
211
|
+
для `defaultChecked` commit и rollback полностью принадлежат самому `PneSwitch`. Нативный input во время
|
|
212
|
+
запроса не становится `disabled`, поэтому не теряет focus и сохраняет текущее ON/OFF-состояние.
|
|
213
|
+
|
|
214
|
+
Внешний `PneField` передаёт control ID, label/helper-связь, `disabled`, `error` и `aria-required`. Как и у
|
|
215
|
+
`PneTextField`, `required` на `PneField` не включает browser constraint validation; для неё задайте `required`
|
|
216
|
+
самому checkbox или switch. `PneLabeledCheckbox` добавляет локальные `label`, `helperText` и `error`, генерирует
|
|
217
|
+
ID helper text, сохраняет явный `helperTextProps.id` и объединяет все `aria-describedby`.
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
<PneField label="Notifications" helperText={error?.message} error={Boolean(error)} required>
|
|
221
|
+
<PneSwitch
|
|
222
|
+
checked={enabled}
|
|
223
|
+
inputRef={controllerRef}
|
|
224
|
+
name="notifications"
|
|
225
|
+
onChange={(_event, checked) => updateNotifications(checked)
|
|
226
|
+
.then(() => setEnabled(checked))}
|
|
227
|
+
/>
|
|
228
|
+
</PneField>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## PneTableSwitchCell
|
|
232
|
+
|
|
233
|
+
Для status-колонки `PneTable` используйте `PneTableSwitchCell`: он размещает `PneSwitch size="small"` в
|
|
234
|
+
компактной ячейке шириной `40px` без vertical padding и не передаёт click в интерактивную строку. Один из
|
|
235
|
+
`aria-label` / `aria-labelledby` обязателен. Интерактивному варианту нужен `onChange(checked, event)`;
|
|
236
|
+
display-only вариант задаётся через `readOnly` без пустого callback. Возвращённый из табличного `onChange`
|
|
237
|
+
Promise передаётся в `PneSwitch`, поэтому optimistic/pending/rollback lifecycle работает в status-колонке без
|
|
238
|
+
дополнительных props ячейки.
|
|
239
|
+
|
|
240
|
+
Props самой ячейки передаются напрямую, а props переключателя — через `switchProps`. В частности, `id`,
|
|
241
|
+
`inputRef`, `name`, `slotProps` и существующие верхнеуровневые `PneSwitch` `data-*` селекторы относятся к
|
|
242
|
+
`switchProps`; селектор сохраняется на том же Switch DOM anchor, что и при прямом использовании `PneSwitch`,
|
|
243
|
+
но это не обязательно внешний wrapper. Размер, controlled state и accessible name принадлежат
|
|
244
|
+
`PneTableSwitchCell`. `autoTestId` создаёт отдельный locator на нативном input и имеет приоритет над одноимённым
|
|
245
|
+
атрибутом в `switchProps.slotProps.input`, не удаляя верхнеуровневый `PneSwitch` locator из `switchProps`.
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
<PneTableSwitchCell
|
|
249
|
+
aria-label="Enable endpoint"
|
|
250
|
+
checked={enabled}
|
|
251
|
+
onChange={setEnabled}
|
|
252
|
+
switchProps={{
|
|
253
|
+
inputRef: controllerRef,
|
|
254
|
+
name: "enabled",
|
|
255
|
+
"data-autotest": "endpoint-status",
|
|
256
|
+
}}
|
|
257
|
+
/>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## PneModal и PneModalActions
|
|
261
|
+
|
|
262
|
+
`PneModal` владеет структурой dialog, focus trap и ARIA-связями. Передайте видимый `title`; для модалок без
|
|
263
|
+
визуального заголовка используйте `ariaLabel`. Если компонент внутри `title` сам возвращает `null`, передайте
|
|
264
|
+
`title={null}` и `ariaLabel` явно: содержимое произвольного React-компонента нельзя определить до его рендера.
|
|
265
|
+
`title` и `subtitle` принимают `ReactNode`. `ref` указывает на
|
|
266
|
+
`HTMLDivElement` с `role="dialog"`. Структурные `role`, `aria-modal`, `aria-labelledby` и `aria-describedby`
|
|
267
|
+
нельзя переопределить через container slot; дополнительное описание подключается через `ariaDescribedBy`.
|
|
268
|
+
|
|
269
|
+
`onClose(event, reason)` различает `closeButtonClick`, `escapeKeyDown` и `backdropClick`. Существующие callbacks
|
|
270
|
+
без аргументов остаются совместимыми. `closeLabel` необязателен и по умолчанию равен `Close`; передавайте перевод
|
|
271
|
+
только там, где он доступен consumer-у. `hideCloseButton` скрывает icon button без дополнительных обязательных
|
|
272
|
+
props.
|
|
273
|
+
|
|
274
|
+
```tsx
|
|
275
|
+
<PneModal
|
|
276
|
+
actions={<PneModalActions
|
|
277
|
+
secondary={<PneButton pneStyle="outlined">Cancel</PneButton>}
|
|
278
|
+
primary={<PneButton>Save</PneButton>}
|
|
279
|
+
/>}
|
|
280
|
+
closeLabel="Close"
|
|
281
|
+
onClose={(_event, reason) => {
|
|
282
|
+
if (reason !== "backdropClick") setOpen(false)
|
|
283
|
+
}}
|
|
284
|
+
open={open}
|
|
285
|
+
title={<span>Edit account</span>}
|
|
286
|
+
slotProps={{
|
|
287
|
+
container: {"data-autotest": "account-dialog"},
|
|
288
|
+
title: {component: "h2"},
|
|
289
|
+
}}
|
|
290
|
+
>
|
|
291
|
+
Account form
|
|
292
|
+
</PneModal>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
`blockingOverlay` предназначен для loading-состояния всей модалки. Пока slot присутствует, dialog получает
|
|
296
|
+
`aria-busy`, header/body/footer становятся inert, focus остаётся на границе dialog, а Escape, backdrop и close
|
|
297
|
+
button не вызывают `onClose`. После снятия overlay прежний focused control восстанавливается, если он всё ещё
|
|
298
|
+
существует. Старый `overlay` оставлен как deprecated alias.
|
|
299
|
+
|
|
300
|
+
Внутренние части настраиваются через `slotProps`, но их element type, owned content и dialog semantics остаются
|
|
301
|
+
фиксированными. `modalProps` содержит только безопасные настройки MUI root и не позволяет подменять root/backdrop
|
|
302
|
+
slots. Прежние `containerProps` и `closeButtonProps` оставлены deprecated на период миграции.
|
|
303
|
+
|
|
304
|
+
Частые тестовые маркеры `data-*` передаются прямо в `PneModal` и попадают на семантический dialog container:
|
|
305
|
+
`<PneModal data-testattribute="edit-modal" ... />`. Для них не требуется обёртка `slotProps.container`;
|
|
306
|
+
этот slot остаётся для остальных безопасных атрибутов и `sx` контейнера.
|
|
307
|
+
|
|
308
|
+
`PneModalActions` сохраняет одни и те же keyed action nodes, но синхронизирует DOM/focus order с layout:
|
|
309
|
+
`leading → secondary → primary` на desktop и `primary → secondary → leading` на экране до 480 px. При смене
|
|
310
|
+
breakpoint существующие controls только перемещаются внутри дерева, не перемонтируются и не теряют focus/state.
|
|
311
|
+
Root фиксирован как `div`, поддерживает `ref`, `sx`, обычные HTML/ARIA/data attributes.
|
|
312
|
+
|
|
313
|
+
## PneSelect
|
|
314
|
+
|
|
315
|
+
`PneSelect` — controlled single-select для произвольного типа option. `value` имеет тип `T | null`, а `onChange`
|
|
316
|
+
получает выбранный `T`. Для строк и чисел key и label выводятся автоматически; объектам нужны явные
|
|
317
|
+
`getOptionKey` и `getOptionLabel`. Все option callbacks получают исходный объект, поэтому дополнительные поля не
|
|
318
|
+
нужно переносить во вспомогательную форму `{value, label}`.
|
|
319
|
+
|
|
320
|
+
`getOptionLabel` всегда возвращает plain `string`: он служит также accessible name для option. Rich JSX
|
|
321
|
+
передавайте отдельно через `renderOption`, сохраняя в `getOptionLabel` текстовый эквивалент.
|
|
322
|
+
|
|
323
|
+
Для HOC сначала зафиксируйте generic явным публичным props-типом: стандартный `ComponentProps<typeof PneSelect>`
|
|
324
|
+
не может представить сразу primitive и object overloads без потери точности.
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
const RegionSelect = (props: PneSelectObjectProps<Region, string>) => <PneSelect {...props}/>
|
|
328
|
+
const MemoRegionSelect = memo(RegionSelect)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
type Region = {
|
|
333
|
+
code: string
|
|
334
|
+
disabled: boolean
|
|
335
|
+
title: string
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const [region, setRegion] = useState<Region | null>(null)
|
|
339
|
+
|
|
340
|
+
<PneSelect
|
|
341
|
+
options={regions}
|
|
342
|
+
value={region}
|
|
343
|
+
onChange={setRegion}
|
|
344
|
+
getOptionKey={option => option.code}
|
|
345
|
+
getOptionLabel={option => option.title}
|
|
346
|
+
getOptionDisabled={option => option.disabled}
|
|
347
|
+
getOptionProps={option => ({'data-region': option.code})}
|
|
348
|
+
placeholder="Please select"
|
|
349
|
+
/>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Компонент намеренно не публикует MUI-режимы `native`, `multiple`, `defaultValue`, custom input и input/slot escape
|
|
353
|
+
hatches: его контракт controlled, single и non-native. `ref` указывает на корневой `HTMLDivElement` внутреннего
|
|
354
|
+
MUI Select; `sx` и `fullWidth` применяются к внешнему FormControl. Для композиции
|
|
355
|
+
label/helper/error/required/fullWidth оборачивайте select в `PneField`.
|
|
356
|
+
`SelectDisplayProps` и `MenuProps` сохраняют styling/data/ARIA-настройки, но не позволяют заменить управляемые
|
|
357
|
+
combobox/listbox roles, keyboard/pointer handlers, identity или open/close lifecycle.
|
|
358
|
+
`getOptionProps` предназначен для неинтерактивных DOM-метаданных, ARIA, styling и `data-*`; содержимое option
|
|
359
|
+
задавайте через `renderOption`, disabled-состояние — через `getOptionDisabled`, а выбор обрабатывайте в `onChange`.
|
|
360
|
+
|
|
361
|
+
`null` обозначает только пустое состояние и не может входить в `options`; `undefined` также не является option.
|
|
362
|
+
Ключи сериализуются в строки, поэтому после сериализации они должны быть уникальны; например, `1` и `"1"`
|
|
363
|
+
конфликтуют. Пустая строка зарезервирована для `null`. Если key текущего `value` отсутствует в `options`, select
|
|
364
|
+
показывает empty/placeholder state без MUI `out-of-range` warning и снова отображает значение после появления
|
|
365
|
+
совпадающей option.
|
|
366
|
+
|
|
367
|
+
При миграции object options передавайте в `value` сам выбранный объект или `null`, а не замаскированный через cast
|
|
368
|
+
numeric/string ID. `getOptionLabel`, `getOptionProps`, `getOptionDisabled`, `renderOption` и `renderValue` теперь
|
|
369
|
+
работают с исходным `T`, а не с нормализованным `{value, label}`.
|
|
370
|
+
|
|
371
|
+
## PneAutocomplete
|
|
372
|
+
|
|
373
|
+
`PneAutocomplete` сохраняет MUI-контракт single/multiple, `disableClearable` и `freeSolo`, но не ограничивает
|
|
374
|
+
данные Paynet DTO. Для строк, чисел и структур `{id, displayName}` / `{choiceId, displayName}` key, label и
|
|
375
|
+
сравнение выводятся автоматически. `id` и `choiceId` могут быть строками или числами; восстановленный из API
|
|
376
|
+
объект считается выбранным по key, а не по ссылке. Значения разных форм (например, freeSolo-строка и объект)
|
|
377
|
+
всегда считаются различными и не приводят к исключению.
|
|
378
|
+
|
|
379
|
+
Для произвольного объекта обязательны `getOptionKey` и `getOptionLabel`. Явный key также становится default
|
|
380
|
+
правилом сравнения, если caller не передал `isOptionEqualToValue`:
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
type Region = {code: string; title: string; disabled: boolean}
|
|
384
|
+
|
|
385
|
+
<PneAutocomplete
|
|
386
|
+
options={regions}
|
|
387
|
+
value={selectedRegion}
|
|
388
|
+
onChange={(_event, value) => setSelectedRegion(value)}
|
|
389
|
+
getOptionKey={region => region.code}
|
|
390
|
+
getOptionLabel={region => region.title}
|
|
391
|
+
getOptionDisabled={region => region.disabled}
|
|
392
|
+
label="Region"
|
|
393
|
+
/>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Обычный `ref` указывает на фиксированный root `HTMLDivElement`, `inputRef` — на нативный `HTMLInputElement`.
|
|
397
|
+
`htmlInputProps` принимает только безопасные native metadata: `data-*`, name/ARIA и ограниченный набор
|
|
398
|
+
текстовых input-атрибутов. Lifecycle handlers, `value`, `id`, `role`, `disabled`, `readOnly` и другие управляемые
|
|
399
|
+
свойства задаются через API Autocomplete. Имя input автоматически переносится на portal listbox; это работает
|
|
400
|
+
для собственного `label`, внешнего `PneField`, `aria-label` и `aria-labelledby`.
|
|
401
|
+
|
|
402
|
+
## PneAsyncAutocomplete
|
|
403
|
+
|
|
404
|
+
`PneAsyncAutocomplete` владеет remote options, loading и отключением локальной MUI-фильтрации. Loader получает
|
|
405
|
+
plain query и контекст запроса:
|
|
406
|
+
|
|
407
|
+
```tsx
|
|
408
|
+
<PneAsyncAutocomplete
|
|
409
|
+
value={merchant}
|
|
410
|
+
onChange={(_event, value) => setMerchant(value)}
|
|
411
|
+
loadOptions={(query, {signal}) => api.searchMerchants({query, signal})}
|
|
412
|
+
reloadKey={manager?.id}
|
|
413
|
+
minQueryLength={2}
|
|
414
|
+
onLoadError={(error, {query, reason}) => reportAutocompleteError(error, query, reason)}
|
|
415
|
+
label="Merchant"
|
|
416
|
+
/>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
```ts
|
|
420
|
+
type PneLoadOptions<T> = (
|
|
421
|
+
query: string,
|
|
422
|
+
context: {
|
|
423
|
+
signal: AbortSignal
|
|
424
|
+
reason: 'open' | 'input' | 'clear' | 'reload'
|
|
425
|
+
},
|
|
426
|
+
) => Promise<readonly T[]>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Новый запрос отменяет предыдущий через `AbortSignal` и дополнительно защищён request ID на случай, если loader
|
|
430
|
+
игнорирует signal. Закрытие и unmount также отменяют активный запрос. Sync throw и rejected Promise переходят в
|
|
431
|
+
одно error-состояние; `AbortError` не вызывает `onLoadError`. `loadErrorText`, `minQueryLengthText`, MUI
|
|
432
|
+
`loadingText` и `noOptionsText` разделяют error/min-query/loading/empty состояния и объявляются assistive
|
|
433
|
+
technology. `keepPreviousOptions` по умолчанию выключен.
|
|
434
|
+
|
|
435
|
+
`open` и `inputValue` поддерживают controlled и uncontrolled режимы с исходными MUI callbacks/reasons.
|
|
436
|
+
Изменение identity `loadOptions` не перезапускает открытый поиск: для реальной зависимости результата от
|
|
437
|
+
manager/status/currency передавайте стабильный primitive `reloadKey`.
|
|
438
|
+
|
|
439
|
+
Компонент намеренно не делает debounce и вызывает loader сразу для `open`, пользовательского `input`, `clear`
|
|
440
|
+
и изменения `reloadKey`. Если сервисный метод уже обёрнут React/service debounce-декоратором, дополнительного
|
|
441
|
+
слоя в компоненте нет и конфликтовать с ним нечему.
|
|
442
|
+
|
|
443
|
+
Breaking migration со старого API выполняется напрямую:
|
|
444
|
+
|
|
445
|
+
```tsx
|
|
446
|
+
// было
|
|
447
|
+
<PneAsyncAutocomplete searchChoices={({searchString}) => search(searchString ?? '')}/>
|
|
448
|
+
|
|
449
|
+
// стало
|
|
450
|
+
<PneAsyncAutocomplete loadOptions={query => search(query)}/>
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
`searchChoices` и `onSearchError` удалены; используйте `loadOptions` и `onLoadError`. Props `options`, `loading`
|
|
454
|
+
и `filterOptions` также не входят в async API, потому что ими владеет компонент. Debounce в эту миграцию не
|
|
455
|
+
входит.
|
|
456
|
+
|
|
32
457
|
## Якоря для автотестов
|
|
33
458
|
|
|
34
459
|
Для нового кода добавляйте якорь непосредственно на существующий DOM-элемент или нужный MUI slot через
|
|
@@ -96,6 +521,152 @@ DOM-позиции или пользовательских/секретных д
|
|
|
96
521
|
- пустой результат: существующая строка `data-autotest="empty-state"`;
|
|
97
522
|
- disabled/checked/selected состояния: только нативные DOM/ARIA-свойства, без test-only копий.
|
|
98
523
|
|
|
524
|
+
#### Выбор строк
|
|
525
|
+
|
|
526
|
+
`useTableSelection` хранит выбор в одной из двух взаимоисключающих форм:
|
|
527
|
+
|
|
528
|
+
- `explicit` — явно выбранные стабильные ID;
|
|
529
|
+
- `allMatching` — все selectable-строки текущей применённой выдачи, кроме `excludedIds`.
|
|
530
|
+
|
|
531
|
+
Header checkbox управляет только загруженной страницей. Выбор всей выдачи является отдельным действием:
|
|
532
|
+
consumer получает точное число selectable-результатов от своего API и передаёт его в
|
|
533
|
+
`selectAllMatching(matchingCount)`. `matchingCount`, `excludedIds`, `isRowSelectable` и backend query обязаны
|
|
534
|
+
описывать один и тот же applied-result scope. Сериализацию `Set` и domain request выполняйте только на границе
|
|
535
|
+
приложения.
|
|
536
|
+
|
|
537
|
+
```tsx
|
|
538
|
+
const selection = useTableSelection({
|
|
539
|
+
rows: orders,
|
|
540
|
+
getRowId: order => order.id,
|
|
541
|
+
maxSelected: 20_000,
|
|
542
|
+
scopeKey: appliedSearchFingerprint,
|
|
543
|
+
})
|
|
544
|
+
|
|
545
|
+
<PneTable<Order>
|
|
546
|
+
autoTestId="orders"
|
|
547
|
+
tableAriaLabel="Orders"
|
|
548
|
+
data={orders}
|
|
549
|
+
createTableHeader={() => <PneTableRow>
|
|
550
|
+
<PneTableSelectionHeaderCell
|
|
551
|
+
aria-label="Select current page"
|
|
552
|
+
state={selection.pageState}
|
|
553
|
+
disabled={selection.interactionDisabled || selection.pageSelectableCount === 0}
|
|
554
|
+
onChange={selection.setPageSelected}
|
|
555
|
+
/>
|
|
556
|
+
{/* business headers */}
|
|
557
|
+
</PneTableRow>}
|
|
558
|
+
createRow={order => <PneTableRow
|
|
559
|
+
key={order.id}
|
|
560
|
+
selected={selection.isRowSelected(order)}
|
|
561
|
+
aria-selected={selection.isRowSelected(order)}
|
|
562
|
+
>
|
|
563
|
+
<PneTableSelectionCell
|
|
564
|
+
aria-label={`Select order ${order.id}`}
|
|
565
|
+
checked={selection.isRowSelected(order)}
|
|
566
|
+
disabled={selection.interactionDisabled || !selection.isRowSelectable(order)}
|
|
567
|
+
onChange={checked => selection.setRowSelected(order, checked)}
|
|
568
|
+
/>
|
|
569
|
+
{/* business cells */}
|
|
570
|
+
</PneTableRow>}
|
|
571
|
+
feedback={consumerOwnedLimitWarning}
|
|
572
|
+
toolbar={<PneTableToolbar
|
|
573
|
+
aria-label="Table controls"
|
|
574
|
+
contextual={<PneTableSelectionControls
|
|
575
|
+
summary={`${selection.selectedCount} selected`}
|
|
576
|
+
actions={consumerOwnedBulkActions}
|
|
577
|
+
/>}
|
|
578
|
+
persistent={optionalViewSelector}
|
|
579
|
+
/>}
|
|
580
|
+
/* остальные props */
|
|
581
|
+
/>
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
`maxSelected` отклоняет всю row/page/all-matching операцию атомарно: возвращённый
|
|
585
|
+
`TableSelectionUpdate.limitExceeded` равен `true`, а модель не меняется. Смена primitive `scopeKey` очищает
|
|
586
|
+
выбор; pagination, sort и refresh не должны входить в этот ключ. В controlled-режиме consumer обязан принять
|
|
587
|
+
scope-reset и вернуть canonical empty-модель `{mode: 'explicit', selectedIds: new Set()}`.
|
|
588
|
+
|
|
589
|
+
`PneTableToolbar` объединяет contextual selection controls и persistent View controls в существующей верхней
|
|
590
|
+
полосе таблицы. Он измеряет фактическое содержимое и сохраняет DOM/keyboard-порядок Selection → View →
|
|
591
|
+
Pagination при переходе на несколько строк, включая поддерживаемую ширину viewport 360px.
|
|
592
|
+
|
|
593
|
+
`PneTable.feedback` — отдельный full-width slot над всей верхней полосой. Warning, error и informational alert
|
|
594
|
+
нужно передавать туда, а не внутрь toolbar: feedback не входит в измерения `PneTableToolbar` и пагинации и
|
|
595
|
+
поэтому не меняет их inline/stacked layout даже при переносе текста на несколько строк.
|
|
596
|
+
|
|
597
|
+
#### Выбор строк в SearchUI
|
|
598
|
+
|
|
599
|
+
`SearchUI.tableSelection` добавляет тот же controller к consumer-owned header/row factories и автоматически
|
|
600
|
+
связывает его scope с применёнными критериями поиска. Draft-фильтры manual search, page, page size, sort и
|
|
601
|
+
value-equivalent refresh сохраняют выбор. Новые применённые критерии очищают его. При настроенных Views в scope
|
|
602
|
+
по умолчанию входит фактически выбранный View; `preserveAcrossViews` включайте только для Views с одинаковой
|
|
603
|
+
семантикой строк и совместимыми ID.
|
|
604
|
+
|
|
605
|
+
```tsx
|
|
606
|
+
<SearchUI<Order, OrderViewId, number>
|
|
607
|
+
/* search props */
|
|
608
|
+
tableSelection={{
|
|
609
|
+
selection,
|
|
610
|
+
onSelectionChange: setSelection,
|
|
611
|
+
getRowId: order => order.id,
|
|
612
|
+
maxSelected: knownClientLimit,
|
|
613
|
+
resolveAllMatchingCount: async ({appliedSearchCriteria, viewId}) => {
|
|
614
|
+
const summary = await getSelectionSummary(appliedSearchCriteria, viewId)
|
|
615
|
+
if (summary.limitExceeded) {
|
|
616
|
+
showConsumerOwnedLimitWarning(summary.selectionLimit)
|
|
617
|
+
throw new Error('Selection limit exceeded')
|
|
618
|
+
}
|
|
619
|
+
return summary.matchingCount
|
|
620
|
+
},
|
|
621
|
+
renderControls: ({selection: controller}) => (
|
|
622
|
+
<PneTableSelectionControls
|
|
623
|
+
summary={`${controller.selectedCount} selected`}
|
|
624
|
+
actions={<button
|
|
625
|
+
disabled={controller.interactionDisabled}
|
|
626
|
+
onClick={() => controller.selectAllMatchingResults?.().catch(handleSelectionError)}
|
|
627
|
+
>
|
|
628
|
+
Select all results
|
|
629
|
+
</button>}
|
|
630
|
+
/>
|
|
631
|
+
),
|
|
632
|
+
renderFeedback: ({selection: controller}) => (
|
|
633
|
+
controller.selectingAllMatching ? 'Selecting…' : selectionFeedback
|
|
634
|
+
),
|
|
635
|
+
toolbarAriaLabel: 'Order table controls',
|
|
636
|
+
}}
|
|
637
|
+
createTableHeader={(params, context) => {
|
|
638
|
+
const controller = context?.selection
|
|
639
|
+
if (!controller) throw new Error('Table selection context is required')
|
|
640
|
+
return <>{/* explicit selection cell + headers */}</>
|
|
641
|
+
}}
|
|
642
|
+
createTableRow={(row, index, data, setData, context) => {
|
|
643
|
+
const controller = context?.selection
|
|
644
|
+
if (!controller) throw new Error('Table selection context is required')
|
|
645
|
+
return <>{/* explicit selection cell + business cells */}</>
|
|
646
|
+
}}
|
|
647
|
+
/>
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
Factory context optional только для source compatibility с прежними прямыми вызовами фабрик; сам `SearchUI`
|
|
651
|
+
всегда передаёт context, а `selection` присутствует при настроенном `tableSelection`. Selection-aware consumer
|
|
652
|
+
всё равно должен сделать явный guard/assertion, чтобы его callback оставался корректным вне вызова из `SearchUI`.
|
|
653
|
+
|
|
654
|
+
`resolveAllMatchingCount` получает snapshot применённых критериев и resolved View. На один SearchUI допускается
|
|
655
|
+
один in-flight запрос: повторный вызов возвращает тот же Promise, controller временно блокирует selection, а
|
|
656
|
+
ответ применяется только к той же occurrence scope. Старые ответы после `A → B → A`, unmount, смены
|
|
657
|
+
`maxSelected` или consumer `disabled` игнорируются. Активная ошибка возвращается caller-коду, после чего controller
|
|
658
|
+
снова доступен. Same-scope refresh/pagination/sort не отменяют запрос. Уже начатый запрос детерминированно
|
|
659
|
+
завершается тем resolver, с которым он был запущен: замена callback действует со следующего запроса, а удаление
|
|
660
|
+
resolver отменяет pending work.
|
|
661
|
+
|
|
662
|
+
Если backend возвращает typed summary, consumer должен обработать server `limitExceeded` до возврата count.
|
|
663
|
+
`maxSelected` — синхронный client-side guard, а не замена повторной серверной проверке при batch operation.
|
|
664
|
+
|
|
665
|
+
Selection не записывается в SearchUI retention/profile/browser storage. Uncontrolled selection исчезает при
|
|
666
|
+
remount. В controlled-режиме lifetime принадлежит consumer: если state намеренно расположен выше размонтируемого
|
|
667
|
+
экрана, consumer сам должен очистить его при navigation/remount. Строковое представление applied scope остаётся
|
|
668
|
+
в памяти библиотеки и не выводится в DOM/storage.
|
|
669
|
+
|
|
99
670
|
### SearchUI и SearchUIFilters
|
|
100
671
|
|
|
101
672
|
Передавайте стабильный несекретный `autoTestId` как Selenium scope поискового интерфейса. Если prop не задан,
|
|
@@ -267,6 +838,11 @@ assertEquals("true", enabled.getAttribute("aria-pressed"));
|
|
|
267
838
|
|---|---|---|
|
|
268
839
|
| Верхняя пагинация | `[data-autotest="pagination"][data-autotest-value="top"]` | Native button `disabled`; `current-page` внутри |
|
|
269
840
|
| Нижняя пагинация | `[data-autotest="pagination"][data-autotest-value="bottom"]` | Native button `disabled`; `current-page` внутри |
|
|
841
|
+
| Feedback над таблицей | `[data-autotest="table-feedback"]` | Full-width slot перед верхней полосой; alert/status semantics задаёт consumer |
|
|
842
|
+
| Общая полоса контролов | `[data-autotest="table-control-bar"]` | `data-autotest-value="inline|stacked"` |
|
|
843
|
+
| Выбор текущей страницы | `input[data-autotest="page-selection"]` | Native `checked`, `disabled`, `aria-checked="mixed"` |
|
|
844
|
+
| Выбор строки | `input[data-autotest="row-selection"]` | Native `checked`, `disabled`; consumer может задать `autoTestId`/`autoTestValue` |
|
|
845
|
+
| Selection summary/actions | `[data-autotest="selection-summary"]`, `[data-autotest="selection-actions"]` | Summary является polite live status |
|
|
270
846
|
| Пустой результат | `[data-autotest="empty-state"]` | Наличие существующей empty row |
|
|
271
847
|
| Загрузка | Semantic `table` | `aria-busy="true|false"` |
|
|
272
848
|
| Активная сортировка | `th[aria-sort="ascending"], th[aria-sort="descending"]` | Значение `aria-sort` |
|
|
@@ -812,9 +1388,68 @@ export const App = () => (
|
|
|
812
1388
|
```
|
|
813
1389
|
|
|
814
1390
|
Важные правила интеграции:
|
|
1391
|
+
|
|
815
1392
|
- если `overlayActions.*` вызываются без смонтированного `OverlayHost`, библиотека пишет явный `console.error`, а snackbar не будет виден пользователю;
|
|
816
1393
|
- если в DOM смонтировано больше одного `OverlayHost`, библиотека пишет явный `console.error`, потому что такая конфигурация дублирует snackbar-ы и может рассинхронизировать их таймеры;
|
|
817
1394
|
- `OverlayHost` должен подключаться в приложении-хосте, а не внутри отдельных виджетов библиотеки.
|
|
1395
|
+
- stacks и permanent overlays по умолчанию уходят одним React portal в `document.body`, не добавляя overlay-wrapper в DOM приложения; для изолированного harness можно передать `container` (или `null` для inline render);
|
|
1396
|
+
- `maxSnack` является жёсткой границей: при переполнении самые старые snackbar удаляются, а не остаются скрытой очередью;
|
|
1397
|
+
- для обычного уведомления о завершившемся действии не передавайте `id`: каждый вызов получит собственную внутреннюю
|
|
1398
|
+
identity, поэтому даже одинаковые сообщения будут показаны отдельными элементами стека;
|
|
1399
|
+
- явный `id` нужен только для управляемого lifecycle, когда вызывающий код должен позднее адресно удалить или заменить
|
|
1400
|
+
конкретный snackbar (например, после Undo);
|
|
1401
|
+
- повторный enqueue с тем же явным `id` игнорируется, пока первый snackbar присутствует. Для замены сначала вызовите `removeSnackbar(id)`.
|
|
1402
|
+
|
|
1403
|
+
## PneConfirmProvider
|
|
1404
|
+
|
|
1405
|
+
Компоненты вызывают подтверждение через Promise API `usePneConfirm`. Подключайте
|
|
1406
|
+
`PneConfirmProvider` ровно один раз рядом с корнем приложения и вызывайте исходное действие только после
|
|
1407
|
+
результата `true`:
|
|
1408
|
+
|
|
1409
|
+
```tsx
|
|
1410
|
+
import { PneConfirmProvider, usePneConfirm } from 'pne-ui'
|
|
1411
|
+
|
|
1412
|
+
const DeleteButton = () => {
|
|
1413
|
+
const { confirm } = usePneConfirm()
|
|
1414
|
+
|
|
1415
|
+
const handleDelete = async () => {
|
|
1416
|
+
const accepted = await confirm({
|
|
1417
|
+
danger: true,
|
|
1418
|
+
title: 'Delete item?',
|
|
1419
|
+
message: 'This action cannot be undone.',
|
|
1420
|
+
confirmLabel: 'Delete',
|
|
1421
|
+
})
|
|
1422
|
+
|
|
1423
|
+
if (accepted) {
|
|
1424
|
+
await deleteItem()
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
return <button onClick={handleDelete}>Delete</button>
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
export const App = () => (
|
|
1432
|
+
<PneConfirmProvider>
|
|
1433
|
+
<ApplicationRoutes />
|
|
1434
|
+
</PneConfirmProvider>
|
|
1435
|
+
)
|
|
1436
|
+
```
|
|
1437
|
+
|
|
1438
|
+
`danger: true` задаёт destructive/error оформление primary action. Для dismissible acknowledgement-flow без
|
|
1439
|
+
Cancel используйте `showCancel: false`: Close, Escape и backdrop по-прежнему возвращают `false`. Параллельные
|
|
1440
|
+
вызовы обслуживаются по FIFO; повторное событие от action предыдущего dialog не подтверждает следующий запрос.
|
|
1441
|
+
При размонтировании provider текущий и ожидающие Promise завершаются значением `false`.
|
|
1442
|
+
|
|
1443
|
+
Поддерживаемые Selenium-якоря размещены на существующих интерактивных/смысловых DOM nodes без
|
|
1444
|
+
дополнительных wrapper-элементов:
|
|
1445
|
+
|
|
1446
|
+
| Якорь | Назначение |
|
|
1447
|
+
|-------|------------|
|
|
1448
|
+
| `alert.container` | контейнер confirm modal |
|
|
1449
|
+
| `alert.message` | содержимое сообщения |
|
|
1450
|
+
| `alert.button.close` | кнопка закрытия |
|
|
1451
|
+
| `alert.button.cancel` | cancel action; отсутствует при `showCancel: false` |
|
|
1452
|
+
| `alert.button.submit` | confirm action |
|
|
818
1453
|
|
|
819
1454
|
## Интеграция SearchUI
|
|
820
1455
|
|
|
@@ -1062,123 +1697,6 @@ export const App = () => (
|
|
|
1062
1697
|
тему MUI (тип `ThemeOptions`). Обёрнутые компоненты получают как базовые цвета skin, так и кастомные
|
|
1063
1698
|
color overrides (`pneNeutral`, `pnePrimaryLight`, `pneAccentuated` и др.), объявленные в `src/index.ts`.
|
|
1064
1699
|
|
|
1065
|
-
## WidgetBoard и работа с лейаутами
|
|
1066
|
-
|
|
1067
|
-
`WidgetBoard` — дашборд с драгабл-виджетами и встраиваемой панелью лейаутов. Компонент инкапсулирует состояние:
|
|
1068
|
-
выбор лейаута, CRUD кастомных схем и сохранение/загрузку лежат внутри `WidgetBoard`; снаружи достаточно передать
|
|
1069
|
-
источники данных. Для связи `WidgetBoard` с `WidgetLayoutsPanel`/`WidgetBoardFab` используйте
|
|
1070
|
-
`WidgetBoardScopeProvider` и `useWidgetBoardScopeStore`.
|
|
1071
|
-
|
|
1072
|
-
Основные пропсы:
|
|
1073
|
-
- `widgets`: список `{ id, title, render }` — содержимое виджетов.
|
|
1074
|
-
- `layoutByBreakpoint`: базовый пресет для дефолтного лейаута.
|
|
1075
|
-
- `loadLayouts(): Promise<{ options; selectedId? } | null>`: обязательная функция загрузки пользовательских схем (вызывается при маунте). `WidgetBoard` сам добавляет и блокирует встроенный `default`-лейаут.
|
|
1076
|
-
- `saveLayouts(options, selectedId?)`: обязательная функция сохранения пользовательских схем (вызывается при select/add/delete и автосохранении изменений в выбранном пользовательском лейауте).
|
|
1077
|
-
|
|
1078
|
-
Панель `WidgetLayoutsPanel` — презентационный компонент. Передавайте `items/selectedId/onSelect/onAdd/onDelete`
|
|
1079
|
-
и прочие данные из scoped store (`useWidgetBoardScopeStore`).
|
|
1080
|
-
|
|
1081
|
-
### Структура данных для лейаутов
|
|
1082
|
-
|
|
1083
|
-
`loadLayouts` и `saveLayouts` работают с массивом `WidgetBoardLayoutOption`:
|
|
1084
|
-
|
|
1085
|
-
- `id: string`: уникальный идентификатор лейаута (можно `uuid` или любое значение бэка).
|
|
1086
|
-
- `name: string`: отображаемое имя пресета.
|
|
1087
|
-
- `layoutByBreakpoint: Record<number | string, BreakpointLayoutConfig>`: карта брейкпоинтов (ключ — число или строка, обычно `12`, `1280`, `1600` и т.д.).
|
|
1088
|
-
- `BreakpointLayoutConfig`: `{ widgets: Record<widgetId, WidgetLayoutConfig> }`.
|
|
1089
|
-
- `WidgetLayoutConfig`: `{ defaultSize: { columnSpan; rowSpan; columnOffset? }; limits?; initialState?; heightMode? }`.
|
|
1090
|
-
- `initialState` поддерживает `isHidden` и `isCollapsed`.
|
|
1091
|
-
|
|
1092
|
-
Формат функции `loadLayouts`:
|
|
1093
|
-
|
|
1094
|
-
```ts
|
|
1095
|
-
type LoadLayoutsResult = {
|
|
1096
|
-
options: WidgetBoardLayoutOption[]
|
|
1097
|
-
selectedId?: string // id активного лейаута, если его нет в options — упадет на первый элемент
|
|
1098
|
-
} | null
|
|
1099
|
-
```
|
|
1100
|
-
|
|
1101
|
-
`saveLayouts` получает тот же `options` (уже с последними изменениями) и `selectedId`.
|
|
1102
|
-
|
|
1103
|
-
### Пример использования
|
|
1104
|
-
|
|
1105
|
-
```tsx
|
|
1106
|
-
import React from 'react'
|
|
1107
|
-
import { Box, Stack } from '@mui/material'
|
|
1108
|
-
import {
|
|
1109
|
-
WidgetBoard,
|
|
1110
|
-
WidgetLayoutsPanel,
|
|
1111
|
-
WidgetBoardScopeProvider,
|
|
1112
|
-
useWidgetBoardScopeStore,
|
|
1113
|
-
type WidgetDefinition,
|
|
1114
|
-
type WidgetBoardLayoutOption,
|
|
1115
|
-
} from 'pne-ui'
|
|
1116
|
-
|
|
1117
|
-
const widgets: WidgetDefinition[] = [
|
|
1118
|
-
{ id: 'traffic', title: 'Traffic', render: () => <div>Traffic content</div> },
|
|
1119
|
-
{ id: 'sales', title: 'Sales', render: () => <div>Sales content</div> },
|
|
1120
|
-
]
|
|
1121
|
-
|
|
1122
|
-
const baseLayoutByBreakpoint = {
|
|
1123
|
-
12: {
|
|
1124
|
-
widgets: {
|
|
1125
|
-
traffic: { defaultSize: { columnSpan: 6, rowSpan: 2 } },
|
|
1126
|
-
sales: { defaultSize: { columnSpan: 6, rowSpan: 2 } },
|
|
1127
|
-
},
|
|
1128
|
-
},
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
// Загрузка/сохранение пресетов
|
|
1132
|
-
const loadLayouts = async (): Promise<{ options: WidgetBoardLayoutOption[]; selectedId?: string }> => {
|
|
1133
|
-
const response = await api.getUserLayouts() // верните { options, selectedId }
|
|
1134
|
-
// Если API пустой, вернем пустой набор: WidgetBoard добавит встроенный default сам
|
|
1135
|
-
return response ?? { options: [], selectedId: 'default' }
|
|
1136
|
-
}
|
|
1137
|
-
const saveLayouts = async (options: WidgetBoardLayoutOption[], selectedId?: string) => {
|
|
1138
|
-
await api.saveUserLayouts({ options, selectedId })
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
const DashboardContent = () => {
|
|
1142
|
-
const boardStore = useWidgetBoardScopeStore()
|
|
1143
|
-
const panelProps = boardStore(state => ({
|
|
1144
|
-
items: state.items,
|
|
1145
|
-
selectedId: state.selectedId,
|
|
1146
|
-
onSelect: state.onSelect,
|
|
1147
|
-
onDelete: state.onDelete,
|
|
1148
|
-
onAdd: state.onAdd,
|
|
1149
|
-
addInfo: state.addInfo,
|
|
1150
|
-
lockedIds: state.lockedIds,
|
|
1151
|
-
}))
|
|
1152
|
-
|
|
1153
|
-
return (
|
|
1154
|
-
<Box sx={{ p: 2 }}>
|
|
1155
|
-
<Stack direction={{ xs: 'column', md: 'row' }} spacing={2} alignItems={{ xs: 'stretch', md: 'flex-start' }}>
|
|
1156
|
-
<Box sx={{ minWidth: 260 }}>
|
|
1157
|
-
<WidgetLayoutsPanel {...panelProps} />
|
|
1158
|
-
</Box>
|
|
1159
|
-
<Box sx={{ flex: 1 }}>
|
|
1160
|
-
<WidgetBoard
|
|
1161
|
-
widgets={widgets}
|
|
1162
|
-
layoutByBreakpoint={baseLayoutByBreakpoint}
|
|
1163
|
-
loadLayouts={loadLayouts}
|
|
1164
|
-
saveLayouts={saveLayouts}
|
|
1165
|
-
/>
|
|
1166
|
-
</Box>
|
|
1167
|
-
</Box>
|
|
1168
|
-
</Box>
|
|
1169
|
-
)
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
export const Dashboard = () => (
|
|
1173
|
-
<WidgetBoardScopeProvider>
|
|
1174
|
-
<DashboardContent />
|
|
1175
|
-
</WidgetBoardScopeProvider>
|
|
1176
|
-
)
|
|
1177
|
-
```
|
|
1178
|
-
|
|
1179
|
-
`WidgetBoard` сам обновляет выбранный лейаут, следит за состоянием виджетов и при изменениях дергает `saveLayouts`
|
|
1180
|
-
с актуальным набором опций.
|
|
1181
|
-
|
|
1182
1700
|
## OverlayHost и уведомления
|
|
1183
1701
|
|
|
1184
1702
|
`OverlayHost` рендерит snackbars из `overlayActions` и принимает декларативные постоянные оверлеи через `PermanentOverlay`
|
|
@@ -1216,8 +1734,11 @@ const AppShell = () => (
|
|
|
1216
1734
|
```
|
|
1217
1735
|
|
|
1218
1736
|
- Для уведомлений используйте `overlayActions.showSuccess/showError/showWarning/showInfo`, `showSnackbar` или `showUndoSnackbar`.
|
|
1737
|
+
- `showError` принимает как готовый UI-текст (`{ message }`), так и исходную Paynet/transport ошибку (`{ error }`). Во втором случае библиотека сама разворачивает Paynet v1, Axios/Fetch/Blob payload, переводит `messageId`, показывает `errorId`, `errorI18N` и доступный пользователю `details`.
|
|
1219
1738
|
- `showUndoSnackbar` возвращает `id` snackbar и добавляет встроенную action-кнопку `Undo` (или ваш `undoLabel`).
|
|
1220
1739
|
- Любой snackbar с конечным `autoHideMs` показывает progress bar вверху карточки; если `autoHideMs` не задан, progress bar не рендерится.
|
|
1740
|
+
- По умолчанию UI рендерится portal-ом в `document.body`; `container` позволяет задать другой `Element` или callback (в том числе через `ref.current`). Layer берётся из `theme.zIndex.snackbar`/`theme.zIndex.modal`.
|
|
1741
|
+
- `maxSnack` удаляет самые старые overflow entries. Явный `id` дедуплицирует pending snackbar по правилу first-wins.
|
|
1221
1742
|
- `PermanentOverlay` можно размещать на любом уровне дерева под хостом; последний зарегистрированный в слоте заменяет предыдущий.
|
|
1222
1743
|
- Слоты фиксированы четырьмя углами; сместить позицию можно через `offset`/`zIndex` пропы на `PermanentOverlay`.
|
|
1223
1744
|
|
|
@@ -1241,7 +1762,7 @@ const AppShell = () => (
|
|
|
1241
1762
|
import { PneFloatingActionButtons, overlayActions } from 'pne-ui'
|
|
1242
1763
|
|
|
1243
1764
|
const actions = [
|
|
1244
|
-
{ id: '
|
|
1765
|
+
{ id: 'refresh', label: 'Refresh data', onClick: () => overlayActions.showInfo({ message: 'Refreshed' }) },
|
|
1245
1766
|
{ id: 'save', label: 'Save', onClick: () => overlayActions.showSuccess({ message: 'Saved' }) },
|
|
1246
1767
|
{ id: 'divider', kind: 'divider' as const },
|
|
1247
1768
|
{ id: 'custom', kind: 'content' as const, node: <div style={{ padding: 8 }}>Any JSX here</div> },
|
|
@@ -1251,7 +1772,7 @@ export const FabDemo = () => (
|
|
|
1251
1772
|
<PneFloatingActionButtons
|
|
1252
1773
|
actions={actions}
|
|
1253
1774
|
fabLabel='Actions'
|
|
1254
|
-
bannerText='
|
|
1775
|
+
bannerText='Page actions'
|
|
1255
1776
|
position={{ bottom: 24, right: 24 }}
|
|
1256
1777
|
mobileBreakpoint={900} // считать мобильным до 900px, иначе поведение как на десктопе
|
|
1257
1778
|
/>
|