@plaudit/gutenberg-api-extensions 2.88.0 → 2.90.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 (112) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/blocks/SNPFlexibleItemsListComponent.d.ts +2 -2
  3. package/dist/blocks/SNPFlexibleItemsListComponent.js +1 -1
  4. package/dist/blocks/SNPFlexibleItemsListComponent.js.map +1 -1
  5. package/dist/blocks/SNPGroupComponent.js +2 -2
  6. package/dist/blocks/SNPGroupComponent.js.map +1 -1
  7. package/dist/blocks/SNPListComponent.js +1 -1
  8. package/dist/blocks/SNPListComponent.js.map +1 -1
  9. package/dist/blocks/basic-custom-block-bindings-support.d.ts +1 -5
  10. package/dist/blocks/basic-custom-block-bindings-support.js +6 -6
  11. package/dist/blocks/basic-custom-block-bindings-support.js.map +1 -1
  12. package/dist/blocks/common-native-property-constructors.js +21 -14
  13. package/dist/blocks/common-native-property-constructors.js.map +1 -1
  14. package/dist/blocks/conditions.js +1 -1
  15. package/dist/blocks/conditions.js.map +1 -1
  16. package/dist/blocks/index.d.ts +2 -2
  17. package/dist/blocks/index.js.map +1 -1
  18. package/dist/blocks/layout/LaidOutProperty.d.ts +1 -1
  19. package/dist/blocks/layout/LaidOutPropertyRow.d.ts +5 -2
  20. package/dist/blocks/layout/LaidOutPropertyRow.js +5 -0
  21. package/dist/blocks/layout/LaidOutPropertyRow.js.map +1 -1
  22. package/dist/blocks/layout/PanelRoot.js +1 -4
  23. package/dist/blocks/layout/PanelRoot.js.map +1 -1
  24. package/dist/blocks/layout/TabsRoot.js +1 -1
  25. package/dist/blocks/layout/TabsRoot.js.map +1 -1
  26. package/dist/blocks/simple-block.d.ts +2 -2
  27. package/dist/blocks/simple-native-property-impl.js +5 -5
  28. package/dist/blocks/simple-native-property-impl.js.map +1 -1
  29. package/dist/controls/AsynchronousFormTokenField.js +1 -1
  30. package/dist/controls/AsynchronousFormTokenField.js.map +1 -1
  31. package/dist/controls/BaseSortableItemsControl.d.ts +1 -1
  32. package/dist/controls/BaseSortableItemsControl.js +2 -2
  33. package/dist/controls/BaseSortableItemsControl.js.map +1 -1
  34. package/dist/controls/ExtendedFormTokenField.js +1 -1
  35. package/dist/controls/ExtendedFormTokenField.js.map +1 -1
  36. package/dist/controls/ExtendedRadioControl.js +1 -1
  37. package/dist/controls/ExtendedRadioControl.js.map +1 -1
  38. package/dist/controls/ExtendedTextareaControl.js +1 -1
  39. package/dist/controls/ExtendedTextareaControl.js.map +1 -1
  40. package/dist/controls/FileControl.js +3 -3
  41. package/dist/controls/FileControl.js.map +1 -1
  42. package/dist/controls/FullSizeToggleControl.js +1 -0
  43. package/dist/controls/FullSizeToggleControl.js.map +1 -1
  44. package/dist/controls/ImageControl.js +5 -5
  45. package/dist/controls/ImageControl.js.map +1 -1
  46. package/dist/controls/LazySuggestionsComboboxControl.js +4 -4
  47. package/dist/controls/LazySuggestionsComboboxControl.js.map +1 -1
  48. package/dist/controls/PickOne.js +2 -2
  49. package/dist/controls/PickOne.js.map +1 -1
  50. package/dist/controls/ProperLinkControl.js +3 -3
  51. package/dist/controls/ProperLinkControl.js.map +1 -1
  52. package/dist/controls/SimpleToggle.js +1 -1
  53. package/dist/controls/SimpleToggle.js.map +1 -1
  54. package/dist/controls/SortableFlexibleItemsControl.d.ts +2 -2
  55. package/dist/controls/SortableFlexibleItemsControl.js +1 -1
  56. package/dist/controls/SortableFlexibleItemsControl.js.map +1 -1
  57. package/dist/controls/SortableItemsControl.js +1 -1
  58. package/dist/controls/SortableItemsControl.js.map +1 -1
  59. package/dist/controls/hooks/useSuggestions.js.map +1 -1
  60. package/dist/index.d.ts +2 -1
  61. package/dist/index.js +25 -3
  62. package/dist/index.js.map +1 -1
  63. package/dist/lib/compat-types.d.ts +34 -0
  64. package/dist/lib/compat-types.js +3 -0
  65. package/dist/lib/compat-types.js.map +1 -0
  66. package/dist/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.d.ts +1 -1
  67. package/dist/lib/gutenberg-api-extensions-state.d.ts +3 -3
  68. package/dist/lib/helpers.d.ts +1 -0
  69. package/dist/lib/helpers.js +21 -2
  70. package/dist/lib/helpers.js.map +1 -1
  71. package/dist/lib/sectioned-cache-store.d.ts +42 -0
  72. package/dist/lib/sectioned-cache-store.js +78 -0
  73. package/dist/lib/sectioned-cache-store.js.map +1 -0
  74. package/dist/lib/useful-types.d.ts +5 -0
  75. package/package.json +13 -13
  76. package/src/blocks/SNPFlexibleItemsListComponent.tsx +4 -4
  77. package/src/blocks/SNPGroupComponent.tsx +3 -3
  78. package/src/blocks/SNPListComponent.tsx +2 -2
  79. package/src/blocks/basic-custom-block-bindings-support.tsx +12 -8
  80. package/src/blocks/common-native-property-constructors.tsx +48 -34
  81. package/src/blocks/conditions.ts +1 -1
  82. package/src/blocks/index.ts +2 -2
  83. package/src/blocks/layout/LaidOutPropertyRow.tsx +7 -1
  84. package/src/blocks/layout/PanelRoot.tsx +2 -5
  85. package/src/blocks/layout/TabsRoot.tsx +2 -2
  86. package/src/blocks/simple-block.tsx +2 -2
  87. package/src/blocks/simple-native-property-impl.tsx +5 -5
  88. package/src/controls/AsynchronousFormTokenField.tsx +1 -0
  89. package/src/controls/BaseSortableItemsControl.tsx +8 -8
  90. package/src/controls/ExtendedFormTokenField.tsx +2 -0
  91. package/src/controls/ExtendedRadioControl.tsx +2 -2
  92. package/src/controls/ExtendedTextareaControl.tsx +1 -1
  93. package/src/controls/FileControl.tsx +4 -4
  94. package/src/controls/FullSizeToggleControl.tsx +1 -0
  95. package/src/controls/ImageControl.tsx +5 -5
  96. package/src/controls/LazySuggestionsComboboxControl.tsx +11 -9
  97. package/src/controls/PickOne.tsx +2 -1
  98. package/src/controls/ProperLinkControl.tsx +11 -6
  99. package/src/controls/SimpleToggle.tsx +1 -1
  100. package/src/controls/SortableFlexibleItemsControl.tsx +5 -3
  101. package/src/controls/SortableItemsControl.tsx +5 -1
  102. package/src/controls/hooks/useSuggestions.ts +1 -1
  103. package/src/index.ts +2 -3
  104. package/src/lib/compat-types.ts +21 -0
  105. package/src/lib/helpers.ts +23 -3
  106. package/src/lib/sectioned-cache-store.ts +120 -0
  107. package/src/lib/useful-types.ts +2 -0
  108. package/styles/editor.pcss +0 -16
  109. package/dist/editor/post-featured-image.d.ts +0 -4
  110. package/dist/editor/post-featured-image.js +0 -125
  111. package/dist/editor/post-featured-image.js.map +0 -1
  112. package/src/editor/post-featured-image.tsx +0 -161
@@ -77,6 +77,7 @@ export const ToggleGroupControlOptionWithOptionalIcon
77
77
  });
78
78
 
79
79
  function i18nSwitchLabel(label: NonNullable<OptionalLabel>): typeof label {
80
+ // eslint-disable-next-line @wordpress/i18n-no-variables -- There's nothing we can do about this - it's a requirement for being able to pass arbitrary labels
80
81
  return typeof label === 'string' ? __(label) : {...label, text: __(label.text)};
81
82
  }
82
83
 
@@ -27,7 +27,7 @@ export function ImageControl(props: ImageControlProps) {
27
27
 
28
28
  const media = useSelect(select => value?.media?.id ? select(coreStore).getMedia(value.media.id) : undefined, [value]);
29
29
  const {baseControlProps, controlProps} = useBaseControlProps({label: Label ? <Label /> : label, help});
30
- return <BaseControl {...baseControlProps}>
30
+ return <BaseControl {...baseControlProps} __nextHasNoMarginBottom>
31
31
  <div {...controlProps} className="editor-post-featured-image">
32
32
  {media
33
33
  ? <ImageControlWithUploadedImage {...props} media={media} />
@@ -52,7 +52,7 @@ function ImageControlWithUploadedImage(props: ImageControlProps&{media: Attachme
52
52
  const {includeFocalPointPicker, media, storage, onChange, value} = props;
53
53
  const onFPPChange = useCallback((pos: FocalPoint) => onChange(mergeInUpdatedValuePart(value, 'pos', {x: pos.x * 100, y: pos.y * 100}, storage)), [onChange, value]);
54
54
  const onSelect = useCallback((media: {id: number}&{[k: string]: any}) => onChange(mergeInUpdatedValuePart(value, 'media', media, storage)), [onChange, value]);
55
- const renderOpenButton = useCallback(({open}: {open(): void}) => <Button onClick={open} variant="secondary">{__('Replace image', 'plaudit')}</Button>, []);
55
+ const renderOpenButton = useCallback(({open}: {open(): void}) => <Button onClick={open} variant="secondary" __next40pxDefaultSize>{__('Replace image', 'plaudit')}</Button>, []);
56
56
  const clear = useCallback(() => onChange(undefined), [onChange]);
57
57
 
58
58
  const fppValue = useMemo(() => ({
@@ -66,6 +66,7 @@ function ImageControlWithUploadedImage(props: ImageControlProps&{media: Attachme
66
66
  onChange={onFPPChange}
67
67
  url={value?.media?.url ?? ''}
68
68
  value={fppValue}
69
+ __nextHasNoMarginBottom
69
70
  />;
70
71
  } else {
71
72
  fppOrMedia = <ResponsiveWrapper
@@ -85,7 +86,7 @@ function ImageControlWithUploadedImage(props: ImageControlProps&{media: Attachme
85
86
  allowedTypes={ALLOWED_TYPES}
86
87
  render={renderOpenButton}
87
88
  />
88
- <Button onClick={clear} isDestructive>{__('Remove image', 'plaudit')}</Button>
89
+ <Button onClick={clear} isDestructive __next40pxDefaultSize>{__('Remove image', 'plaudit')}</Button>
89
90
  </MediaUploadCheck>
90
91
  </>;
91
92
  }
@@ -94,8 +95,7 @@ function ImageControlWithoutUploadedImage(props: ImageControlProps&{media: Attac
94
95
  const onSelect = useCallback((media: {id: number}&{[k: string]: any}) => onChange(mergeInUpdatedValuePart(value, 'media', media, storage)), [onChange, value]);
95
96
  const renderOpenButton = useCallback(({open}: {open(): void}) => (
96
97
  <Button
97
- className={!value?.media?.id ? 'editor-post-featured-image__toggle' : 'editor-post-featured-image__preview'}
98
- onClick={open}
98
+ className={value?.media?.id ? 'editor-post-featured-image__preview' : 'editor-post-featured-image__toggle'} onClick={open} __next40pxDefaultSize
99
99
  >
100
100
  {!value?.media?.id && __('Choose an image', 'plaudit')}
101
101
  {media &&
@@ -1,10 +1,10 @@
1
1
  import {BaseControl, ComboboxControl, Spinner} from "@wordpress/components";
2
2
  import {useCallback, useMemo, useState} from "@wordpress/element";
3
- import {__} from "@wordpress/i18n";
3
+ import {__, sprintf} from "@wordpress/i18n";
4
4
 
5
5
  import {useSuggestions} from "./hooks/useSuggestions";
6
6
 
7
- import type {ComponentProps} from "react";
7
+ import type {ComponentProps, FocusEvent} from "react";
8
8
 
9
9
  type ComboboxControlProps = ComponentProps<typeof ComboboxControl>;
10
10
  type ComboboxControlOption = ComboboxControlProps['options'][number];
@@ -24,8 +24,8 @@ export function LazySuggestionsComboboxControl(props: LazySuggestionsComboboxCon
24
24
  () => hasFocus && input.length < 2 || (isLoading && !suggestions.length) ? [{label: input, value: "", disabled: true}] : suggestions,
25
25
  [hasFocus, input, isLoading, suggestions]);
26
26
 
27
- const onFocus = useCallback((e: React.FocusEvent<HTMLElement>) => setHasFocus(e.currentTarget.contains(e.target)), [setHasFocus]);
28
- const onBlur = useCallback((e: React.FocusEvent<HTMLElement>) => setHasFocus(e.currentTarget.contains(e.relatedTarget)), [setHasFocus]);
27
+ const onFocus = useCallback((e: FocusEvent<HTMLElement>) => setHasFocus(e.currentTarget.contains(e.target)), [setHasFocus]);
28
+ const onBlur = useCallback((e: FocusEvent<HTMLElement>) => setHasFocus(e.currentTarget.contains(e.relatedTarget)), [setHasFocus]);
29
29
 
30
30
  const onFilterValueChange = useCallback((value: string) => {
31
31
  if (props.onFilterValueChange) {
@@ -35,13 +35,13 @@ export function LazySuggestionsComboboxControl(props: LazySuggestionsComboboxCon
35
35
  }, [props.onFilterValueChange, setInput]);
36
36
 
37
37
  const __experimentalRenderItem = useMemo(() => {
38
- return hasFocus && input.length < 2 ? () => __("Start typing to see suggestions")
39
- : (isLoading && !suggestions.length ? () => __("Loading suggestions") : undefined);
38
+ return hasFocus && input.length < 2 ? () => __("Start typing to see suggestions", 'plaudit')
39
+ : (isLoading && !suggestions.length ? () => __("Loading suggestions", 'plaudit') : undefined);
40
40
  }, [hasFocus, input, isLoading, suggestions])
41
41
 
42
42
  if (isInitializing) {
43
- return <BaseControl {...props}>
44
- <Spinner /><span>{__(`Initializing ${props.label}`)}</span>
43
+ return <BaseControl {...props} __nextHasNoMarginBottom>
44
+ <Spinner /><span>{/* translators: %s is replaced with the label of the property */ sprintf(__("Initializing %s", 'plaudit'), props.label)}</span>
45
45
  </BaseControl>
46
46
  }
47
47
 
@@ -56,7 +56,9 @@ export function LazySuggestionsComboboxControl(props: LazySuggestionsComboboxCon
56
56
  onFilterValueChange={onFilterValueChange}
57
57
  __experimentalRenderItem={__experimentalRenderItem}
58
58
  allowReset={allowReset !== false}
59
+ __next40pxDefaultSize
60
+ __nextHasNoMarginBottom
59
61
  />
60
- {hasLoadingError && <div><span className="components-base-control__help">{__("An error occurred while updating suggestions")}</span></div>}
62
+ {hasLoadingError && <div><span className="components-base-control__help">{__("An error occurred while updating suggestions", 'plaudit')}</span></div>}
61
63
  </div>;
62
64
  }
@@ -42,6 +42,7 @@ export function PickOneFromSelect<T extends string>(props: SimpleBlockControlPro
42
42
  return <SelectControl
43
43
  {...makeSharedRadioAndSelectProps(props)}
44
44
  value={props.attributes[props.attribute]}
45
+ __next40pxDefaultSize __nextHasNoMarginBottom
45
46
  />;
46
47
  }
47
48
  export function PickOneFromRadios<T extends string>(props: SimpleBlockControlProps<T, string>& { options: PickableOptions<string> }) {
@@ -71,7 +72,7 @@ export function PickOneFromColors<T extends string>(props: SimpleBlockControlPro
71
72
 
72
73
  const currentColor = valueToColorMap.get(props.attributes[props.attribute]) ?? props.attributes[props.attribute];
73
74
  const {baseControlProps, controlProps} = useBaseControlProps({label: props.label, help: props.help});
74
- return <BaseControl {...baseControlProps}>
75
+ return <BaseControl {...baseControlProps} __nextHasNoMarginBottom>
75
76
  <ColorPalette
76
77
  {...controlProps}
77
78
  disableCustomColors={true}
@@ -52,15 +52,17 @@ export function ProperLinkControl(props: ProperLinkControlProps) {
52
52
 
53
53
  const renderableSettings = settings === false ? [] : settings;
54
54
  const renderControlBottom = useCallback(() => (value?.url && renderableSettings?.length && <>
55
- <Button variant="tertiary" onClick={() => setAreAdvancedSettingsVisible(!areAdvancedSettingsVisible)}
56
- icon={areAdvancedSettingsVisible ? chevronUp : chevronDown} iconPosition="right" text="Advanced"
55
+ <Button
56
+ variant="tertiary" onClick={() => setAreAdvancedSettingsVisible(!areAdvancedSettingsVisible)}
57
+ icon={areAdvancedSettingsVisible ? chevronUp : chevronDown} iconPosition="right" text="Advanced"
58
+ __next40pxDefaultSize accessibleWhenDisabled
57
59
  />
58
60
  <div ref={advancedSettingsRef} style={{display: "none", transition: "max-height 200ms ease-in-out", overflow: "hidden"}}>
59
- {...renderableSettings.map(setting => <ProperLinkControlSetting setting={setting} onChange={onChange} value={value} />)}
61
+ {...renderableSettings.map(setting => <ProperLinkControlSetting key={setting.id} setting={setting} onChange={onChange} value={value} />)}
60
62
  </div>
61
63
  </>) || "", [value, settings, areAdvancedSettingsVisible, onChange]);
62
64
 
63
- return <BaseControl id="" label={props.label} help={props.help}>
65
+ return <BaseControl __nextHasNoMarginBottom id="" label={props.label} help={props.help}>
64
66
  <LinkControl
65
67
  {...linkControlProps}
66
68
  value={value}
@@ -84,8 +86,11 @@ type ProperLinkControlSettingProps = {value?: LinkControl.Value, onChange?: (nex
84
86
  function ProperLinkControlSetting({value, onChange, setting}: ProperLinkControlSettingProps) {
85
87
  return <div style={{marginTop: "8px"}}>
86
88
  {setting.type === 'text'
87
- ? <TextControl style={{marginTop: "8px"}} value={value?.[setting.id] ?? setting.default ?? ''} label={setting.title}
88
- onChange={v => onChange?.({...value, [setting.id]: v})} />
89
+ ? <TextControl
90
+ style={{marginTop: "8px"}} value={value?.[setting.id] ?? setting.default ?? ''} label={setting.title}
91
+ onChange={v => onChange?.({...value, [setting.id]: v})}
92
+ __next40pxDefaultSize __nextHasNoMarginBottom
93
+ />
89
94
  : <ToggleControl style={{marginTop: "8px"}} checked={value?.[setting.id] ?? setting.default ?? false} label={setting.title}
90
95
  onChange={v => onChange?.({...value, [setting.id]: v})} />
91
96
  }
@@ -5,5 +5,5 @@ import type {SimpleBlockControlProps} from "./types";
5
5
 
6
6
  export function SimpleToggle<T extends string>(props: SimpleBlockControlProps<T, boolean>) {
7
7
  const onChange = useCallback((checked: boolean) => props.setAttributes({[props.attribute]: checked}), [props.setAttributes, props.attribute]);
8
- return <ToggleControl checked={props.attributes[props.attribute]} label={props.label} onChange={onChange} />;
8
+ return <ToggleControl __nextHasNoMarginBottom checked={props.attributes[props.attribute]} label={props.label} onChange={onChange} />;
9
9
  }
@@ -11,8 +11,8 @@ type SortableFlexibleItemsControlSpecificProps<T extends string> = {
11
11
  availableTypes: NonEmptyArray<{label: string, value: T}>,
12
12
  emptyValueBuilder: (type: T) => FlexibleItem<T>
13
13
  };
14
- export type SortableFlexibleItemsControl<T extends string> = Omit<BaseSortableItemsControlProps<FlexibleItem<T>>, 'buttonsArea'>&SortableFlexibleItemsControlSpecificProps<T>;
15
- export function SortableFlexibleItemsControl<T extends string>({availableTypes, emptyValueBuilder, ...baseProps}: SortableFlexibleItemsControl<T>) {
14
+ export type SortableFlexibleItemsControlProps<T extends string> = Omit<BaseSortableItemsControlProps<FlexibleItem<T>>, 'buttonsArea'>&SortableFlexibleItemsControlSpecificProps<T>;
15
+ export function SortableFlexibleItemsControl<T extends string>({availableTypes, emptyValueBuilder, ...baseProps}: SortableFlexibleItemsControlProps<T>) {
16
16
  const buttonsArea = useCallback<BaseSortableItemsControlProps<FlexibleItem<T>>['buttonsArea']>(
17
17
  // Unfortunately, the typedefs for React memo components don't allow us to properly check the emptyValueBuilder function
18
18
  args => <ButtonsArea {...args} availableTypes={availableTypes} emptyValueBuilder={emptyValueBuilder} />, [availableTypes, emptyValueBuilder]);
@@ -23,8 +23,10 @@ type ButtonsAreaProps<T extends string> = Parameters<BaseSortableItemsControlPro
23
23
  function ButtonsArea<T extends string>({addHandler, disabled, availableTypes, emptyValueBuilder}: ButtonsAreaProps<T>): ReactNode {
24
24
  const [selectedType, setSelectedType] = useState(availableTypes[0].value);
25
25
  return <div className="plaudit-sortable-items-buttons flexible-items">
26
- <Button icon="insert" disabled={disabled} onClick={() => addHandler(emptyValueBuilder(selectedType))}>Add</Button>
26
+ <Button icon="insert" disabled={disabled} onClick={() => addHandler(emptyValueBuilder(selectedType))} __next40pxDefaultSize accessibleWhenDisabled>Add</Button>
27
27
  <SelectControl
28
+ __next40pxDefaultSize
29
+ __nextHasNoMarginBottom
28
30
  label="Type"
29
31
  hideLabelFromVision={true}
30
32
  value={selectedType}
@@ -13,6 +13,10 @@ export function SortableItemsControl<D>({emptyValue, addRowText, ...baseProps}:
13
13
  type ButtonsAreaProps<D = any> = Parameters<BaseSortableItemsControlProps<D>['buttonsArea']>[0]&{emptyValue: D, addRowText?: string};
14
14
  function ButtonsArea<D>({addHandler, disabled, emptyValue, addRowText}: ButtonsAreaProps<D>) {
15
15
  return <div className="plaudit-sortable-items-buttons">
16
- <Button icon="insert" disabled={disabled} onClick={() => addHandler(typeof emptyValue === 'object' ? {...emptyValue} : emptyValue)}>{addRowText ?? "Add Row"}</Button>
16
+ <Button
17
+ icon="insert" disabled={disabled}
18
+ onClick={() => addHandler(typeof emptyValue === 'object' ? {...emptyValue} : emptyValue)}
19
+ __next40pxDefaultSize accessibleWhenDisabled
20
+ >{addRowText ?? "Add Row"}</Button>
17
21
  </div>
18
22
  }
@@ -15,7 +15,7 @@ type SuggestionState<T> = {
15
15
  requestId: number
16
16
  };
17
17
  function useSimpleDebouncer(delay: number) {
18
- const timerId = useRef<ReturnType<typeof window['setTimeout']>|undefined>(undefined);
18
+ const timerId = useRef<ReturnType<typeof setTimeout>>(undefined);
19
19
  return useCallback((action: () => void) => {
20
20
  if (timerId.current !== undefined) {
21
21
  clearTimeout(timerId.current);
package/src/index.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import {installSimpleNativePropertiesSupport} from "./blocks/simple-native-property-impl";
2
- import {installPostFeaturedImageCardFocusTargeting} from "./editor/post-featured-image";
3
2
  import {installSimpleGutenbergApisSupport, type store as endpointStore} from "./editor/simple-gutenberg-endpoints-impl";
4
3
  import {registerStore, type store as apiStore} from "./lib/gutenberg-api-extensions-state";
5
4
 
6
5
  export * from "./blocks";
7
6
  export * from "./controls";
8
7
  export * from "./editor/simple-gutenberg-endpoints-api";
9
- export {TemporalLRUCache} from "./lib/helpers";
8
+ export {TemporalLRUCache, useAdoptedStyleSheet} from "./lib/helpers";
10
9
  export * from "./lib/plaudit-icons";
10
+ export * as SectionedCacheStore from "./lib/sectioned-cache-store";
11
11
  export * from "./lib/suspense";
12
12
  export type * from "./lib/useful-types";
13
13
 
@@ -16,7 +16,6 @@ export function installGutenbergExtensions() {
16
16
  installGutenbergExtensions.called = true;
17
17
  registerStore();
18
18
  installSimpleNativePropertiesSupport();
19
- installPostFeaturedImageCardFocusTargeting();
20
19
  installSimpleGutenbergApisSupport();
21
20
  }
22
21
  }
@@ -0,0 +1,21 @@
1
+ import {DbSource} from "./useful-types";
2
+
3
+ declare module '@wordpress/blocks' {
4
+ type BaseRegisterBlockBindingsSourceFunctionArgs = {
5
+ bindings?: {[key: string]: string|{[key in string]: unknown}}, clientId?: string,
6
+ context: {[key in string]: any}, select: unknown
7
+ };
8
+ type ExtendedRegisterBlockBindingsSourceFunctionArgs = BaseRegisterBlockBindingsSourceFunctionArgs&{dispatch: {[key in string]: (...args: unknown[]) => unknown}};
9
+
10
+ type RegisterBlockBindingsSourceArgs = {
11
+ name: string, label: string, usesContext?: string[],
12
+ getValues?(args: BaseRegisterBlockBindingsSourceFunctionArgs): unknown,
13
+ setValues?: unknown,
14
+ getFieldsList?(args: BaseRegisterBlockBindingsSourceFunctionArgs): unknown,
15
+ canUserEditValue(args: BaseRegisterBlockBindingsSourceFunctionArgs): boolean,
16
+ dbSources?: DbSource[]
17
+ };
18
+ function registerBlockBindingsSource(args: RegisterBlockBindingsSourceArgs): void;
19
+
20
+ function getBlockBindingsSources(): {[key: string]: RegisterBlockBindingsSourceArgs};
21
+ }
@@ -1,3 +1,5 @@
1
+ import {useEffect, useRef} from "@wordpress/element";
2
+
1
3
  import type {SubsequentArgsOfFunc} from "./useful-types";
2
4
 
3
5
  export function clone<T>(value: T): T {
@@ -37,9 +39,27 @@ export function combineSelectors<S extends SelectorsArg<any>>(selectors: S) {
37
39
  })) as CombinedSelectors<typeof selectors>;
38
40
  }
39
41
 
42
+ export function useAdoptedStyleSheet() {
43
+ const sheet = useRef<CSSStyleSheet>();
44
+ if (sheet.current === undefined) {
45
+ sheet.current = new CSSStyleSheet();
46
+ }
47
+ useEffect(() => {
48
+ if (sheet.current !== undefined && !document.adoptedStyleSheets.includes(sheet.current)) {
49
+ document.adoptedStyleSheets.push(sheet.current);
50
+ }
51
+ return () => {
52
+ if (sheet.current !== undefined) {
53
+ document.adoptedStyleSheets.splice(document.adoptedStyleSheets.indexOf(sheet.current), 1);
54
+ }
55
+ }
56
+ });
57
+ return sheet.current;
58
+ }
59
+
40
60
  export class TemporalLRUCache<K, V extends NonNullable<any>|undefined> {
41
61
  private readonly cache: Map<K, [V, number]> = new Map();
42
- private timeout?: ReturnType<Window['setTimeout']>;
62
+ private timeout?: ReturnType<typeof setTimeout>;
43
63
 
44
64
  public constructor(
45
65
  private readonly capacity: number,
@@ -68,12 +88,12 @@ export class TemporalLRUCache<K, V extends NonNullable<any>|undefined> {
68
88
 
69
89
  cancelTimeout() {
70
90
  if (this.timeout !== undefined) {
71
- window.clearTimeout(this.timeout);
91
+ clearTimeout(this.timeout);
72
92
  this.timeout = undefined;
73
93
  }
74
94
  }
75
95
  private beginTimeout() {
76
- this.timeout = window.setTimeout(() => {
96
+ this.timeout = setTimeout(() => {
77
97
  const now = Date.now();
78
98
  const droppableItems = [...this.cache.entries()]
79
99
  .filter(([_, v]) => now - v[1] >= this.minDroppableAccessTime)
@@ -0,0 +1,120 @@
1
+ import {createReduxStore} from "@wordpress/data";
2
+
3
+ import {TemporalLRUCache} from "./helpers";
4
+ import {use, type WrappedPromise, wrapPromise} from "./suspense/promise-handlers";
5
+
6
+ type SelectorsBuilder<
7
+ PROPS,
8
+ DATA,
9
+ SELECTORS extends { [name in string]: (...args: any[]) => any }
10
+ > = (handleCacheMiss: (props: PROPS) => Promise<SectionedCacheFetchResult<DATA>>) => SELECTORS;
11
+ type SectionedCacheFetchResult<DATA> = {error?: false, data: DATA}|{error: true, data: string};
12
+ type GetCacheForPropsFunction<PROPS, DATA, KEY> = (props: PROPS) => TemporalLRUCache<KEY, WrappedPromise<SectionedCacheFetchResult<DATA>>>;
13
+ type WarmingPromiseGetter<PROPS, DATA, KEY> = (
14
+ storeChanged: () => void, props: FetchWarmingDataArgs<PROPS, DATA, KEY>[0], ...args: DropFirst<FetchWarmingDataArgs<PROPS, DATA, KEY>>
15
+ ) => WrappedPromise<void>|undefined;
16
+
17
+ type SectionedCacheStoreArgs<
18
+ PROPS,
19
+ DATA,
20
+ KEY,
21
+ SELECTORS extends { [name in string]: (...args: any[]) => any }
22
+ > = {
23
+ keyify: (props: PROPS) => KEY
24
+ name: string
25
+ selectorsBuilder: SelectorsBuilder<PROPS, DATA, SELECTORS>
26
+ getCacheForProps?: GetCacheForPropsFunction<PROPS, DATA, KEY>
27
+ getIndividualItemFetchPromise: (props: PROPS) => Promise<SectionedCacheFetchResult<DATA>>
28
+ getWarmingPromise: WarmingPromiseGetter<PROPS, DATA, KEY>
29
+ }
30
+ type AddBSStateArg<S extends {[name in string]: (...args: any[]) => any}> = {[name in keyof S]: (state: any, ...args: Parameters<S[name]>) => ReturnType<S[name]>};
31
+ export function create<PROPS, DATA, KEY, SELECTORS extends { [name in string]: (...args: any[]) => any }>(
32
+ args: SectionedCacheStoreArgs<PROPS, DATA, KEY, SELECTORS>
33
+ ) {
34
+ type ReduxSelectors = AddBSStateArg<SELECTORS>;
35
+ const {getCacheForProps = makeDefaultCacheForPropsGetter(), getIndividualItemFetchPromise, getWarmingPromise, keyify, name, selectorsBuilder} = args;
36
+ return {
37
+ name,
38
+ instantiate: () => {
39
+ const listeners = new Set<() => void>();
40
+
41
+ const storeChanged = () => {
42
+ for (const listener of listeners) {
43
+ listener();
44
+ }
45
+ }
46
+
47
+ const warmCache = (props: PROPS) => {
48
+ const warmingPromise = getWarmingPromise(storeChanged, props, getCacheForProps, keyify);
49
+ if (warmingPromise !== undefined) {
50
+ return use(warmingPromise);
51
+ }
52
+ }
53
+
54
+ const fetchItemContents = async (props: PROPS) => {
55
+ try {
56
+ return await getIndividualItemFetchPromise(props);
57
+ } catch (err) {
58
+ return ({error: true, data: (err?.toString() as string|undefined) ?? "EMPTY_RESPONSE"} as const) satisfies SectionedCacheFetchResult<DATA>;
59
+ }
60
+ }
61
+
62
+ const handleCacheMiss = (props: PROPS): Promise<SectionedCacheFetchResult<DATA>> => {
63
+ const key = keyify(props);
64
+ warmCache(props);
65
+ const cache = getCacheForProps(props);
66
+ const existingPromise = cache.get(key);
67
+ if (existingPromise !== null) {
68
+ return existingPromise;
69
+ }
70
+ const res = wrapPromise(fetchItemContents(props));
71
+ res.finally(storeChanged);
72
+ cache.set(key, res);
73
+ return res;
74
+ }
75
+
76
+ const selectors = selectorsBuilder(handleCacheMiss);
77
+
78
+ return {
79
+ getSelectors: () => selectors,
80
+ getSuspendSelectors: () => selectors,
81
+ getActions: () => ({}),
82
+ subscribe: (listener: () => void) => {
83
+ listeners.add(listener);
84
+ return () => listeners.delete(listener);
85
+ }
86
+ };
87
+ }
88
+ } satisfies ReturnType<typeof createReduxStore<{}, {}, ReduxSelectors>> as ReturnType<typeof createReduxStore<{}, {}, ReduxSelectors>>;
89
+ }
90
+
91
+ function makeDefaultCacheForPropsGetter<PROPS, DATA, KEY>() {
92
+ const cache: ReturnType<GetCacheForPropsFunction<PROPS, DATA, KEY>> = new TemporalLRUCache(10);
93
+ return () => cache;
94
+ }
95
+
96
+ type DropFirst<A extends any[]> = A extends [any, ...infer R] ? R : never;
97
+ type FetchWarmingDataArgs<PROPS, DATA, KEY> = [props: PROPS, getCacheForProps: GetCacheForPropsFunction<PROPS, DATA, KEY>, keyify: (props: PROPS) => KEY];
98
+ type MakeSimpleWarmingPromisesGetterArgs<PROPS, DATA, KEY> = {
99
+ warmingPromisesKeyify: (props: PROPS) => string|number|undefined, // Returning undefined short-circuits the rest of the function, skipping any waiting at all
100
+ fetchWarmingData: (...args: FetchWarmingDataArgs<PROPS, DATA, KEY>) => Promise<void>,
101
+ shouldWarm?: ((props: PROPS) => boolean)
102
+ };
103
+ export function makeSimpleWarmingPromisesGetter<PROPS, DATA, KEY>(
104
+ {warmingPromisesKeyify, fetchWarmingData, shouldWarm = () => true}: MakeSimpleWarmingPromisesGetterArgs<PROPS, DATA, KEY>
105
+ ): WarmingPromiseGetter<PROPS, DATA, KEY> {
106
+ const warmingPromises: Record<string|number, WrappedPromise<void>> = {};
107
+ return (storeChanged, props, ...args) => {
108
+ const key = warmingPromisesKeyify(props);
109
+ if (key === undefined) {
110
+ return;
111
+ }
112
+ if (!warmingPromises[key]) {
113
+ if (!shouldWarm(props)) {
114
+ return; // We don't want to go back to the server for the entire dataset unless we're going to be working with most of it
115
+ }
116
+ warmingPromises[key] = wrapPromise(fetchWarmingData(props, ...args).finally(storeChanged));
117
+ }
118
+ return warmingPromises[key];
119
+ };
120
+ }
@@ -47,3 +47,5 @@ export type WPTaxonomyQuery = {
47
47
  }|WPTaxonomyQueryFirstOrderClause;
48
48
  type WPTaxonomyQueryFirstOrderClause = {include_children?: boolean, operator?: 'AND'|'IN'|'NOT IN'|'EXISTS'|'NOT EXISTS'}&
49
49
  (({taxonomy: string}&({terms: number|number[], field?: 'term_id'}|{terms: string|string[], field: 'slug'|'name'}))|{taxonomy?: string, terms: number|number[], field: 'term_taxonomy_id'});
50
+
51
+ export type DbSource = {label: string, value: string, help?: string};
@@ -1,19 +1,3 @@
1
- .plauditPostFeaturedImageWithFocalPoint__wrapper {
2
- position: relative;
3
-
4
- &:hover .plauditPostFeaturedImageWithFocalPoint__toggle, &:hover .editor-post-featured-image__actions {
5
- opacity: 1;
6
- }
7
- }
8
- .plauditPostFeaturedImageWithFocalPoint__toggle {
9
- position: absolute;
10
- z-index: 10000;
11
- top: 0;
12
- right: 0;
13
- opacity: 0;
14
- padding: 8px;
15
- }
16
-
17
1
  .plaudit-snp-laid-out-properties-wrapper {
18
2
  min-width: 240px;
19
3
  }
@@ -1,4 +0,0 @@
1
- export declare function installPostFeaturedImageCardFocusTargeting(): void;
2
- export declare namespace installPostFeaturedImageCardFocusTargeting {
3
- let called: boolean;
4
- }
@@ -1,125 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.installPostFeaturedImageCardFocusTargeting = installPostFeaturedImageCardFocusTargeting;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const components_1 = require("@wordpress/components");
6
- const data_1 = require("@wordpress/data");
7
- const editor_1 = require("@wordpress/editor");
8
- const element_1 = require("@wordpress/element");
9
- const hooks_1 = require("@wordpress/hooks");
10
- const i18n_1 = require("@wordpress/i18n");
11
- function getMediaDetails(media, postId) {
12
- if (!media) {
13
- return {};
14
- }
15
- const sizes = (media?.media_details?.['sizes'] ?? {});
16
- const activeSize = sizes[getImageSize('large', media, postId)];
17
- if (activeSize !== undefined) {
18
- return {
19
- mediaWidth: activeSize.width,
20
- mediaHeight: activeSize.height,
21
- mediaSourceUrl: activeSize.source_url,
22
- };
23
- }
24
- // Use fallbackSize when defaultSize is not available.
25
- const fallbackSize = sizes[getImageSize('thumbnail', media, postId)];
26
- if (fallbackSize !== undefined) {
27
- return {
28
- mediaWidth: fallbackSize.width,
29
- mediaHeight: fallbackSize.height,
30
- mediaSourceUrl: fallbackSize.source_url,
31
- };
32
- }
33
- // Use full image size when fallbackSize and defaultSize are not available.
34
- return {
35
- mediaWidth: media.media_details['width'],
36
- mediaHeight: media.media_details['height'],
37
- mediaSourceUrl: media.source_url,
38
- };
39
- }
40
- function getLivePosition(selectFunction = data_1.select) {
41
- const { x = 50, y = 50 } = (selectFunction(editor_1.store).getEditedPostAttribute('meta')?.["plaudit_card-image_pos"] ?? {});
42
- return { x: x / 100, y: y / 100 };
43
- }
44
- function setLivePosition({ x, y }) {
45
- (0, data_1.dispatch)(editor_1.store)
46
- .editPost({
47
- meta: { "plaudit_card-image_pos": { x: Math.round(x * 100), y: Math.round(y * 100) } }
48
- })
49
- .catch(e => {
50
- console.error(e);
51
- });
52
- }
53
- function getRawLivePosition() {
54
- return { x: 50, y: 50, ...((0, data_1.select)(editor_1.store).getEditedPostAttribute('meta')?.["plaudit_card-image_pos"] ?? {}) };
55
- }
56
- function getImageSize(defaultSize, media, postId) {
57
- let filteredSize = (0, hooks_1.applyFilters)('editor.PostFeaturedImage.imageSize', defaultSize, media.id, postId);
58
- if (typeof filteredSize !== 'string') {
59
- console.error(`The 'editor.PostFeaturedImage.imageSize' filter returned a non-string size (${filteredSize}).`, `Using '${defaultSize}' as a fallback.`);
60
- return defaultSize;
61
- }
62
- return filteredSize;
63
- }
64
- function wrapPostFeaturedImage(OriginalComponent) {
65
- return (props) => {
66
- const [inFocusMode, setInFocusMode] = (0, element_1.useState)(false);
67
- // This useMemo call makes it so that we only update restorablePosition when the state changes.
68
- const restorablePosition = (0, element_1.useMemo)(getLivePosition, [inFocusMode]);
69
- const { mediaSourceUrl } = getMediaDetails(props.media, props.currentPostId);
70
- if (!mediaSourceUrl) {
71
- if ((0, data_1.select)(editor_1.store).getEditedPostAttribute('featured_media')) {
72
- return (0, jsx_runtime_1.jsx)(components_1.Spinner, {});
73
- }
74
- return (0, jsx_runtime_1.jsx)(OriginalComponent, { ...props });
75
- }
76
- else if (!inFocusMode) {
77
- return (0, jsx_runtime_1.jsx)(NotInFocusMode, { OriginalComponent: OriginalComponent, props: props, setInFocusMode: setInFocusMode });
78
- }
79
- return (0, jsx_runtime_1.jsx)(InFocusMode, { mediaSourceUrl: mediaSourceUrl, props: props, restorablePosition: restorablePosition, setInFocusMode: setInFocusMode });
80
- };
81
- }
82
- const NotInFocusMode = (0, element_1.memo)(({ OriginalComponent, props, setInFocusMode }) => {
83
- const { x, y } = getRawLivePosition();
84
- (0, element_1.useEffect)(() => {
85
- let sheet = document.adoptedStyleSheets.find(s => s.identifier === '__POST_FEATURED_IMAGE__');
86
- if (!sheet) {
87
- sheet = new CSSStyleSheet();
88
- sheet.identifier = '__POST_FEATURED_IMAGE__';
89
- }
90
- sheet.replace(`.plauditPostFeaturedImageWithFocalPoint__wrapper .editor-post-featured-image__preview-image {object-fit: ${x}% ${y}% !important;}`)
91
- .catch(e => {
92
- console.error(e);
93
- });
94
- return () => {
95
- const sheet = document.adoptedStyleSheets.findIndex(s => s.identifier === '__POST_FEATURED_IMAGE__');
96
- if (sheet) {
97
- document.adoptedStyleSheets.splice(sheet, 1);
98
- }
99
- };
100
- }, [x, y]);
101
- return (0, jsx_runtime_1.jsx)(editor_1.PostFeaturedImageCheck, { children: (0, jsx_runtime_1.jsxs)("div", { className: "plauditPostFeaturedImageWithFocalPoint__wrapper", children: [(0, jsx_runtime_1.jsx)("div", { className: "plauditPostFeaturedImageWithFocalPoint__toggle", children: (0, jsx_runtime_1.jsx)(components_1.Button, { onClick: (0, element_1.useCallback)(() => setInFocusMode(true), [setInFocusMode]), className: "editor-post-featured-image__action", text: (0, i18n_1.__)("Change Focal Point", 'plaudit') }) }), (0, jsx_runtime_1.jsx)(OriginalComponent, { ...props })] }) });
102
- });
103
- const InFocusMode = (0, element_1.memo)(({ mediaSourceUrl, props, restorablePosition, setInFocusMode }) => {
104
- // This assembly makes it so that we both get updates if something else triggers a position change while making the focus picker doesn't reset itself
105
- const { x, y } = (0, data_1.useSelect)(getLivePosition, []);
106
- const [position, setPosition] = (0, element_1.useState)({ x, y });
107
- (0, element_1.useEffect)(() => setPosition(getLivePosition()), [x, y]);
108
- return (0, jsx_runtime_1.jsxs)(editor_1.PostFeaturedImageCheck, { children: [props.noticeUI, (0, jsx_runtime_1.jsxs)("div", { className: "editor-post-featured-image", children: [(0, jsx_runtime_1.jsx)(components_1.FocalPointPicker, { onChange: (0, element_1.useCallback)(pos => {
109
- setPosition(pos);
110
- setLivePosition(pos);
111
- }, [setPosition]), url: mediaSourceUrl, value: position }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(components_1.Button, { text: (0, i18n_1.__)("Done", 'plaudit'), onClick: (0, element_1.useCallback)(() => setInFocusMode(false), [setInFocusMode]), variant: "primary" }), (0, jsx_runtime_1.jsx)(components_1.Button, { text: (0, i18n_1.__)('Cancel', 'plaudit'), onClick: (0, element_1.useCallback)(() => {
112
- setLivePosition(restorablePosition);
113
- setInFocusMode(false);
114
- }, [setInFocusMode]), isDestructive: true })] })] })] });
115
- });
116
- function installPostFeaturedImageCardFocusTargeting() {
117
- if (!installPostFeaturedImageCardFocusTargeting.called) {
118
- installPostFeaturedImageCardFocusTargeting.called = true;
119
- (0, hooks_1.addFilter)('editor.PostFeaturedImage', 'plaudit-gutenberg-api-extensions/inject-post-featured-image-card-focus-targeting', wrapPostFeaturedImage);
120
- }
121
- }
122
- (function (installPostFeaturedImageCardFocusTargeting) {
123
- installPostFeaturedImageCardFocusTargeting.called = false;
124
- })(installPostFeaturedImageCardFocusTargeting || (exports.installPostFeaturedImageCardFocusTargeting = installPostFeaturedImageCardFocusTargeting = {}));
125
- //# sourceMappingURL=post-featured-image.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"post-featured-image.js","sourceRoot":"","sources":["../../src/editor/post-featured-image.tsx"],"names":[],"mappings":"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"}