@plaudit/gutenberg-api-extensions 2.79.0 → 2.80.0
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/dist/blocks/MoveError.js +10 -0
- package/dist/blocks/MoveError.js.map +1 -0
- package/{build → dist}/blocks/PathError.js +7 -3
- package/dist/blocks/PathError.js.map +1 -0
- package/{build → dist}/blocks/SNPFlexibleItemsListComponent.d.ts +1 -1
- package/dist/blocks/SNPFlexibleItemsListComponent.js +18 -0
- package/dist/blocks/SNPFlexibleItemsListComponent.js.map +1 -0
- package/{build → dist}/blocks/SNPGroupComponent.d.ts +2 -2
- package/dist/blocks/SNPGroupComponent.js +20 -0
- package/dist/blocks/SNPGroupComponent.js.map +1 -0
- package/{build → dist}/blocks/SNPListComponent.d.ts +1 -1
- package/dist/blocks/SNPListComponent.js +18 -0
- package/dist/blocks/SNPListComponent.js.map +1 -0
- package/dist/blocks/SNPTreeContext.js +14 -0
- package/dist/blocks/SNPTreeContext.js.map +1 -0
- package/dist/blocks/basic-custom-block-bindings-support.js +157 -0
- package/dist/blocks/basic-custom-block-bindings-support.js.map +1 -0
- package/dist/blocks/common-native-property-constructors.d.ts +13 -0
- package/{build → dist}/blocks/common-native-property-constructors.js +105 -151
- package/dist/blocks/common-native-property-constructors.js.map +1 -0
- package/{build → dist}/blocks/conditions.js +12 -7
- package/dist/blocks/conditions.js.map +1 -0
- package/dist/blocks/csnp-api.d.ts +166 -0
- package/dist/blocks/csnp-api.js +74 -0
- package/dist/blocks/csnp-api.js.map +1 -0
- package/{build → dist}/blocks/data-controller-manager.js +4 -1
- package/dist/blocks/data-controller-manager.js.map +1 -0
- package/{build → dist}/blocks/data-controller.js +74 -70
- package/dist/blocks/data-controller.js.map +1 -0
- package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/select.js +14 -11
- package/dist/blocks/hooks/built-in-suspendable-option-protocols/select.js.map +1 -0
- package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/settings.js +9 -6
- package/dist/blocks/hooks/built-in-suspendable-option-protocols/settings.js.map +1 -0
- package/{build → dist}/blocks/hooks/useSuspendableOptions.d.ts +1 -1
- package/{build → dist}/blocks/hooks/useSuspendableOptions.js +30 -23
- package/dist/blocks/hooks/useSuspendableOptions.js.map +1 -0
- package/dist/blocks/index.js +35 -0
- package/dist/blocks/index.js.map +1 -0
- package/{build → dist}/blocks/layered-styles-api.d.ts +2 -2
- package/{build → dist}/blocks/layered-styles-api.js +10 -6
- package/dist/blocks/layered-styles-api.js.map +1 -0
- package/{build → dist}/blocks/layered-styles-impl.js +14 -9
- package/dist/blocks/layered-styles-impl.js.map +1 -0
- package/{build → dist}/blocks/layout/LaidOutProperty.d.ts +1 -2
- package/dist/blocks/layout/LaidOutProperty.js +47 -0
- package/dist/blocks/layout/LaidOutProperty.js.map +1 -0
- package/dist/blocks/layout/LaidOutPropertyRow.js +15 -0
- package/dist/blocks/layout/LaidOutPropertyRow.js.map +1 -0
- package/{build → dist}/blocks/layout/NodeContext.d.ts +2 -2
- package/dist/blocks/layout/NodeContext.js +44 -0
- package/dist/blocks/layout/NodeContext.js.map +1 -0
- package/dist/blocks/layout/PanelRoot.js +29 -0
- package/dist/blocks/layout/PanelRoot.js.map +1 -0
- package/{build → dist}/blocks/layout/TabsRoot.js +16 -13
- package/dist/blocks/layout/TabsRoot.js.map +1 -0
- package/dist/blocks/layout/ToolsPanelContext.js +23 -0
- package/dist/blocks/layout/ToolsPanelContext.js.map +1 -0
- package/dist/blocks/shared-exportable-types.js +3 -0
- package/dist/blocks/shared-internal-types.js +3 -0
- package/{build → dist}/blocks/simple-block.d.ts +1 -1
- package/dist/blocks/simple-block.js +45 -0
- package/dist/blocks/simple-block.js.map +1 -0
- package/{build → dist}/blocks/simple-native-property-api.d.ts +1 -1
- package/{build → dist}/blocks/simple-native-property-api.js +16 -10
- package/dist/blocks/simple-native-property-api.js.map +1 -0
- package/{build → dist}/blocks/simple-native-property-impl.js +60 -55
- package/dist/blocks/simple-native-property-impl.js.map +1 -0
- package/{build → dist}/blocks/simple-native-property-internal-shared.js +6 -2
- package/dist/blocks/simple-native-property-internal-shared.js.map +1 -0
- package/{build → dist}/blocks/snp-api.d.ts +1 -0
- package/dist/blocks/snp-api.js +7 -0
- package/dist/blocks/snp-api.js.map +1 -0
- package/{build → dist}/blocks/snp-data-store.js +8 -4
- package/dist/blocks/snp-data-store.js.map +1 -0
- package/{build → dist}/blocks/utilities.d.ts +1 -1
- package/dist/blocks/utilities.js +79 -0
- package/dist/blocks/utilities.js.map +1 -0
- package/{build → dist}/controls/AsynchronousFormTokenField.d.ts +1 -1
- package/dist/controls/AsynchronousFormTokenField.js +36 -0
- package/dist/controls/AsynchronousFormTokenField.js.map +1 -0
- package/{build → dist}/controls/BaseSortableItemsControl.d.ts +3 -3
- package/dist/controls/BaseSortableItemsControl.js +25 -0
- package/dist/controls/BaseSortableItemsControl.js.map +1 -0
- package/{build → dist}/controls/ExtendedFormTokenField.d.ts +3 -3
- package/dist/controls/ExtendedFormTokenField.js +64 -0
- package/dist/controls/ExtendedFormTokenField.js.map +1 -0
- package/dist/controls/ExtendedPostPicker.js +28 -0
- package/dist/controls/ExtendedPostPicker.js.map +1 -0
- package/dist/controls/ExtendedRadioControl.d.ts +12 -0
- package/dist/controls/ExtendedRadioControl.js +33 -0
- package/dist/controls/ExtendedRadioControl.js.map +1 -0
- package/{build → dist}/controls/ExtendedTaxonomyPicker.d.ts +1 -1
- package/dist/controls/ExtendedTaxonomyPicker.js +71 -0
- package/dist/controls/ExtendedTaxonomyPicker.js.map +1 -0
- package/{build → dist}/controls/ExtendedTermPicker.d.ts +1 -1
- package/dist/controls/ExtendedTermPicker.js +33 -0
- package/dist/controls/ExtendedTermPicker.js.map +1 -0
- package/dist/controls/ExtendedTextareaControl.d.ts +12 -0
- package/{build → dist}/controls/ExtendedTextareaControl.js +15 -12
- package/dist/controls/ExtendedTextareaControl.js.map +1 -0
- package/dist/controls/ExtendedUserPicker.js +28 -0
- package/dist/controls/ExtendedUserPicker.js.map +1 -0
- package/{build → dist}/controls/FullSizeToggleControl.d.ts +6 -4
- package/dist/controls/FullSizeToggleControl.js +110 -0
- package/dist/controls/FullSizeToggleControl.js.map +1 -0
- package/{build → dist}/controls/ImageControl.d.ts +1 -1
- package/dist/controls/ImageControl.js +81 -0
- package/dist/controls/ImageControl.js.map +1 -0
- package/{build → dist}/controls/InspectorPanel.d.ts +4 -3
- package/dist/controls/InspectorPanel.js +29 -0
- package/dist/controls/InspectorPanel.js.map +1 -0
- package/{build → dist}/controls/LazySuggestionsComboboxControl.d.ts +5 -1
- package/dist/controls/LazySuggestionsComboboxControl.js +32 -0
- package/dist/controls/LazySuggestionsComboboxControl.js.map +1 -0
- package/{build → dist}/controls/MultiSelectControl.d.ts +1 -1
- package/dist/controls/MultiSelectControl.js +33 -0
- package/dist/controls/MultiSelectControl.js.map +1 -0
- package/{build → dist}/controls/PickOne.d.ts +1 -1
- package/dist/controls/PickOne.js +54 -0
- package/dist/controls/PickOne.js.map +1 -0
- package/{build → dist}/controls/PromisableComponent.d.ts +2 -2
- package/{build → dist}/controls/PromisableComponent.js +14 -11
- package/dist/controls/PromisableComponent.js.map +1 -0
- package/{build → dist}/controls/ProperLinkControl.d.ts +1 -1
- package/dist/controls/ProperLinkControl.js +59 -0
- package/dist/controls/ProperLinkControl.js.map +1 -0
- package/dist/controls/SimpleToggle.js +11 -0
- package/dist/controls/SimpleToggle.js.map +1 -0
- package/dist/controls/SortableFlexibleItemsControl.js +18 -0
- package/dist/controls/SortableFlexibleItemsControl.js.map +1 -0
- package/dist/controls/SortableItemsControl.js +15 -0
- package/dist/controls/SortableItemsControl.js.map +1 -0
- package/{build → dist}/controls/basicNumericallyIdedItemPicker.d.ts +1 -1
- package/dist/controls/basicNumericallyIdedItemPicker.js +37 -0
- package/dist/controls/basicNumericallyIdedItemPicker.js.map +1 -0
- package/{build → dist}/controls/hooks/useImprovedTokenManager.d.ts +7 -5
- package/{build → dist}/controls/hooks/useImprovedTokenManager.js +21 -15
- package/dist/controls/hooks/useImprovedTokenManager.js.map +1 -0
- package/{build → dist}/controls/hooks/useMultiSingleConversionLayer.d.ts +1 -1
- package/dist/controls/hooks/useMultiSingleConversionLayer.js +14 -0
- package/dist/controls/hooks/useMultiSingleConversionLayer.js.map +1 -0
- package/dist/controls/hooks/useNonRenderingCounter.js +9 -0
- package/dist/controls/hooks/useNonRenderingCounter.js.map +1 -0
- package/{build → dist}/controls/hooks/useOutputMemoizingFilter.js +7 -4
- package/dist/controls/hooks/useOutputMemoizingFilter.js.map +1 -0
- package/{build → dist}/controls/hooks/useSortableItemsModel.js +14 -11
- package/dist/controls/hooks/useSortableItemsModel.js.map +1 -0
- package/{build → dist}/controls/hooks/useSuggestions.js +16 -13
- package/dist/controls/hooks/useSuggestions.js.map +1 -0
- package/{build → dist}/controls/hooks/useTokenManager.d.ts +5 -3
- package/{build → dist}/controls/hooks/useTokenManager.js +37 -34
- package/dist/controls/hooks/useTokenManager.js.map +1 -0
- package/dist/controls/index.js +41 -0
- package/dist/controls/index.js.map +1 -0
- package/{build → dist}/controls/shared.js +18 -8
- package/dist/controls/shared.js.map +1 -0
- package/dist/controls/types.js +3 -0
- package/dist/editor/post-featured-image.js +125 -0
- package/dist/editor/post-featured-image.js.map +1 -0
- package/dist/editor/simple-gutenberg-endpoints-api.js +26 -0
- package/dist/editor/simple-gutenberg-endpoints-api.js.map +1 -0
- package/{build → dist}/editor/simple-gutenberg-endpoints-impl.js +24 -17
- package/dist/editor/simple-gutenberg-endpoints-impl.js.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js +27 -0
- package/dist/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js.map +1 -0
- package/{build → dist}/lib/gutenberg-api-extensions-state/general-logic.js +12 -8
- package/dist/lib/gutenberg-api-extensions-state/general-logic.js.map +1 -0
- package/{build → dist}/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js +10 -6
- package/dist/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js.map +1 -0
- package/{build → dist}/lib/gutenberg-api-extensions-state/snp-logic.js +33 -26
- package/dist/lib/gutenberg-api-extensions-state/snp-logic.js.map +1 -0
- package/{build → dist}/lib/gutenberg-api-extensions-state.d.ts +2 -2
- package/dist/lib/gutenberg-api-extensions-state.js +52 -0
- package/dist/lib/gutenberg-api-extensions-state.js.map +1 -0
- package/{build → dist}/lib/helpers.d.ts +3 -3
- package/{build → dist}/lib/helpers.js +13 -6
- package/dist/lib/helpers.js.map +1 -0
- package/dist/lib/plaudit-icons/column-1.js +6 -0
- package/dist/lib/plaudit-icons/column-1.js.map +1 -0
- package/dist/lib/plaudit-icons/column-2.js +6 -0
- package/dist/lib/plaudit-icons/column-2.js.map +1 -0
- package/dist/lib/plaudit-icons/column-3.js +6 -0
- package/dist/lib/plaudit-icons/column-3.js.map +1 -0
- package/dist/lib/plaudit-icons/placement-center.js +6 -0
- package/dist/lib/plaudit-icons/placement-center.js.map +1 -0
- package/dist/lib/plaudit-icons/placement-end.js +6 -0
- package/dist/lib/plaudit-icons/placement-end.js.map +1 -0
- package/dist/lib/plaudit-icons/placement-start.js +6 -0
- package/dist/lib/plaudit-icons/placement-start.js.map +1 -0
- package/dist/lib/plaudit-icons/placement-stretch.js +6 -0
- package/dist/lib/plaudit-icons/placement-stretch.js.map +1 -0
- package/dist/lib/plaudit-icons/plaudit-icon.js +6 -0
- package/dist/lib/plaudit-icons/plaudit-icon.js.map +1 -0
- package/dist/lib/plaudit-icons/reusable-block-marker.js +6 -0
- package/{build → dist}/lib/plaudit-icons/reusable-block-marker.js.map +1 -1
- package/dist/lib/plaudit-icons.js +29 -0
- package/dist/lib/plaudit-icons.js.map +1 -0
- package/{build → dist}/lib/suspense/promise-handlers.js +16 -7
- package/dist/lib/suspense/promise-handlers.js.map +1 -0
- package/{build → dist}/lib/suspense.d.ts +2 -2
- package/dist/lib/suspense.js +31 -0
- package/dist/lib/suspense.js.map +1 -0
- package/{build → dist}/lib/useful-types.d.ts +4 -1
- package/dist/lib/useful-types.js +11 -0
- package/dist/lib/useful-types.js.map +1 -0
- package/package.json +22 -30
- package/src/blocks/MoveError.ts +7 -0
- package/src/blocks/PathError.ts +18 -0
- package/src/blocks/SNPFlexibleItemsListComponent.tsx +30 -0
- package/src/blocks/SNPGroupComponent.tsx +38 -0
- package/src/blocks/SNPListComponent.tsx +25 -0
- package/src/blocks/SNPTreeContext.tsx +13 -0
- package/src/blocks/basic-custom-block-bindings-support.tsx +243 -0
- package/src/blocks/common-native-property-constructors.tsx +877 -0
- package/src/blocks/conditions.ts +260 -0
- package/src/blocks/csnp-api.ts +214 -0
- package/src/blocks/data-controller-manager.ts +50 -0
- package/src/blocks/data-controller.ts +736 -0
- package/src/blocks/hooks/built-in-suspendable-option-protocols/select.ts +51 -0
- package/src/blocks/hooks/built-in-suspendable-option-protocols/settings.ts +70 -0
- package/src/blocks/hooks/useSuspendableOptions.ts +123 -0
- package/src/blocks/index.ts +20 -0
- package/src/blocks/layered-styles-api.ts +142 -0
- package/src/blocks/layered-styles-impl.ts +94 -0
- package/src/blocks/layout/LaidOutProperty.tsx +72 -0
- package/src/blocks/layout/LaidOutPropertyRow.tsx +22 -0
- package/src/blocks/layout/NodeContext.tsx +54 -0
- package/src/blocks/layout/PanelRoot.tsx +33 -0
- package/src/blocks/layout/TabsRoot.tsx +56 -0
- package/src/blocks/layout/ToolsPanelContext.tsx +22 -0
- package/src/blocks/shared-exportable-types.ts +6 -0
- package/src/blocks/shared-internal-types.ts +18 -0
- package/src/blocks/simple-block.tsx +74 -0
- package/src/blocks/simple-native-property-api.ts +170 -0
- package/src/blocks/simple-native-property-impl.tsx +329 -0
- package/src/blocks/simple-native-property-internal-shared.ts +46 -0
- package/src/blocks/snp-api.ts +5 -0
- package/src/blocks/snp-data-store.ts +66 -0
- package/src/blocks/utilities.ts +80 -0
- package/src/controls/AsynchronousFormTokenField.tsx +85 -0
- package/src/controls/BaseSortableItemsControl.tsx +84 -0
- package/src/controls/ExtendedFormTokenField.tsx +121 -0
- package/src/controls/ExtendedPostPicker.ts +57 -0
- package/src/controls/ExtendedRadioControl.tsx +107 -0
- package/src/controls/ExtendedTaxonomyPicker.tsx +100 -0
- package/src/controls/ExtendedTermPicker.tsx +62 -0
- package/src/controls/ExtendedTextareaControl.tsx +65 -0
- package/src/controls/ExtendedUserPicker.ts +56 -0
- package/src/controls/FullSizeToggleControl.tsx +94 -0
- package/src/controls/ImageControl.tsx +143 -0
- package/src/controls/InspectorPanel.tsx +37 -0
- package/src/controls/LazySuggestionsComboboxControl.tsx +62 -0
- package/src/controls/MultiSelectControl.tsx +59 -0
- package/src/controls/PickOne.tsx +84 -0
- package/src/controls/PromisableComponent.tsx +56 -0
- package/src/controls/ProperLinkControl.tsx +93 -0
- package/src/controls/SimpleToggle.tsx +9 -0
- package/src/controls/SortableFlexibleItemsControl.tsx +35 -0
- package/src/controls/SortableItemsControl.tsx +18 -0
- package/src/controls/basicNumericallyIdedItemPicker.tsx +76 -0
- package/src/controls/hooks/useImprovedTokenManager.ts +157 -0
- package/src/controls/hooks/useMultiSingleConversionLayer.ts +17 -0
- package/src/controls/hooks/useNonRenderingCounter.ts +6 -0
- package/src/controls/hooks/useOutputMemoizingFilter.ts +16 -0
- package/src/controls/hooks/useSortableItemsModel.ts +196 -0
- package/src/controls/hooks/useSuggestions.ts +91 -0
- package/src/controls/hooks/useTokenManager.ts +177 -0
- package/{build/controls/index.js → src/controls/index.ts} +3 -2
- package/src/controls/shared.ts +50 -0
- package/src/controls/types.ts +18 -0
- package/src/editor/post-featured-image.tsx +161 -0
- package/src/editor/simple-gutenberg-endpoints-api.ts +31 -0
- package/src/editor/simple-gutenberg-endpoints-impl.ts +119 -0
- package/src/index.ts +32 -0
- package/src/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.ts +34 -0
- package/src/lib/gutenberg-api-extensions-state/general-logic.ts +41 -0
- package/src/lib/gutenberg-api-extensions-state/layered-block-styles-logic.ts +42 -0
- package/src/lib/gutenberg-api-extensions-state/snp-logic.ts +240 -0
- package/src/lib/gutenberg-api-extensions-state.ts +69 -0
- package/src/lib/helpers.ts +114 -0
- package/src/lib/plaudit-icons/column-1.tsx +6 -0
- package/src/lib/plaudit-icons/column-2.tsx +6 -0
- package/src/lib/plaudit-icons/column-3.tsx +6 -0
- package/src/lib/plaudit-icons/placement-center.tsx +3 -0
- package/src/lib/plaudit-icons/placement-end.tsx +3 -0
- package/src/lib/plaudit-icons/placement-start.tsx +3 -0
- package/src/lib/plaudit-icons/placement-stretch.tsx +3 -0
- package/src/lib/plaudit-icons/plaudit-icon.tsx +4 -0
- package/src/lib/plaudit-icons/reusable-block-marker.tsx +3 -0
- package/{build/lib/plaudit-icons.js → src/lib/plaudit-icons.ts} +1 -1
- package/src/lib/suspense/promise-handlers.ts +72 -0
- package/src/lib/suspense.tsx +18 -0
- package/src/lib/useful-types.ts +65 -0
- package/build/blocks/MoveError.js +0 -6
- package/build/blocks/MoveError.js.map +0 -1
- package/build/blocks/PathError.js.map +0 -1
- package/build/blocks/SNPFlexibleItemsListComponent.js +0 -15
- package/build/blocks/SNPFlexibleItemsListComponent.js.map +0 -1
- package/build/blocks/SNPGroupComponent.js +0 -17
- package/build/blocks/SNPGroupComponent.js.map +0 -1
- package/build/blocks/SNPListComponent.js +0 -15
- package/build/blocks/SNPListComponent.js.map +0 -1
- package/build/blocks/SNPTreeContext.js +0 -10
- package/build/blocks/SNPTreeContext.js.map +0 -1
- package/build/blocks/basic-custom-block-bindings-support.js +0 -150
- package/build/blocks/basic-custom-block-bindings-support.js.map +0 -1
- package/build/blocks/common-native-property-constructors.d.ts +0 -208
- package/build/blocks/common-native-property-constructors.js.map +0 -1
- package/build/blocks/conditions.js.map +0 -1
- package/build/blocks/data-controller-manager.js.map +0 -1
- package/build/blocks/data-controller.js.map +0 -1
- package/build/blocks/hooks/built-in-suspendable-option-protocols/select.js.map +0 -1
- package/build/blocks/hooks/built-in-suspendable-option-protocols/settings.js.map +0 -1
- package/build/blocks/hooks/useSuspendableOptions.js.map +0 -1
- package/build/blocks/index.js +0 -15
- package/build/blocks/index.js.map +0 -1
- package/build/blocks/layered-styles-api.js.map +0 -1
- package/build/blocks/layered-styles-impl.js.map +0 -1
- package/build/blocks/layout/LaidOutProperty.js +0 -44
- package/build/blocks/layout/LaidOutProperty.js.map +0 -1
- package/build/blocks/layout/LaidOutPropertyRow.js +0 -12
- package/build/blocks/layout/LaidOutPropertyRow.js.map +0 -1
- package/build/blocks/layout/NodeContext.js +0 -37
- package/build/blocks/layout/NodeContext.js.map +0 -1
- package/build/blocks/layout/PanelRoot.js +0 -26
- package/build/blocks/layout/PanelRoot.js.map +0 -1
- package/build/blocks/layout/TabsRoot.js.map +0 -1
- package/build/blocks/layout/ToolsPanelContext.js +0 -18
- package/build/blocks/layout/ToolsPanelContext.js.map +0 -1
- package/build/blocks/shared-exportable-types.js +0 -2
- package/build/blocks/shared-internal-types.js +0 -2
- package/build/blocks/simple-block.js +0 -41
- package/build/blocks/simple-block.js.map +0 -1
- package/build/blocks/simple-native-property-api.js.map +0 -1
- package/build/blocks/simple-native-property-impl.js.map +0 -1
- package/build/blocks/simple-native-property-internal-shared.js.map +0 -1
- package/build/blocks/snp-api.js +0 -2
- package/build/blocks/snp-api.js.map +0 -1
- package/build/blocks/snp-data-store.js.map +0 -1
- package/build/blocks/utilities.js +0 -67
- package/build/blocks/utilities.js.map +0 -1
- package/build/controls/AsynchronousFormTokenField.js +0 -32
- package/build/controls/AsynchronousFormTokenField.js.map +0 -1
- package/build/controls/BaseSortableItemsControl.js +0 -22
- package/build/controls/BaseSortableItemsControl.js.map +0 -1
- package/build/controls/ExtendedFormTokenField.js +0 -58
- package/build/controls/ExtendedFormTokenField.js.map +0 -1
- package/build/controls/ExtendedPostPicker.js +0 -22
- package/build/controls/ExtendedPostPicker.js.map +0 -1
- package/build/controls/ExtendedRadioControl.d.ts +0 -10
- package/build/controls/ExtendedRadioControl.js +0 -30
- package/build/controls/ExtendedRadioControl.js.map +0 -1
- package/build/controls/ExtendedTaxonomyPicker.js +0 -68
- package/build/controls/ExtendedTaxonomyPicker.js.map +0 -1
- package/build/controls/ExtendedTermPicker.js +0 -27
- package/build/controls/ExtendedTermPicker.js.map +0 -1
- package/build/controls/ExtendedTextareaControl.d.ts +0 -14
- package/build/controls/ExtendedTextareaControl.js.map +0 -1
- package/build/controls/ExtendedUserPicker.js +0 -22
- package/build/controls/ExtendedUserPicker.js.map +0 -1
- package/build/controls/FullSizeToggleControl.js +0 -70
- package/build/controls/FullSizeToggleControl.js.map +0 -1
- package/build/controls/ImageControl.js +0 -76
- package/build/controls/ImageControl.js.map +0 -1
- package/build/controls/InspectorPanel.js +0 -26
- package/build/controls/InspectorPanel.js.map +0 -1
- package/build/controls/LazySuggestionsComboboxControl.js +0 -29
- package/build/controls/LazySuggestionsComboboxControl.js.map +0 -1
- package/build/controls/MultiSelectControl.js +0 -30
- package/build/controls/MultiSelectControl.js.map +0 -1
- package/build/controls/PickOne.js +0 -48
- package/build/controls/PickOne.js.map +0 -1
- package/build/controls/PromisableComponent.js.map +0 -1
- package/build/controls/ProperLinkControl.js +0 -56
- package/build/controls/ProperLinkControl.js.map +0 -1
- package/build/controls/SimpleToggle.js +0 -8
- package/build/controls/SimpleToggle.js.map +0 -1
- package/build/controls/SortableFlexibleItemsControl.js +0 -15
- package/build/controls/SortableFlexibleItemsControl.js.map +0 -1
- package/build/controls/SortableItemsControl.js +0 -12
- package/build/controls/SortableItemsControl.js.map +0 -1
- package/build/controls/basicNumericallyIdedItemPicker.js +0 -34
- package/build/controls/basicNumericallyIdedItemPicker.js.map +0 -1
- package/build/controls/hooks/useImprovedTokenManager.js.map +0 -1
- package/build/controls/hooks/useMultiSingleConversionLayer.js +0 -11
- package/build/controls/hooks/useMultiSingleConversionLayer.js.map +0 -1
- package/build/controls/hooks/useNonRenderingCounter.js +0 -6
- package/build/controls/hooks/useNonRenderingCounter.js.map +0 -1
- package/build/controls/hooks/useOutputMemoizingFilter.js.map +0 -1
- package/build/controls/hooks/useSortableItemsModel.js.map +0 -1
- package/build/controls/hooks/useSuggestions.js.map +0 -1
- package/build/controls/hooks/useTokenManager.js.map +0 -1
- package/build/controls/index.js.map +0 -1
- package/build/controls/shared.js.map +0 -1
- package/build/controls/types.js +0 -2
- package/build/editor/post-featured-image.js +0 -122
- package/build/editor/post-featured-image.js.map +0 -1
- package/build/editor/simple-gutenberg-endpoints-api.js +0 -22
- package/build/editor/simple-gutenberg-endpoints-api.js.map +0 -1
- package/build/editor/simple-gutenberg-endpoints-impl.js.map +0 -1
- package/build/index.js +0 -22
- package/build/index.js.map +0 -1
- package/build/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js +0 -23
- package/build/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js.map +0 -1
- package/build/lib/gutenberg-api-extensions-state/general-logic.js.map +0 -1
- package/build/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js.map +0 -1
- package/build/lib/gutenberg-api-extensions-state/snp-logic.js.map +0 -1
- package/build/lib/gutenberg-api-extensions-state.js +0 -48
- package/build/lib/gutenberg-api-extensions-state.js.map +0 -1
- package/build/lib/helpers.js.map +0 -1
- package/build/lib/plaudit-icons/column-1.js +0 -3
- package/build/lib/plaudit-icons/column-1.js.map +0 -1
- package/build/lib/plaudit-icons/column-2.js +0 -3
- package/build/lib/plaudit-icons/column-2.js.map +0 -1
- package/build/lib/plaudit-icons/column-3.js +0 -3
- package/build/lib/plaudit-icons/column-3.js.map +0 -1
- package/build/lib/plaudit-icons/placement-center.js +0 -3
- package/build/lib/plaudit-icons/placement-center.js.map +0 -1
- package/build/lib/plaudit-icons/placement-end.js +0 -3
- package/build/lib/plaudit-icons/placement-end.js.map +0 -1
- package/build/lib/plaudit-icons/placement-start.js +0 -3
- package/build/lib/plaudit-icons/placement-start.js.map +0 -1
- package/build/lib/plaudit-icons/placement-stretch.js +0 -3
- package/build/lib/plaudit-icons/placement-stretch.js.map +0 -1
- package/build/lib/plaudit-icons/plaudit-icon.js +0 -3
- package/build/lib/plaudit-icons/plaudit-icon.js.map +0 -1
- package/build/lib/plaudit-icons/reusable-block-marker.js +0 -3
- package/build/lib/plaudit-icons.js.map +0 -1
- package/build/lib/suspense/promise-handlers.js.map +0 -1
- package/build/lib/suspense.js +0 -14
- package/build/lib/suspense.js.map +0 -1
- package/build/lib/useful-types.js +0 -7
- package/build/lib/useful-types.js.map +0 -1
- /package/{build → dist}/blocks/MoveError.d.ts +0 -0
- /package/{build → dist}/blocks/PathError.d.ts +0 -0
- /package/{build → dist}/blocks/SNPTreeContext.d.ts +0 -0
- /package/{build → dist}/blocks/basic-custom-block-bindings-support.d.ts +0 -0
- /package/{build → dist}/blocks/conditions.d.ts +0 -0
- /package/{build → dist}/blocks/data-controller-manager.d.ts +0 -0
- /package/{build → dist}/blocks/data-controller.d.ts +0 -0
- /package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/select.d.ts +0 -0
- /package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/settings.d.ts +0 -0
- /package/{build → dist}/blocks/index.d.ts +0 -0
- /package/{build → dist}/blocks/layered-styles-impl.d.ts +0 -0
- /package/{build → dist}/blocks/layout/LaidOutPropertyRow.d.ts +0 -0
- /package/{build → dist}/blocks/layout/PanelRoot.d.ts +0 -0
- /package/{build → dist}/blocks/layout/TabsRoot.d.ts +0 -0
- /package/{build → dist}/blocks/layout/ToolsPanelContext.d.ts +0 -0
- /package/{build → dist}/blocks/shared-exportable-types.d.ts +0 -0
- /package/{build → dist}/blocks/shared-exportable-types.js.map +0 -0
- /package/{build → dist}/blocks/shared-internal-types.d.ts +0 -0
- /package/{build → dist}/blocks/shared-internal-types.js.map +0 -0
- /package/{build → dist}/blocks/simple-native-property-impl.d.ts +0 -0
- /package/{build → dist}/blocks/simple-native-property-internal-shared.d.ts +0 -0
- /package/{build → dist}/blocks/snp-data-store.d.ts +0 -0
- /package/{build → dist}/controls/ExtendedPostPicker.d.ts +0 -0
- /package/{build → dist}/controls/ExtendedUserPicker.d.ts +0 -0
- /package/{build → dist}/controls/SimpleToggle.d.ts +0 -0
- /package/{build → dist}/controls/SortableFlexibleItemsControl.d.ts +0 -0
- /package/{build → dist}/controls/SortableItemsControl.d.ts +0 -0
- /package/{build → dist}/controls/hooks/useNonRenderingCounter.d.ts +0 -0
- /package/{build → dist}/controls/hooks/useOutputMemoizingFilter.d.ts +0 -0
- /package/{build → dist}/controls/hooks/useSortableItemsModel.d.ts +0 -0
- /package/{build → dist}/controls/hooks/useSuggestions.d.ts +0 -0
- /package/{build → dist}/controls/index.d.ts +0 -0
- /package/{build → dist}/controls/shared.d.ts +0 -0
- /package/{build → dist}/controls/types.d.ts +0 -0
- /package/{build → dist}/controls/types.js.map +0 -0
- /package/{build → dist}/editor/post-featured-image.d.ts +0 -0
- /package/{build → dist}/editor/simple-gutenberg-endpoints-api.d.ts +0 -0
- /package/{build → dist}/editor/simple-gutenberg-endpoints-impl.d.ts +0 -0
- /package/{build → dist}/index.d.ts +0 -0
- /package/{build → dist}/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.d.ts +0 -0
- /package/{build → dist}/lib/gutenberg-api-extensions-state/general-logic.d.ts +0 -0
- /package/{build → dist}/lib/gutenberg-api-extensions-state/layered-block-styles-logic.d.ts +0 -0
- /package/{build → dist}/lib/gutenberg-api-extensions-state/snp-logic.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/column-1.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/column-2.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/column-3.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/placement-center.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/placement-end.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/placement-start.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/placement-stretch.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/plaudit-icon.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons/reusable-block-marker.d.ts +0 -0
- /package/{build → dist}/lib/plaudit-icons.d.ts +0 -0
- /package/{build → dist}/lib/suspense/promise-handlers.d.ts +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {BaseControl, Button, useBaseControlProps} from "@wordpress/components";
|
|
2
|
+
import {useCallback} from "@wordpress/element";
|
|
3
|
+
import {dragHandle, Icon} from "@wordpress/icons";
|
|
4
|
+
|
|
5
|
+
import {ProvidedSlot} from "../blocks";
|
|
6
|
+
|
|
7
|
+
import {Reorder, useDragControls} from "framer-motion";
|
|
8
|
+
import type {ReactNode} from "react";
|
|
9
|
+
import {IndexedItemActionsMaker, KeyedValue, useSortableItemsModel} from "./hooks/useSortableItemsModel";
|
|
10
|
+
|
|
11
|
+
export type BaseSortableItemsControlProps<D> = Omit<Parameters<typeof useBaseControlProps>[0], 'children'|'id'>&{
|
|
12
|
+
id?: string,
|
|
13
|
+
value: D[]|undefined,
|
|
14
|
+
onAdd?: (index: number, value: D) => void,
|
|
15
|
+
onChange?: (value: D[]) => void,
|
|
16
|
+
onRemove?: (index: number) => void,
|
|
17
|
+
onReorder?: (oldIndex: number, newIndex: number) => void,
|
|
18
|
+
children: (datum: D, onDatumChange: (datum: D) => void, index: number) => ReactNode,
|
|
19
|
+
buttonsArea: (props: {addHandler: (added: D, index?: number) => void, disabled: boolean}) => ReactNode,
|
|
20
|
+
min?: number,
|
|
21
|
+
max?: number,
|
|
22
|
+
emptyValue?: D,
|
|
23
|
+
Label?: ProvidedSlot, Messages?: ProvidedSlot
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export function BaseSortableItemsControl<D>({
|
|
27
|
+
value, onChange, onRemove, onReorder, onAdd, children: makeChild, min, max, label, Label, Messages, buttonsArea, emptyValue, ...wrapperProps
|
|
28
|
+
}: BaseSortableItemsControlProps<D>) {
|
|
29
|
+
const {add: addHandler, commit, makeIndexedItemActions, keyedValues} = useSortableItemsModel({onAdd, onChange, onRemove, onReorder, emptyValue, value});
|
|
30
|
+
|
|
31
|
+
const listLength = value?.length ?? 0;
|
|
32
|
+
const addDisabled = max !== undefined && listLength >= max;
|
|
33
|
+
const removeDisabled = min !== undefined && listLength <= min;
|
|
34
|
+
const {baseControlProps, controlProps} = useBaseControlProps({...wrapperProps, label: Label ? <Label /> : label});
|
|
35
|
+
|
|
36
|
+
return <BaseControl {...baseControlProps}>
|
|
37
|
+
<div {...controlProps} className="plaudit-sortable-items-container">
|
|
38
|
+
<Reorder.Group
|
|
39
|
+
axis="y" onReorder={commit} values={keyedValues}
|
|
40
|
+
children={keyedValues.map((datum, index) => <SortableItemsListNode
|
|
41
|
+
addDisabled={addDisabled} datum={datum} index={index} key={datum.key} listLength={listLength}
|
|
42
|
+
makeChild={makeChild} makeIndexedItemActions={makeIndexedItemActions} removeDisabled={removeDisabled}
|
|
43
|
+
/>)}
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
46
|
+
{buttonsArea({addHandler, disabled: addDisabled})}
|
|
47
|
+
{Messages && <Messages />}
|
|
48
|
+
</BaseControl>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type SortableItemsListNodeProps<D> = {
|
|
52
|
+
addDisabled: boolean, datum: KeyedValue<D>, index: number, listLength: number,
|
|
53
|
+
makeChild: BaseSortableItemsControlProps<D>['children'], removeDisabled: boolean,
|
|
54
|
+
makeIndexedItemActions: IndexedItemActionsMaker<D>
|
|
55
|
+
};
|
|
56
|
+
function SortableItemsListNode<D>({datum, index, listLength, makeChild, makeIndexedItemActions, removeDisabled}: SortableItemsListNodeProps<D>) {
|
|
57
|
+
const {remove, moveUp, moveDown, change} = makeIndexedItemActions(index, datum.key);
|
|
58
|
+
//TODO: If used, implement addBefore and addAfter the same way as moveUp and moveDown
|
|
59
|
+
|
|
60
|
+
const dragControls = useDragControls();
|
|
61
|
+
const dragStartHandler = useCallback((event: React.PointerEvent) => dragControls.start(event), [dragControls]);
|
|
62
|
+
|
|
63
|
+
return <Reorder.Item className="plaudit-sortable-items-row" data-index={index} dragListener={false} dragControls={dragControls} layout="position" value={datum}>
|
|
64
|
+
<div className="plaudit-sortable-items-ordering-controls">
|
|
65
|
+
<div className="plaudit-sortable-items-ordering-control">
|
|
66
|
+
<Icon icon={dragHandle} onPointerDown={dragStartHandler} />
|
|
67
|
+
</div>
|
|
68
|
+
<div className="plaudit-sortable-items-ordering-control">
|
|
69
|
+
<Button icon="arrow-up" aria-label="Move Up" disabled={index < 1} onClick={moveUp} />
|
|
70
|
+
<Button icon="arrow-down" aria-label="Move Down" disabled={index >= listLength - 1} onClick={moveDown} />
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div className="plaudit-sortable-items-inputs plaudit-sortable-items-padded">
|
|
74
|
+
{makeChild(datum.value, change, index)}
|
|
75
|
+
</div>
|
|
76
|
+
<div className="plaudit-sortable-items-presence-controls plaudit-sortable-items-padded">
|
|
77
|
+
{/*addEmptyHandlers && index === 0 &&
|
|
78
|
+
<Button icon="insert" className="insert-before" disabled={addDisabled} onClick={addEmptyHandlers[0]} aria-label="Insert Before"/>*/}
|
|
79
|
+
<Button icon="remove" disabled={removeDisabled} onClick={remove} aria-label="Remove"/>
|
|
80
|
+
{/*addEmptyHandlers && <Button icon="insert" className="insert-after" disabled={addDisabled} onClick={addEmptyHandlers[1]}
|
|
81
|
+
aria-label={index < listLength - 1 ? "Insert Between" : "Insert After"}/>*/}
|
|
82
|
+
</div>
|
|
83
|
+
</Reorder.Item>;
|
|
84
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {Spinner, FormTokenField} from '@wordpress/components';
|
|
2
|
+
import {useDebounce} from "@wordpress/compose";
|
|
3
|
+
import {useSelect} from "@wordpress/data";
|
|
4
|
+
import type {MapSelect} from "@wordpress/data/types";
|
|
5
|
+
import {useCallback, useEffect, useMemo, useRef, useState} from "@wordpress/element";
|
|
6
|
+
import {__} from "@wordpress/i18n";
|
|
7
|
+
|
|
8
|
+
import type {SNPControlSlots} from "../blocks";
|
|
9
|
+
import type {TokenItem} from "../lib/useful-types";
|
|
10
|
+
import {packDisplayTokenText, unpackDisplayedTokenText, useImprovedTokenManager, ValidationState} from "./hooks/useImprovedTokenManager";
|
|
11
|
+
import {useMultiSingleConversionLayer} from "./hooks/useMultiSingleConversionLayer";
|
|
12
|
+
|
|
13
|
+
export {packDisplayTokenText, unpackDisplayedTokenText, ValidationState};
|
|
14
|
+
|
|
15
|
+
import type {ReactNode} from "react";
|
|
16
|
+
|
|
17
|
+
type ExtendedFormTokenFieldPropsBase = {
|
|
18
|
+
label?: string;
|
|
19
|
+
help?: ReactNode;
|
|
20
|
+
|
|
21
|
+
validationQuery(tokens: string[], ...args: Parameters<MapSelect>): TokenItem[]|undefined;
|
|
22
|
+
suggestionQuery(input: string, ...args: Parameters<MapSelect>): TokenItem[]|undefined;
|
|
23
|
+
stringToTokenConverter(suggestion: string): TokenItem;
|
|
24
|
+
validator?: (value: string) => boolean;
|
|
25
|
+
expandOnFocus?: boolean;
|
|
26
|
+
initialSuggestions?: TokenItem[];
|
|
27
|
+
hasLoadingError?: (input: string, ...args: Parameters<MapSelect>) => boolean;
|
|
28
|
+
hasValidationError?: (...args: Parameters<MapSelect>) => boolean;
|
|
29
|
+
}&Partial<Pick<SNPControlSlots, 'Messages'>>;
|
|
30
|
+
type ExtendedFormTokenFieldPropsSingle = ExtendedFormTokenFieldPropsBase&{
|
|
31
|
+
value?: string;
|
|
32
|
+
onChange: (value: string) => void;
|
|
33
|
+
multiple: false;
|
|
34
|
+
};
|
|
35
|
+
type ExtendedFormTokenFieldPropsMultiple = ExtendedFormTokenFieldPropsBase&{
|
|
36
|
+
value?: string[];
|
|
37
|
+
onChange: (value: string[]) => void;
|
|
38
|
+
multiple?: true|undefined;
|
|
39
|
+
maxLength?: number;
|
|
40
|
+
};
|
|
41
|
+
export type ExtendedFormTokenFieldProps = ExtendedFormTokenFieldPropsSingle|ExtendedFormTokenFieldPropsMultiple;
|
|
42
|
+
|
|
43
|
+
export function ExtendedFormTokenField(props: ExtendedFormTokenFieldProps) {
|
|
44
|
+
const [debouncedInput, setDebouncedInput, setImmediateInput, input] = useDebouncedValue('');
|
|
45
|
+
|
|
46
|
+
const tokenTitleCacheRef = useRef<Map<TokenItem['value'], TokenItem['title']>|undefined>(undefined);
|
|
47
|
+
if (tokenTitleCacheRef.current === undefined) {
|
|
48
|
+
tokenTitleCacheRef.current = new Map();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const {rawSuggestions, isLoading, hasLoadingError} = useSelect((select, registry) => {
|
|
52
|
+
if (!debouncedInput && props.initialSuggestions !== undefined) {
|
|
53
|
+
return {rawSuggestions: props.initialSuggestions, isLoading: false};
|
|
54
|
+
}
|
|
55
|
+
const res = props.suggestionQuery(debouncedInput, select, registry);
|
|
56
|
+
if (res === undefined) {
|
|
57
|
+
return {rawSuggestions: props.initialSuggestions, isLoading: true};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {rawSuggestions: res, isLoading: false, hasLoadingError: props.hasLoadingError?.(debouncedInput, select, registry)};
|
|
61
|
+
}, [debouncedInput, props.initialSuggestions, props.suggestionQuery]);
|
|
62
|
+
const suggestions = useMemo(() => rawSuggestions?.map(packDisplayTokenText), [rawSuggestions]);
|
|
63
|
+
|
|
64
|
+
const [value, setValue] = useMultiSingleConversionLayer(props.value, props.onChange, props.stringToTokenConverter, props.multiple);
|
|
65
|
+
const {currentTokens, isValidating, updateComponentValue, tokenStatusCache}
|
|
66
|
+
= useImprovedTokenManager(value, setValue, props.validationQuery, props.stringToTokenConverter, tokenTitleCacheRef.current);
|
|
67
|
+
|
|
68
|
+
// This is just a trick to avoid needing to repeat requests when pulling from suggestions
|
|
69
|
+
useMemo(() => {
|
|
70
|
+
if (rawSuggestions) {
|
|
71
|
+
for (const suggestion of rawSuggestions) {
|
|
72
|
+
if (suggestion.status !== undefined && !tokenStatusCache.has(suggestion.value)) {
|
|
73
|
+
tokenStatusCache.set(suggestion.value, suggestion.status);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}, [rawSuggestions, tokenStatusCache]);
|
|
78
|
+
|
|
79
|
+
const {hasValidationError} = useSelect((select, registry) => ({
|
|
80
|
+
hasValidationError: props.hasValidationError?.(select, registry)
|
|
81
|
+
}), [props.hasLoadingError, props.hasValidationError]);
|
|
82
|
+
|
|
83
|
+
const {help, expandOnFocus = false} = props;
|
|
84
|
+
|
|
85
|
+
//TODO: If focus is in field but user hasn't started typing, show a message telling them to start typing
|
|
86
|
+
return <>
|
|
87
|
+
<FormTokenField
|
|
88
|
+
value={currentTokens}
|
|
89
|
+
label={props.label}
|
|
90
|
+
placeholder="Start typing to see suggestions"
|
|
91
|
+
suggestions={suggestions}
|
|
92
|
+
onChange={updateComponentValue}
|
|
93
|
+
displayTransform={useCallback((token: string) => tokenTitleCacheRef.current!.get(unpackDisplayedTokenText(token).value) ?? token, [tokenTitleCacheRef])}
|
|
94
|
+
maxLength={props.multiple !== false ? props.maxLength : 1}
|
|
95
|
+
__experimentalValidateInput={props.validator}
|
|
96
|
+
__experimentalAutoSelectFirstMatch={true}
|
|
97
|
+
__experimentalExpandOnFocus={expandOnFocus}
|
|
98
|
+
__experimentalShowHowTo={props.multiple !== false}
|
|
99
|
+
onInputChange={setDebouncedInput}
|
|
100
|
+
onFocus={useCallback(() => setImmediateInput(input), [input])}
|
|
101
|
+
/>
|
|
102
|
+
{help && <div><span className="components-form-token-field__help">{help}</span></div>}
|
|
103
|
+
{hasLoadingError && <div><Spinner /><span className="components-form-token-field__help">{__("An Error Occurred While Loading Suggestions")}</span></div>}
|
|
104
|
+
{isLoading && <div><Spinner /><span className="components-form-token-field__help">{__("Updating Suggestions")}</span></div>}
|
|
105
|
+
{hasValidationError && <div><Spinner /><span className="components-form-token-field__help">{__("An Error Occurred While Validating")}</span></div>}
|
|
106
|
+
{isValidating && <div><Spinner /><span className="components-form-token-field__help">{__("Validating")}</span></div>}
|
|
107
|
+
</>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function useDebouncedValue<V>(defaultValue: V): [V, (value: V) => any, (value: V) => any, V] {
|
|
111
|
+
const [value, setValue] = useState(defaultValue);
|
|
112
|
+
const [debouncedValue, setDebouncedState] = useState(defaultValue);
|
|
113
|
+
const setDebounced = useDebounce(setDebouncedState, 100);
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
setDebounced(value);
|
|
116
|
+
}, [value, setDebounced]);
|
|
117
|
+
return [debouncedValue, setValue, useCallback((value: V) => {
|
|
118
|
+
setValue(value);
|
|
119
|
+
setDebouncedState(value);
|
|
120
|
+
}, [setValue, setDebounced]), value];
|
|
121
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import apiFetch from "@wordpress/api-fetch";
|
|
2
|
+
import {memo, useMemo} from "@wordpress/element";
|
|
3
|
+
|
|
4
|
+
import {basicNumericallyIdedItemPicker} from "./basicNumericallyIdedItemPicker";
|
|
5
|
+
import type {SNPControlSlots} from "../blocks";
|
|
6
|
+
import {ValidationState} from "./ExtendedFormTokenField";
|
|
7
|
+
import {registerSimpleGutenbergApiEndpoint} from "../editor/simple-gutenberg-endpoints-api";
|
|
8
|
+
import type {TokenItem, WPTaxonomyQuery} from "../lib/useful-types";
|
|
9
|
+
|
|
10
|
+
import type {ReactNode} from "react";
|
|
11
|
+
|
|
12
|
+
type ExtendedPostPickerPropsBase = {
|
|
13
|
+
label?: string;
|
|
14
|
+
help?: ReactNode;
|
|
15
|
+
postTypes?: string[];
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
taxonomyQuery?: WPTaxonomyQuery;
|
|
18
|
+
}&Partial<Pick<SNPControlSlots, 'Messages'>>;
|
|
19
|
+
type ExtendedPostPickerPropsSingle = ExtendedPostPickerPropsBase&{
|
|
20
|
+
onChange(value: string): void;
|
|
21
|
+
value?: string;
|
|
22
|
+
multiple: false;
|
|
23
|
+
};
|
|
24
|
+
type ExtendedPostPickerPropsMultiple = ExtendedPostPickerPropsBase&{
|
|
25
|
+
onChange(value: string[]): void;
|
|
26
|
+
value?: string[];
|
|
27
|
+
multiple?: true|undefined;
|
|
28
|
+
};
|
|
29
|
+
export type ExtendedPostPickerProps = ExtendedPostPickerPropsSingle|ExtendedPostPickerPropsMultiple;
|
|
30
|
+
export type ExtendedPostPickerConstructorProps = ExtendedPostPickerProps;
|
|
31
|
+
|
|
32
|
+
registerSimpleGutenbergApiEndpoint(
|
|
33
|
+
"plaudit-common.post-table-search-options",
|
|
34
|
+
data => apiFetch<Array<{id: number, title: string, type: string}>>({data, method: 'POST', path: "/plaudit/common/v1/post-table-search"}),
|
|
35
|
+
{
|
|
36
|
+
transformer: posts => posts.map(post => ({value: post.id.toString(), title: post.title, status: ValidationState.Valid})),
|
|
37
|
+
maxCachedResults: 10
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
registerSimpleGutenbergApiEndpoint(
|
|
41
|
+
"plaudit-common.post-table-search-validation",
|
|
42
|
+
data => apiFetch<Array<{id: number, title: string, type: string}>>({data, method: 'POST', path: "/plaudit/common/v1/post-table-search"}),
|
|
43
|
+
{
|
|
44
|
+
transformer: posts => posts
|
|
45
|
+
.map((post): TokenItem => ({value: post.id.toString(), title: post.title, status: ValidationState.Valid})),
|
|
46
|
+
maxCachedResults: 10
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export const ExtendedPostPicker = memo((props: ExtendedPostPickerProps) => {
|
|
51
|
+
const {postTypes, taxonomyQuery, ...passthrough} = props;
|
|
52
|
+
|
|
53
|
+
const queryArgs = useMemo(() => {
|
|
54
|
+
return {postTypes: postTypes?.join(','), taxonomyQuery};
|
|
55
|
+
}, [postTypes, taxonomyQuery]);
|
|
56
|
+
return basicNumericallyIdedItemPicker(passthrough, "plaudit-common.post-table-search", queryArgs);
|
|
57
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import {BaseControl, RadioControl, __experimentalVStack as VStack} from "@wordpress/components";
|
|
2
|
+
import {useInstanceId} from "@wordpress/compose";
|
|
3
|
+
import {useCallback, useState} from "@wordpress/element";
|
|
4
|
+
|
|
5
|
+
import type {SNPControlSlots} from "../blocks";
|
|
6
|
+
|
|
7
|
+
import type {ChangeEvent, ComponentPropsWithoutRef, ElementType} from "react";
|
|
8
|
+
|
|
9
|
+
type RawElementSafeProps<P, T extends ElementType> = P&Omit<ComponentPropsWithoutRef<T>, 'as' | keyof P | 'children'>;
|
|
10
|
+
export type ExtendedRadioControlProps = RawElementSafeProps<ComponentPropsWithoutRef<typeof RadioControl> & { allowCustom?: boolean }, 'input'>&Partial<SNPControlSlots>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* This is a variant of WordPress'
|
|
14
|
+
*/
|
|
15
|
+
export function ExtendedRadioControl(props: ExtendedRadioControlProps) {
|
|
16
|
+
const {
|
|
17
|
+
label,
|
|
18
|
+
className,
|
|
19
|
+
selected,
|
|
20
|
+
help,
|
|
21
|
+
onChange,
|
|
22
|
+
hideLabelFromVision,
|
|
23
|
+
options = [],
|
|
24
|
+
allowCustom,
|
|
25
|
+
Label, Messages,
|
|
26
|
+
...additionalProps
|
|
27
|
+
} = props;
|
|
28
|
+
const instanceId = useInstanceId( ExtendedRadioControl );
|
|
29
|
+
const id = `inspector-radio-control-${instanceId}`;
|
|
30
|
+
const [valueIsCustom, setValueIsCustom] = useState(
|
|
31
|
+
() => options.find(option => option.value === selected) === undefined);
|
|
32
|
+
const [customValue, setCustomValue] = useState(valueIsCustom ? selected : "");
|
|
33
|
+
|
|
34
|
+
const onChangeValue = useCallback((event: ChangeEvent<HTMLInputElement>) => {
|
|
35
|
+
setValueIsCustom(options.find(option => option.value === event.target.value) === undefined);
|
|
36
|
+
onChange(event.target.value);
|
|
37
|
+
}, [onChange, options, setValueIsCustom]);
|
|
38
|
+
const onChangeCustom = useCallback((e: ChangeEvent<HTMLInputElement>) => {
|
|
39
|
+
onChangeValue(e);
|
|
40
|
+
setValueIsCustom(true);
|
|
41
|
+
setCustomValue(e.target.value);
|
|
42
|
+
}, [onChangeValue, setValueIsCustom, setCustomValue]);
|
|
43
|
+
|
|
44
|
+
if (!options?.length) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const distinctnessSet = new Set<string>();
|
|
49
|
+
const classNames = [...className?.split(/\s+/g) ?? [], 'components-radio-control'].filter(cn => distinctnessSet.add(cn)).join(' ');
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<BaseControl
|
|
53
|
+
__nextHasNoMarginBottom
|
|
54
|
+
label={Label ? <Label /> : label}
|
|
55
|
+
id={id}
|
|
56
|
+
hideLabelFromVision={hideLabelFromVision}
|
|
57
|
+
help={help}
|
|
58
|
+
className={classNames}
|
|
59
|
+
>
|
|
60
|
+
<VStack spacing={1}>
|
|
61
|
+
{options.map((option, index) => (
|
|
62
|
+
<div
|
|
63
|
+
key={`${id}-${index}`}
|
|
64
|
+
className="components-radio-control__option"
|
|
65
|
+
>
|
|
66
|
+
<input
|
|
67
|
+
id={`${id}-${index}`}
|
|
68
|
+
className="components-radio-control__input"
|
|
69
|
+
type="radio"
|
|
70
|
+
name={id}
|
|
71
|
+
value={option.value}
|
|
72
|
+
onChange={onChangeValue}
|
|
73
|
+
checked={option.value === selected}
|
|
74
|
+
aria-describedby={!!help ? `${id}__help` : undefined}
|
|
75
|
+
{...additionalProps}
|
|
76
|
+
/>
|
|
77
|
+
<label
|
|
78
|
+
className="components-radio-control__label"
|
|
79
|
+
htmlFor={`${id}-${index}`}
|
|
80
|
+
>
|
|
81
|
+
{option.label}
|
|
82
|
+
</label>
|
|
83
|
+
</div>
|
|
84
|
+
))}
|
|
85
|
+
{allowCustom && <div
|
|
86
|
+
key={`${id}-${options.length}`}
|
|
87
|
+
className="components-radio-control__option"
|
|
88
|
+
>
|
|
89
|
+
<input
|
|
90
|
+
id={`${id}-${options.length}`}
|
|
91
|
+
className="components-radio-control__input"
|
|
92
|
+
type="radio"
|
|
93
|
+
name={id}
|
|
94
|
+
value={customValue ?? ''}
|
|
95
|
+
onChange={onChangeValue}
|
|
96
|
+
checked={valueIsCustom}
|
|
97
|
+
aria-describedby={!!help ? `${id}__help` : undefined}
|
|
98
|
+
{...additionalProps}
|
|
99
|
+
/>
|
|
100
|
+
<label id={`${id}-custom-label`} className="components-radio-control__label" htmlFor={`${id}-${options.length}`}>Custom:</label>
|
|
101
|
+
<input aria-labelledby={`${id}-custom-label`} type="text" value={customValue ?? ''} onChange={onChangeCustom} />
|
|
102
|
+
</div>}
|
|
103
|
+
</VStack>
|
|
104
|
+
{Messages && <Messages/>}
|
|
105
|
+
</BaseControl>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {type BaseEntityRecords, store as coreStore, type Taxonomy} from "@wordpress/core-data";
|
|
2
|
+
import {useSelect} from "@wordpress/data";
|
|
3
|
+
import {useCallback, useMemo} from "@wordpress/element";
|
|
4
|
+
|
|
5
|
+
import type {SNPControlSlots} from "../blocks";
|
|
6
|
+
import type {TokenItem} from "../lib/useful-types";
|
|
7
|
+
import {useOutputMemoizingFilter} from "./hooks/useOutputMemoizingFilter";
|
|
8
|
+
import {ExtendedFormTokenField, unpackDisplayedTokenText, ValidationState} from "./ExtendedFormTokenField";
|
|
9
|
+
|
|
10
|
+
import type {ReactNode} from "react";
|
|
11
|
+
|
|
12
|
+
type ExtendedTaxonomyPickerPropsBase = {
|
|
13
|
+
label?: string;
|
|
14
|
+
help?: ReactNode;
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
visibility?: Partial<BaseEntityRecords.TaxonomyVisibility>
|
|
17
|
+
}&Partial<Pick<SNPControlSlots, 'Messages'>>;
|
|
18
|
+
export type ExtendedTaxonomyPickerPropsSingle = {
|
|
19
|
+
onChange(value: string): void;
|
|
20
|
+
value?: string;
|
|
21
|
+
multiple: false;
|
|
22
|
+
};
|
|
23
|
+
export type ExtendedTaxonomyPickerPropsMultiple = {
|
|
24
|
+
onChange(value: string[]): void;
|
|
25
|
+
value?: string[];
|
|
26
|
+
multiple?: true|undefined;
|
|
27
|
+
};
|
|
28
|
+
export type ExtendedTaxonomyPickerProps = ExtendedTaxonomyPickerPropsBase&(ExtendedTaxonomyPickerPropsSingle|ExtendedTaxonomyPickerPropsMultiple);
|
|
29
|
+
|
|
30
|
+
export function ExtendedTaxonomyPicker(props: ExtendedTaxonomyPickerProps) {
|
|
31
|
+
const {visibility, ...extendedFormTokenFieldProps} = props;
|
|
32
|
+
const availableTaxonomies = useTaxonomiesFilteredByVisibility(visibility);
|
|
33
|
+
const taxonomyVisibilityFilter = makeTaxonomyVisibilityFilter(visibility);
|
|
34
|
+
|
|
35
|
+
const taxonomySuggestionQuery = useOutputMemoizingFilter((input: string, taxonomies: Taxonomy[]|null) => {
|
|
36
|
+
return taxonomies?.filter(taxonomy => !props.value?.includes(taxonomy.slug))
|
|
37
|
+
.filter(taxonomy => taxonomy.name.toLowerCase().includes(input.toLowerCase()) || taxonomy.slug.toLowerCase().includes(input.toLowerCase()))
|
|
38
|
+
.map(taxonomy => ({value: taxonomy.slug, status: ValidationState.Valid, title: taxonomy.name})) ?? [];
|
|
39
|
+
}, [props.value]);
|
|
40
|
+
const taxonomyValidationQuery = useOutputMemoizingFilter((tokens: string[], rawTaxonomies: Taxonomy[]|null) => {
|
|
41
|
+
if (rawTaxonomies === null) {
|
|
42
|
+
return tokens.map(token => ({value: token, status: ValidationState.Validating}));
|
|
43
|
+
}
|
|
44
|
+
const tokenItemCreator = (taxonomy: Taxonomy): [string, TokenItem] => {
|
|
45
|
+
return [taxonomy.slug, {value: taxonomy.slug, status: ValidationState.Valid, title: taxonomy.name}];
|
|
46
|
+
};
|
|
47
|
+
const taxonomies = rawTaxonomies?.length ? Object.fromEntries(rawTaxonomies.map(tokenItemCreator)) : undefined;
|
|
48
|
+
if (!taxonomies) {
|
|
49
|
+
return tokens.map(token => ({value: token, status: ValidationState.Invalid}));
|
|
50
|
+
}
|
|
51
|
+
return tokens.map(token => taxonomies[token] ?? {value: token, status: ValidationState.Invalid});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return <ExtendedFormTokenField
|
|
55
|
+
expandOnFocus={true}
|
|
56
|
+
{...extendedFormTokenFieldProps}
|
|
57
|
+
stringToTokenConverter={useCallback(token => {
|
|
58
|
+
if (availableTaxonomies === null) {
|
|
59
|
+
return {value: token, status: ValidationState.Validating};
|
|
60
|
+
}
|
|
61
|
+
const {value, title} = unpackDisplayedTokenText(token);
|
|
62
|
+
const foundTaxonomy = availableTaxonomies.find(taxonomy => taxonomy.slug === value);
|
|
63
|
+
if (foundTaxonomy) {
|
|
64
|
+
return {value: foundTaxonomy.slug, status: ValidationState.Valid, title: foundTaxonomy.name};
|
|
65
|
+
}
|
|
66
|
+
return title === undefined ? {value, status: ValidationState.Validating} : {value, status: ValidationState.Invalid, title};
|
|
67
|
+
}, [availableTaxonomies])}
|
|
68
|
+
suggestionQuery={useCallback((input, select) => {
|
|
69
|
+
return taxonomySuggestionQuery(input, taxonomyVisibilityFilter(select(coreStore).getTaxonomies()));
|
|
70
|
+
}, [taxonomyVisibilityFilter, taxonomySuggestionQuery])}
|
|
71
|
+
validationQuery={useCallback((tokens, select) => {
|
|
72
|
+
return taxonomyValidationQuery(tokens, taxonomyVisibilityFilter(select(coreStore).getTaxonomies()));
|
|
73
|
+
}, [taxonomyVisibilityFilter, taxonomyValidationQuery])}
|
|
74
|
+
validator={useCallback((token: string) => {
|
|
75
|
+
if (!availableTaxonomies) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const {value} = unpackDisplayedTokenText(token);
|
|
79
|
+
return availableTaxonomies.find(taxonomy => taxonomy.slug === value) !== undefined;
|
|
80
|
+
}, [availableTaxonomies])}
|
|
81
|
+
/>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function useTaxonomiesFilteredByVisibility(visibility: ExtendedTaxonomyPickerProps['visibility']) {
|
|
85
|
+
const taxonomies = useSelect(select => select(coreStore).getTaxonomies(), []);
|
|
86
|
+
return useMemo(() => filterTaxonomiesByVisibility(taxonomies, visibility), [taxonomies, visibility]);
|
|
87
|
+
}
|
|
88
|
+
function makeTaxonomyVisibilityFilter(visibility: Parameters<typeof filterTaxonomiesByVisibility>[1]) {
|
|
89
|
+
return useOutputMemoizingFilter((taxonomies: Parameters<typeof filterTaxonomiesByVisibility>[0]) => filterTaxonomiesByVisibility(taxonomies, visibility), [visibility]);
|
|
90
|
+
}
|
|
91
|
+
function filterTaxonomiesByVisibility(taxonomies: Taxonomy[]|null, visibility: ExtendedTaxonomyPickerProps['visibility']) {
|
|
92
|
+
if (!taxonomies || !visibility) {
|
|
93
|
+
return taxonomies;
|
|
94
|
+
}
|
|
95
|
+
const tests = Object.entries(visibility)
|
|
96
|
+
.filter((entry): entry is [keyof BaseEntityRecords.TaxonomyVisibility, boolean] => entry[1] !== undefined && entry[1] !== null);
|
|
97
|
+
return tests.length
|
|
98
|
+
? taxonomies.filter(taxonomy => tests.every(([key, value]) => taxonomy.visibility[key] === value))
|
|
99
|
+
: taxonomies;
|
|
100
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import apiFetch from "@wordpress/api-fetch";
|
|
2
|
+
import {select as dataSelect} from "@wordpress/data";
|
|
3
|
+
import {useCallback} from "@wordpress/element";
|
|
4
|
+
|
|
5
|
+
import type {SNPControlSlots} from "../blocks";
|
|
6
|
+
import {ExtendedFormTokenField, unpackDisplayedTokenText, ValidationState} from "./ExtendedFormTokenField";
|
|
7
|
+
import {registerSimpleGutenbergApiEndpoint} from "../editor/simple-gutenberg-endpoints-api";
|
|
8
|
+
import type {TokenItem} from "../lib/useful-types";
|
|
9
|
+
|
|
10
|
+
import type {ReactNode} from "react";
|
|
11
|
+
|
|
12
|
+
type ExtendedTermPickerPropsBase = {
|
|
13
|
+
label?: string;
|
|
14
|
+
help?: ReactNode;
|
|
15
|
+
taxonomy: string;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
}&Partial<Pick<SNPControlSlots, 'Messages'>>;
|
|
18
|
+
export type ExtendedTermPickerPropsSingle = ExtendedTermPickerPropsBase&{
|
|
19
|
+
onChange(value: string): void;
|
|
20
|
+
value?: string;
|
|
21
|
+
multiple: false;
|
|
22
|
+
};
|
|
23
|
+
export type ExtendedTermPickerPropsMultiple = ExtendedTermPickerPropsBase&{
|
|
24
|
+
onChange(value: string[]): void;
|
|
25
|
+
value?: string[];
|
|
26
|
+
multiple?: true|undefined;
|
|
27
|
+
};
|
|
28
|
+
export type ExtendedTermPickerProps = ExtendedTermPickerPropsSingle|ExtendedTermPickerPropsMultiple;
|
|
29
|
+
|
|
30
|
+
export type TermDataStruct = {term_id: number, name: string, slug: number, term_taxonomy_id: number, taxonomy: string};
|
|
31
|
+
registerSimpleGutenbergApiEndpoint(
|
|
32
|
+
"plaudit-common.term-table-search-options",
|
|
33
|
+
data => apiFetch<TermDataStruct[]>({data, method: 'POST', path: "/plaudit/common/v1/term-table-search"}),
|
|
34
|
+
{
|
|
35
|
+
transformer: terms => terms.map(term => ({value: term.slug, title: term.name, status: ValidationState.Valid})),
|
|
36
|
+
maxCachedResults: 10
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
registerSimpleGutenbergApiEndpoint(
|
|
40
|
+
"plaudit-common.term-table-search-validation",
|
|
41
|
+
data => apiFetch<TermDataStruct[]>({data, method: 'POST', path: "/plaudit/common/v1/term-table-search"}),
|
|
42
|
+
{
|
|
43
|
+
transformer: terms => terms
|
|
44
|
+
.map((term) => ({value: term.slug, title: term.name, status: ValidationState.Valid})),
|
|
45
|
+
maxCachedResults: 10
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export function ExtendedTermPicker(props: ExtendedTermPickerProps) {
|
|
50
|
+
const {taxonomy} = props;
|
|
51
|
+
|
|
52
|
+
const suggestionQuery = useCallback((input: string, select: typeof dataSelect) => {
|
|
53
|
+
return select('plaudit/simple-gutenberg-apis')
|
|
54
|
+
.get("plaudit-common.term-table-search-options", {search: input, taxonomy}) as TokenItem[]|undefined;
|
|
55
|
+
}, [taxonomy]);
|
|
56
|
+
const validationQuery = useCallback((slugsBeingValidated: string[], select: typeof dataSelect) => {
|
|
57
|
+
return (select('plaudit/simple-gutenberg-apis')
|
|
58
|
+
.get("plaudit-common.term-table-search-validation", {slugs: slugsBeingValidated.join(','), taxonomy}) as TokenItem[]|undefined);
|
|
59
|
+
}, [taxonomy]);
|
|
60
|
+
|
|
61
|
+
return <ExtendedFormTokenField {...props} validationQuery={validationQuery} suggestionQuery={suggestionQuery} stringToTokenConverter={unpackDisplayedTokenText} />;
|
|
62
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {TextareaControl} from "@wordpress/components";
|
|
2
|
+
import {useDebounce} from "@wordpress/compose";
|
|
3
|
+
|
|
4
|
+
import {forwardRef, useCallback, useEffect, useImperativeHandle, useRef} from "@wordpress/element";
|
|
5
|
+
|
|
6
|
+
import type {SNPControlSlots} from "../blocks";
|
|
7
|
+
|
|
8
|
+
import type {ComponentProps} from "react";
|
|
9
|
+
|
|
10
|
+
export type TextareaControlPropsExtension = {newline?: undefined|"\n"|"br"|"p", placeholder?: string|undefined, rich?: boolean};
|
|
11
|
+
export type ExtendedTextAreaControlProps = Omit<ComponentProps<typeof TextareaControl>, 'value'>&{value: ComponentProps<typeof TextareaControl>['value']|null|undefined}
|
|
12
|
+
&Partial<Pick<SNPControlSlots, 'Messages'>>&TextareaControlPropsExtension;
|
|
13
|
+
export const ExtendedTextareaControl = (() => {
|
|
14
|
+
const debouncerSettings = {leading: false, maxWait: 250, trailing: true};
|
|
15
|
+
return forwardRef<HTMLTextAreaElement, ExtendedTextAreaControlProps>((props, ref) => {
|
|
16
|
+
const {newline, onChange, placeholder, rich, value, Messages, ...forwardedProps} = props;
|
|
17
|
+
let v = value ?? '';
|
|
18
|
+
if (!rich) {
|
|
19
|
+
if (newline === "br") {
|
|
20
|
+
v = v.replaceAll(/<br>\s*<\/br>|<br\/?>/gi, "\n");
|
|
21
|
+
} else if (newline === "p") {
|
|
22
|
+
v = v.replaceAll(/<p>(.*?)<\/p>/gi, "$1\n");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const safeOnChange = useCallback((v: string) => {
|
|
26
|
+
if (rich) {
|
|
27
|
+
onChange(v);
|
|
28
|
+
} else if (newline === "br") {
|
|
29
|
+
onChange(v.replaceAll(/\r?\n/g, "<br/>"));
|
|
30
|
+
} else if (newline === "p") {
|
|
31
|
+
onChange(v.split(/\r?\n/g).map(v => "<p>" + v + "</p>").join(""));
|
|
32
|
+
} else {
|
|
33
|
+
onChange(v);
|
|
34
|
+
}
|
|
35
|
+
}, [onChange]);
|
|
36
|
+
|
|
37
|
+
const textareaRef = useRef<HTMLTextAreaElement|null>(null);
|
|
38
|
+
useImperativeHandle(ref, () => textareaRef.current!, []);
|
|
39
|
+
|
|
40
|
+
const debouncedUpdate = useDebounce(safeOnChange, 100, debouncerSettings);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const id = textareaRef.current?.id;
|
|
44
|
+
if (id && rich && document.getElementById(id)) {
|
|
45
|
+
(window as any).tinymce.EditorManager.execCommand('mceAddEditor', true, id);
|
|
46
|
+
const editor = (window as any).tinymce.editors.findLast((e: {id: string}) => e.id === id);
|
|
47
|
+
editor.on('input', () => debouncedUpdate(editor.getContent()));
|
|
48
|
+
editor.on('NodeChange', () => debouncedUpdate(editor.getContent()));
|
|
49
|
+
editor.on('change', () => {
|
|
50
|
+
debouncedUpdate.cancel();
|
|
51
|
+
safeOnChange(editor.getContent());
|
|
52
|
+
});
|
|
53
|
+
return () => {
|
|
54
|
+
(window as any).tinymce.EditorManager.execCommand('mceRemoveEditor', true, id);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return () => {};
|
|
58
|
+
}, [rich, debouncedUpdate, textareaRef.current]);
|
|
59
|
+
|
|
60
|
+
return <>
|
|
61
|
+
<TextareaControl ref={textareaRef} {...forwardedProps} value={v} onChange={safeOnChange} />
|
|
62
|
+
{Messages && <Messages/>}
|
|
63
|
+
</>;
|
|
64
|
+
})
|
|
65
|
+
})();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import apiFetch from "@wordpress/api-fetch";
|
|
2
|
+
import {memo, useMemo} from "@wordpress/element";
|
|
3
|
+
|
|
4
|
+
import {basicNumericallyIdedItemPicker} from "./basicNumericallyIdedItemPicker";
|
|
5
|
+
import type {SNPControlSlots} from "../blocks";
|
|
6
|
+
import {ValidationState} from "./ExtendedFormTokenField";
|
|
7
|
+
import {registerSimpleGutenbergApiEndpoint} from "../editor/simple-gutenberg-endpoints-api";
|
|
8
|
+
import type {TokenItem} from "../lib/useful-types";
|
|
9
|
+
|
|
10
|
+
import type {ReactNode} from "react";
|
|
11
|
+
|
|
12
|
+
type ExtendedUserPickerPropsBase = {
|
|
13
|
+
label?: string;
|
|
14
|
+
help?: ReactNode;
|
|
15
|
+
userRoles?: string[];
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
}&Partial<Pick<SNPControlSlots, 'Messages'>>;
|
|
18
|
+
type ExtendedUserPickerPropsSingle = ExtendedUserPickerPropsBase&{
|
|
19
|
+
onChange(value: string): void;
|
|
20
|
+
value?: string;
|
|
21
|
+
multiple: false;
|
|
22
|
+
};
|
|
23
|
+
type ExtendedUserPickerPropsMultiple = ExtendedUserPickerPropsBase&{
|
|
24
|
+
onChange(value: string[]): void;
|
|
25
|
+
value?: string[];
|
|
26
|
+
multiple?: true|undefined;
|
|
27
|
+
};
|
|
28
|
+
export type ExtendedUserPickerProps = ExtendedUserPickerPropsSingle|ExtendedUserPickerPropsMultiple;
|
|
29
|
+
|
|
30
|
+
registerSimpleGutenbergApiEndpoint(
|
|
31
|
+
"plaudit-common.user-table-search-options",
|
|
32
|
+
data => apiFetch<Array<{id: number, name: string, roles?: string[]}>>({data, method: 'POST', path: "/plaudit/common/v1/user-table-search"}),
|
|
33
|
+
{
|
|
34
|
+
transformer: users => users.map(user => ({value: user.id.toString(), title: user.name, status: ValidationState.Valid})),
|
|
35
|
+
maxCachedResults: 10
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
registerSimpleGutenbergApiEndpoint(
|
|
39
|
+
"plaudit-common.user-table-search-validation",
|
|
40
|
+
data => apiFetch<Array<{id: number, name: string, roles?: string[]}>>({data, method: 'POST', path: "/plaudit/common/v1/user-table-search"}),
|
|
41
|
+
{
|
|
42
|
+
transformer: user => user
|
|
43
|
+
.map((user): TokenItem => ({value: user.id.toString(), title: user.name, status: ValidationState.Valid})),
|
|
44
|
+
maxCachedResults: 10
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export const ExtendedUserPicker = memo((props: ExtendedUserPickerProps) => {
|
|
49
|
+
const {userRoles, ...passthrough} = props;
|
|
50
|
+
|
|
51
|
+
const queryArgs = useMemo(() => {
|
|
52
|
+
return {roles: userRoles?.join(",")};
|
|
53
|
+
}, [userRoles]);
|
|
54
|
+
|
|
55
|
+
return basicNumericallyIdedItemPicker(passthrough, "plaudit-common.user-table-search", queryArgs);
|
|
56
|
+
})
|