@plaudit/gutenberg-api-extensions 2.79.0 → 2.80.1
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 -4
- 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 +23 -31
- 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 +120 -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 +156 -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 +113 -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,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption,
|
|
3
|
+
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, PanelBody, TabPanel
|
|
4
|
+
} from "@wordpress/components";
|
|
5
|
+
import {memo, useCallback, useMemo} from "@wordpress/element";
|
|
6
|
+
import {__} from "@wordpress/i18n";
|
|
7
|
+
import * as icons from "@wordpress/icons";
|
|
8
|
+
|
|
9
|
+
import type {TogglePropertyCSNPConfig} from "../blocks/csnp-api";
|
|
10
|
+
import * as plauditIcons from "../lib/plaudit-icons";
|
|
11
|
+
import type {IconName, OptionalLabel} from "../blocks";
|
|
12
|
+
import type {CSNPControlComponentProps, NormalSwitch, PlauditIconName, WordPressIconName} from "../blocks/shared-internal-types";
|
|
13
|
+
|
|
14
|
+
import parse from "html-react-parser";
|
|
15
|
+
|
|
16
|
+
import type {ComponentPropsWithoutRef, ReactElement} from "react";
|
|
17
|
+
|
|
18
|
+
type ToggleGroupControlProps = ComponentPropsWithoutRef<typeof ToggleGroupControl>;
|
|
19
|
+
export type FullSizeToggleControlProps = Omit<CSNPControlComponentProps<TogglePropertyCSNPConfig, boolean, {switchCfg: NormalSwitch}>, 'config'>&{
|
|
20
|
+
componentConfig?: Partial<ToggleGroupControlProps>,
|
|
21
|
+
label: ToggleGroupControlProps['label'],
|
|
22
|
+
help?: ToggleGroupControlProps['help']
|
|
23
|
+
};
|
|
24
|
+
export function FullSizeToggleControl({componentConfig, label, help, onChange, switchCfg, value}: FullSizeToggleControlProps) {
|
|
25
|
+
const [switchLabels, style] = useMemo(() => {
|
|
26
|
+
let switchLabels: {onLabel: NonNullable<OptionalLabel>, offLabel: NonNullable<OptionalLabel>};
|
|
27
|
+
if (typeof switchCfg === 'string') {
|
|
28
|
+
switchCfg = {type: switchCfg};
|
|
29
|
+
}
|
|
30
|
+
switch (switchCfg.type) {
|
|
31
|
+
case "showHide":
|
|
32
|
+
switchLabels = {onLabel: "Show", offLabel: "Hide"};
|
|
33
|
+
break;
|
|
34
|
+
case "yesNo":
|
|
35
|
+
switchLabels = {onLabel: "Yes", offLabel: "No"};
|
|
36
|
+
break;
|
|
37
|
+
default:
|
|
38
|
+
if (switchCfg.type !== undefined) {
|
|
39
|
+
console.error("Invalid switch type:", switchCfg.type);
|
|
40
|
+
}
|
|
41
|
+
switchLabels = {onLabel: "On", offLabel: "Off"};
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
if (switchCfg.onLabel) {
|
|
45
|
+
switchLabels.onLabel = switchCfg.onLabel;
|
|
46
|
+
}
|
|
47
|
+
if (switchCfg.offLabel) {
|
|
48
|
+
switchLabels.offLabel = switchCfg.offLabel;
|
|
49
|
+
}
|
|
50
|
+
return [{onLabel: i18nSwitchLabel(switchLabels.onLabel), offLabel: i18nSwitchLabel(switchLabels.offLabel)}, {width: switchCfg.narrow ? "min-content" : undefined}];
|
|
51
|
+
}, [switchCfg]);
|
|
52
|
+
|
|
53
|
+
const safeOnChange = useCallback((v: string|number|undefined) => onChange(v === "true"), [onChange]);
|
|
54
|
+
|
|
55
|
+
return <ToggleGroupControl
|
|
56
|
+
{...componentConfig}
|
|
57
|
+
value={value ? "true" : "false"} label={label} help={help} isBlock
|
|
58
|
+
onChange={safeOnChange} style={style}
|
|
59
|
+
>
|
|
60
|
+
<ToggleGroupControlOptionWithOptionalIcon key="true" value="true" label={switchLabels.onLabel} />
|
|
61
|
+
<ToggleGroupControlOptionWithOptionalIcon key="false" value="false" label={switchLabels.offLabel} />
|
|
62
|
+
</ToggleGroupControl>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const ToggleGroupControlOptionWithOptionalIcon
|
|
66
|
+
= memo(function<V extends string|number>({value, label}: {value: V, label: NonNullable<OptionalLabel>}) {
|
|
67
|
+
if (typeof label === 'string') {
|
|
68
|
+
return <ToggleGroupControlOption value={value} label={label} />;
|
|
69
|
+
} else {
|
|
70
|
+
const icon = resolveIcon(label.icon);
|
|
71
|
+
if (icon) {
|
|
72
|
+
return <ToggleGroupControlOptionIcon value={value} label={label.text} icon={icon} aria-label={label.tooltip} />;
|
|
73
|
+
} else {
|
|
74
|
+
return <ToggleGroupControlOption value={value} label={label.text} aria-label={label.tooltip} showTooltip={!!label.tooltip} />;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
function i18nSwitchLabel(label: NonNullable<OptionalLabel>): typeof label {
|
|
80
|
+
return typeof label === 'string' ? __(label) : {...label, text: __(label.text)};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resolveIcon(icon: ReactElement|IconName|undefined): ReactElement|undefined {
|
|
84
|
+
if (typeof icon !== 'string') {
|
|
85
|
+
return icon;
|
|
86
|
+
}
|
|
87
|
+
if (icon.startsWith("plaudit:")) {
|
|
88
|
+
return plauditIcons[icon.substring(8) as PlauditIconName];
|
|
89
|
+
} else if (icon.startsWith("<svg")) {
|
|
90
|
+
return parse(icon) as ReactElement;
|
|
91
|
+
} else {
|
|
92
|
+
return icons[icon as WordPressIconName];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {MediaUpload, MediaUploadCheck} from "@wordpress/block-editor";
|
|
2
|
+
import {BaseControl, Button, FocalPointPicker, ResponsiveWrapper, useBaseControlProps} from "@wordpress/components";
|
|
3
|
+
import {type Attachment, type Context, store as coreStore} from "@wordpress/core-data";
|
|
4
|
+
import {useSelect} from "@wordpress/data";
|
|
5
|
+
import {useCallback, useMemo} from "@wordpress/element";
|
|
6
|
+
import {__} from "@wordpress/i18n";
|
|
7
|
+
|
|
8
|
+
import type {ProvidedSlot} from "../blocks";
|
|
9
|
+
|
|
10
|
+
import type {ComponentPropsWithoutRef, ReactNode} from "react";
|
|
11
|
+
|
|
12
|
+
export type ImageData = {media?: {id?: number, url?: string}, pos?: {x?: number, y?: number}};
|
|
13
|
+
|
|
14
|
+
type FocalPoint = ComponentPropsWithoutRef<typeof FocalPointPicker>['value'];
|
|
15
|
+
|
|
16
|
+
export type ImageControlProps = {
|
|
17
|
+
includeFocalPointPicker?: boolean,
|
|
18
|
+
label: string,
|
|
19
|
+
help?: ReactNode,
|
|
20
|
+
onChange: (value?: Record<string|number, unknown>) => void,
|
|
21
|
+
value?: ImageData,
|
|
22
|
+
Label?: ProvidedSlot, Messages?: ProvidedSlot,
|
|
23
|
+
storage?: 'default'|'slim'
|
|
24
|
+
};
|
|
25
|
+
export function ImageControl(props: ImageControlProps) {
|
|
26
|
+
const {label, help, value, Label, Messages} = props;
|
|
27
|
+
|
|
28
|
+
const media = useSelect(select => value?.media?.id ? select(coreStore).getMedia(value.media.id) : undefined, [value]);
|
|
29
|
+
const {baseControlProps, controlProps} = useBaseControlProps({label: Label ? <Label /> : label, help});
|
|
30
|
+
return <BaseControl {...baseControlProps}>
|
|
31
|
+
<div {...controlProps} className="editor-post-featured-image">
|
|
32
|
+
{media
|
|
33
|
+
? <ImageControlWithUploadedImage {...props} media={media} />
|
|
34
|
+
: <ImageControlWithoutUploadedImage {...props} media={media} />}
|
|
35
|
+
</div>
|
|
36
|
+
{Messages && <Messages />}
|
|
37
|
+
</BaseControl>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const RETAINED_FIELDS = ["id", "filename", "url", "date", "mime", "height", "width", "orientation"] as const;
|
|
41
|
+
export const MINIMAL_STORAGE_FIELDS = ['id', 'url'];
|
|
42
|
+
type HypotheticalImageDataType<C extends Context> = Partial<Attachment<C>>&ImageData['media']&{[k in typeof RETAINED_FIELDS[number]]?: k extends keyof Attachment<C> ? Attachment<C>[k] : unknown};
|
|
43
|
+
export function filterImageValueForSaving<C extends Context = 'edit'>(attachment: HypotheticalImageDataType<C>, storage: 'default'|'slim'): Pick<HypotheticalImageDataType<C>, typeof RETAINED_FIELDS[number]> {
|
|
44
|
+
if (storage === 'slim') {
|
|
45
|
+
return Object.fromEntries(Object.entries(attachment).filter((entry): entry is [typeof MINIMAL_STORAGE_FIELDS[number], any] => MINIMAL_STORAGE_FIELDS.includes(entry[0] as any)));
|
|
46
|
+
}
|
|
47
|
+
return Object.fromEntries(Object.entries(attachment).filter((entry): entry is [typeof RETAINED_FIELDS[number], any] => RETAINED_FIELDS.includes(entry[0] as any)));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const ALLOWED_TYPES = ['image'];
|
|
51
|
+
function ImageControlWithUploadedImage(props: ImageControlProps&{media: Attachment}) {
|
|
52
|
+
const {includeFocalPointPicker, media, storage, onChange, value} = props;
|
|
53
|
+
const onFPPChange = useCallback((pos: FocalPoint) => onChange(mergeInUpdatedValuePart(value, 'pos', {x: pos.x * 100, y: pos.y * 100}, storage)), [onChange, value]);
|
|
54
|
+
const onSelect = useCallback((media: {id: number}&{[k: string]: any}) => onChange(mergeInUpdatedValuePart(value, 'media', media, storage)), [onChange, value]);
|
|
55
|
+
const renderOpenButton = useCallback(({open}: {open(): void}) => <Button onClick={open} variant="secondary">{__('Replace image', 'plaudit')}</Button>, []);
|
|
56
|
+
const clear = useCallback(() => onChange(undefined), [onChange]);
|
|
57
|
+
|
|
58
|
+
const fppValue = useMemo(() => ({
|
|
59
|
+
x: (value?.pos?.x ?? 50) / 100,
|
|
60
|
+
y: (value?.pos?.y ?? 50) / 100
|
|
61
|
+
}), [value?.pos?.x, value?.pos?.y]);
|
|
62
|
+
|
|
63
|
+
let fppOrMedia;
|
|
64
|
+
if (includeFocalPointPicker !== false) {
|
|
65
|
+
fppOrMedia = <FocalPointPicker
|
|
66
|
+
onChange={onFPPChange}
|
|
67
|
+
url={value?.media?.url ?? ''}
|
|
68
|
+
value={fppValue}
|
|
69
|
+
/>;
|
|
70
|
+
} else {
|
|
71
|
+
fppOrMedia = <ResponsiveWrapper
|
|
72
|
+
naturalWidth={parsePossiblyUndefinedFloat(media.media_details["width"])}
|
|
73
|
+
naturalHeight={parsePossiblyUndefinedFloat(media.media_details["height"])}
|
|
74
|
+
>
|
|
75
|
+
<img src={value?.media?.url ?? ''} alt="The currently-selected image." />
|
|
76
|
+
</ResponsiveWrapper>
|
|
77
|
+
}
|
|
78
|
+
return <>
|
|
79
|
+
{value?.media?.url && fppOrMedia}
|
|
80
|
+
<MediaUploadCheck>
|
|
81
|
+
<MediaUpload
|
|
82
|
+
title={__('Replace image', 'plaudit')}
|
|
83
|
+
value={value?.media?.id ?? 0}
|
|
84
|
+
onSelect={onSelect}
|
|
85
|
+
allowedTypes={ALLOWED_TYPES}
|
|
86
|
+
render={renderOpenButton}
|
|
87
|
+
/>
|
|
88
|
+
<Button onClick={clear} isDestructive>{__('Remove image', 'plaudit')}</Button>
|
|
89
|
+
</MediaUploadCheck>
|
|
90
|
+
</>;
|
|
91
|
+
}
|
|
92
|
+
function ImageControlWithoutUploadedImage(props: ImageControlProps&{media: Attachment|undefined}) {
|
|
93
|
+
const {media, onChange, storage, value} = props;
|
|
94
|
+
const onSelect = useCallback((media: {id: number}&{[k: string]: any}) => onChange(mergeInUpdatedValuePart(value, 'media', media, storage)), [onChange, value]);
|
|
95
|
+
const renderOpenButton = useCallback(({open}: {open(): void}) => (
|
|
96
|
+
<Button
|
|
97
|
+
className={!value?.media?.id ? 'editor-post-featured-image__toggle' : 'editor-post-featured-image__preview'}
|
|
98
|
+
onClick={open}
|
|
99
|
+
>
|
|
100
|
+
{!value?.media?.id && __('Choose an image', 'plaudit')}
|
|
101
|
+
{media &&
|
|
102
|
+
<ResponsiveWrapper
|
|
103
|
+
naturalWidth={parsePossiblyUndefinedFloat(media.media_details["width"])}
|
|
104
|
+
naturalHeight={parsePossiblyUndefinedFloat(media.media_details["height"])}
|
|
105
|
+
>
|
|
106
|
+
<img src={media.source_url} alt="The currently-selected image." />
|
|
107
|
+
</ResponsiveWrapper>
|
|
108
|
+
}
|
|
109
|
+
</Button>
|
|
110
|
+
), [media, value?.media?.id]);
|
|
111
|
+
return <MediaUploadCheck>
|
|
112
|
+
<MediaUpload
|
|
113
|
+
onSelect={onSelect}
|
|
114
|
+
value={value?.media?.id ?? 0}
|
|
115
|
+
allowedTypes={ALLOWED_TYPES}
|
|
116
|
+
render={renderOpenButton}
|
|
117
|
+
/>
|
|
118
|
+
</MediaUploadCheck>;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function parsePossiblyUndefinedFloat(string: string|number|undefined): number|undefined {
|
|
122
|
+
return typeof string === 'number' ? string : (string !== undefined ? parseFloat(string) : undefined);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function mergeInUpdatedValuePart(value: ImageData|undefined, partName: 'media'|'pos', part: Required<ImageData>[typeof partName]|undefined, storage: 'default'|'slim'|undefined): ImageData|undefined {
|
|
126
|
+
if (part === undefined) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
if (partName === 'media') {
|
|
130
|
+
const prt = (part as Required<ImageData>[typeof partName]);
|
|
131
|
+
if (prt.id === 0) {
|
|
132
|
+
return undefined;
|
|
133
|
+
} else if (value === undefined) {
|
|
134
|
+
return {media: filterImageValueForSaving(prt, storage ?? 'default'), pos: {x: 50, y: 50}};
|
|
135
|
+
}
|
|
136
|
+
return {media: filterImageValueForSaving(prt, storage ?? 'default'), pos: {x: value.pos?.x ?? 50, y: value.pos?.y ?? 50}};
|
|
137
|
+
} else if (value === undefined || !value.media?.id) {
|
|
138
|
+
return undefined;
|
|
139
|
+
} else {
|
|
140
|
+
const prt = (part as Required<ImageData>[typeof partName]);
|
|
141
|
+
return {media: value.media, pos: {x: prt.x ?? value.pos?.x ?? 50, y: prt.y ?? value.pos?.y ?? 50}};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {InspectorControls} from "@wordpress/block-editor";
|
|
2
|
+
import {Panel, PanelBody, TabPanel} from "@wordpress/components";
|
|
3
|
+
import {useState} from "@wordpress/element";
|
|
4
|
+
|
|
5
|
+
import {type ComponentPropsWithoutRef, type ReactNode, useCallback} from "react";
|
|
6
|
+
|
|
7
|
+
type TabPanelProps = ComponentPropsWithoutRef<typeof TabPanel>;
|
|
8
|
+
type PanelBodyProps = ComponentPropsWithoutRef<typeof PanelBody>;
|
|
9
|
+
type Tab = TabPanelProps['tabs'][number]&{items: ReactNode};
|
|
10
|
+
type GroupAndCondition = {group?: string, condition?(): boolean};
|
|
11
|
+
type NormalPanelInspectorPanelProps = {tabbed?: false|undefined, raw?: boolean|undefined}&Omit<PanelBodyProps, 'children'>&Pick<InspectorControls.Props, 'children'>&GroupAndCondition;
|
|
12
|
+
type TabbedPanelInspectorPanelProps = {tabbed: true, tabs: Tab[]}&Omit<TabPanelProps, 'children'|'tabs'>&GroupAndCondition;
|
|
13
|
+
export type InspectorPanelProps = (NormalPanelInspectorPanelProps|TabbedPanelInspectorPanelProps);
|
|
14
|
+
export function InspectorPanel(props: InspectorPanelProps) {
|
|
15
|
+
if (props["tabbed"]) {
|
|
16
|
+
const {tabbed, tabs, group, condition, ...tabPanelProps} = props;
|
|
17
|
+
return <InspectorControls group={group}>
|
|
18
|
+
<TabPanel {...tabPanelProps} tabs={condition === undefined || condition() ? tabs : []}>
|
|
19
|
+
{tab => <Panel>{(tab as Tab).items}</Panel>}
|
|
20
|
+
</TabPanel>
|
|
21
|
+
</InspectorControls>;
|
|
22
|
+
} else {
|
|
23
|
+
return <InspectorPanelPanel {...props} />;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function InspectorPanelPanel(props: NormalPanelInspectorPanelProps) {
|
|
27
|
+
const {tabbed, raw, group, condition, children, onToggle, initialOpen, ...panelBodyProps} = props;
|
|
28
|
+
const [wasOpened, setWasOpened] = useState(initialOpen);
|
|
29
|
+
const memoOnToggle = useCallback((value: boolean) => {
|
|
30
|
+
onToggle?.(value);
|
|
31
|
+
setWasOpened(value);
|
|
32
|
+
}, [onToggle, setWasOpened]);
|
|
33
|
+
return <InspectorControls group={group} children={raw
|
|
34
|
+
? (condition === undefined || condition() ? children : [])
|
|
35
|
+
: <PanelBody {...panelBodyProps} children={condition === undefined || condition() ? children : []} onToggle={memoOnToggle} initialOpen={wasOpened} />
|
|
36
|
+
} />;
|
|
37
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {BaseControl, ComboboxControl, Spinner} from "@wordpress/components";
|
|
2
|
+
import {useCallback, useMemo, useState} from "@wordpress/element";
|
|
3
|
+
import {__} from "@wordpress/i18n";
|
|
4
|
+
|
|
5
|
+
import {useSuggestions} from "./hooks/useSuggestions";
|
|
6
|
+
|
|
7
|
+
import type {ComponentProps} from "react";
|
|
8
|
+
|
|
9
|
+
type ComboboxControlProps = ComponentProps<typeof ComboboxControl>;
|
|
10
|
+
type ComboboxControlOption = ComboboxControlProps['options'][number];
|
|
11
|
+
export type LazySuggestionsComboboxControlProps = Omit<ComboboxControlProps, 'options'> & {
|
|
12
|
+
getOption(value?: string): Promise<ComboboxControlOption|undefined>;
|
|
13
|
+
getSuggestions(filterValue: string): Promise<ComboboxControlOption[]>;
|
|
14
|
+
};
|
|
15
|
+
export function LazySuggestionsComboboxControl(props: LazySuggestionsComboboxControlProps) {
|
|
16
|
+
const {help, allowReset, className, ...passthroughProps} = props;
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
hasLoadingError, isInitializing, isLoading, suggestions, input, setInput
|
|
20
|
+
} = useSuggestions(props.value, props);
|
|
21
|
+
|
|
22
|
+
const [hasFocus, setHasFocus] = useState(false);
|
|
23
|
+
const options = useMemo(
|
|
24
|
+
() => hasFocus && input.length < 2 || (isLoading && !suggestions.length) ? [{label: input, value: "", disabled: true}] : suggestions,
|
|
25
|
+
[hasFocus, input, isLoading, suggestions]);
|
|
26
|
+
|
|
27
|
+
const onFocus = useCallback((e: React.FocusEvent<HTMLElement>) => setHasFocus(e.currentTarget.contains(e.target)), [setHasFocus]);
|
|
28
|
+
const onBlur = useCallback((e: React.FocusEvent<HTMLElement>) => setHasFocus(e.currentTarget.contains(e.relatedTarget)), [setHasFocus]);
|
|
29
|
+
|
|
30
|
+
const onFilterValueChange = useCallback((value: string) => {
|
|
31
|
+
if (props.onFilterValueChange) {
|
|
32
|
+
props.onFilterValueChange(value);
|
|
33
|
+
}
|
|
34
|
+
setInput(value);
|
|
35
|
+
}, [props.onFilterValueChange, setInput]);
|
|
36
|
+
|
|
37
|
+
const __experimentalRenderItem = useMemo(() => {
|
|
38
|
+
return hasFocus && input.length < 2 ? () => __("Start typing to see suggestions")
|
|
39
|
+
: (isLoading && !suggestions.length ? () => __("Loading suggestions") : undefined);
|
|
40
|
+
}, [hasFocus, input, isLoading, suggestions])
|
|
41
|
+
|
|
42
|
+
if (isInitializing) {
|
|
43
|
+
return <BaseControl {...props}>
|
|
44
|
+
<Spinner /><span>{__(`Initializing ${props.label}`)}</span>
|
|
45
|
+
</BaseControl>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const needsGreyOut = input.length < 2 || (isLoading && !suggestions.length);
|
|
49
|
+
return <div onFocus={onFocus} onBlur={onBlur}>
|
|
50
|
+
{isLoading && <Spinner style={{marginTop: "30px", position: "absolute", right: "40px"}} aria-label="Updating Suggestions" />}
|
|
51
|
+
<ComboboxControl
|
|
52
|
+
{...passthroughProps}
|
|
53
|
+
className={className ? `${className}${needsGreyOut ? " insufficient-input-length" : ""}` : (needsGreyOut ? "insufficient-input-length" : undefined)}
|
|
54
|
+
help={help}
|
|
55
|
+
options={options}
|
|
56
|
+
onFilterValueChange={onFilterValueChange}
|
|
57
|
+
__experimentalRenderItem={__experimentalRenderItem}
|
|
58
|
+
allowReset={allowReset !== false}
|
|
59
|
+
/>
|
|
60
|
+
{hasLoadingError && <div><span className="components-base-control__help">{__("An error occurred while updating suggestions")}</span></div>}
|
|
61
|
+
</div>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {useCallback, useMemo} from "@wordpress/element";
|
|
2
|
+
|
|
3
|
+
import {ExtendedFormTokenField, ValidationState} from "./ExtendedFormTokenField";
|
|
4
|
+
import type {SNPControlSlots} from "../blocks";
|
|
5
|
+
import {getLabel, normalizePickableOptionsToPairs} from "./shared";
|
|
6
|
+
import type {PickableOptions} from "./types";
|
|
7
|
+
|
|
8
|
+
import type {ReactNode} from "react";
|
|
9
|
+
|
|
10
|
+
type MultiSelectProps = {
|
|
11
|
+
onChange: (value: string[]) => void;
|
|
12
|
+
options: PickableOptions<string|number>;
|
|
13
|
+
label: string;
|
|
14
|
+
help?: ReactNode;
|
|
15
|
+
placeholder: string;
|
|
16
|
+
value?: string[];
|
|
17
|
+
expandOnFocus?: boolean;
|
|
18
|
+
maxLength?: number;
|
|
19
|
+
}&Partial<Pick<SNPControlSlots, 'Messages'>>;
|
|
20
|
+
|
|
21
|
+
type MandatoryKeys = 'onChange'|'value'|'label'|'options';
|
|
22
|
+
export type MultiSelectConstructorProps = Partial<Omit<MultiSelectProps, MandatoryKeys>> & Pick<MultiSelectProps, MandatoryKeys>;
|
|
23
|
+
|
|
24
|
+
export function MultiSelectControl(props: MultiSelectConstructorProps) {
|
|
25
|
+
const {value, options, ...fieldProps} = props;
|
|
26
|
+
const normalizedOptions = useMemo(() => normalizePickableOptionsToPairs(options), [options]);
|
|
27
|
+
const validOptions = useMemo(
|
|
28
|
+
() => Object.fromEntries(normalizedOptions.map(opt => [opt[0], getLabel(opt)])),
|
|
29
|
+
[normalizedOptions]);
|
|
30
|
+
|
|
31
|
+
return <ExtendedFormTokenField
|
|
32
|
+
{...fieldProps}
|
|
33
|
+
value={value}
|
|
34
|
+
multiple={true}
|
|
35
|
+
stringToTokenConverter={useCallback(token => {
|
|
36
|
+
if (validOptions[token]) {
|
|
37
|
+
return {value: token, title: validOptions[token], status: ValidationState.Valid};
|
|
38
|
+
} else {
|
|
39
|
+
const result = /(.+) \(#([^)]+)\)$/.exec(token);
|
|
40
|
+
return result && result[1] && result[2] ? {value: result[2], title: result[1], status: ValidationState.Validating} : {value: token, status: ValidationState.Invalid};
|
|
41
|
+
}
|
|
42
|
+
}, [validOptions])}
|
|
43
|
+
suggestionQuery={useCallback(input => {
|
|
44
|
+
return normalizedOptions
|
|
45
|
+
.filter(option => option[0]?.toString().includes(input) || getLabel(option).includes(input))
|
|
46
|
+
.map(option => ({value: option[0]?.toString(), status: ValidationState.Valid, title: getLabel(option)}));
|
|
47
|
+
}, [normalizedOptions])}
|
|
48
|
+
validationQuery={useCallback(values => {
|
|
49
|
+
return values
|
|
50
|
+
.filter(value => validOptions[value] !== undefined)
|
|
51
|
+
.map(value => ({value, title: validOptions[value], status: ValidationState.Valid}));
|
|
52
|
+
}, [validOptions])}
|
|
53
|
+
validator={validator}
|
|
54
|
+
/>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function validator(token: string) {
|
|
58
|
+
return /\(#([^)]+)\)$/.exec(token)?.[1] !== undefined;
|
|
59
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__experimentalToggleGroupControl as ToggleGroupControl,
|
|
3
|
+
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
|
|
4
|
+
__experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, BaseControl,
|
|
5
|
+
ColorPalette, RadioControl, SelectControl, useBaseControlProps
|
|
6
|
+
} from "@wordpress/components";
|
|
7
|
+
|
|
8
|
+
import {normalizePickableOptionsToPairs} from "./shared";
|
|
9
|
+
import type {PickableOptions, SimpleBlockControlProps} from "./types";
|
|
10
|
+
|
|
11
|
+
import type {ComponentPropsWithoutRef, ReactElement} from "react";
|
|
12
|
+
|
|
13
|
+
function makeSharedRadioAndSelectProps<T extends string>(props: SimpleBlockControlProps<T, string>&{options: PickableOptions<string>}) {
|
|
14
|
+
return {
|
|
15
|
+
label: props.label,
|
|
16
|
+
help: props.help,
|
|
17
|
+
onChange(value: string) {
|
|
18
|
+
props.setAttributes({[props.attribute]: value});
|
|
19
|
+
},
|
|
20
|
+
options: normalizePickableOptionsToPairs(props.options).map(([value, label]) => ({
|
|
21
|
+
value, label: typeof label === 'string' ? label : label.text
|
|
22
|
+
}))
|
|
23
|
+
} as Pick<Parameters<typeof RadioControl>[0], 'label'|'options'>&{onChange(value: string): void};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type PickOneFromToggleGroupProps<T extends string> = SimpleBlockControlProps<T, string|number>&{options: PickableOptions<string, {icon: ReactElement}>};
|
|
27
|
+
export function PickOneFromToggleGroup<T extends string>(props: PickOneFromToggleGroupProps<T>) {
|
|
28
|
+
return <ToggleGroupControl
|
|
29
|
+
label={props.label}
|
|
30
|
+
help={props.help}
|
|
31
|
+
value={props.attributes[props.attribute]}
|
|
32
|
+
onChange={value => props.setAttributes({[props.attribute]: value})}
|
|
33
|
+
children={
|
|
34
|
+
normalizePickableOptionsToPairs(props.options).map(([value, label]) => typeof label === 'string'
|
|
35
|
+
? <ToggleGroupControlOption key={value} value={value} label={label} />
|
|
36
|
+
: <ToggleGroupControlOptionIcon key={value} value={value} label={label.text} icon={label.icon} />)
|
|
37
|
+
}
|
|
38
|
+
/>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function PickOneFromSelect<T extends string>(props: SimpleBlockControlProps<T, string>& { options: PickableOptions<string> }) {
|
|
42
|
+
return <SelectControl
|
|
43
|
+
{...makeSharedRadioAndSelectProps(props)}
|
|
44
|
+
value={props.attributes[props.attribute]}
|
|
45
|
+
/>;
|
|
46
|
+
}
|
|
47
|
+
export function PickOneFromRadios<T extends string>(props: SimpleBlockControlProps<T, string>& { options: PickableOptions<string> }) {
|
|
48
|
+
return <RadioControl
|
|
49
|
+
{...makeSharedRadioAndSelectProps(props)}
|
|
50
|
+
selected={props.attributes[props.attribute]}
|
|
51
|
+
/>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type ColorObject = Exclude<NonNullable<ComponentPropsWithoutRef<typeof ColorPalette>['colors']>, {colors: any}[]>[number];
|
|
55
|
+
|
|
56
|
+
export function PickOneFromColors<T extends string>(props: SimpleBlockControlProps<T, string>&{options: PickableOptions<string, {color?: string|undefined}>}) {
|
|
57
|
+
const valueToColorMap = new Map<string, string>();
|
|
58
|
+
const colorToValueMap = new Map<string, string>();
|
|
59
|
+
const colors: ColorObject[] = [];
|
|
60
|
+
for (const [value, display] of normalizePickableOptionsToPairs(props.options)) {
|
|
61
|
+
if (typeof display === 'string') {
|
|
62
|
+
colors.push({color: value, name: display});
|
|
63
|
+
} else if (display.color) {
|
|
64
|
+
valueToColorMap.set(value, display.color);
|
|
65
|
+
colorToValueMap.set(display.color, value);
|
|
66
|
+
colors.push({color: display.color, name: display.text});
|
|
67
|
+
} else {
|
|
68
|
+
colors.push({color: value, name: display.text});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const currentColor = valueToColorMap.get(props.attributes[props.attribute]) ?? props.attributes[props.attribute];
|
|
73
|
+
const {baseControlProps, controlProps} = useBaseControlProps({label: props.label, help: props.help});
|
|
74
|
+
return <BaseControl {...baseControlProps}>
|
|
75
|
+
<ColorPalette
|
|
76
|
+
{...controlProps}
|
|
77
|
+
disableCustomColors={true}
|
|
78
|
+
onChange={color => props.setAttributes({[props.attribute]: colorToValueMap.get(color ?? currentColor) ?? color ?? currentColor})}
|
|
79
|
+
colors={colors}
|
|
80
|
+
value={currentColor}
|
|
81
|
+
clearable={false}
|
|
82
|
+
/>
|
|
83
|
+
</BaseControl>;
|
|
84
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {Spinner} from '@wordpress/components';
|
|
2
|
+
import {useRef} from "@wordpress/element";
|
|
3
|
+
|
|
4
|
+
import {use, type WrappedPromise, wrapPromise} from "../lib/suspense";
|
|
5
|
+
|
|
6
|
+
import {Suspense, type ReactNode} from "react";
|
|
7
|
+
|
|
8
|
+
export type AwaitedProps<T extends object> = {[K in keyof T]: Awaited<T[K]>};
|
|
9
|
+
export type PromisableComponentProps<T extends Awaited<object>> = {
|
|
10
|
+
promisedProps: T|Promise<T>, initializing?: (() => ReactNode)|ReactNode, renderer(props: AwaitedProps<T>): ReactNode,
|
|
11
|
+
forceSuspend?: boolean
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function PromisableComponent<T extends Awaited<object>>(props: PromisableComponentProps<T>) {
|
|
15
|
+
const wrappedPromise = useWrappedArgsParameter(props.promisedProps, props.forceSuspend);
|
|
16
|
+
if (!(wrappedPromise instanceof Promise)) {
|
|
17
|
+
return props.renderer(wrappedPromise);
|
|
18
|
+
}
|
|
19
|
+
return <Suspense fallback={typeof props.initializing === 'function' ? props.initializing() : <><Spinner /> {props.initializing}</>}>
|
|
20
|
+
<PromisableComponentDelegator promise={wrappedPromise} children={props.renderer} />
|
|
21
|
+
</Suspense>;
|
|
22
|
+
}
|
|
23
|
+
function PromisableComponentDelegator<T extends AwaitedProps<Awaited<object>>>(
|
|
24
|
+
{promise, children}: {promise: WrappedPromise<T>, children(props: T): ReactNode}
|
|
25
|
+
) {
|
|
26
|
+
return children(use(promise));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function useWrappedArgsParameter<T extends {}>(args: T, forcePromise?: boolean) {
|
|
30
|
+
const ref = useRef<WrappedArgsHolder<T>|null>(null);
|
|
31
|
+
if (ref.current === null || args !== ref.current.args || forcePromise !== ref.current.forcePromise) {
|
|
32
|
+
return (ref.current = {args, forcePromise, value: actuallyWrapTheArgsParameter(args, forcePromise)}).value;
|
|
33
|
+
} else {
|
|
34
|
+
const oldArgs = Object.values(ref.current.args);
|
|
35
|
+
const newArgs = Object.values(args);
|
|
36
|
+
if (oldArgs.length !== newArgs.length) {
|
|
37
|
+
return (ref.current = {args, forcePromise, value: actuallyWrapTheArgsParameter(args, forcePromise)}).value;
|
|
38
|
+
}
|
|
39
|
+
for (let i = 0; i < newArgs.length; i++) {
|
|
40
|
+
if (newArgs[i] !== oldArgs[i]) {
|
|
41
|
+
return (ref.current = {args, forcePromise, value: actuallyWrapTheArgsParameter(args, forcePromise)}).value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return ref.current.value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type WrappedArgsHolder<T extends {}> = {args: T, forcePromise?: boolean, value: ReturnType<typeof actuallyWrapTheArgsParameter<T>>};
|
|
49
|
+
function actuallyWrapTheArgsParameter<T extends {}>(args: T, forcePromise?: boolean) {
|
|
50
|
+
if (!Object.values(args).some(v => v instanceof Promise)) {
|
|
51
|
+
return forcePromise ? (wrapPromise(Promise.resolve(args)) as WrappedPromise<AwaitedProps<Awaited<T>>>) : (args as AwaitedProps<Awaited<T>>);
|
|
52
|
+
}
|
|
53
|
+
return wrapPromise(Promise
|
|
54
|
+
.all(Object.entries(args).map(async ([key, value]): Promise<[typeof key, Awaited<typeof value>]> => [key, await value]))
|
|
55
|
+
.then<AwaitedProps<T>>(entries => Object.fromEntries(entries) as any));
|
|
56
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {LinkControl} from "@wordpress/block-editor";
|
|
2
|
+
import {BaseControl, Button, TextControl, ToggleControl} from "@wordpress/components";
|
|
3
|
+
import {useCallback, useEffect, useRef, useState} from "@wordpress/element";
|
|
4
|
+
import {chevronDown, chevronUp} from "@wordpress/icons";
|
|
5
|
+
|
|
6
|
+
import type {ReactNode} from "react";
|
|
7
|
+
|
|
8
|
+
export type ProperLinkControlSetting = LinkControl.Setting&({type?: 'toggle'|undefined, default?: boolean|undefined}|{type: 'text', default?: string|undefined});
|
|
9
|
+
|
|
10
|
+
export type ProperLinkControlProps = Omit<LinkControl.Props, 'settings'>&{label: ReactNode, help?: ReactNode, settings?: ProperLinkControlSetting[]|false};
|
|
11
|
+
export function ProperLinkControl(props: ProperLinkControlProps) {
|
|
12
|
+
const {value, onChange, onRemove, label, help,
|
|
13
|
+
settings = ProperLinkControl.DEFAULT_LINK_SETTINGS, ...linkControlProps} = props;
|
|
14
|
+
const [areAdvancedSettingsVisible, setAreAdvancedSettingsVisible] = useState(false);
|
|
15
|
+
const advancedSettingsRef = useRef<HTMLDivElement|null>(null);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const advancedSettingsElement = advancedSettingsRef.current;
|
|
19
|
+
if (!advancedSettingsElement) {
|
|
20
|
+
return () => {};
|
|
21
|
+
}
|
|
22
|
+
const transitionListener = (evt: TransitionEvent) => {
|
|
23
|
+
if (evt.propertyName === 'max-height' && evt.target === advancedSettingsElement) {
|
|
24
|
+
if (advancedSettingsElement.style.maxHeight === '0px') {
|
|
25
|
+
advancedSettingsElement.style.display = 'none';
|
|
26
|
+
} else {
|
|
27
|
+
advancedSettingsElement.style.maxHeight = '';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
advancedSettingsElement.addEventListener('transitionend', transitionListener);
|
|
32
|
+
return () => advancedSettingsElement.addEventListener('transitionend', transitionListener);
|
|
33
|
+
}, [advancedSettingsRef]);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const advancedSettingsElement = advancedSettingsRef.current;
|
|
37
|
+
if (!advancedSettingsElement) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (areAdvancedSettingsVisible) {
|
|
41
|
+
advancedSettingsElement.style.display = '';
|
|
42
|
+
advancedSettingsElement.style.maxHeight = advancedSettingsElement.scrollHeight + "px";
|
|
43
|
+
} else {
|
|
44
|
+
advancedSettingsElement.style.maxHeight = advancedSettingsElement.scrollHeight + "px";
|
|
45
|
+
// We have to use window.requestAnimationFrame in order to force the maxHeight to be treated as "recalculated".
|
|
46
|
+
// Unless something else on the page goes horribly wrong, there shouldn't be any actual painting done as part of updating the max height.
|
|
47
|
+
window.requestAnimationFrame(() => advancedSettingsElement.style.maxHeight = "0px");
|
|
48
|
+
}
|
|
49
|
+
}, [areAdvancedSettingsVisible, advancedSettingsRef]);
|
|
50
|
+
|
|
51
|
+
const safeOnRemove = useCallback(() => onRemove !== undefined ? onRemove() : onChange?.(undefined), [onRemove, onChange]);
|
|
52
|
+
|
|
53
|
+
const renderableSettings = settings === false ? [] : settings;
|
|
54
|
+
const renderControlBottom = useCallback(() => (value?.url && renderableSettings?.length && <>
|
|
55
|
+
<Button variant="tertiary" onClick={() => setAreAdvancedSettingsVisible(!areAdvancedSettingsVisible)}
|
|
56
|
+
icon={areAdvancedSettingsVisible ? chevronUp : chevronDown} iconPosition="right" text="Advanced"
|
|
57
|
+
/>
|
|
58
|
+
<div ref={advancedSettingsRef} style={{display: "none", transition: "max-height 200ms ease-in-out", overflow: "hidden"}}>
|
|
59
|
+
{...renderableSettings.map(setting => <ProperLinkControlSetting setting={setting} onChange={onChange} value={value} />)}
|
|
60
|
+
</div>
|
|
61
|
+
</>) || "", [value, settings, areAdvancedSettingsVisible, onChange]);
|
|
62
|
+
|
|
63
|
+
return <BaseControl id="" label={props.label} help={props.help}>
|
|
64
|
+
<LinkControl
|
|
65
|
+
{...linkControlProps}
|
|
66
|
+
value={value}
|
|
67
|
+
onChange={onChange}
|
|
68
|
+
onRemove={safeOnRemove}
|
|
69
|
+
settings={ProperLinkControl.DUMMY_LINK_SETTINGS}
|
|
70
|
+
renderControlBottom={renderControlBottom}
|
|
71
|
+
/>
|
|
72
|
+
</BaseControl>
|
|
73
|
+
}
|
|
74
|
+
ProperLinkControl.DEFAULT_LINK_SETTINGS = LinkControl.DEFAULT_LINK_SETTINGS;
|
|
75
|
+
ProperLinkControl.DUMMY_LINK_SETTINGS = [] as LinkControl.Setting[];
|
|
76
|
+
|
|
77
|
+
export interface ProperLinkControl {
|
|
78
|
+
(props: ProperLinkControlProps): ReactNode;
|
|
79
|
+
readonly DEFAULT_LINK_SETTINGS: ReadonlyArray<ProperLinkControlSetting>;
|
|
80
|
+
readonly DUMMY_LINK_SETTINGS: ReadonlyArray<LinkControl.Setting>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type ProperLinkControlSettingProps = {value?: LinkControl.Value, onChange?: (nextValue?: LinkControl.Value) => void, setting: ProperLinkControlSetting};
|
|
84
|
+
function ProperLinkControlSetting({value, onChange, setting}: ProperLinkControlSettingProps) {
|
|
85
|
+
return <div style={{marginTop: "8px"}}>
|
|
86
|
+
{setting.type === 'text'
|
|
87
|
+
? <TextControl style={{marginTop: "8px"}} value={value?.[setting.id] ?? setting.default ?? ''} label={setting.title}
|
|
88
|
+
onChange={v => onChange?.({...value, [setting.id]: v})} />
|
|
89
|
+
: <ToggleControl style={{marginTop: "8px"}} checked={value?.[setting.id] ?? setting.default ?? false} label={setting.title}
|
|
90
|
+
onChange={v => onChange?.({...value, [setting.id]: v})} />
|
|
91
|
+
}
|
|
92
|
+
</div>;
|
|
93
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {ToggleControl} from "@wordpress/components";
|
|
2
|
+
import {useCallback} from "@wordpress/element";
|
|
3
|
+
|
|
4
|
+
import type {SimpleBlockControlProps} from "./types";
|
|
5
|
+
|
|
6
|
+
export function SimpleToggle<T extends string>(props: SimpleBlockControlProps<T, boolean>) {
|
|
7
|
+
const onChange = useCallback((checked: boolean) => props.setAttributes({[props.attribute]: checked}), [props.setAttributes, props.attribute]);
|
|
8
|
+
return <ToggleControl checked={props.attributes[props.attribute]} label={props.label} onChange={onChange} />;
|
|
9
|
+
}
|