@plaudit/gutenberg-api-extensions 2.84.4 → 2.85.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/blocks/common-native-property-constructors.js +12 -0
  3. package/dist/blocks/common-native-property-constructors.js.map +1 -1
  4. package/dist/blocks/csnp-api.d.ts +4 -3
  5. package/dist/blocks/csnp-api.js +3 -2
  6. package/dist/blocks/csnp-api.js.map +1 -1
  7. package/dist/blocks/data-controller/reducer.js +3 -2
  8. package/dist/blocks/data-controller/reducer.js.map +1 -1
  9. package/dist/blocks/data-controller/trigger-handlers.js +3 -3
  10. package/dist/blocks/data-controller/trigger-handlers.js.map +1 -1
  11. package/dist/blocks/data-controller/utils.d.ts +5 -2
  12. package/dist/blocks/data-controller/utils.js +25 -2
  13. package/dist/blocks/data-controller/utils.js.map +1 -1
  14. package/dist/blocks/data-controller.d.ts +1 -1
  15. package/dist/blocks/data-controller.js +1 -1
  16. package/dist/blocks/data-controller.js.map +1 -1
  17. package/dist/controls/FileControl.d.ts +9 -0
  18. package/dist/controls/FileControl.js +27 -0
  19. package/dist/controls/FileControl.js.map +1 -0
  20. package/dist/controls/index.d.ts +1 -0
  21. package/dist/controls/index.js +1 -0
  22. package/dist/controls/index.js.map +1 -1
  23. package/package.json +5 -5
  24. package/simple-native-properties.md +122 -89
  25. package/src/blocks/common-native-property-constructors.tsx +13 -1
  26. package/src/blocks/csnp-api.ts +11 -8
  27. package/src/blocks/data-controller/reducer.ts +4 -3
  28. package/src/blocks/data-controller/trigger-handlers.ts +5 -4
  29. package/src/blocks/data-controller/utils.ts +27 -4
  30. package/src/blocks/data-controller.ts +2 -2
  31. package/src/controls/FileControl.tsx +48 -0
  32. package/src/controls/index.ts +1 -0
@@ -109,8 +109,8 @@ export function descendIntoDCNodeChild(current: DCNode|undefined, path: RawPath,
109
109
  return current;
110
110
  }
111
111
 
112
- export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError: false): DataStore|undefined;
113
- export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError?: undefined|true): DataStore;
112
+ export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError: true): DataStore;
113
+ export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError?: undefined|boolean|false): DataStore|undefined;
114
114
  export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError = true): DataStore|undefined {
115
115
  let dataStore = state.dataStores.byProperty[property];
116
116
  if (dataStore) {
@@ -127,7 +127,7 @@ export function getDataStore(property: string, state: Draft<DCStoreState>, throw
127
127
 
128
128
  export function getOptionalValue(path: NodePath, state: Draft<DCStoreState>) {
129
129
  try {
130
- return walkToNodeInValue(getDataStore(path[0], state).getValue(path[0]), path);
130
+ return walkToNodeInValue(getDataStore(path[0], state, true).getValue(path[0]), path);
131
131
  } catch (e) {
132
132
  if (e instanceof PathError) {
133
133
  return undefined;
@@ -162,7 +162,7 @@ export function writeValueToBackingDataStoreWithCorrections(path: NodePath, stat
162
162
  if (rootDCNode === undefined) {
163
163
  throw new PathError("Encountered a path pointing to a non-existent root node.", path, 0);
164
164
  }
165
- const dataStore = getDataStore(path[0], state);
165
+ const dataStore = getDataStore(path[0], state, true);
166
166
 
167
167
  // This path both handles scalar values and ensures that the root "value" of Groups and Lists are initialized before writing the actual attribute
168
168
  // To avoid accidentally overwriting group data when lazily adding items (i.e., via a ToolsPanel instance), we skip this code path if the group's root value has already been initialized
@@ -306,6 +306,29 @@ export function recordCloneableDefaultValueForNode<T extends HydratedSimpleNativ
306
306
  return definition as HydratedSimpleNativeProperty<{uuid: UUID}>;
307
307
  }
308
308
 
309
+ const recordedBackupValues: Record<UUID, any> = {};
310
+ export function recordBackupForNode(node: DCNode, value: any) {
311
+ if (!node.backup) {
312
+ node.backup = crypto.randomUUID();
313
+ }
314
+ recordedBackupValues[node.backup] = value;
315
+ }
316
+
317
+ export function restoreValueFromPotentialBackup(node: DCNode) {
318
+ if (node.backup && node.backup in recordedBackupValues) {
319
+ const res = recordedBackupValues[node.backup];
320
+ delete recordedBackupValues[node.backup];
321
+ return res ?? buildDefaultValueFromDefinition(node.definition);
322
+ }
323
+ return buildDefaultValueFromDefinition(node.definition)
324
+ }
325
+
326
+ export function removeBackupForNode(node: DCNode) {
327
+ if (node.backup && node.backup in recordedBackupValues) {
328
+ delete recordedBackupValues[node.backup];
329
+ }
330
+ }
331
+
309
332
  export function buildDefaultValueFromDefinition(definition: (HydratedSimpleNativeProperty<{uuid: UUID}>)|undefined, requireNonNullValueOnObject = true): any {
310
333
  if (definition === undefined) {
311
334
  return undefined;
@@ -15,7 +15,7 @@ import {getDataStore, getOptionalValue, UUID, walkToNode} from "./data-controlle
15
15
 
16
16
  type DescendantsWrapper = {[key: string]: DCNode}|DCNode[];
17
17
  export type DCNode = {
18
- backup?: any,
18
+ backup?: UUID,
19
19
  rendered?: boolean,
20
20
  condition?: Condition,
21
21
  children?: DescendantsWrapper,
@@ -39,7 +39,7 @@ export function useDataController(blockClientId: string): DataController {
39
39
  function getDataStoreImpl(property: string, required: true): DataStore;
40
40
  function getDataStoreImpl(property: string, required?: undefined|false): DataStore|undefined;
41
41
  function getDataStoreImpl(property: string, required?: boolean): DataStore|undefined {
42
- return required ? getDataStore(property, store.getState(), true) : getDataStore(property, store.getState(), false);
42
+ return getDataStore(property, store.getState(), required);
43
43
  }
44
44
  const dataController: DataController = {
45
45
  getDataStore: getDataStoreImpl,
@@ -0,0 +1,48 @@
1
+ import {MediaUpload, MediaUploadCheck} from "@wordpress/block-editor";
2
+ import {BaseControl, Button, useBaseControlProps} from "@wordpress/components";
3
+ import {store as coreStore} from "@wordpress/core-data";
4
+ import {useSuspenseSelect} from "@wordpress/data";
5
+ import {useCallback} from "@wordpress/element";
6
+ import {__} from "@wordpress/i18n";
7
+
8
+ import type {ReactNode} from "react";
9
+
10
+ export type FileControlProps = {
11
+ label: ReactNode,
12
+ help?: ReactNode,
13
+ onChange: (value?: number) => void,
14
+ value?: number,
15
+ allowedTypes?: string[]
16
+ };
17
+ export function FileControl(props: FileControlProps) {
18
+ const {allowedTypes, help, label, onChange, value} = props;
19
+ const onSelect = useCallback((media: {id: number}) => {
20
+ if (media.id !== value) {
21
+ onChange(media.id);
22
+ }
23
+ }, [onChange, value]);
24
+
25
+ const attachment = useSuspenseSelect(select => value !== undefined ? select(coreStore).getMedia(value) : undefined, [value]);
26
+ const {baseControlProps, controlProps} = useBaseControlProps({label, help});
27
+ return <BaseControl {...baseControlProps}>
28
+ <MediaUploadCheck>
29
+ <MediaUpload
30
+ onSelect={onSelect}
31
+ value={value}
32
+ allowedTypes={allowedTypes}
33
+ render={useCallback(({open}) => {
34
+ if (!attachment?.id) {
35
+ return <div {...controlProps}><Button onClick={open} children={__('Select a File', 'plaudit')}/></div>
36
+ }
37
+ return <div {...controlProps}>
38
+ <p>{__('Selected File', 'plaudit')}: <a href={attachment.source_url} target="_blank" rel="noopener noreferrer">{attachment.title.rendered}</a></p>
39
+ <div className="selected-file-control-buttons">
40
+ <Button onClick={open} variant="secondary" children="Replace File" />
41
+ <Button onClick={() => onChange(undefined)} isDestructive children={__('Remove File', 'plaudit')} />
42
+ </div>
43
+ </div>;
44
+ }, [attachment, onChange, controlProps])}
45
+ />
46
+ </MediaUploadCheck>
47
+ </BaseControl>;
48
+ }
@@ -7,6 +7,7 @@ export * from "./ExtendedTaxonomyPicker";
7
7
  export * from "./ExtendedTermPicker";
8
8
  export * from "./ExtendedTextareaControl";
9
9
  export * from "./ExtendedUserPicker";
10
+ export * from "./FileControl";
10
11
  export * from "./FullSizeToggleControl";
11
12
  export * from "./ImageControl";
12
13
  export * from "./InspectorPanel";