@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.
Files changed (103) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/lib/useful-types.d.ts +1 -4
  3. package/package.json +4 -4
  4. package/src/blocks/MoveError.ts +0 -7
  5. package/src/blocks/PathError.ts +0 -18
  6. package/src/blocks/SNPFlexibleItemsListComponent.tsx +0 -30
  7. package/src/blocks/SNPGroupComponent.tsx +0 -38
  8. package/src/blocks/SNPListComponent.tsx +0 -25
  9. package/src/blocks/SNPTreeContext.tsx +0 -13
  10. package/src/blocks/basic-custom-block-bindings-support.tsx +0 -248
  11. package/src/blocks/common-native-property-constructors.tsx +0 -927
  12. package/src/blocks/conditions.ts +0 -261
  13. package/src/blocks/csnp-api.ts +0 -221
  14. package/src/blocks/data-controller/actions.ts +0 -20
  15. package/src/blocks/data-controller/reducer.ts +0 -146
  16. package/src/blocks/data-controller/trigger-handlers.ts +0 -150
  17. package/src/blocks/data-controller/utils.ts +0 -415
  18. package/src/blocks/data-controller-manager.ts +0 -50
  19. package/src/blocks/data-controller.ts +0 -165
  20. package/src/blocks/hooks/built-in-suspendable-option-protocols/select.ts +0 -51
  21. package/src/blocks/hooks/built-in-suspendable-option-protocols/settings.ts +0 -70
  22. package/src/blocks/hooks/useSuspendableOptions.ts +0 -122
  23. package/src/blocks/index.ts +0 -23
  24. package/src/blocks/layered-styles-api.ts +0 -142
  25. package/src/blocks/layered-styles-impl.ts +0 -95
  26. package/src/blocks/layout/LaidOutProperty.tsx +0 -72
  27. package/src/blocks/layout/LaidOutPropertyRow.tsx +0 -28
  28. package/src/blocks/layout/NodeContext.tsx +0 -54
  29. package/src/blocks/layout/PanelRoot.tsx +0 -30
  30. package/src/blocks/layout/TabsRoot.tsx +0 -56
  31. package/src/blocks/layout/ToolsPanelContext.tsx +0 -22
  32. package/src/blocks/problematic-blocks-blocker.ts +0 -24
  33. package/src/blocks/problematic-variations-blocker.ts +0 -32
  34. package/src/blocks/shared-exportable-types.ts +0 -6
  35. package/src/blocks/shared-internal-types.ts +0 -18
  36. package/src/blocks/simple-block.tsx +0 -74
  37. package/src/blocks/simple-native-property-api.ts +0 -173
  38. package/src/blocks/simple-native-property-impl.tsx +0 -335
  39. package/src/blocks/simple-native-property-internal-shared.ts +0 -19
  40. package/src/blocks/snp-api.ts +0 -5
  41. package/src/blocks/snp-data-store.ts +0 -72
  42. package/src/blocks/utilities.ts +0 -66
  43. package/src/controls/AsynchronousFormTokenField.tsx +0 -86
  44. package/src/controls/BaseSortableItemsControl.tsx +0 -84
  45. package/src/controls/ExtendedFormTokenField.tsx +0 -144
  46. package/src/controls/ExtendedPostPicker.ts +0 -57
  47. package/src/controls/ExtendedRadioControl.tsx +0 -107
  48. package/src/controls/ExtendedTaxonomyPicker.tsx +0 -100
  49. package/src/controls/ExtendedTermPicker.tsx +0 -61
  50. package/src/controls/ExtendedTextareaControl.tsx +0 -65
  51. package/src/controls/ExtendedUserPicker.ts +0 -56
  52. package/src/controls/FileControl.tsx +0 -48
  53. package/src/controls/FullSizeToggleControl.tsx +0 -95
  54. package/src/controls/ImageControl.tsx +0 -143
  55. package/src/controls/InspectorPanel.tsx +0 -37
  56. package/src/controls/LazySuggestionsComboboxControl.tsx +0 -64
  57. package/src/controls/MultiSelectControl.tsx +0 -59
  58. package/src/controls/PickOne.tsx +0 -88
  59. package/src/controls/PromisableComponent.tsx +0 -56
  60. package/src/controls/ProperLinkControl.tsx +0 -98
  61. package/src/controls/SimpleToggle.tsx +0 -9
  62. package/src/controls/SortableFlexibleItemsControl.tsx +0 -37
  63. package/src/controls/SortableItemsControl.tsx +0 -22
  64. package/src/controls/basicNumericallyIdedItemPicker.tsx +0 -75
  65. package/src/controls/hooks/useImprovedTokenManager.ts +0 -163
  66. package/src/controls/hooks/useMultiSingleConversionLayer.ts +0 -17
  67. package/src/controls/hooks/useNonRenderingCounter.ts +0 -6
  68. package/src/controls/hooks/useOutputMemoizingFilter.ts +0 -16
  69. package/src/controls/hooks/useSortableItemsModel.ts +0 -196
  70. package/src/controls/hooks/useSuggestions.ts +0 -91
  71. package/src/controls/hooks/useTokenManager.ts +0 -177
  72. package/src/controls/index.ts +0 -24
  73. package/src/controls/shared.ts +0 -50
  74. package/src/controls/types.ts +0 -18
  75. package/src/editor/insert-sibling-or-child-block-shortcut.tsx +0 -60
  76. package/src/editor/install-insert-sole-allowed-block-shortcut-support.tsx +0 -51
  77. package/src/editor/simple-gutenberg-endpoints-api.ts +0 -31
  78. package/src/editor/simple-gutenberg-endpoints-impl.ts +0 -126
  79. package/src/index.ts +0 -30
  80. package/src/lib/compat-types.ts +0 -21
  81. package/src/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.ts +0 -35
  82. package/src/lib/gutenberg-api-extensions-state/general-logic.ts +0 -41
  83. package/src/lib/gutenberg-api-extensions-state/layered-block-styles-logic.ts +0 -43
  84. package/src/lib/gutenberg-api-extensions-state/snp-logic.ts +0 -240
  85. package/src/lib/gutenberg-api-extensions-state.ts +0 -69
  86. package/src/lib/helpers.ts +0 -115
  87. package/src/lib/modified-fast-deep-equals.ts +0 -91
  88. package/src/lib/plaudit-icons/column-1.tsx +0 -6
  89. package/src/lib/plaudit-icons/column-2.tsx +0 -6
  90. package/src/lib/plaudit-icons/column-3.tsx +0 -6
  91. package/src/lib/plaudit-icons/placement-center.tsx +0 -3
  92. package/src/lib/plaudit-icons/placement-end.tsx +0 -3
  93. package/src/lib/plaudit-icons/placement-start.tsx +0 -3
  94. package/src/lib/plaudit-icons/placement-stretch.tsx +0 -3
  95. package/src/lib/plaudit-icons/plaudit-icon.tsx +0 -4
  96. package/src/lib/plaudit-icons/reusable-block-marker.tsx +0 -3
  97. package/src/lib/plaudit-icons.ts +0 -13
  98. package/src/lib/sectioned-cache-store.ts +0 -120
  99. package/src/lib/suspense/promise-handlers.ts +0 -72
  100. package/src/lib/suspense.tsx +0 -18
  101. package/src/lib/useful-types.ts +0 -82
  102. package/src/schemas/README.md +0 -1
  103. 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.94.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",
@@ -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
- }
@@ -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
- }