@plaudit/gutenberg-api-extensions 2.82.0 → 2.84.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 (53) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/blocks/SNPGroupComponent.js.map +1 -1
  3. package/dist/blocks/common-native-property-constructors.js +3 -2
  4. package/dist/blocks/common-native-property-constructors.js.map +1 -1
  5. package/dist/blocks/data-controller/actions.d.ts +135 -0
  6. package/dist/blocks/data-controller/actions.js +19 -0
  7. package/dist/blocks/data-controller/actions.js.map +1 -0
  8. package/dist/blocks/data-controller/reducer.d.ts +4 -0
  9. package/dist/blocks/data-controller/reducer.js +143 -0
  10. package/dist/blocks/data-controller/reducer.js.map +1 -0
  11. package/dist/blocks/data-controller/trigger-handlers.d.ts +140 -0
  12. package/dist/blocks/data-controller/trigger-handlers.js +117 -0
  13. package/dist/blocks/data-controller/trigger-handlers.js.map +1 -0
  14. package/dist/blocks/data-controller/utils.d.ts +43 -0
  15. package/dist/blocks/data-controller/utils.js +359 -0
  16. package/dist/blocks/data-controller/utils.js.map +1 -0
  17. package/dist/blocks/data-controller.d.ts +4 -37
  18. package/dist/blocks/data-controller.js +33 -604
  19. package/dist/blocks/data-controller.js.map +1 -1
  20. package/dist/blocks/layered-styles-impl.js +9 -8
  21. package/dist/blocks/layered-styles-impl.js.map +1 -1
  22. package/dist/blocks/layout/NodeContext.js +3 -3
  23. package/dist/blocks/layout/NodeContext.js.map +1 -1
  24. package/dist/blocks/simple-native-property-api.d.ts +10 -7
  25. package/dist/blocks/simple-native-property-api.js.map +1 -1
  26. package/dist/blocks/simple-native-property-impl.js +29 -24
  27. package/dist/blocks/simple-native-property-impl.js.map +1 -1
  28. package/dist/blocks/snp-data-store.d.ts +9 -6
  29. package/dist/blocks/snp-data-store.js +17 -12
  30. package/dist/blocks/snp-data-store.js.map +1 -1
  31. package/dist/controls/FullSizeToggleControl.d.ts +1 -1
  32. package/dist/controls/FullSizeToggleControl.js.map +1 -1
  33. package/dist/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js +12 -12
  34. package/dist/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js.map +1 -1
  35. package/dist/lib/gutenberg-api-extensions-state/snp-logic.js +2 -2
  36. package/dist/lib/gutenberg-api-extensions-state/snp-logic.js.map +1 -1
  37. package/package.json +7 -7
  38. package/simple-native-properties.md +1 -0
  39. package/src/blocks/SNPGroupComponent.tsx +1 -1
  40. package/src/blocks/common-native-property-constructors.tsx +3 -2
  41. package/src/blocks/data-controller/actions.ts +20 -0
  42. package/src/blocks/data-controller/reducer.ts +149 -0
  43. package/src/blocks/data-controller/trigger-handlers.ts +138 -0
  44. package/src/blocks/data-controller/utils.ts +339 -0
  45. package/src/blocks/data-controller.ts +38 -605
  46. package/src/blocks/layered-styles-impl.ts +10 -9
  47. package/src/blocks/layout/NodeContext.tsx +3 -3
  48. package/src/blocks/simple-native-property-api.ts +12 -10
  49. package/src/blocks/simple-native-property-impl.tsx +31 -24
  50. package/src/blocks/snp-data-store.ts +22 -13
  51. package/src/controls/FullSizeToggleControl.tsx +3 -3
  52. package/src/lib/gutenberg-api-extensions-state/layered-block-styles-logic.ts +12 -11
  53. package/src/lib/gutenberg-api-extensions-state/snp-logic.ts +2 -2
@@ -1,5 +1,6 @@
1
1
  import {select} from "@wordpress/data";
2
2
 
3
+ import {store as gutenbergApiExtensionsStore} from "../lib/gutenberg-api-extensions-state";
3
4
  import type {ActualBlockEditProps} from "../lib/useful-types";
4
5
  import type {PDSimpleNativeProperty} from "./simple-native-property-api";
5
6
  import {makeHasPropClassName} from "./simple-native-property-impl";
@@ -8,20 +9,21 @@ import {SNPDataStore} from "./snp-data-store";
8
9
  export class LayeredStylesDataStore extends SNPDataStore {
9
10
  getAttribute(name: string): any {
10
11
  if (name.startsWith("__plaudit/")) {
11
- return this.blockEditProps.attributes[name];
12
+ return this.getRawBlockAttributes()[name];
12
13
  }
13
- const layer = select('plaudit/gutenberg-api-extensions').blockStylesLayer(this.blockEditProps.name, name);
14
+ const layer = select(gutenbergApiExtensionsStore).blockStylesLayer(this.blockName, name);
14
15
  if (layer === undefined) {
15
16
  return undefined;
16
17
  }
17
- return extractStyleLayerValueFromAttributes(this.blockEditProps.attributes, layer.name) ?? layer.default;
18
+
19
+ return extractStyleLayerValueFromAttributes(this.getRawBlockAttributes(), layer.name) ?? layer.default;
18
20
  }
19
21
  setAttribute(name: string, rawValue: any) {
20
22
  if (name.startsWith("__plaudit/")) {
21
- this.blockEditProps.setAttributes({[name]: rawValue});
23
+ this.setRawBlockAttributes({[name]: rawValue});
22
24
  return;
23
25
  }
24
- const layers = select('plaudit/gutenberg-api-extensions').blockStylesLayers(this.blockEditProps.name);
26
+ const layers = select(gutenbergApiExtensionsStore).blockStylesLayers(this.blockName);
25
27
  if (layers === undefined) {
26
28
  return;
27
29
  }
@@ -29,14 +31,13 @@ export class LayeredStylesDataStore extends SNPDataStore {
29
31
  if (layer === undefined) {
30
32
  return;
31
33
  }
32
-
33
- const className = this.blockEditProps.attributes['className'];
34
+ const className = this.getRawBlockAttributes()['className'];
34
35
 
35
36
  const value = rawValue?.toString() || (layer.default ?? '');
36
37
  const currentLayerClassPrefix = `style-${name}-`;
37
38
  if (typeof className !== 'string' || !className) {
38
39
  if (value.length) {
39
- this.blockEditProps.setAttributes({
40
+ this.setRawBlockAttributes({
40
41
  className: "styleProperty" in layer && layer.styleProperty
41
42
  ? `${currentLayerClassPrefix}${value} ${makeHasPropClassName(layer.name)}`
42
43
  : `${currentLayerClassPrefix}${value}`
@@ -44,7 +45,7 @@ export class LayeredStylesDataStore extends SNPDataStore {
44
45
  }
45
46
  return;
46
47
  }
47
- this.blockEditProps.setAttributes({className: this.incorporateLayerValue(Object.values(layers), layer, name, value, className)});
48
+ this.setRawBlockAttributes({className: this.incorporateLayerValue(Object.values(layers), layer, name, value, className)});
48
49
  }
49
50
 
50
51
  private incorporateLayerValue(layers: PDSimpleNativeProperty[], currentLayer: PDSimpleNativeProperty, name: string, value: string, className: string): string {
@@ -19,15 +19,15 @@ function makeNodeContextValue(path: NodePath, dataController: DataController): N
19
19
  const value = dataController.getValue(path);
20
20
  const node = dataController.getNode(path);
21
21
  // We memoize actions separately to reduce later re-render calls
22
- const actions = useMemo<NodeContextValueActions>(() => ({
22
+ const memoizedActions = useMemo<NodeContextValueActions>(() => ({
23
23
  setValue: value => dataController.setValue(path, value),
24
24
  addNode: (name, value) => dataController.addNode([...path, name], value),
25
25
  removeNode: name => dataController.removeNode([...path, name]),
26
26
  moveNode: indices => dataController.moveNode(path, indices),
27
- validateNode: () => dataController.dispatch({type: "validateNode", path})
27
+ validateNode: () => dataController.validateNode(path)
28
28
  }), [path, dataController]);
29
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, ...actions}), [actions, node, value]);
30
+ return useMemo(() => ({path, dataController, rendered: node.rendered ?? true, validationError: node.validationError, value, ...memoizedActions}), [memoizedActions, node, value]);
31
31
  }
32
32
 
33
33
  export function useNodeContext(action: string): NodeContextValue {
@@ -1,13 +1,11 @@
1
- import type {configureStore} from "@reduxjs/toolkit/src/configureStore";
2
-
3
1
  import type {createSlotFill} from "@wordpress/components";
4
2
  import {dispatch, select} from "@wordpress/data";
5
3
 
6
4
  import type {CSNPConfig} from "./csnp-api";
7
5
  import type {Condition} from "./conditions";
8
- import type {DataControllerActions, DCNode, DCStoreState} from "./data-controller";
6
+ import type {DCNode} from "./data-controller";
9
7
  import {installGutenbergExtensions} from "../index";
10
- import type {ActualBlockEditProps, BlockName} from "../lib/useful-types";
8
+ import type {BlockName} from "../lib/useful-types";
11
9
  import type {HydratedLaidOutProperties} from "./simple-native-property-internal-shared";
12
10
 
13
11
  import type {ReactElement, ReactNode} from "react";
@@ -15,28 +13,30 @@ import type {ReactElement, ReactNode} from "react";
15
13
  export type InspectorPanelGroup = 'layered-styles'|'post'|'default'|'advanced'|'background'|'border'|'color'|'dimensions'|'effects'|'filter'|'list'|'position'|'settings'|'styles'|'typography';
16
14
  export type {Condition, ConditionFunction, ConditionStruct} from './conditions';
17
15
 
18
- export interface DataStore<B = unknown> {
16
+ export interface DataStore {
17
+ readonly id: string;
19
18
  getValue(name: string): any;
20
19
  setValue(name: string, value: any): void;
21
20
 
22
- reattach(blockEditProps: B, attributeCache: Record<string, any>): DataStore<B>;
21
+ reattach(attributeCache: Record<string, any>): void;
23
22
 
24
23
  handlesProperty(name: string): boolean;
25
24
 
26
25
  addProperty(property: HydratedSimpleNativeProperty, writeThroughOnUndefined?: boolean): void;
27
-
28
- blockEditProps: ActualBlockEditProps;
29
26
  }
30
27
  export type RawPath = (string|number)[];
31
28
  export type NodePath = [string, ...(string|number)[]];
32
29
  export type DataController = {
33
- dispatch: ReturnType<typeof configureStore<DCStoreState, DataControllerActions, []>>['dispatch'],
34
30
  getDataStore(property: string, required: true): DataStore,
35
31
  getDataStore(property: string, required?: undefined|false): DataStore|undefined,
36
32
  getDataStore(property: string, required?: boolean): DataStore|undefined,
37
33
  getAllDataStores(): DataStore[],
38
34
  makePropertyValueResolver(contextPath: RawPath): (propertyPath: RawPath) => any,
39
35
 
36
+ checkConditions(): void,
37
+ validateNodes(): void,
38
+ commitBatchAddedProperties(): void,
39
+
40
40
  getValue(path: NodePath): any|undefined,
41
41
  setValue(path: NodePath, value: any): void,
42
42
 
@@ -44,6 +44,7 @@ export type DataController = {
44
44
  addNode(path: NodePath, value?: any): void,
45
45
  removeNode(path: NodePath): void,
46
46
  moveNode(path: NodePath, indices: {from: number, to: number}|{from: string, to: string}): void,
47
+ validateNode(path: NodePath): void,
47
48
 
48
49
  hasRenderedNode(properties: HydratedLaidOutProperties): boolean,
49
50
  hasValidationErrors(properties?: HydratedLaidOutProperties): boolean,
@@ -106,7 +107,8 @@ export type SimpleNativePanel = {
106
107
  condition?: Condition,
107
108
  position?: number,
108
109
  raw?: boolean,
109
- identifier?: any
110
+ identifier?: any,
111
+ dataStoreTypeOverride?: 'layered-styles'|'attribute'
110
112
  };
111
113
 
112
114
  export type SimpleNativeTab = {
@@ -10,6 +10,7 @@ import {DataControllerManager, createDataControllerManager} from "./data-control
10
10
  import {extractStyleLayerValueFromAttributes, LayeredStylesDataStore} from "./layered-styles-impl";
11
11
  import {TabsRoot} from "./layout/TabsRoot";
12
12
  import {PanelRoot} from "./layout/PanelRoot";
13
+ import {store as gutenbergApiExtensionsStore} from "../lib/gutenberg-api-extensions-state";
13
14
  import {ActualBEPAttrs, ActualBlockEditProps, ActualBlockListBlockProps, isBlockJsonNativePropsConfig, RegisterBlockAttrs} from "../lib/useful-types";
14
15
  import {PathError} from "./PathError";
15
16
  import type {DataController, DataStore, HydratedSimpleNativeProperty, InspectorPanelGroup} from "./simple-native-property-api";
@@ -19,11 +20,11 @@ import {SNPTreeContext} from "./SNPTreeContext";
19
20
 
20
21
  class AttributeDataStore extends SNPDataStore {
21
22
  public getAttribute(name: string): any {
22
- return this.blockEditProps.attributes[name];
23
+ return this.getRawBlockAttributes()[name];
23
24
  }
24
25
 
25
26
  public setAttribute(name: string, value: any) {
26
- this.blockEditProps.setAttributes(name === 'className' ? {className: value?.toString()} : {[name]: value});
27
+ this.setRawBlockAttributes(name === 'className' ? {className: value?.toString()} : {[name]: value});
27
28
  }
28
29
  }
29
30
 
@@ -43,18 +44,18 @@ export function installSimpleNativePropertiesSupport() {
43
44
  if (registeredBlocks.has(atts.name)) {
44
45
  isPlauditNative = registeredBlocks.get(atts.name)!;
45
46
  } else {
46
- dispatch('plaudit/gutenberg-api-extensions').recordBaselineBlockAttrs(atts);
47
+ dispatch(gutenbergApiExtensionsStore).recordBaselineBlockAttrs(atts);
47
48
  if ((isPlauditNative = isBlockJsonNativePropsConfig(atts.plaudit)) && atts.plaudit.properties !== undefined
48
49
  && (Array.isArray(atts.plaudit.properties) ? atts.plaudit.properties.length : atts.plaudit.properties)
49
50
  ) {
50
- dispatch('plaudit/gutenberg-api-extensions').addProperties(atts.name, atts.plaudit.properties);
51
+ dispatch(gutenbergApiExtensionsStore).addProperties(atts.name, atts.plaudit.properties);
51
52
  }
52
53
  registeredBlocks.set(atts.name, isPlauditNative);
53
54
  }
54
55
  //TODO: Figure out some way to re-register a block when its attributes are changed
55
- const blockSimpleNativePanelsAndTabs = select('plaudit/gutenberg-api-extensions').preppedProperties(atts.name);
56
+ const blockSimpleNativePanelsAndTabs = select(gutenbergApiExtensionsStore).preppedProperties(atts.name);
56
57
  if (blockSimpleNativePanelsAndTabs) {
57
- const extraPropTransforms = select('plaudit/gutenberg-api-extensions').extraPropTransforms(atts.name) ?? {};
58
+ const extraPropTransforms = select(gutenbergApiExtensionsStore).extraPropTransforms(atts.name) ?? {};
58
59
  const attsAttributes = {...atts.attributes};
59
60
  if (isPlauditNative && Object.values(extraPropTransforms).some(cfg => cfg.styleProperty)) {
60
61
  attsAttributes['__plaudit/computed-style-attr'] = {type: "object"};
@@ -86,7 +87,7 @@ export function installSimpleNativePropertiesSupport() {
86
87
 
87
88
  addFilter('editor.BlockEdit', 'plaudit/gutenberg-api-extensions/simple-native-properties',
88
89
  createHigherOrderComponent(BlockEdit => (blockEditProps: ActualBlockEditProps) => {
89
- const blockSimpleNativePanelsAndTabs = select('plaudit/gutenberg-api-extensions').preppedProperties(blockEditProps.name);
90
+ const blockSimpleNativePanelsAndTabs = select(gutenbergApiExtensionsStore).preppedProperties(blockEditProps.name);
90
91
  if (!blockSimpleNativePanelsAndTabs) {
91
92
  return <BlockEdit {...blockEditProps} />;
92
93
  }
@@ -121,7 +122,7 @@ export function installSimpleNativePropertiesSupport() {
121
122
  addFilter('editor.BlockListBlock', 'plaudit/gutenberg-api-extensions/simple-native-properties',
122
123
  createHigherOrderComponent(BlockListBlock => (props: ActualBlockListBlockProps) => {
123
124
  const wrapperProps: {className?: string, style?: Record<string, unknown>} = {...props.wrapperProps};
124
- const extraPropTransforms = select('plaudit/gutenberg-api-extensions').computedExtraPropTransforms(props.name);
125
+ const extraPropTransforms = select(gutenbergApiExtensionsStore).computedExtraPropTransforms(props.name);
125
126
  if (!extraPropTransforms || !extraPropTransforms.appliesInEditor) {
126
127
  const dataController = dataControllerManager.getDataController(props.clientId);
127
128
  if (!dataController) {
@@ -130,7 +131,7 @@ export function installSimpleNativePropertiesSupport() {
130
131
 
131
132
  const hasValidationError = dataController.hasValidationErrors();
132
133
  dataControllerManager.notifyOfValidationErrorStatusChange(props.clientId, hasValidationError);
133
- dataController.dispatch({type: "checkConditions"}); // We don't want to wrap this in a useEffect because this function is already only called when necessary.
134
+ dataController.checkConditions(); // We don't want to wrap this in a useEffect because this function is already only called when necessary.
134
135
 
135
136
  if (hasValidationError) {
136
137
  //TODO: Should I set isValid?
@@ -150,7 +151,7 @@ export function installSimpleNativePropertiesSupport() {
150
151
 
151
152
  const hasValidationError = dataController.hasValidationErrors();
152
153
  dataControllerManager.notifyOfValidationErrorStatusChange(props.clientId, hasValidationError);
153
- dataController.dispatch({type: "checkConditions"}); // We don't want to wrap this in a useEffect because this function is already only called when necessary.
154
+ dataController.checkConditions(); // We don't want to wrap this in a useEffect because this function is already only called when necessary.
154
155
 
155
156
  if (hasValidationError) {
156
157
  //TODO: Should I set isValid?
@@ -169,7 +170,7 @@ export function installSimpleNativePropertiesSupport() {
169
170
  if (isBlockJsonNativePropsConfig(blockType.plaudit)) {
170
171
  return props;
171
172
  }
172
- const extraPropTransforms = select('plaudit/gutenberg-api-extensions').computedExtraPropTransforms(blockType.name);
173
+ const extraPropTransforms = select(gutenbergApiExtensionsStore).computedExtraPropTransforms(blockType.name);
173
174
 
174
175
  return extraPropTransforms && extraPropTransforms.appliesInEditor ? produce(props, draft => {
175
176
  applyExtraPropTransforms(extraPropTransforms.transforms, attributes, draft);
@@ -248,35 +249,41 @@ function applyExtraPropTransforms(
248
249
  return draft;
249
250
  }
250
251
 
251
- function makeDataStoreForPanelOrTab(blockEditProps: ActualBlockEditProps, group: string|undefined, attributeCache: Record<string, any>) {
252
- return group === 'layered-styles' ? new LayeredStylesDataStore(blockEditProps, attributeCache) : new AttributeDataStore(blockEditProps, attributeCache);
252
+ function makeDataStoreForPanelOrTab(
253
+ blockEditProps: ActualBlockEditProps, group: string|undefined, attributeCache: Record<string, any>, identifier: string, dataStoreTypeOverride?: 'layered-styles'|'attribute'
254
+ ) {
255
+ const args = [blockEditProps, attributeCache, `${blockEditProps.clientId}-${identifier}`] as const;
256
+ if (dataStoreTypeOverride) {
257
+ return dataStoreTypeOverride === 'layered-styles' ? new LayeredStylesDataStore(...args) : new AttributeDataStore(...args);
258
+ }
259
+ return group === 'layered-styles' ? new LayeredStylesDataStore(...args) : new AttributeDataStore(...args);
253
260
  }
254
261
  type SNPPropsWrapperProps = {blockSimpleNativePanelsAndTabs: PreppedSimpleNativePanelsAndTabs, blockEditProps: ActualBlockEditProps, dataController: DataController};
255
262
  function SNPPropsWrapper({blockSimpleNativePanelsAndTabs, blockEditProps, dataController}: SNPPropsWrapperProps) {
256
263
  useMemo(() => {
257
264
  const attributeCache = Object.create(null);
258
- for (const panel of blockSimpleNativePanelsAndTabs.panels) {
259
- const dataStore = makeDataStoreForPanelOrTab(blockEditProps, panel[1].group, attributeCache);
260
- dataController.addProperties(panel[1].properties, dataStore, true);
265
+ for (const [identifier, panel] of blockSimpleNativePanelsAndTabs.panels) {
266
+ const dataStore = makeDataStoreForPanelOrTab(blockEditProps, panel.group, attributeCache, identifier, panel.dataStoreTypeOverride);
267
+ dataController.addProperties(panel.properties, dataStore, true);
261
268
  }
262
- for (const [group, [_, tabs]] of Object.entries(blockSimpleNativePanelsAndTabs.tabs)) {
263
- const dataStore = makeDataStoreForPanelOrTab(blockEditProps, group, attributeCache);
269
+ for (const [group, [identifier, tabs]] of Object.entries(blockSimpleNativePanelsAndTabs.tabs)) {
270
+ const dataStore = makeDataStoreForPanelOrTab(blockEditProps, group, attributeCache, identifier);
264
271
  for (const tab of Object.values(tabs)) {
265
272
  for (const panel of tab.items) {
266
273
  dataController.addProperties(panel.properties, dataStore, true);
267
274
  }
268
275
  }
269
276
  }
270
- dataController.dispatch({type: "checkConditions"});
271
- dataController.dispatch({type: "validateNodes"});
272
- dataController.dispatch({type: "commitBatchAddedProperties"});
277
+ dataController.checkConditions();
278
+ dataController.validateNodes();
279
+ dataController.commitBatchAddedProperties();
273
280
  }, [blockSimpleNativePanelsAndTabs, dataController]); // We don't depend on blockEditProps here - that is handled by the following useEffect
274
281
 
275
282
  // We have to reattach dataStores in the useMemo segment in order for Panel- and Tab-level conditions to work
276
283
  useMemo(() => {
277
284
  const attributeCache = Object.create(null);
278
285
  for (const dataStore of dataController.getAllDataStores()) {
279
- dataStore.reattach(blockEditProps, attributeCache);
286
+ dataStore.reattach(attributeCache);
280
287
  }
281
288
  }, [dataController.getAllDataStores(), blockEditProps]);
282
289
 
@@ -285,8 +292,8 @@ function SNPPropsWrapper({blockSimpleNativePanelsAndTabs, blockEditProps, dataCo
285
292
  if (dataController.getWasChangedByManagedControl()) {
286
293
  dataController.markManagedControlChangeHandled();
287
294
  } else{
288
- dataController.dispatch({type: "checkConditions"});
289
- dataController.dispatch({type: "validateNodes"});
295
+ dataController.checkConditions();
296
+ dataController.validateNodes();
290
297
  }
291
298
  }, [dataController.getAllDataStores(), blockEditProps]);
292
299
 
@@ -1,19 +1,25 @@
1
- import type {ActualBlockEditProps} from "../lib/useful-types";
1
+ import {store as blockEditorStore} from "@wordpress/block-editor";
2
+ import {dispatch, select} from "@wordpress/data";
3
+
4
+ import type {ActualBlockEditProps, BlockName} from "../lib/useful-types";
2
5
  import type {DataStore, HydratedSimpleNativeProperty} from "./simple-native-property-api";
3
6
  import {buildDefaultValueFromDefinition} from "./simple-native-property-internal-shared";
4
7
 
5
- export abstract class SNPDataStore implements DataStore<ActualBlockEditProps> {
8
+ export abstract class SNPDataStore implements DataStore {
6
9
  private readonly managedPropertyNames: {[propertyName in string]: true};
7
10
 
11
+ protected readonly blockClientId: string;
12
+ protected readonly blockName: BlockName;
13
+
8
14
  public constructor(
9
- protected explicitBlockEditProps: ActualBlockEditProps,
10
- private attributeCache: Record<string, any>
15
+ explicitBlockEditProps: ActualBlockEditProps,
16
+ private attributeCache: Record<string, any>,
17
+ public readonly id: string
11
18
  ) {
12
19
  this.managedPropertyNames = Object.create(null);
13
- }
14
20
 
15
- get blockEditProps() {
16
- return this.explicitBlockEditProps;
21
+ this.blockClientId = explicitBlockEditProps.clientId;
22
+ this.blockName = explicitBlockEditProps.name;
17
23
  }
18
24
 
19
25
  getValue(attr: string): any {
@@ -31,17 +37,20 @@ export abstract class SNPDataStore implements DataStore<ActualBlockEditProps> {
31
37
  return name in this.managedPropertyNames;
32
38
  }
33
39
 
34
- reattach(explicitBlockEditProps: ActualBlockEditProps, attributeCache: Record<string, any>) {
35
- if (this.explicitBlockEditProps !== explicitBlockEditProps) { // If the block's properties haven't changed, there's no reason to clear the attribute cache
36
- this.explicitBlockEditProps = explicitBlockEditProps;
37
- this.attributeCache = attributeCache;
38
- }
39
- return this;
40
+ reattach(attributeCache: Record<string, any>) {
41
+ this.attributeCache = attributeCache;
40
42
  }
41
43
 
42
44
  protected abstract getAttribute(name: string): any;
43
45
  protected abstract setAttribute(name: string, value: any): void;
44
46
 
47
+ protected getRawBlockAttributes() {
48
+ return select(blockEditorStore).getBlockAttributes(this.blockClientId) ?? {};
49
+ }
50
+ protected setRawBlockAttributes(attributes: Record<string, any>) {
51
+ dispatch(blockEditorStore).updateBlockAttributes!(this.blockClientId, attributes);
52
+ }
53
+
45
54
  protected getCachedValue(attr: string) {
46
55
  return this.attributeCache[attr];
47
56
  }
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption,
3
- __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, PanelBody, TabPanel
3
+ __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon
4
4
  } from "@wordpress/components";
5
5
  import {memo, useCallback, useMemo} from "@wordpress/element";
6
6
  import {__} from "@wordpress/i18n";
7
7
  import * as icons from "@wordpress/icons";
8
8
 
9
- import type {TogglePropertyCSNPConfig} from "../blocks/csnp-api";
10
- import * as plauditIcons from "../lib/plaudit-icons";
11
9
  import type {IconName, OptionalLabel} from "../blocks";
10
+ import type {TogglePropertyCSNPConfig} from "../blocks/csnp-api";
12
11
  import type {CSNPControlComponentProps, NormalSwitch, PlauditIconName, WordPressIconName} from "../blocks/shared-internal-types";
12
+ import * as plauditIcons from "../lib/plaudit-icons";
13
13
 
14
14
  import parse from "html-react-parser";
15
15
 
@@ -26,17 +26,18 @@ export const layeredBlockStylesLogicSelectors = {
26
26
  };
27
27
 
28
28
  export function layeredBlockStylesLogic(state: LayeredBlockStylesLogicState, action: LayeredBlockStylesLogicActions|WordPressMetaActions): typeof state {
29
- if (action.type === "ADD_LAYERED_BLOCK_STYLES") {
30
- return produce(state, (draft: typeof state) => {
31
- const blockLayeredStyles = draft.layeredBlockStyles[action.blockName] ?? (draft.layeredBlockStyles[action.blockName] = {});
32
- for (const layer of action.properties) {
33
- blockLayeredStyles[layer.name] = layer;
34
- }
35
- });
36
- } else if (action.type === "SET_LAYERED_BLOCK_STYLES") {
37
- return produce(state, (draft: typeof state) => {
38
- draft.layeredBlockStyles[action.blockName] = action.properties;
39
- });
29
+ switch (action.type) {
30
+ case "ADD_LAYERED_BLOCK_STYLES":
31
+ return produce(state, (draft: typeof state) => {
32
+ const blockLayeredStyles = draft.layeredBlockStyles[action.blockName] ?? (draft.layeredBlockStyles[action.blockName] = {});
33
+ for (const layer of action.properties) {
34
+ blockLayeredStyles[layer.name] = layer;
35
+ }
36
+ });
37
+ case "SET_LAYERED_BLOCK_STYLES":
38
+ return produce(state, (draft: typeof state) => {
39
+ draft.layeredBlockStyles[action.blockName] = action.properties;
40
+ });
40
41
  }
41
42
  return state;
42
43
  }
@@ -80,7 +80,7 @@ export function snpLogic(state: SNPLogicState, action: SNPLogicActions|WordPress
80
80
  });
81
81
  case "ADD_OR_UPDATE_EXTRA_PROP_TRANSFORM":
82
82
  return produce(state, (draft: typeof state) => {
83
- const blockTransforms = draft.extraPropTransforms[action.blockName] ?? (draft.extraPropTransforms[action.blockName] = {});
83
+ const blockTransforms = (draft.extraPropTransforms[action.blockName] ??= {});
84
84
  if (blockTransforms[action.propPath]) {
85
85
  blockTransforms[action.propPath]!.styleProperty = action.extraPropTransform.styleProperty;
86
86
  } else {
@@ -106,7 +106,7 @@ export function snpLogic(state: SNPLogicState, action: SNPLogicActions|WordPress
106
106
  }
107
107
 
108
108
  export function addProperties(block: BlockName, properties: PropertiesParameter, simpleNativePanelsAndTabs: SNPLogicState['desiccatedProperties']) {
109
- const panels = (simpleNativePanelsAndTabs[block] ?? (simpleNativePanelsAndTabs[block] = []));
109
+ const panels = (simpleNativePanelsAndTabs[block] ??= []);
110
110
  if ('title' in properties) {
111
111
  panels.push(properties);
112
112
  return;