@plaudit/gutenberg-api-extensions 2.95.0 → 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 +8 -0
- package/dist/lib/useful-types.d.ts +1 -4
- package/package.json +1 -2
- 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
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import {createSlotFill, __experimentalToolsPanelItem as ToolsPanelItem, Spinner} from "@wordpress/components";
|
|
2
|
-
import {memo, useCallback, useMemo} from "@wordpress/element";
|
|
3
|
-
|
|
4
|
-
import {type NodeContextValue, useNodeContext} from "./NodeContext";
|
|
5
|
-
import type {HydratedSimpleNativeProperty, SNPControlSlots} from "../simple-native-property-api";
|
|
6
|
-
import {useToolsPanelContext} from "./ToolsPanelContext";
|
|
7
|
-
|
|
8
|
-
import {Suspense} from "react";
|
|
9
|
-
|
|
10
|
-
export type LaidOutPropertyProps = {property: HydratedSimpleNativeProperty, inToolsPanel?: boolean};
|
|
11
|
-
export const LaidOutProperty = memo(function({property, inToolsPanel}: LaidOutPropertyProps) {
|
|
12
|
-
const nodeContext = useNodeContext("render a node");
|
|
13
|
-
if (nodeContext.rendered) {
|
|
14
|
-
return <ActualPropertyRenderer property={property} nodeContext={nodeContext} inToolsPanel={inToolsPanel} />;
|
|
15
|
-
}
|
|
16
|
-
return null;
|
|
17
|
-
});
|
|
18
|
-
const divStyle = {flex: "1"};
|
|
19
|
-
function ActualPropertyRenderer({property, nodeContext, inToolsPanel}: {property: HydratedSimpleNativeProperty, nodeContext: NodeContextValue, inToolsPanel?: boolean}) {
|
|
20
|
-
const [
|
|
21
|
-
{Slot: Label, Fill: LabelFill},
|
|
22
|
-
{Slot: Messages, Fill: MessagesFill}
|
|
23
|
-
] = useMemo(() => [
|
|
24
|
-
createSlotFill(Symbol("laid-out-property-label")),
|
|
25
|
-
createSlotFill(Symbol("laid-out-property-messages"))
|
|
26
|
-
], []);
|
|
27
|
-
const onBlur = useCallback(() => nodeContext.validateNode(), [nodeContext]);
|
|
28
|
-
|
|
29
|
-
const classNames = ["plaudit-snp-laid-out-property"];
|
|
30
|
-
if (property.required) {
|
|
31
|
-
classNames.push("required");
|
|
32
|
-
}
|
|
33
|
-
if (nodeContext.validationError) {
|
|
34
|
-
classNames.push("has-validation-error");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const transformedValue = useMemo(() => property.transformer ? property.transformer.to(nodeContext.value) : nodeContext.value,
|
|
38
|
-
[nodeContext.value, property.transformer]);
|
|
39
|
-
const onChangeWithTransform = useCallback((value: any) => {
|
|
40
|
-
nodeContext.setValue(property.transformer ? property.transformer.from(value) : value);
|
|
41
|
-
}, [nodeContext.setValue, property.transformer]);
|
|
42
|
-
|
|
43
|
-
const commonParts = <>
|
|
44
|
-
<LabelFill>{property.label}{property.required && <span className="requiredMarker">*</span>}</LabelFill>
|
|
45
|
-
<MessagesFill>
|
|
46
|
-
{nodeContext.validationError && <div className="validation-error-message">{nodeContext.validationError.split(/\r?\n/gi).map(line => <>{line}<br/></>)}</div>}
|
|
47
|
-
</MessagesFill>
|
|
48
|
-
</>;
|
|
49
|
-
if (inToolsPanel) {
|
|
50
|
-
const toolsPanelContext = useToolsPanelContext("render a tools-panel property");
|
|
51
|
-
return <ToolsPanelItem
|
|
52
|
-
label={property.label ?? property.name}
|
|
53
|
-
hasValue={useCallback(() => transformedValue !== undefined, [transformedValue])}
|
|
54
|
-
onSelect={useCallback(() => nodeContext.setValue(toolsPanelContext.getDefaultValue(property.name)), [nodeContext.setValue, toolsPanelContext, property.name])}
|
|
55
|
-
onDeselect={useCallback(() => nodeContext.setValue(undefined), [nodeContext.setValue])}
|
|
56
|
-
resetAllFilter={useCallback((a: any) => a ? Object.fromEntries(Object.entries(a).filter(([name]) => name !== property.name)) : a, [property.name])}
|
|
57
|
-
>
|
|
58
|
-
{commonParts}{renderPropInner(property, onBlur, classNames, transformedValue, onChangeWithTransform, {Label, Messages})}
|
|
59
|
-
</ToolsPanelItem>;
|
|
60
|
-
} else {
|
|
61
|
-
return <>{commonParts}{renderPropInner(property, onBlur, classNames, transformedValue, onChangeWithTransform, {Label, Messages})}</>;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function renderPropInner(
|
|
65
|
-
property: HydratedSimpleNativeProperty, onBlur: () => void, classNames: string[], transformedValue: any, onChangeWithTransform: (value: any) => void, slots: SNPControlSlots
|
|
66
|
-
) {
|
|
67
|
-
return <div style={divStyle} className={classNames.join(" ")} onBlur={onBlur} data-plaudit-snp-control-type={property.controlType}>
|
|
68
|
-
<Suspense fallback={typeof property.initializing === 'function' ? property.initializing() : <><Spinner /> {property.initializing}</>}>
|
|
69
|
-
<property.control value={transformedValue} onChange={onChangeWithTransform} slots={slots} />
|
|
70
|
-
</Suspense>
|
|
71
|
-
</div>;
|
|
72
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {LaidOutProperty} from "./LaidOutProperty";
|
|
2
|
-
import {NodeContextWrapper} from "./NodeContext";
|
|
3
|
-
import type {DataController} from "../simple-native-property-api";
|
|
4
|
-
import type {HydratedLaidOutProperties} from "../simple-native-property-internal-shared";
|
|
5
|
-
|
|
6
|
-
import React from "react";
|
|
7
|
-
|
|
8
|
-
type LaidOutPropertyRowProps = {property: HydratedLaidOutProperties[number], dataController?: DataController, inToolsPanel?: boolean};
|
|
9
|
-
export function LaidOutPropertyRow(
|
|
10
|
-
{property, dataController, inToolsPanel}: LaidOutPropertyRowProps
|
|
11
|
-
) {
|
|
12
|
-
if (Array.isArray(property)) {
|
|
13
|
-
return <div style={{display: "flex", flexWrap: "wrap", columnGap: "8px"}}>
|
|
14
|
-
{...property.map(prop => <NodeContextWrapper key={prop.name} nodeName={prop.name} dataController={dataController}>
|
|
15
|
-
<LaidOutProperty property={prop} inToolsPanel={inToolsPanel} />
|
|
16
|
-
</NodeContextWrapper>)}
|
|
17
|
-
</div>;
|
|
18
|
-
} else {
|
|
19
|
-
return <NodeContextWrapper nodeName={property.name} dataController={dataController}>
|
|
20
|
-
<LaidOutProperty property={property} inToolsPanel={inToolsPanel} />
|
|
21
|
-
</NodeContextWrapper>;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function makeLaidOutPropertyRow({property, ...args}: LaidOutPropertyRowProps) {
|
|
26
|
-
const key = Array.isArray(property) ? property.map(prop => prop.name).join('-') : property.name;
|
|
27
|
-
return <LaidOutPropertyRow key={key} property={property} {...args} />;
|
|
28
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import {createContext, useContext, useMemo} from "@wordpress/element";
|
|
2
|
-
|
|
3
|
-
import type {DataController, NodePath} from "../simple-native-property-api";
|
|
4
|
-
|
|
5
|
-
import type {ReactNode} from "react";
|
|
6
|
-
|
|
7
|
-
type NodeContextValueActions = {
|
|
8
|
-
setValue(value: any): void,
|
|
9
|
-
addNode(name: string|number, value?: any): void,
|
|
10
|
-
removeNode(name: string|number): void,
|
|
11
|
-
moveNode(indices: {from: number, to: number}|{from: string, to: string}): void,
|
|
12
|
-
validateNode(): void
|
|
13
|
-
};
|
|
14
|
-
export type NodeContextValue = {path: NodePath, dataController: DataController, rendered: boolean, validationError?: string, value: any}&NodeContextValueActions;
|
|
15
|
-
|
|
16
|
-
export const NodeContext = createContext<NodeContextValue|undefined>(undefined);
|
|
17
|
-
|
|
18
|
-
function makeNodeContextValue(path: NodePath, dataController: DataController): NodeContextValue {
|
|
19
|
-
const value = dataController.getValue(path);
|
|
20
|
-
const node = dataController.getNode(path);
|
|
21
|
-
// We memoize actions separately to reduce later re-render calls
|
|
22
|
-
const memoizedActions = useMemo<NodeContextValueActions>(() => ({
|
|
23
|
-
setValue: value => dataController.setValue(path, value),
|
|
24
|
-
addNode: (name, value) => dataController.addNode([...path, name], value),
|
|
25
|
-
removeNode: name => dataController.removeNode([...path, name]),
|
|
26
|
-
moveNode: indices => dataController.moveNode(path, indices),
|
|
27
|
-
validateNode: () => dataController.validateNode(path)
|
|
28
|
-
}), [path, dataController]);
|
|
29
|
-
// We can skip testing path and dataController because we're checking actions
|
|
30
|
-
return useMemo(() => ({path, dataController, rendered: node.rendered ?? true, validationError: node.validationError, value, ...memoizedActions}), [memoizedActions, node, value]);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function useNodeContext(action: string): NodeContextValue {
|
|
34
|
-
const currentContext = useContext(NodeContext);
|
|
35
|
-
if (currentContext === undefined) {
|
|
36
|
-
throw new Error(`Cannot ${action} outside of an existing NodeContext`);
|
|
37
|
-
}
|
|
38
|
-
return currentContext;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function DescendantNodeContext({nodeName, children}: {nodeName: string|number, children: ReactNode}) {
|
|
42
|
-
const currentContext = useNodeContext("create a descendant NodeContext");
|
|
43
|
-
const descendantPath = useMemo(
|
|
44
|
-
() => currentContext.path.toSpliced(currentContext.path.length, 0, nodeName) as NodePath, [nodeName, currentContext.path]);
|
|
45
|
-
return <NodeContext.Provider value={makeNodeContextValue(descendantPath, currentContext.dataController)} children={children} />;
|
|
46
|
-
}
|
|
47
|
-
export function RootNodeContext({nodeName, dataController, children}: {nodeName: string, dataController: DataController, children: ReactNode}) {
|
|
48
|
-
const path = useMemo<NodePath>(() => [nodeName], [nodeName]);
|
|
49
|
-
return <NodeContext.Provider value={makeNodeContextValue(path, dataController)} children={children} />;
|
|
50
|
-
}
|
|
51
|
-
type NodeContextWrapperProps = {nodeName: string|number, children: ReactNode, dataController?: undefined}|{nodeName: string, dataController: DataController, children: ReactNode};
|
|
52
|
-
export function NodeContextWrapper(props: NodeContextWrapperProps) {
|
|
53
|
-
return props.dataController !== undefined ? RootNodeContext(props) : DescendantNodeContext(props);
|
|
54
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import {InspectorControls} from "@wordpress/block-editor";
|
|
2
|
-
import {PanelBody} from "@wordpress/components";
|
|
3
|
-
import {cautionFilled} from "@wordpress/icons";
|
|
4
|
-
|
|
5
|
-
import {testCondition} from "../conditions";
|
|
6
|
-
import {makeLaidOutPropertyRow} from "./LaidOutPropertyRow";
|
|
7
|
-
import {HydratedSimpleNativePanel, isRootLevelPanelGroup} from "../simple-native-property-internal-shared";
|
|
8
|
-
import {useSNPTreeContext} from "../SNPTreeContext";
|
|
9
|
-
|
|
10
|
-
import type {ComponentPropsWithoutRef} from "react";
|
|
11
|
-
|
|
12
|
-
export type PanelRootProps = {panel: HydratedSimpleNativePanel};
|
|
13
|
-
export function PanelRoot({panel}: PanelRootProps) {
|
|
14
|
-
const {condition, properties, raw, ...panelBodyProps} = panel;
|
|
15
|
-
|
|
16
|
-
const dataController = useSNPTreeContext("construct a PanelRoot");
|
|
17
|
-
|
|
18
|
-
if (!dataController.hasRenderedNode(properties)
|
|
19
|
-
|| !testCondition(condition, dataController.makePropertyValueResolver([]))) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const bonusProps: Partial<ComponentPropsWithoutRef<typeof PanelBody>> = dataController.hasValidationErrors(properties)
|
|
24
|
-
? {icon: cautionFilled, buttonProps: {className: "has-validation-error components-panel__body-toggle"}} //We have to include the default button class for some insane reason
|
|
25
|
-
: {};
|
|
26
|
-
|
|
27
|
-
const panelGroup = panel.group === 'layered-styles' ? 'styles' : panel.group;
|
|
28
|
-
const children = properties.map(property => makeLaidOutPropertyRow({property, dataController}));
|
|
29
|
-
return <InspectorControls group={panelGroup} children={(raw ?? !isRootLevelPanelGroup(panelGroup)) ? children : <PanelBody {...panelBodyProps} {...bonusProps} children={children} />} />;
|
|
30
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import {InspectorControls} from "@wordpress/block-editor";
|
|
2
|
-
import {PanelBody, TabPanel} from "@wordpress/components";
|
|
3
|
-
|
|
4
|
-
import {testCondition} from "../conditions";
|
|
5
|
-
import {LaidOutPropertyRow, makeLaidOutPropertyRow} from "./LaidOutPropertyRow";
|
|
6
|
-
import type {DataController, InspectorPanelGroup} from "../simple-native-property-api";
|
|
7
|
-
import type {HydratedSimpleNativeTab, HydratedSimpleNativeTabItem, HydratedSimpleNativeTabGroup} from "../simple-native-property-internal-shared";
|
|
8
|
-
import {useSNPTreeContext} from "../SNPTreeContext";
|
|
9
|
-
|
|
10
|
-
import type {ComponentPropsWithoutRef, ReactNode} from "react";
|
|
11
|
-
|
|
12
|
-
type Tab = ComponentPropsWithoutRef<typeof TabPanel>['tabs'][number]&{panels: [boolean, HydratedSimpleNativeTab['items'][number], string][]};
|
|
13
|
-
|
|
14
|
-
export type TabsRootProps = {tabs: HydratedSimpleNativeTabGroup, tabGroupName: InspectorPanelGroup};
|
|
15
|
-
export function TabsRoot({tabs, tabGroupName}: TabsRootProps) {
|
|
16
|
-
//TODO: It should be possible to use immer to make this entire thing memoized
|
|
17
|
-
const dataController = useSNPTreeContext("construct a TabsRoot component");
|
|
18
|
-
const instantiatedTabs = instantiateTabsForRenderCycle(tabs, dataController);
|
|
19
|
-
if (instantiatedTabs.every(tab => tab.disabled)) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
return <InspectorControls group={tabGroupName}>
|
|
23
|
-
<TabPanel tabs={instantiatedTabs} children={tab => (tab as Tab).panels
|
|
24
|
-
.filter(([rendered]) => rendered)
|
|
25
|
-
.map(([_, panel, key]) => <RenderedTabPanel dataController={dataController} panel={panel} key={key} />)} />
|
|
26
|
-
</InspectorControls>;
|
|
27
|
-
}
|
|
28
|
-
//TODO: Figure out how to memoize this (will probably need some sort of panel/tab-based cache in the dataController)
|
|
29
|
-
function instantiateTabsForRenderCycle(hydratedTabs: {[name: string]: HydratedSimpleNativeTab}, dataController: DataController): Tab[] {
|
|
30
|
-
const propertyValueResolver = dataController.makePropertyValueResolver([]);
|
|
31
|
-
return Object.entries(hydratedTabs).map(([name, hydratedTab]) => {
|
|
32
|
-
const instantiatedPanels: Tab['panels'] = [];
|
|
33
|
-
let disabled = true;
|
|
34
|
-
let index = 0;
|
|
35
|
-
let hasValidationErrors = false;
|
|
36
|
-
for (const panel of hydratedTab.items) {
|
|
37
|
-
const rendered = dataController.hasRenderedNode(panel.properties) && (panel.condition === undefined || testCondition(panel.condition, propertyValueResolver));
|
|
38
|
-
if (rendered) {
|
|
39
|
-
if (!hasValidationErrors && dataController.hasValidationErrors(panel.properties)) {
|
|
40
|
-
hasValidationErrors = true;
|
|
41
|
-
}
|
|
42
|
-
disabled = false;
|
|
43
|
-
}
|
|
44
|
-
instantiatedPanels.push([rendered, panel, `rendered-tab-panel-${name}-${panel.title?.replaceAll(/\W+/gi, "-") ?? ""}-${index++}`]);
|
|
45
|
-
}
|
|
46
|
-
return {name, title: hydratedTab.title, panels: instantiatedPanels, disabled, className: hasValidationErrors ? "has-validation-error components-tab-panel__tabs-item" : undefined};
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
type RenderedTabPanelProps = {dataController: DataController, panel: HydratedSimpleNativeTabItem};
|
|
51
|
-
function RenderedTabPanel({dataController, panel}: RenderedTabPanelProps): ReactNode {
|
|
52
|
-
// We have already tested the rendered-ness of the Panel earlier, so there's no need to redo it
|
|
53
|
-
const {condition, properties, raw, ...panelBodyProps} = panel;
|
|
54
|
-
const children = properties.map(property => makeLaidOutPropertyRow({property, dataController}));
|
|
55
|
-
return raw ? children : <PanelBody {...panelBodyProps} opened={panelBodyProps.title ? undefined : true} children={children} />;
|
|
56
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {createContext, useContext, useMemo} from "@wordpress/element";
|
|
2
|
-
|
|
3
|
-
export type ToolsPanelContextValue = {getDefaultValue(name: string): unknown, panelId: string};
|
|
4
|
-
|
|
5
|
-
export const ToolsPanelContext = createContext<ToolsPanelContextValue|undefined>(undefined);
|
|
6
|
-
|
|
7
|
-
let nextPanelId = 0;
|
|
8
|
-
export function makeToolsPanelContextValue(actualDefaultValues: {[key in string]: unknown}): ToolsPanelContextValue {
|
|
9
|
-
const panelId = useMemo(() => (nextPanelId++).toString(), []);
|
|
10
|
-
return useMemo(() => ({
|
|
11
|
-
panelId,
|
|
12
|
-
getDefaultValue: (name: string) => actualDefaultValues[name]
|
|
13
|
-
}), [panelId, actualDefaultValues]);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function useToolsPanelContext(action: string): ToolsPanelContextValue {
|
|
17
|
-
const currentContext = useContext(ToolsPanelContext);
|
|
18
|
-
if (currentContext === undefined) {
|
|
19
|
-
throw new Error(`Cannot ${action} outside of an existing ToolsPanelContext`);
|
|
20
|
-
}
|
|
21
|
-
return currentContext;
|
|
22
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {addFilter} from "@wordpress/hooks";
|
|
2
|
-
|
|
3
|
-
import {type BlockName, isBlockName, type RegisterBlockAttrs} from "../lib/useful-types";
|
|
4
|
-
|
|
5
|
-
const blocksNamesToHide: Record<BlockName, boolean> = {};
|
|
6
|
-
|
|
7
|
-
export function markBlocksAsProblematic(...blockNames: (string|BlockName)[]) {
|
|
8
|
-
for (const blockName of blockNames) {
|
|
9
|
-
blocksNamesToHide[isBlockName(blockName) ? blockName : `core/${blockName}` satisfies BlockName] = true;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
addFilter('blocks.registerBlockType', 'plaudit-gutenberg-api-extensions/problematic-blocks-blocker', (atts: RegisterBlockAttrs) => {
|
|
14
|
-
if (blocksNamesToHide[atts.name]) {
|
|
15
|
-
return {
|
|
16
|
-
...atts,
|
|
17
|
-
supports: {
|
|
18
|
-
...(atts.supports ?? {}),
|
|
19
|
-
inserter: false
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return atts;
|
|
24
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {addFilter} from "@wordpress/hooks";
|
|
2
|
-
|
|
3
|
-
import type {BlockName, RegisterBlockAttrs} from "../lib/useful-types";
|
|
4
|
-
|
|
5
|
-
const blockVariationsToHide: Record<BlockName, Record<string, boolean>> = {};
|
|
6
|
-
|
|
7
|
-
export function markVariationsAsProblematic(blockName: BlockName, variations: string[]) {
|
|
8
|
-
const variationsToHide = blockVariationsToHide[blockName] ??= {};
|
|
9
|
-
for (const variation of variations) {
|
|
10
|
-
variationsToHide[variation] = true;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
addFilter('blocks.registerBlockType', 'plaudit-gutenberg-api-extensions/problematic-blocks-blocker', (atts: RegisterBlockAttrs) => {
|
|
15
|
-
const problematicVariations = blockVariationsToHide[atts.name];
|
|
16
|
-
if (!atts.variations || !problematicVariations) {
|
|
17
|
-
return atts;
|
|
18
|
-
}
|
|
19
|
-
if (Array.isArray(atts.variations)) {
|
|
20
|
-
return {
|
|
21
|
-
...atts,
|
|
22
|
-
variations: atts.variations.map(variation => problematicVariations[variation.name] ? {...variation, scope: []} : variation)
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
if (problematicVariations[atts.variations.name]) {
|
|
26
|
-
return {
|
|
27
|
-
...atts,
|
|
28
|
-
variations: {...atts.variations, scope: []}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
return atts;
|
|
32
|
-
});
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type {PlauditIconName, WordPressIconName} from "./shared-internal-types";
|
|
2
|
-
|
|
3
|
-
import type {ReactElement} from "react";
|
|
4
|
-
|
|
5
|
-
export type IconName = WordPressIconName|`plaudit:${PlauditIconName}`|`<svg${string}`;
|
|
6
|
-
export type OptionalLabel = string|{text: string, icon?: ReactElement|IconName, tooltip?: string}|undefined;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type * as icons from "@wordpress/icons";
|
|
2
|
-
|
|
3
|
-
import type * as plauditIcons from "../lib/plaudit-icons";
|
|
4
|
-
import type {OptionalLabel} from "./shared-exportable-types";
|
|
5
|
-
|
|
6
|
-
export type PlauditIconName = keyof typeof plauditIcons;
|
|
7
|
-
export type WordPressIconName = Exclude<keyof typeof icons, 'Icon'>;
|
|
8
|
-
|
|
9
|
-
export type NamedSwitchTypes = "showHide"|"yesNo";
|
|
10
|
-
export type BaseSwitch = {onLabel?: OptionalLabel, offLabel?: OptionalLabel, type?: NamedSwitchTypes};
|
|
11
|
-
export type SmallSwitch = {small: true}&BaseSwitch;
|
|
12
|
-
export type NormalSwitch = ({small?: false|undefined, narrow?: boolean}&BaseSwitch)|NamedSwitchTypes;
|
|
13
|
-
|
|
14
|
-
export type CSNPControlComponentProps<C, V, P extends {[key: Exclude<string, 'config'|'onChange'|'value'>]: any} = {}> = {
|
|
15
|
-
config: C,
|
|
16
|
-
onChange: (v: V|undefined) => void,
|
|
17
|
-
value: V|undefined
|
|
18
|
-
}&P;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {type Block, type BlockConfiguration, type BlockSaveProps, registerBlockType} from "@wordpress/blocks";
|
|
2
|
-
import {InnerBlocks, useBlockProps, useInnerBlocksProps} from "@wordpress/block-editor";
|
|
3
|
-
import type {UseBlockProps} from "@wordpress/block-editor/components/use-block-props";
|
|
4
|
-
|
|
5
|
-
import {plauditIcon} from "../lib/plaudit-icons";
|
|
6
|
-
|
|
7
|
-
import type {ComponentType, ReactElement, ReactNode} from "react";
|
|
8
|
-
|
|
9
|
-
export type SimpleBlockTypeConfig<TAttributes extends Record<string, any>> = {
|
|
10
|
-
icon?: BlockConfiguration<TAttributes>['icon']|undefined,
|
|
11
|
-
defaults?: Required<TAttributes>,
|
|
12
|
-
controls?: NonNullable<Block<TAttributes>['edit']>,
|
|
13
|
-
renderer: (attributes: BlockSaveProps<TAttributes>, wrapperProps: UseBlockProps|UseBlockProps['save'], InnerBlocks: () => ReactElement, mode: "edit"|"save") => ReactNode,
|
|
14
|
-
innerBlocksProps?: InnerBlocks.Props,
|
|
15
|
-
settings?: Partial<BlockConfiguration<TAttributes>>,
|
|
16
|
-
};
|
|
17
|
-
function applyDefaults<TAttributes extends Record<string, any>, K extends BlockSaveProps<TAttributes>>(
|
|
18
|
-
config: Omit<SimpleBlockTypeConfig<TAttributes>, 'renderer'>, props: K
|
|
19
|
-
) {
|
|
20
|
-
type attrs = { [P in keyof K['attributes']]: K['attributes'][P] };
|
|
21
|
-
const mutableProps = {...props, attributes: {...props.attributes}} as Omit<typeof props, 'attributes'>&{attributes: attrs};
|
|
22
|
-
for (const [k, v] of Object.entries(config.defaults ?? {}) as Array<[keyof typeof mutableProps.attributes, any]>) {
|
|
23
|
-
if (mutableProps.attributes[k] === undefined) {
|
|
24
|
-
mutableProps.attributes[k] = v;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return mutableProps;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function registerSimpleBlockType<TAttributes extends Record<string, any> = {}>(
|
|
31
|
-
metadata: BlockConfiguration<TAttributes>, config: SimpleBlockTypeConfig<TAttributes>
|
|
32
|
-
): Block<TAttributes>|undefined {
|
|
33
|
-
return registerBlockType<TAttributes>(metadata, {
|
|
34
|
-
...config.settings,
|
|
35
|
-
icon: config.icon ?? plauditIcon,
|
|
36
|
-
edit(props) {
|
|
37
|
-
const populatedProps = applyDefaults(config, props);
|
|
38
|
-
return <>
|
|
39
|
-
{config.controls && <config.controls {...populatedProps} />}
|
|
40
|
-
{config.renderer(populatedProps, useBlockProps, () => <InnerBlocks {...config.innerBlocksProps} />, "edit")}
|
|
41
|
-
</>;
|
|
42
|
-
},
|
|
43
|
-
save(props) {
|
|
44
|
-
return config.renderer(applyDefaults(config, props), useBlockProps.save, () => <InnerBlocks.Content />, "save");
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
type SimpleContainerTypeConfig<TAttributes extends Record<string, any>> = Omit<SimpleBlockTypeConfig<TAttributes>, 'renderer'>&{
|
|
50
|
-
tag?: ComponentType,
|
|
51
|
-
attributesFromProps?: (arg: ReturnType<typeof applyDefaults<TAttributes, BlockSaveProps<TAttributes>>>, mode: "edit"|"save") => Parameters<UseBlockProps|UseBlockProps['save']>[0]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function registerSimpleContainerBlock<TAttributes extends Record<string, any> = {}>(
|
|
55
|
-
metadata: BlockConfiguration<TAttributes>, config: SimpleContainerTypeConfig<TAttributes>
|
|
56
|
-
): Block<TAttributes>|undefined {
|
|
57
|
-
const Tag = config.tag ?? ((props: any) => <div {...props} />);
|
|
58
|
-
return registerBlockType<TAttributes>(metadata, {
|
|
59
|
-
...config.settings,
|
|
60
|
-
icon: config.icon ?? plauditIcon,
|
|
61
|
-
edit(props) {
|
|
62
|
-
const populatedProps = applyDefaults(config, props);
|
|
63
|
-
return <>
|
|
64
|
-
{config.controls && <config.controls {...populatedProps} />}
|
|
65
|
-
<Tag {...useInnerBlocksProps(useBlockProps(
|
|
66
|
-
(config.attributesFromProps ?? (() => ({} as Parameters<UseBlockProps>[0])))(populatedProps, "edit")), config.innerBlocksProps)} />
|
|
67
|
-
</>;
|
|
68
|
-
},
|
|
69
|
-
save(props) {
|
|
70
|
-
return <Tag {...useInnerBlocksProps.save(useBlockProps.save(
|
|
71
|
-
(config.attributesFromProps ?? (() => ({} as Parameters<UseBlockProps['save']>[0])))(applyDefaults(config, props), "edit")))} />;
|
|
72
|
-
}
|
|
73
|
-
})
|
|
74
|
-
}
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import type {createSlotFill} from "@wordpress/components";
|
|
2
|
-
import {dispatch, select} from "@wordpress/data";
|
|
3
|
-
|
|
4
|
-
import type {CSNPConfig} from "./csnp-api";
|
|
5
|
-
import type {Condition} from "./conditions";
|
|
6
|
-
import type {DCNode} from "./data-controller";
|
|
7
|
-
import {installGutenbergExtensions} from "../index";
|
|
8
|
-
import {store as apiExtensionsStore} from "../lib/gutenberg-api-extensions-state";
|
|
9
|
-
import type {HydratedLaidOutProperties} from "./simple-native-property-internal-shared";
|
|
10
|
-
import type {BlockName} from "../lib/useful-types";
|
|
11
|
-
|
|
12
|
-
import type {ReactElement, ReactNode} from "react";
|
|
13
|
-
|
|
14
|
-
export type InspectorPanelGroup = 'layered-styles'|'post'|'default'|'advanced'|'background'|'border'|'color'|'dimensions'|'effects'|'filter'|'list'|'position'|'settings'|'styles'|'typography';
|
|
15
|
-
export type {Condition, ConditionFunction, ConditionStruct} from './conditions';
|
|
16
|
-
|
|
17
|
-
export interface DataStore {
|
|
18
|
-
readonly id: string;
|
|
19
|
-
getValue(name: string): any;
|
|
20
|
-
setValue(name: string, value: any): void;
|
|
21
|
-
|
|
22
|
-
reattach(attributeCache: Record<string, any>): void;
|
|
23
|
-
|
|
24
|
-
handlesProperty(name: string): boolean;
|
|
25
|
-
|
|
26
|
-
addProperty(property: HydratedSimpleNativeProperty): void;
|
|
27
|
-
}
|
|
28
|
-
export type RawPath = (string|number)[];
|
|
29
|
-
export type NodePath = [string, ...(string|number)[]];
|
|
30
|
-
export type DataController = {
|
|
31
|
-
getDataStore(property: string, required: true): DataStore,
|
|
32
|
-
getDataStore(property: string, required?: undefined|false): DataStore|undefined,
|
|
33
|
-
getDataStore(property: string, required?: boolean): DataStore|undefined,
|
|
34
|
-
getAllDataStores(): DataStore[],
|
|
35
|
-
makePropertyValueResolver(contextPath: RawPath): (propertyPath: RawPath) => any,
|
|
36
|
-
|
|
37
|
-
checkConditions(): void,
|
|
38
|
-
validateNodes(): void,
|
|
39
|
-
commitBatchAddedProperties(): void,
|
|
40
|
-
|
|
41
|
-
getValue(path: NodePath): any|undefined,
|
|
42
|
-
setValue(path: NodePath, value: any): void,
|
|
43
|
-
|
|
44
|
-
addProperties(properties: HydratedLaidOutProperties, dataStore: DataStore, inBatch?: boolean): void,
|
|
45
|
-
addNode(path: NodePath, value?: any): void,
|
|
46
|
-
removeNode(path: NodePath): void,
|
|
47
|
-
moveNode(path: NodePath, indices: {from: number, to: number}|{from: string, to: string}): void,
|
|
48
|
-
validateNode(path: NodePath): void,
|
|
49
|
-
|
|
50
|
-
hasRenderedNode(properties: HydratedLaidOutProperties): boolean,
|
|
51
|
-
hasValidationErrors(properties?: HydratedLaidOutProperties): boolean,
|
|
52
|
-
getIsRendered(path: NodePath): boolean,
|
|
53
|
-
getNode(path: NodePath): DCNode,
|
|
54
|
-
getValidationError(path: NodePath): string|undefined,
|
|
55
|
-
|
|
56
|
-
getWasChangedByManagedControl(): boolean,
|
|
57
|
-
markManagedControlChangeHandled(): void,
|
|
58
|
-
blockClientId: string
|
|
59
|
-
};
|
|
60
|
-
export enum NodeMessageSeverity {
|
|
61
|
-
info,
|
|
62
|
-
warning,
|
|
63
|
-
error
|
|
64
|
-
}
|
|
65
|
-
export type NodeMessage = {
|
|
66
|
-
message: string,
|
|
67
|
-
severity: NodeMessageSeverity
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export type ProvidedSlot = ReturnType<typeof createSlotFill>['Slot'];
|
|
71
|
-
export type SimpleNativePropertyType = 'string'|'number'|'boolean'|'array'|'object';
|
|
72
|
-
export type SNPControlProps<T> = {value: T|undefined, onChange: (v: T|undefined) => void, slots: SNPControlSlots};
|
|
73
|
-
export type GenericSimpleNativeProperty<T, V extends SimpleNativePropertyType> = {
|
|
74
|
-
name: string,
|
|
75
|
-
label?: string,
|
|
76
|
-
type: V,
|
|
77
|
-
enum?: T[],
|
|
78
|
-
default?: T,
|
|
79
|
-
alwaysStore?: boolean|undefined,
|
|
80
|
-
control(props: SNPControlProps<T>): ReactElement,
|
|
81
|
-
condition?: Condition,
|
|
82
|
-
required?: boolean,
|
|
83
|
-
validator?(value: T|undefined): string|null|undefined,
|
|
84
|
-
transformer?: {
|
|
85
|
-
to(input: unknown): T|undefined,
|
|
86
|
-
from(value: T|undefined): any
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
export type SimpleNativeProperty = GenericSimpleNativeProperty<string, 'string'>&{enum?: string[], styleProperty?: string}
|
|
90
|
-
|GenericSimpleNativeProperty<number, 'number'>&{enum?: number[], styleProperty?: string}
|
|
91
|
-
|GenericSimpleNativeProperty<boolean, 'boolean'>
|
|
92
|
-
|GenericSimpleNativeProperty<any[], 'array'>
|
|
93
|
-
|GenericSimpleNativeProperty<Record<string|number, unknown>, 'object'>;
|
|
94
|
-
|
|
95
|
-
export type PDSimpleNativeProperty = SimpleNativeProperty|CSNPConfig;
|
|
96
|
-
export type PotentiallyDesiccatedSimpleNativeProperty = PDSimpleNativeProperty;
|
|
97
|
-
|
|
98
|
-
export type HydratedSimpleNativeProperty<ADDITIONAL_DATA extends Record<string, any> = {}> = SimpleNativeProperty&ADDITIONAL_DATA
|
|
99
|
-
&{children?: {[subtype: string]: HydratedSimpleNativeProperty<ADDITIONAL_DATA>[]}|HydratedSimpleNativeProperty<ADDITIONAL_DATA>[], controlType?: string, branching?: boolean, initializing?: ReactNode|(() => ReactNode)};
|
|
100
|
-
export type SNPControlSlots = {Label: ProvidedSlot, Messages: ProvidedSlot};
|
|
101
|
-
|
|
102
|
-
export type LaidOutProperties = Array<PDSimpleNativeProperty|Array<PDSimpleNativeProperty>>;
|
|
103
|
-
export type SimpleNativePanel = {
|
|
104
|
-
title: string,
|
|
105
|
-
group?: InspectorPanelGroup,
|
|
106
|
-
initialOpen?: boolean,
|
|
107
|
-
properties: LaidOutProperties,
|
|
108
|
-
condition?: Condition,
|
|
109
|
-
position?: number,
|
|
110
|
-
raw?: boolean,
|
|
111
|
-
identifier?: any,
|
|
112
|
-
dataStoreTypeOverride?: 'layered-styles'|'attribute'
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
export type SimpleNativeTab = {
|
|
116
|
-
title: string,
|
|
117
|
-
group?: InspectorPanelGroup,
|
|
118
|
-
items: Array<Omit<SimpleNativePanel, 'group'>|LaidOutProperties[number]>,
|
|
119
|
-
identifier?: any
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export type PropertiesParameter = SimpleNativePanel|SimpleNativeTab|Array<LaidOutProperties[number]|SimpleNativePanel|SimpleNativeTab>;
|
|
123
|
-
|
|
124
|
-
export function registerSimpleNativeProperties(config: {block: BlockName|Array<BlockName>, properties: PropertiesParameter}) {
|
|
125
|
-
dispatch(apiExtensionsStore).addProperties(config.block, config.properties);
|
|
126
|
-
}
|
|
127
|
-
export function getSimpleNativeProperties(block: BlockName): Array<PDSimpleNativeProperty>|undefined {
|
|
128
|
-
const panelsAndTabs = select(apiExtensionsStore).desiccatedProperties(block);
|
|
129
|
-
if (panelsAndTabs === undefined) {
|
|
130
|
-
return undefined;
|
|
131
|
-
}
|
|
132
|
-
const res: PDSimpleNativeProperty[] = [];
|
|
133
|
-
for (const panelOrTab of panelsAndTabs) {
|
|
134
|
-
if ('items' in panelOrTab) {
|
|
135
|
-
for (const item of panelOrTab.items) {
|
|
136
|
-
if ('properties' in item) {
|
|
137
|
-
res.push(...flattenLaidOutProperties(item.properties));
|
|
138
|
-
} else if (Array.isArray(item)) {
|
|
139
|
-
res.push(...flattenLaidOutProperties(item));
|
|
140
|
-
} else {
|
|
141
|
-
res.push(item);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
} else {
|
|
145
|
-
for (const property of panelOrTab.properties) {
|
|
146
|
-
if (Array.isArray(property)) {
|
|
147
|
-
res.push(...flattenLaidOutProperties(property));
|
|
148
|
-
} else {
|
|
149
|
-
res.push(property);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return res;
|
|
155
|
-
}
|
|
156
|
-
function flattenLaidOutProperties(properties: LaidOutProperties): PDSimpleNativeProperty[] {
|
|
157
|
-
const res: PDSimpleNativeProperty[] = [];
|
|
158
|
-
for (const property of properties) {
|
|
159
|
-
if (Array.isArray(property)) {
|
|
160
|
-
res.push(...flattenLaidOutProperties(property));
|
|
161
|
-
} else {
|
|
162
|
-
res.push(property);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return res;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @deprecated use installGutenbergExtensions() instead.
|
|
170
|
-
*/
|
|
171
|
-
export function installSimpleNativePropertiesSupport() {
|
|
172
|
-
installGutenbergExtensions();
|
|
173
|
-
}
|