@plaudit/gutenberg-api-extensions 2.94.2 → 2.96.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/CHANGELOG.md +12 -0
- package/dist/lib/useful-types.d.ts +1 -4
- package/package.json +4 -4
- package/src/blocks/MoveError.ts +0 -7
- package/src/blocks/PathError.ts +0 -18
- package/src/blocks/SNPFlexibleItemsListComponent.tsx +0 -30
- package/src/blocks/SNPGroupComponent.tsx +0 -38
- package/src/blocks/SNPListComponent.tsx +0 -25
- package/src/blocks/SNPTreeContext.tsx +0 -13
- package/src/blocks/basic-custom-block-bindings-support.tsx +0 -248
- package/src/blocks/common-native-property-constructors.tsx +0 -927
- package/src/blocks/conditions.ts +0 -261
- package/src/blocks/csnp-api.ts +0 -221
- package/src/blocks/data-controller/actions.ts +0 -20
- package/src/blocks/data-controller/reducer.ts +0 -146
- package/src/blocks/data-controller/trigger-handlers.ts +0 -150
- package/src/blocks/data-controller/utils.ts +0 -415
- package/src/blocks/data-controller-manager.ts +0 -50
- package/src/blocks/data-controller.ts +0 -165
- package/src/blocks/hooks/built-in-suspendable-option-protocols/select.ts +0 -51
- package/src/blocks/hooks/built-in-suspendable-option-protocols/settings.ts +0 -70
- package/src/blocks/hooks/useSuspendableOptions.ts +0 -122
- package/src/blocks/index.ts +0 -23
- package/src/blocks/layered-styles-api.ts +0 -142
- package/src/blocks/layered-styles-impl.ts +0 -95
- package/src/blocks/layout/LaidOutProperty.tsx +0 -72
- package/src/blocks/layout/LaidOutPropertyRow.tsx +0 -28
- package/src/blocks/layout/NodeContext.tsx +0 -54
- package/src/blocks/layout/PanelRoot.tsx +0 -30
- package/src/blocks/layout/TabsRoot.tsx +0 -56
- package/src/blocks/layout/ToolsPanelContext.tsx +0 -22
- package/src/blocks/problematic-blocks-blocker.ts +0 -24
- package/src/blocks/problematic-variations-blocker.ts +0 -32
- package/src/blocks/shared-exportable-types.ts +0 -6
- package/src/blocks/shared-internal-types.ts +0 -18
- package/src/blocks/simple-block.tsx +0 -74
- package/src/blocks/simple-native-property-api.ts +0 -173
- package/src/blocks/simple-native-property-impl.tsx +0 -335
- package/src/blocks/simple-native-property-internal-shared.ts +0 -19
- package/src/blocks/snp-api.ts +0 -5
- package/src/blocks/snp-data-store.ts +0 -72
- package/src/blocks/utilities.ts +0 -66
- package/src/controls/AsynchronousFormTokenField.tsx +0 -86
- package/src/controls/BaseSortableItemsControl.tsx +0 -84
- package/src/controls/ExtendedFormTokenField.tsx +0 -144
- package/src/controls/ExtendedPostPicker.ts +0 -57
- package/src/controls/ExtendedRadioControl.tsx +0 -107
- package/src/controls/ExtendedTaxonomyPicker.tsx +0 -100
- package/src/controls/ExtendedTermPicker.tsx +0 -61
- package/src/controls/ExtendedTextareaControl.tsx +0 -65
- package/src/controls/ExtendedUserPicker.ts +0 -56
- package/src/controls/FileControl.tsx +0 -48
- package/src/controls/FullSizeToggleControl.tsx +0 -95
- package/src/controls/ImageControl.tsx +0 -143
- package/src/controls/InspectorPanel.tsx +0 -37
- package/src/controls/LazySuggestionsComboboxControl.tsx +0 -64
- package/src/controls/MultiSelectControl.tsx +0 -59
- package/src/controls/PickOne.tsx +0 -88
- package/src/controls/PromisableComponent.tsx +0 -56
- package/src/controls/ProperLinkControl.tsx +0 -98
- package/src/controls/SimpleToggle.tsx +0 -9
- package/src/controls/SortableFlexibleItemsControl.tsx +0 -37
- package/src/controls/SortableItemsControl.tsx +0 -22
- package/src/controls/basicNumericallyIdedItemPicker.tsx +0 -75
- package/src/controls/hooks/useImprovedTokenManager.ts +0 -163
- package/src/controls/hooks/useMultiSingleConversionLayer.ts +0 -17
- package/src/controls/hooks/useNonRenderingCounter.ts +0 -6
- package/src/controls/hooks/useOutputMemoizingFilter.ts +0 -16
- package/src/controls/hooks/useSortableItemsModel.ts +0 -196
- package/src/controls/hooks/useSuggestions.ts +0 -91
- package/src/controls/hooks/useTokenManager.ts +0 -177
- package/src/controls/index.ts +0 -24
- package/src/controls/shared.ts +0 -50
- package/src/controls/types.ts +0 -18
- package/src/editor/insert-sibling-or-child-block-shortcut.tsx +0 -60
- package/src/editor/install-insert-sole-allowed-block-shortcut-support.tsx +0 -51
- package/src/editor/simple-gutenberg-endpoints-api.ts +0 -31
- package/src/editor/simple-gutenberg-endpoints-impl.ts +0 -126
- package/src/index.ts +0 -30
- package/src/lib/compat-types.ts +0 -21
- package/src/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.ts +0 -35
- package/src/lib/gutenberg-api-extensions-state/general-logic.ts +0 -41
- package/src/lib/gutenberg-api-extensions-state/layered-block-styles-logic.ts +0 -43
- package/src/lib/gutenberg-api-extensions-state/snp-logic.ts +0 -240
- package/src/lib/gutenberg-api-extensions-state.ts +0 -69
- package/src/lib/helpers.ts +0 -115
- package/src/lib/modified-fast-deep-equals.ts +0 -91
- package/src/lib/plaudit-icons/column-1.tsx +0 -6
- package/src/lib/plaudit-icons/column-2.tsx +0 -6
- package/src/lib/plaudit-icons/column-3.tsx +0 -6
- package/src/lib/plaudit-icons/placement-center.tsx +0 -3
- package/src/lib/plaudit-icons/placement-end.tsx +0 -3
- package/src/lib/plaudit-icons/placement-start.tsx +0 -3
- package/src/lib/plaudit-icons/placement-stretch.tsx +0 -3
- package/src/lib/plaudit-icons/plaudit-icon.tsx +0 -4
- package/src/lib/plaudit-icons/reusable-block-marker.tsx +0 -3
- package/src/lib/plaudit-icons.ts +0 -13
- package/src/lib/sectioned-cache-store.ts +0 -120
- package/src/lib/suspense/promise-handlers.ts +0 -72
- package/src/lib/suspense.tsx +0 -18
- package/src/lib/useful-types.ts +0 -82
- package/src/schemas/README.md +0 -1
- package/src/schemas/plaudit-block-schema.json +0 -818
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.96.0] - 2026-04-29
|
|
9
|
+
### Added
|
|
10
|
+
- `setAttributes` to `ActualBlockListBlockProps`
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
- The `src` folder from the list of included files
|
|
14
|
+
- All it was doing was causing problems with contextual suggestions
|
|
15
|
+
|
|
16
|
+
## [2.95.0] - 2026-04-28
|
|
17
|
+
### Added
|
|
18
|
+
- An entrypoint for `lib/useful-types` for use with rollup
|
|
19
|
+
|
|
8
20
|
## [2.94.2] - 2026-04-28
|
|
9
21
|
### Fixed
|
|
10
22
|
- The `useful-types` export being incorrectly forced to a type-only export
|
|
@@ -18,10 +18,7 @@ export type ActualBlockEditProps = {
|
|
|
18
18
|
name: BlockName;
|
|
19
19
|
clientId: string;
|
|
20
20
|
};
|
|
21
|
-
export type ActualBlockListBlockProps = {
|
|
22
|
-
attributes: ActualBEPAttrs;
|
|
23
|
-
name: BlockName;
|
|
24
|
-
clientId: string;
|
|
21
|
+
export type ActualBlockListBlockProps = ActualBlockEditProps & {
|
|
25
22
|
className?: string;
|
|
26
23
|
style?: Record<string, unknown>;
|
|
27
24
|
wrapperProps?: Record<string, unknown>;
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaudit/gutenberg-api-extensions",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.96.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist",
|
|
7
7
|
"./styles",
|
|
8
|
-
"./src",
|
|
9
8
|
"CHANGELOG.md",
|
|
10
9
|
"LICENSE.md",
|
|
11
10
|
"README.md",
|
|
@@ -14,11 +13,12 @@
|
|
|
14
13
|
"sideEffects": false,
|
|
15
14
|
"exports": {
|
|
16
15
|
".": "./dist/index.js",
|
|
17
|
-
"./lib/plaudit-icons": "./dist/lib/plaudit-icons.js",
|
|
18
16
|
"./blocks": "./dist/blocks/index.js",
|
|
19
17
|
"./blocks/csnp-api": "./dist/blocks/csnp-api.js",
|
|
20
18
|
"./blocks/snp-api": "./dist/blocks/snp-api.js",
|
|
21
|
-
"./controls": "./dist/controls/index.js"
|
|
19
|
+
"./controls": "./dist/controls/index.js",
|
|
20
|
+
"./lib/plaudit-icons": "./dist/lib/plaudit-icons.js",
|
|
21
|
+
"./lib/useful-types": "./dist/lib/useful-types.js"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@reduxjs/toolkit": "^2.11.2",
|
package/src/blocks/MoveError.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type {RawPath} from "./simple-native-property-api";
|
|
2
|
-
|
|
3
|
-
export class MoveError extends Error {
|
|
4
|
-
constructor(message: string, path: RawPath, {from, to}: {from: number, to: number}|{from: string, to: string}) {
|
|
5
|
-
super(`${message}: ${path.join(".")}.{${from} => ${to}}`);
|
|
6
|
-
}
|
|
7
|
-
}
|
package/src/blocks/PathError.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type {RawPath} from "./simple-native-property-api";
|
|
2
|
-
|
|
3
|
-
export enum PathErrorType {
|
|
4
|
-
UNKNOWN,
|
|
5
|
-
UNEXPECTED_LEAF,
|
|
6
|
-
INSUFFICIENT_LENGTH
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class PathError extends Error {
|
|
10
|
-
constructor(
|
|
11
|
-
message: string,
|
|
12
|
-
public readonly path: RawPath,
|
|
13
|
-
public readonly errorIndex: number = path.length - 1,
|
|
14
|
-
public readonly errorType = PathErrorType.UNKNOWN
|
|
15
|
-
) {
|
|
16
|
-
super(`${message} Full Path: ${path.join('.')}; Error Path: ${path.slice(0, errorIndex + 1).join('.')}`);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import {useCallback} from "@wordpress/element";
|
|
2
|
-
|
|
3
|
-
import type {FlexibleItemsListPropertyConfig} from "./csnp-api";
|
|
4
|
-
import {type FlexibleItem, SortableFlexibleItemsControl} from "../controls";
|
|
5
|
-
import {makeLaidOutPropertyRow} from "./layout/LaidOutPropertyRow";
|
|
6
|
-
import {NodeContextWrapper, useNodeContext} from "./layout/NodeContext";
|
|
7
|
-
import type {NonEmptyArray} from "../lib/useful-types";
|
|
8
|
-
import type {CSNPControlComponentProps} from "./shared-internal-types";
|
|
9
|
-
import type {HydratedSimpleNativeProperty, SNPControlSlots} from "./simple-native-property-api";
|
|
10
|
-
|
|
11
|
-
export type SNPFlexibleItemsListComponentProps<T extends string> = CSNPControlComponentProps<FlexibleItemsListPropertyConfig<T>, FlexibleItem<T>[], {
|
|
12
|
-
availableTypes: NonEmptyArray<{value: T, label: string}>, emptyValues: {[key in T]?: FlexibleItem<T>}
|
|
13
|
-
hydratedProperties: {[key in T]: (HydratedSimpleNativeProperty|HydratedSimpleNativeProperty[])[]}
|
|
14
|
-
}>&SNPControlSlots;
|
|
15
|
-
export function SNPFlexibleItemsListComponent(
|
|
16
|
-
{config, availableTypes, emptyValues, hydratedProperties, value, Label, Messages}: SNPFlexibleItemsListComponentProps<string>
|
|
17
|
-
) {
|
|
18
|
-
const context = useNodeContext("build a SNP List");
|
|
19
|
-
const onReorder = useCallback((oldIndex: number, newIndex: number) => context.moveNode({from: oldIndex, to: newIndex}), [context]);
|
|
20
|
-
const emptyValueBuilder = useCallback((type: string) => ({...emptyValues[type], type}), [emptyValues]);
|
|
21
|
-
const childRenderer = useCallback((datum: FlexibleItem, onDatumChange: (datum: FlexibleItem) => void, index: number) => {
|
|
22
|
-
return <NodeContextWrapper nodeName={index} children={(hydratedProperties[datum.type] ?? []).map(property => makeLaidOutPropertyRow({property}))} />;
|
|
23
|
-
}, [hydratedProperties]);
|
|
24
|
-
|
|
25
|
-
return <SortableFlexibleItemsControl
|
|
26
|
-
availableTypes={availableTypes} emptyValueBuilder={emptyValueBuilder}
|
|
27
|
-
value={value} min={config.min} max={config.max} Label={Label} Messages={Messages} help={config.help}
|
|
28
|
-
{...config.component} onAdd={context.addNode} onRemove={context.removeNode} onReorder={onReorder} children={childRenderer}
|
|
29
|
-
/>;
|
|
30
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import {__experimentalToolsPanel as ToolsPanel} from "@wordpress/components";
|
|
2
|
-
import {useCallback} from "@wordpress/element";
|
|
3
|
-
|
|
4
|
-
import type {GroupPropertyCSNPConfig} from "./csnp-api";
|
|
5
|
-
import type {Dict} from "../controls";
|
|
6
|
-
import {LaidOutPropertyRow, makeLaidOutPropertyRow} from "./layout/LaidOutPropertyRow";
|
|
7
|
-
import {useNodeContext} from "./layout/NodeContext";
|
|
8
|
-
import type {CSNPControlComponentProps} from "./shared-internal-types";
|
|
9
|
-
import type {SNPControlSlots} from "./simple-native-property-api";
|
|
10
|
-
import type {HydratedLaidOutProperties} from "./simple-native-property-internal-shared";
|
|
11
|
-
|
|
12
|
-
export type SNPGroupComponentProps = CSNPControlComponentProps<GroupPropertyCSNPConfig, Dict<any>, {hydratedProperties: HydratedLaidOutProperties}>&SNPControlSlots;
|
|
13
|
-
export function SNPGroupComponent({config, hydratedProperties, Label, Messages}: SNPGroupComponentProps) {
|
|
14
|
-
if (config.interface === 'toolsPanel') {
|
|
15
|
-
const {value, setValue} = useNodeContext("render a toolsPanel");
|
|
16
|
-
return <>
|
|
17
|
-
<ToolsPanel
|
|
18
|
-
{...config.component}
|
|
19
|
-
className={config.component?.className ? `plaudit-snp-group-component ${config.component.className}` : "plaudit-snp-group-component"}
|
|
20
|
-
label={config.label}
|
|
21
|
-
resetAll={useCallback(resetAllFilters => {
|
|
22
|
-
setValue((resetAllFilters ?? []).reduce((q: any, filter) => filter(q), value))
|
|
23
|
-
}, [value, setValue])}
|
|
24
|
-
>
|
|
25
|
-
{...hydratedProperties.map(property => makeLaidOutPropertyRow({property, inToolsPanel: true}))}
|
|
26
|
-
</ToolsPanel>
|
|
27
|
-
<Messages/>
|
|
28
|
-
</>;
|
|
29
|
-
} else {
|
|
30
|
-
return <fieldset {...config.component} className={config.component?.className ? `plaudit-snp-group-component ${config.component.className}` : "plaudit-snp-group-component"}>
|
|
31
|
-
<legend><Label/></legend>
|
|
32
|
-
<div className="plaudit-snp-laid-out-properties-wrapper">
|
|
33
|
-
{...hydratedProperties.map(property => makeLaidOutPropertyRow({property}))}
|
|
34
|
-
</div>
|
|
35
|
-
<Messages/>
|
|
36
|
-
</fieldset>;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import {useCallback, useMemo} from "@wordpress/element";
|
|
2
|
-
|
|
3
|
-
import type {ObjectListPropertyConfig} from "./csnp-api";
|
|
4
|
-
import {type Dict, SortableItemsControl} from "../controls";
|
|
5
|
-
import {LaidOutPropertyRow, makeLaidOutPropertyRow} from "./layout/LaidOutPropertyRow";
|
|
6
|
-
import {NodeContextWrapper, useNodeContext} from "./layout/NodeContext";
|
|
7
|
-
import type {CSNPControlComponentProps} from "./shared-internal-types";
|
|
8
|
-
import type {HydratedSimpleNativeProperty, SNPControlSlots} from "./simple-native-property-api";
|
|
9
|
-
|
|
10
|
-
export type SNPListComponentProps = CSNPControlComponentProps<ObjectListPropertyConfig, Dict<any>[], {
|
|
11
|
-
hydratedProperties: (HydratedSimpleNativeProperty|HydratedSimpleNativeProperty[])[]
|
|
12
|
-
}>&SNPControlSlots;
|
|
13
|
-
export function SNPListComponent({config, hydratedProperties, value, Label, Messages}: SNPListComponentProps) {
|
|
14
|
-
const context = useNodeContext("build a SNP List");
|
|
15
|
-
const onReorder = useCallback((oldIndex: number, newIndex: number) => context.moveNode({from: oldIndex, to: newIndex}), [context]);
|
|
16
|
-
const emptyValue = useMemo(() => config.emptyValue ?? {}, [config.emptyValue]);
|
|
17
|
-
const childRenderer = useCallback((datum: Dict<any>, onDatumChange: (datum: Dict<any>) => void, index: number) => {
|
|
18
|
-
return <NodeContextWrapper nodeName={index} children={hydratedProperties.map(property => makeLaidOutPropertyRow({property}))} />
|
|
19
|
-
}, [hydratedProperties]);
|
|
20
|
-
|
|
21
|
-
return <SortableItemsControl
|
|
22
|
-
value={value} min={config.min} max={config.max} Label={Label} Messages={Messages} help={config.help} emptyValue={emptyValue}
|
|
23
|
-
{...config.component} onAdd={context.addNode} onRemove={context.removeNode} onReorder={onReorder} onChange={context.setValue} children={childRenderer}
|
|
24
|
-
/>;
|
|
25
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import {createContext, useContext} from "@wordpress/element";
|
|
2
|
-
|
|
3
|
-
import type {DataController} from "./simple-native-property-api";
|
|
4
|
-
|
|
5
|
-
export const SNPTreeContext = createContext<DataController|undefined>(undefined);
|
|
6
|
-
|
|
7
|
-
export function useSNPTreeContext(action: string) {
|
|
8
|
-
const SNPTreeContextValue = useContext(SNPTreeContext);
|
|
9
|
-
if (SNPTreeContextValue === undefined) {
|
|
10
|
-
throw new Error(`Cannot ${action} outside of a SNPTreeContext`);
|
|
11
|
-
}
|
|
12
|
-
return SNPTreeContextValue;
|
|
13
|
-
}
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import apiFetch from "@wordpress/api-fetch"
|
|
2
|
-
import {getBlockBindingsSources, type registerBlockBindingsSource} from "@wordpress/blocks";
|
|
3
|
-
import {InspectorAdvancedControls, useBlockBindingsUtils} from "@wordpress/block-editor";
|
|
4
|
-
import {
|
|
5
|
-
__experimentalToolsPanel as ToolsPanel,
|
|
6
|
-
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
7
|
-
SelectControl, Spinner, TextControl, Tooltip
|
|
8
|
-
} from '@wordpress/components';
|
|
9
|
-
import {createHigherOrderComponent} from "@wordpress/compose";
|
|
10
|
-
import {dispatch, select, useSuspenseSelect} from "@wordpress/data";
|
|
11
|
-
import {store as editorStore} from "@wordpress/editor";
|
|
12
|
-
import {memo, useMemo} from "@wordpress/element";
|
|
13
|
-
import {addFilter} from "@wordpress/hooks";
|
|
14
|
-
|
|
15
|
-
import {registerSimpleGutenbergApiEndpoint} from "../editor/simple-gutenberg-endpoints-api";
|
|
16
|
-
import {store as endpointsStore} from "../editor/simple-gutenberg-endpoints-impl";
|
|
17
|
-
import {store as apiExtensionsStore} from "../lib/gutenberg-api-extensions-state";
|
|
18
|
-
import type {ActualBlockEditProps, BlockName, DbSource} from "../lib/useful-types";
|
|
19
|
-
|
|
20
|
-
import {type ReactElement, Suspense} from "react";
|
|
21
|
-
import {ErrorBoundary, FallbackProps} from "react-error-boundary";
|
|
22
|
-
|
|
23
|
-
const BLOCK_BINDINGS_ALLOWED_BLOCKS: {[key: BlockName]: string[]} = {
|
|
24
|
-
'core/paragraph': ['content'],
|
|
25
|
-
'core/heading': ['content'],
|
|
26
|
-
'core/image': ['id', 'url', 'title', 'alt'],
|
|
27
|
-
'core/button': ['url', 'text', 'linkTarget', 'rel']
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
type CBBParams = {dbSources?: DbSource[]/*, supportsContext?: boolean*/};
|
|
31
|
-
export function registerCustomBlockBindingsSource(args: Parameters<typeof registerBlockBindingsSource>[0]&CBBParams) {
|
|
32
|
-
installCustomBlockBindingsSupport();
|
|
33
|
-
dispatch(apiExtensionsStore).registerCustomBlockBindingsSource(args);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function installCustomBlockBindingsSupport() {
|
|
37
|
-
if (installCustomBlockBindingsSupport.called) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
installCustomBlockBindingsSupport.called = true;
|
|
41
|
-
|
|
42
|
-
registerSimpleGutenbergApiEndpoint(
|
|
43
|
-
"plaudit-base.custom-bindings.source.options",
|
|
44
|
-
data => apiFetch<Array<{id: number, title: string, type: string}>>({data, method: 'POST', path: "/plaudit/base/v1/custom-bindings/source/options"}),
|
|
45
|
-
{maxCachedResults: 20}
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
addFilter('editor.BlockEdit', 'plaudit/gutenberg-api-extensions/basic-custom-block-bindings-support',
|
|
49
|
-
createHigherOrderComponent(BlockEdit => function CustomBlockBindingsSupportBlockEdit(blockEditProps: ActualBlockEditProps) {
|
|
50
|
-
const availableBindingsList = BLOCK_BINDINGS_ALLOWED_BLOCKS[blockEditProps.name];
|
|
51
|
-
if (!availableBindingsList?.length) {
|
|
52
|
-
return <BlockEdit {...blockEditProps} />;
|
|
53
|
-
}
|
|
54
|
-
const {removeAllBlockBindings, updateBlockBindings} = useBlockBindingsUtils();
|
|
55
|
-
const currentPost = select(editorStore).getCurrentPost();
|
|
56
|
-
const bindingConfigs = useMemo(
|
|
57
|
-
() => {
|
|
58
|
-
return availableBindingsList.map((binding): [Parameters<typeof ToolsPanelItem>[0], BlockBindingToolProps] => {
|
|
59
|
-
return [
|
|
60
|
-
{
|
|
61
|
-
label: binding,
|
|
62
|
-
hasValue() {
|
|
63
|
-
return blockEditProps.attributes['metadata']?.['bindings']?.[binding] !== undefined;
|
|
64
|
-
},
|
|
65
|
-
onDeselect() {
|
|
66
|
-
updateBlockBindings({[binding]: undefined});
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
label: binding,
|
|
71
|
-
value: blockEditProps.attributes['metadata']?.['bindings']?.[binding],
|
|
72
|
-
currentPost,
|
|
73
|
-
binding
|
|
74
|
-
}
|
|
75
|
-
];
|
|
76
|
-
});
|
|
77
|
-
}, [blockEditProps.attributes, currentPost, availableBindingsList, updateBlockBindings]);
|
|
78
|
-
return <>
|
|
79
|
-
<BlockEdit {...blockEditProps} />
|
|
80
|
-
<InspectorAdvancedControls>
|
|
81
|
-
<ToolsPanel
|
|
82
|
-
label="Custom Block Bindings" resetAll={removeAllBlockBindings}
|
|
83
|
-
children={bindingConfigs.map(([bindingConfig, bbtConfig]) => (
|
|
84
|
-
<ToolsPanelItem key={bindingConfig.label} {...bindingConfig}>
|
|
85
|
-
<BlockBindingTool {...bbtConfig} />
|
|
86
|
-
</ToolsPanelItem>
|
|
87
|
-
))}
|
|
88
|
-
/>
|
|
89
|
-
</InspectorAdvancedControls>
|
|
90
|
-
</>;
|
|
91
|
-
}, 'plauditGutenbergApiExtensionsBasicBlockBindingsSupport')
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
type BlockBindingToolProps = {
|
|
95
|
-
value: { source: string, args: { [key: string]: any } } | undefined,
|
|
96
|
-
currentPost: any,
|
|
97
|
-
label: string,
|
|
98
|
-
binding: string
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
type SelectableOptions = Array<{ label: string, value: string, subfields: 'custom' | { label: string, value: string }[] }>;
|
|
102
|
-
type GetSelectableOptionsResponse = Array<{
|
|
103
|
-
label: string,
|
|
104
|
-
value: string,
|
|
105
|
-
subfields: 'custom' | { label: string, value: string }[],
|
|
106
|
-
disabled?: string | boolean,
|
|
107
|
-
binding: string
|
|
108
|
-
}>;
|
|
109
|
-
const BlockBindingTool = memo(({label, value, binding, currentPost}: BlockBindingToolProps) => {
|
|
110
|
-
const bindingSources = Object.entries(getBlockBindingsSources())
|
|
111
|
-
.filter(([key]) => key !== 'core/pattern-overrides' && key !== 'core/post-meta')
|
|
112
|
-
.map(([key, {label}]) => ({label, value: key}));
|
|
113
|
-
const {updateBlockBindings} = useBlockBindingsUtils();
|
|
114
|
-
|
|
115
|
-
return <fieldset className="custom-bindings-configuration-chain" style={{border: "revert", padding: "revert", margin: "revert"}}>
|
|
116
|
-
<legend>{label}</legend>
|
|
117
|
-
<SelectControl
|
|
118
|
-
key="source"
|
|
119
|
-
label="Source"
|
|
120
|
-
__next40pxDefaultSize
|
|
121
|
-
__nextHasNoMarginBottom
|
|
122
|
-
onChange={source => updateBlockBindings({[binding]: {source, args: {}}})}
|
|
123
|
-
options={[
|
|
124
|
-
{
|
|
125
|
-
disabled: true,
|
|
126
|
-
label: "Select a Binding Source",
|
|
127
|
-
value: ''
|
|
128
|
-
},
|
|
129
|
-
...bindingSources
|
|
130
|
-
]}
|
|
131
|
-
value={value?.source ?? ''}
|
|
132
|
-
/>
|
|
133
|
-
<ErrorBoundary FallbackComponent={Fallback} onError={console.error}>
|
|
134
|
-
<Suspense fallback={<p><Spinner/> Loading Binding Options</p>}>
|
|
135
|
-
<SourceSubconfig value={value} currentPost={currentPost} binding={binding} />
|
|
136
|
-
</Suspense>
|
|
137
|
-
</ErrorBoundary>
|
|
138
|
-
</fieldset>
|
|
139
|
-
});
|
|
140
|
-
const SourceSubconfig = memo(({currentPost, value, binding}: Omit<BlockBindingToolProps, 'label'>) => {
|
|
141
|
-
type SuspenseResult = {selectableOptions: NonNullable<Parameters<typeof SelectControl>[0]['options']>, params: CBBParams};
|
|
142
|
-
const {selectableOptions, params: {dbSources/*, supportsContext*/}} = useSuspenseSelect((select): SuspenseResult => {
|
|
143
|
-
if (value?.source) {
|
|
144
|
-
const sourceQueryArgs = {current_post: currentPost, source: value.source};
|
|
145
|
-
const sourceOptions = select(endpointsStore).get("plaudit-base.custom-bindings.source.options", sourceQueryArgs) as GetSelectableOptionsResponse;
|
|
146
|
-
return {
|
|
147
|
-
selectableOptions: sourceOptions.map(option => {
|
|
148
|
-
return typeof option.disabled === 'string'
|
|
149
|
-
? {...option, label: `${option.label} (${option.disabled})`, disabled: true}
|
|
150
|
-
: {...option, disabled: !!option.disabled};
|
|
151
|
-
}),
|
|
152
|
-
params: select(apiExtensionsStore).customBlockBindingsSource(value.source) ?? {}
|
|
153
|
-
};
|
|
154
|
-
} else {
|
|
155
|
-
return {selectableOptions: [], params: {}};
|
|
156
|
-
}
|
|
157
|
-
}, [currentPost, value?.source]);
|
|
158
|
-
const {updateBlockBindings} = useBlockBindingsUtils();
|
|
159
|
-
|
|
160
|
-
const subfieldKeys = useMemo<SelectableOptions[number]['subfields']>(() => {
|
|
161
|
-
if (Array.isArray(selectableOptions)) {
|
|
162
|
-
const key = value?.args['key'];
|
|
163
|
-
return key ? selectableOptions.find(option => option.value === key)?.subfields ?? [] : [];
|
|
164
|
-
}
|
|
165
|
-
return [];
|
|
166
|
-
}, [selectableOptions, value?.args['key']]);
|
|
167
|
-
|
|
168
|
-
const controls: ReactElement[] = [];
|
|
169
|
-
if (selectableOptions.length) {
|
|
170
|
-
controls.push(<SelectControl
|
|
171
|
-
key="field"
|
|
172
|
-
label="Field"
|
|
173
|
-
__next40pxDefaultSize
|
|
174
|
-
__nextHasNoMarginBottom
|
|
175
|
-
// We exclude subfield from this update because we need to reset it when the selected field changes
|
|
176
|
-
onChange={key => updateBlockBindings({[binding]: (value ? {...value, args: {key}} : undefined)})}
|
|
177
|
-
options={[
|
|
178
|
-
{
|
|
179
|
-
disabled: true,
|
|
180
|
-
label: "Select a Field",
|
|
181
|
-
value: ''
|
|
182
|
-
},
|
|
183
|
-
...selectableOptions
|
|
184
|
-
]}
|
|
185
|
-
value={value?.args['key'] ?? ''}
|
|
186
|
-
/>);
|
|
187
|
-
|
|
188
|
-
if (subfieldKeys.length) {
|
|
189
|
-
if (subfieldKeys === 'custom') {
|
|
190
|
-
controls.push(<TextControl
|
|
191
|
-
key="subfield"
|
|
192
|
-
label="Subfield"
|
|
193
|
-
__next40pxDefaultSize
|
|
194
|
-
__nextHasNoMarginBottom
|
|
195
|
-
onChange={subfield => updateBlockBindings({[binding]: (value ? {...value, args: {...value.args, subfield}} : undefined)})}
|
|
196
|
-
value={value?.args['subfield'] ?? ''}
|
|
197
|
-
help="Please enter the name of a subfield. You may need to inspect the raw data from this binding to determine the subfield."
|
|
198
|
-
/>);
|
|
199
|
-
} else {
|
|
200
|
-
controls.push(<SelectControl
|
|
201
|
-
key="subfield"
|
|
202
|
-
label="Subfield"
|
|
203
|
-
__next40pxDefaultSize
|
|
204
|
-
__nextHasNoMarginBottom
|
|
205
|
-
onChange={subfield => updateBlockBindings({[binding]: (value ? {...value, args: {...value.args, subfield}} : undefined)})}
|
|
206
|
-
options={[
|
|
207
|
-
{
|
|
208
|
-
disabled: true,
|
|
209
|
-
label: "Select a Subfield",
|
|
210
|
-
value: ''
|
|
211
|
-
},
|
|
212
|
-
...subfieldKeys
|
|
213
|
-
]}
|
|
214
|
-
value={value?.args['subfield'] ?? ''}
|
|
215
|
-
/>);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (value?.args['key'] && dbSources?.length) {
|
|
220
|
-
controls.push(<SelectControl
|
|
221
|
-
key="db-source"
|
|
222
|
-
label="DB Source"
|
|
223
|
-
__next40pxDefaultSize
|
|
224
|
-
__nextHasNoMarginBottom
|
|
225
|
-
onChange={db_source => updateBlockBindings({[binding]: (value ? {...value, args: {...value.args, db_source}} : undefined)})}
|
|
226
|
-
options={dbSources}
|
|
227
|
-
value={value?.args['db_source'] ?? dbSources[0]!.value}
|
|
228
|
-
help={dbSources.find(dbs => dbs.value === value?.args['db_source'])?.help}
|
|
229
|
-
/>);
|
|
230
|
-
} else if (value?.args['db_source']) {
|
|
231
|
-
const {db_source, ...updatedArgs} = value.args;
|
|
232
|
-
updateBlockBindings({[binding]: {...value, args: updatedArgs}});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (controls.length === 0) {
|
|
236
|
-
controls.push(<p key="no-options-found-text">No Options Found</p>);
|
|
237
|
-
}
|
|
238
|
-
return controls;
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
export namespace installCustomBlockBindingsSupport {
|
|
242
|
-
export let called: boolean = false;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function Fallback({error}: FallbackProps) {
|
|
246
|
-
const baseDisplay = <p style={{color: '#CC1818'}}>An error occurred while loading binding options</p>;
|
|
247
|
-
return typeof error === 'object' && error && 'message' in error && typeof error.message === 'string' ? <Tooltip text={error.message}>{baseDisplay}</Tooltip> : baseDisplay;
|
|
248
|
-
}
|