@plaudit/gutenberg-api-extensions 2.79.0 → 2.80.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 (489) hide show
  1. package/dist/blocks/MoveError.js +10 -0
  2. package/dist/blocks/MoveError.js.map +1 -0
  3. package/{build → dist}/blocks/PathError.js +7 -3
  4. package/dist/blocks/PathError.js.map +1 -0
  5. package/{build → dist}/blocks/SNPFlexibleItemsListComponent.d.ts +1 -1
  6. package/dist/blocks/SNPFlexibleItemsListComponent.js +18 -0
  7. package/dist/blocks/SNPFlexibleItemsListComponent.js.map +1 -0
  8. package/{build → dist}/blocks/SNPGroupComponent.d.ts +2 -2
  9. package/dist/blocks/SNPGroupComponent.js +20 -0
  10. package/dist/blocks/SNPGroupComponent.js.map +1 -0
  11. package/{build → dist}/blocks/SNPListComponent.d.ts +1 -1
  12. package/dist/blocks/SNPListComponent.js +18 -0
  13. package/dist/blocks/SNPListComponent.js.map +1 -0
  14. package/dist/blocks/SNPTreeContext.js +14 -0
  15. package/dist/blocks/SNPTreeContext.js.map +1 -0
  16. package/dist/blocks/basic-custom-block-bindings-support.js +157 -0
  17. package/dist/blocks/basic-custom-block-bindings-support.js.map +1 -0
  18. package/dist/blocks/common-native-property-constructors.d.ts +13 -0
  19. package/{build → dist}/blocks/common-native-property-constructors.js +105 -151
  20. package/dist/blocks/common-native-property-constructors.js.map +1 -0
  21. package/{build → dist}/blocks/conditions.js +12 -7
  22. package/dist/blocks/conditions.js.map +1 -0
  23. package/dist/blocks/csnp-api.d.ts +166 -0
  24. package/dist/blocks/csnp-api.js +74 -0
  25. package/dist/blocks/csnp-api.js.map +1 -0
  26. package/{build → dist}/blocks/data-controller-manager.js +4 -1
  27. package/dist/blocks/data-controller-manager.js.map +1 -0
  28. package/{build → dist}/blocks/data-controller.js +74 -70
  29. package/dist/blocks/data-controller.js.map +1 -0
  30. package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/select.js +14 -11
  31. package/dist/blocks/hooks/built-in-suspendable-option-protocols/select.js.map +1 -0
  32. package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/settings.js +9 -6
  33. package/dist/blocks/hooks/built-in-suspendable-option-protocols/settings.js.map +1 -0
  34. package/{build → dist}/blocks/hooks/useSuspendableOptions.d.ts +1 -1
  35. package/{build → dist}/blocks/hooks/useSuspendableOptions.js +30 -23
  36. package/dist/blocks/hooks/useSuspendableOptions.js.map +1 -0
  37. package/dist/blocks/index.js +35 -0
  38. package/dist/blocks/index.js.map +1 -0
  39. package/{build → dist}/blocks/layered-styles-api.d.ts +2 -2
  40. package/{build → dist}/blocks/layered-styles-api.js +10 -6
  41. package/dist/blocks/layered-styles-api.js.map +1 -0
  42. package/{build → dist}/blocks/layered-styles-impl.js +14 -9
  43. package/dist/blocks/layered-styles-impl.js.map +1 -0
  44. package/{build → dist}/blocks/layout/LaidOutProperty.d.ts +1 -2
  45. package/dist/blocks/layout/LaidOutProperty.js +47 -0
  46. package/dist/blocks/layout/LaidOutProperty.js.map +1 -0
  47. package/dist/blocks/layout/LaidOutPropertyRow.js +15 -0
  48. package/dist/blocks/layout/LaidOutPropertyRow.js.map +1 -0
  49. package/{build → dist}/blocks/layout/NodeContext.d.ts +2 -2
  50. package/dist/blocks/layout/NodeContext.js +44 -0
  51. package/dist/blocks/layout/NodeContext.js.map +1 -0
  52. package/dist/blocks/layout/PanelRoot.js +29 -0
  53. package/dist/blocks/layout/PanelRoot.js.map +1 -0
  54. package/{build → dist}/blocks/layout/TabsRoot.js +16 -13
  55. package/dist/blocks/layout/TabsRoot.js.map +1 -0
  56. package/dist/blocks/layout/ToolsPanelContext.js +23 -0
  57. package/dist/blocks/layout/ToolsPanelContext.js.map +1 -0
  58. package/dist/blocks/shared-exportable-types.js +3 -0
  59. package/dist/blocks/shared-internal-types.js +3 -0
  60. package/{build → dist}/blocks/simple-block.d.ts +1 -1
  61. package/dist/blocks/simple-block.js +45 -0
  62. package/dist/blocks/simple-block.js.map +1 -0
  63. package/{build → dist}/blocks/simple-native-property-api.d.ts +1 -1
  64. package/{build → dist}/blocks/simple-native-property-api.js +16 -10
  65. package/dist/blocks/simple-native-property-api.js.map +1 -0
  66. package/{build → dist}/blocks/simple-native-property-impl.js +60 -55
  67. package/dist/blocks/simple-native-property-impl.js.map +1 -0
  68. package/{build → dist}/blocks/simple-native-property-internal-shared.js +6 -2
  69. package/dist/blocks/simple-native-property-internal-shared.js.map +1 -0
  70. package/{build → dist}/blocks/snp-api.d.ts +1 -0
  71. package/dist/blocks/snp-api.js +7 -0
  72. package/dist/blocks/snp-api.js.map +1 -0
  73. package/{build → dist}/blocks/snp-data-store.js +8 -4
  74. package/dist/blocks/snp-data-store.js.map +1 -0
  75. package/{build → dist}/blocks/utilities.d.ts +1 -1
  76. package/dist/blocks/utilities.js +79 -0
  77. package/dist/blocks/utilities.js.map +1 -0
  78. package/{build → dist}/controls/AsynchronousFormTokenField.d.ts +1 -1
  79. package/dist/controls/AsynchronousFormTokenField.js +36 -0
  80. package/dist/controls/AsynchronousFormTokenField.js.map +1 -0
  81. package/{build → dist}/controls/BaseSortableItemsControl.d.ts +3 -3
  82. package/dist/controls/BaseSortableItemsControl.js +25 -0
  83. package/dist/controls/BaseSortableItemsControl.js.map +1 -0
  84. package/{build → dist}/controls/ExtendedFormTokenField.d.ts +3 -3
  85. package/dist/controls/ExtendedFormTokenField.js +64 -0
  86. package/dist/controls/ExtendedFormTokenField.js.map +1 -0
  87. package/dist/controls/ExtendedPostPicker.js +28 -0
  88. package/dist/controls/ExtendedPostPicker.js.map +1 -0
  89. package/dist/controls/ExtendedRadioControl.d.ts +12 -0
  90. package/dist/controls/ExtendedRadioControl.js +33 -0
  91. package/dist/controls/ExtendedRadioControl.js.map +1 -0
  92. package/{build → dist}/controls/ExtendedTaxonomyPicker.d.ts +1 -1
  93. package/dist/controls/ExtendedTaxonomyPicker.js +71 -0
  94. package/dist/controls/ExtendedTaxonomyPicker.js.map +1 -0
  95. package/{build → dist}/controls/ExtendedTermPicker.d.ts +1 -1
  96. package/dist/controls/ExtendedTermPicker.js +33 -0
  97. package/dist/controls/ExtendedTermPicker.js.map +1 -0
  98. package/dist/controls/ExtendedTextareaControl.d.ts +12 -0
  99. package/{build → dist}/controls/ExtendedTextareaControl.js +15 -12
  100. package/dist/controls/ExtendedTextareaControl.js.map +1 -0
  101. package/dist/controls/ExtendedUserPicker.js +28 -0
  102. package/dist/controls/ExtendedUserPicker.js.map +1 -0
  103. package/{build → dist}/controls/FullSizeToggleControl.d.ts +6 -4
  104. package/dist/controls/FullSizeToggleControl.js +110 -0
  105. package/dist/controls/FullSizeToggleControl.js.map +1 -0
  106. package/{build → dist}/controls/ImageControl.d.ts +1 -1
  107. package/dist/controls/ImageControl.js +81 -0
  108. package/dist/controls/ImageControl.js.map +1 -0
  109. package/{build → dist}/controls/InspectorPanel.d.ts +4 -3
  110. package/dist/controls/InspectorPanel.js +29 -0
  111. package/dist/controls/InspectorPanel.js.map +1 -0
  112. package/{build → dist}/controls/LazySuggestionsComboboxControl.d.ts +5 -1
  113. package/dist/controls/LazySuggestionsComboboxControl.js +32 -0
  114. package/dist/controls/LazySuggestionsComboboxControl.js.map +1 -0
  115. package/{build → dist}/controls/MultiSelectControl.d.ts +1 -1
  116. package/dist/controls/MultiSelectControl.js +33 -0
  117. package/dist/controls/MultiSelectControl.js.map +1 -0
  118. package/{build → dist}/controls/PickOne.d.ts +1 -1
  119. package/dist/controls/PickOne.js +54 -0
  120. package/dist/controls/PickOne.js.map +1 -0
  121. package/{build → dist}/controls/PromisableComponent.d.ts +2 -2
  122. package/{build → dist}/controls/PromisableComponent.js +14 -11
  123. package/dist/controls/PromisableComponent.js.map +1 -0
  124. package/{build → dist}/controls/ProperLinkControl.d.ts +1 -1
  125. package/dist/controls/ProperLinkControl.js +59 -0
  126. package/dist/controls/ProperLinkControl.js.map +1 -0
  127. package/dist/controls/SimpleToggle.js +11 -0
  128. package/dist/controls/SimpleToggle.js.map +1 -0
  129. package/dist/controls/SortableFlexibleItemsControl.js +18 -0
  130. package/dist/controls/SortableFlexibleItemsControl.js.map +1 -0
  131. package/dist/controls/SortableItemsControl.js +15 -0
  132. package/dist/controls/SortableItemsControl.js.map +1 -0
  133. package/{build → dist}/controls/basicNumericallyIdedItemPicker.d.ts +1 -1
  134. package/dist/controls/basicNumericallyIdedItemPicker.js +37 -0
  135. package/dist/controls/basicNumericallyIdedItemPicker.js.map +1 -0
  136. package/{build → dist}/controls/hooks/useImprovedTokenManager.d.ts +7 -5
  137. package/{build → dist}/controls/hooks/useImprovedTokenManager.js +21 -15
  138. package/dist/controls/hooks/useImprovedTokenManager.js.map +1 -0
  139. package/{build → dist}/controls/hooks/useMultiSingleConversionLayer.d.ts +1 -1
  140. package/dist/controls/hooks/useMultiSingleConversionLayer.js +14 -0
  141. package/dist/controls/hooks/useMultiSingleConversionLayer.js.map +1 -0
  142. package/dist/controls/hooks/useNonRenderingCounter.js +9 -0
  143. package/dist/controls/hooks/useNonRenderingCounter.js.map +1 -0
  144. package/{build → dist}/controls/hooks/useOutputMemoizingFilter.js +7 -4
  145. package/dist/controls/hooks/useOutputMemoizingFilter.js.map +1 -0
  146. package/{build → dist}/controls/hooks/useSortableItemsModel.js +14 -11
  147. package/dist/controls/hooks/useSortableItemsModel.js.map +1 -0
  148. package/{build → dist}/controls/hooks/useSuggestions.js +16 -13
  149. package/dist/controls/hooks/useSuggestions.js.map +1 -0
  150. package/{build → dist}/controls/hooks/useTokenManager.d.ts +5 -3
  151. package/{build → dist}/controls/hooks/useTokenManager.js +37 -34
  152. package/dist/controls/hooks/useTokenManager.js.map +1 -0
  153. package/dist/controls/index.js +41 -0
  154. package/dist/controls/index.js.map +1 -0
  155. package/{build → dist}/controls/shared.js +18 -8
  156. package/dist/controls/shared.js.map +1 -0
  157. package/dist/controls/types.js +3 -0
  158. package/dist/editor/post-featured-image.js +125 -0
  159. package/dist/editor/post-featured-image.js.map +1 -0
  160. package/dist/editor/simple-gutenberg-endpoints-api.js +26 -0
  161. package/dist/editor/simple-gutenberg-endpoints-api.js.map +1 -0
  162. package/{build → dist}/editor/simple-gutenberg-endpoints-impl.js +24 -17
  163. package/dist/editor/simple-gutenberg-endpoints-impl.js.map +1 -0
  164. package/dist/index.js +39 -0
  165. package/dist/index.js.map +1 -0
  166. package/dist/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js +27 -0
  167. package/dist/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js.map +1 -0
  168. package/{build → dist}/lib/gutenberg-api-extensions-state/general-logic.js +12 -8
  169. package/dist/lib/gutenberg-api-extensions-state/general-logic.js.map +1 -0
  170. package/{build → dist}/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js +10 -6
  171. package/dist/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js.map +1 -0
  172. package/{build → dist}/lib/gutenberg-api-extensions-state/snp-logic.js +33 -26
  173. package/dist/lib/gutenberg-api-extensions-state/snp-logic.js.map +1 -0
  174. package/{build → dist}/lib/gutenberg-api-extensions-state.d.ts +2 -2
  175. package/dist/lib/gutenberg-api-extensions-state.js +52 -0
  176. package/dist/lib/gutenberg-api-extensions-state.js.map +1 -0
  177. package/{build → dist}/lib/helpers.d.ts +3 -4
  178. package/{build → dist}/lib/helpers.js +13 -6
  179. package/dist/lib/helpers.js.map +1 -0
  180. package/dist/lib/plaudit-icons/column-1.js +6 -0
  181. package/dist/lib/plaudit-icons/column-1.js.map +1 -0
  182. package/dist/lib/plaudit-icons/column-2.js +6 -0
  183. package/dist/lib/plaudit-icons/column-2.js.map +1 -0
  184. package/dist/lib/plaudit-icons/column-3.js +6 -0
  185. package/dist/lib/plaudit-icons/column-3.js.map +1 -0
  186. package/dist/lib/plaudit-icons/placement-center.js +6 -0
  187. package/dist/lib/plaudit-icons/placement-center.js.map +1 -0
  188. package/dist/lib/plaudit-icons/placement-end.js +6 -0
  189. package/dist/lib/plaudit-icons/placement-end.js.map +1 -0
  190. package/dist/lib/plaudit-icons/placement-start.js +6 -0
  191. package/dist/lib/plaudit-icons/placement-start.js.map +1 -0
  192. package/dist/lib/plaudit-icons/placement-stretch.js +6 -0
  193. package/dist/lib/plaudit-icons/placement-stretch.js.map +1 -0
  194. package/dist/lib/plaudit-icons/plaudit-icon.js +6 -0
  195. package/dist/lib/plaudit-icons/plaudit-icon.js.map +1 -0
  196. package/dist/lib/plaudit-icons/reusable-block-marker.js +6 -0
  197. package/{build → dist}/lib/plaudit-icons/reusable-block-marker.js.map +1 -1
  198. package/dist/lib/plaudit-icons.js +29 -0
  199. package/dist/lib/plaudit-icons.js.map +1 -0
  200. package/{build → dist}/lib/suspense/promise-handlers.js +16 -7
  201. package/dist/lib/suspense/promise-handlers.js.map +1 -0
  202. package/{build → dist}/lib/suspense.d.ts +2 -2
  203. package/dist/lib/suspense.js +31 -0
  204. package/dist/lib/suspense.js.map +1 -0
  205. package/{build → dist}/lib/useful-types.d.ts +4 -1
  206. package/dist/lib/useful-types.js +11 -0
  207. package/dist/lib/useful-types.js.map +1 -0
  208. package/package.json +23 -31
  209. package/src/blocks/MoveError.ts +7 -0
  210. package/src/blocks/PathError.ts +18 -0
  211. package/src/blocks/SNPFlexibleItemsListComponent.tsx +30 -0
  212. package/src/blocks/SNPGroupComponent.tsx +38 -0
  213. package/src/blocks/SNPListComponent.tsx +25 -0
  214. package/src/blocks/SNPTreeContext.tsx +13 -0
  215. package/src/blocks/basic-custom-block-bindings-support.tsx +243 -0
  216. package/src/blocks/common-native-property-constructors.tsx +877 -0
  217. package/src/blocks/conditions.ts +260 -0
  218. package/src/blocks/csnp-api.ts +214 -0
  219. package/src/blocks/data-controller-manager.ts +50 -0
  220. package/src/blocks/data-controller.ts +736 -0
  221. package/src/blocks/hooks/built-in-suspendable-option-protocols/select.ts +51 -0
  222. package/src/blocks/hooks/built-in-suspendable-option-protocols/settings.ts +70 -0
  223. package/src/blocks/hooks/useSuspendableOptions.ts +123 -0
  224. package/src/blocks/index.ts +20 -0
  225. package/src/blocks/layered-styles-api.ts +142 -0
  226. package/src/blocks/layered-styles-impl.ts +94 -0
  227. package/src/blocks/layout/LaidOutProperty.tsx +72 -0
  228. package/src/blocks/layout/LaidOutPropertyRow.tsx +22 -0
  229. package/src/blocks/layout/NodeContext.tsx +54 -0
  230. package/src/blocks/layout/PanelRoot.tsx +33 -0
  231. package/src/blocks/layout/TabsRoot.tsx +56 -0
  232. package/src/blocks/layout/ToolsPanelContext.tsx +22 -0
  233. package/src/blocks/shared-exportable-types.ts +6 -0
  234. package/src/blocks/shared-internal-types.ts +18 -0
  235. package/src/blocks/simple-block.tsx +74 -0
  236. package/src/blocks/simple-native-property-api.ts +170 -0
  237. package/src/blocks/simple-native-property-impl.tsx +329 -0
  238. package/src/blocks/simple-native-property-internal-shared.ts +46 -0
  239. package/src/blocks/snp-api.ts +5 -0
  240. package/src/blocks/snp-data-store.ts +66 -0
  241. package/src/blocks/utilities.ts +80 -0
  242. package/src/controls/AsynchronousFormTokenField.tsx +85 -0
  243. package/src/controls/BaseSortableItemsControl.tsx +84 -0
  244. package/src/controls/ExtendedFormTokenField.tsx +120 -0
  245. package/src/controls/ExtendedPostPicker.ts +57 -0
  246. package/src/controls/ExtendedRadioControl.tsx +107 -0
  247. package/src/controls/ExtendedTaxonomyPicker.tsx +100 -0
  248. package/src/controls/ExtendedTermPicker.tsx +62 -0
  249. package/src/controls/ExtendedTextareaControl.tsx +65 -0
  250. package/src/controls/ExtendedUserPicker.ts +56 -0
  251. package/src/controls/FullSizeToggleControl.tsx +94 -0
  252. package/src/controls/ImageControl.tsx +143 -0
  253. package/src/controls/InspectorPanel.tsx +37 -0
  254. package/src/controls/LazySuggestionsComboboxControl.tsx +62 -0
  255. package/src/controls/MultiSelectControl.tsx +59 -0
  256. package/src/controls/PickOne.tsx +84 -0
  257. package/src/controls/PromisableComponent.tsx +56 -0
  258. package/src/controls/ProperLinkControl.tsx +93 -0
  259. package/src/controls/SimpleToggle.tsx +9 -0
  260. package/src/controls/SortableFlexibleItemsControl.tsx +35 -0
  261. package/src/controls/SortableItemsControl.tsx +18 -0
  262. package/src/controls/basicNumericallyIdedItemPicker.tsx +76 -0
  263. package/src/controls/hooks/useImprovedTokenManager.ts +156 -0
  264. package/src/controls/hooks/useMultiSingleConversionLayer.ts +17 -0
  265. package/src/controls/hooks/useNonRenderingCounter.ts +6 -0
  266. package/src/controls/hooks/useOutputMemoizingFilter.ts +16 -0
  267. package/src/controls/hooks/useSortableItemsModel.ts +196 -0
  268. package/src/controls/hooks/useSuggestions.ts +91 -0
  269. package/src/controls/hooks/useTokenManager.ts +177 -0
  270. package/{build/controls/index.js → src/controls/index.ts} +3 -2
  271. package/src/controls/shared.ts +50 -0
  272. package/src/controls/types.ts +18 -0
  273. package/src/editor/post-featured-image.tsx +161 -0
  274. package/src/editor/simple-gutenberg-endpoints-api.ts +31 -0
  275. package/src/editor/simple-gutenberg-endpoints-impl.ts +119 -0
  276. package/src/index.ts +32 -0
  277. package/src/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.ts +34 -0
  278. package/src/lib/gutenberg-api-extensions-state/general-logic.ts +41 -0
  279. package/src/lib/gutenberg-api-extensions-state/layered-block-styles-logic.ts +42 -0
  280. package/src/lib/gutenberg-api-extensions-state/snp-logic.ts +240 -0
  281. package/src/lib/gutenberg-api-extensions-state.ts +69 -0
  282. package/src/lib/helpers.ts +113 -0
  283. package/src/lib/plaudit-icons/column-1.tsx +6 -0
  284. package/src/lib/plaudit-icons/column-2.tsx +6 -0
  285. package/src/lib/plaudit-icons/column-3.tsx +6 -0
  286. package/src/lib/plaudit-icons/placement-center.tsx +3 -0
  287. package/src/lib/plaudit-icons/placement-end.tsx +3 -0
  288. package/src/lib/plaudit-icons/placement-start.tsx +3 -0
  289. package/src/lib/plaudit-icons/placement-stretch.tsx +3 -0
  290. package/src/lib/plaudit-icons/plaudit-icon.tsx +4 -0
  291. package/src/lib/plaudit-icons/reusable-block-marker.tsx +3 -0
  292. package/{build/lib/plaudit-icons.js → src/lib/plaudit-icons.ts} +1 -1
  293. package/src/lib/suspense/promise-handlers.ts +72 -0
  294. package/src/lib/suspense.tsx +18 -0
  295. package/src/lib/useful-types.ts +65 -0
  296. package/build/blocks/MoveError.js +0 -6
  297. package/build/blocks/MoveError.js.map +0 -1
  298. package/build/blocks/PathError.js.map +0 -1
  299. package/build/blocks/SNPFlexibleItemsListComponent.js +0 -15
  300. package/build/blocks/SNPFlexibleItemsListComponent.js.map +0 -1
  301. package/build/blocks/SNPGroupComponent.js +0 -17
  302. package/build/blocks/SNPGroupComponent.js.map +0 -1
  303. package/build/blocks/SNPListComponent.js +0 -15
  304. package/build/blocks/SNPListComponent.js.map +0 -1
  305. package/build/blocks/SNPTreeContext.js +0 -10
  306. package/build/blocks/SNPTreeContext.js.map +0 -1
  307. package/build/blocks/basic-custom-block-bindings-support.js +0 -150
  308. package/build/blocks/basic-custom-block-bindings-support.js.map +0 -1
  309. package/build/blocks/common-native-property-constructors.d.ts +0 -208
  310. package/build/blocks/common-native-property-constructors.js.map +0 -1
  311. package/build/blocks/conditions.js.map +0 -1
  312. package/build/blocks/data-controller-manager.js.map +0 -1
  313. package/build/blocks/data-controller.js.map +0 -1
  314. package/build/blocks/hooks/built-in-suspendable-option-protocols/select.js.map +0 -1
  315. package/build/blocks/hooks/built-in-suspendable-option-protocols/settings.js.map +0 -1
  316. package/build/blocks/hooks/useSuspendableOptions.js.map +0 -1
  317. package/build/blocks/index.js +0 -15
  318. package/build/blocks/index.js.map +0 -1
  319. package/build/blocks/layered-styles-api.js.map +0 -1
  320. package/build/blocks/layered-styles-impl.js.map +0 -1
  321. package/build/blocks/layout/LaidOutProperty.js +0 -44
  322. package/build/blocks/layout/LaidOutProperty.js.map +0 -1
  323. package/build/blocks/layout/LaidOutPropertyRow.js +0 -12
  324. package/build/blocks/layout/LaidOutPropertyRow.js.map +0 -1
  325. package/build/blocks/layout/NodeContext.js +0 -37
  326. package/build/blocks/layout/NodeContext.js.map +0 -1
  327. package/build/blocks/layout/PanelRoot.js +0 -26
  328. package/build/blocks/layout/PanelRoot.js.map +0 -1
  329. package/build/blocks/layout/TabsRoot.js.map +0 -1
  330. package/build/blocks/layout/ToolsPanelContext.js +0 -18
  331. package/build/blocks/layout/ToolsPanelContext.js.map +0 -1
  332. package/build/blocks/shared-exportable-types.js +0 -2
  333. package/build/blocks/shared-internal-types.js +0 -2
  334. package/build/blocks/simple-block.js +0 -41
  335. package/build/blocks/simple-block.js.map +0 -1
  336. package/build/blocks/simple-native-property-api.js.map +0 -1
  337. package/build/blocks/simple-native-property-impl.js.map +0 -1
  338. package/build/blocks/simple-native-property-internal-shared.js.map +0 -1
  339. package/build/blocks/snp-api.js +0 -2
  340. package/build/blocks/snp-api.js.map +0 -1
  341. package/build/blocks/snp-data-store.js.map +0 -1
  342. package/build/blocks/utilities.js +0 -67
  343. package/build/blocks/utilities.js.map +0 -1
  344. package/build/controls/AsynchronousFormTokenField.js +0 -32
  345. package/build/controls/AsynchronousFormTokenField.js.map +0 -1
  346. package/build/controls/BaseSortableItemsControl.js +0 -22
  347. package/build/controls/BaseSortableItemsControl.js.map +0 -1
  348. package/build/controls/ExtendedFormTokenField.js +0 -58
  349. package/build/controls/ExtendedFormTokenField.js.map +0 -1
  350. package/build/controls/ExtendedPostPicker.js +0 -22
  351. package/build/controls/ExtendedPostPicker.js.map +0 -1
  352. package/build/controls/ExtendedRadioControl.d.ts +0 -10
  353. package/build/controls/ExtendedRadioControl.js +0 -30
  354. package/build/controls/ExtendedRadioControl.js.map +0 -1
  355. package/build/controls/ExtendedTaxonomyPicker.js +0 -68
  356. package/build/controls/ExtendedTaxonomyPicker.js.map +0 -1
  357. package/build/controls/ExtendedTermPicker.js +0 -27
  358. package/build/controls/ExtendedTermPicker.js.map +0 -1
  359. package/build/controls/ExtendedTextareaControl.d.ts +0 -14
  360. package/build/controls/ExtendedTextareaControl.js.map +0 -1
  361. package/build/controls/ExtendedUserPicker.js +0 -22
  362. package/build/controls/ExtendedUserPicker.js.map +0 -1
  363. package/build/controls/FullSizeToggleControl.js +0 -70
  364. package/build/controls/FullSizeToggleControl.js.map +0 -1
  365. package/build/controls/ImageControl.js +0 -76
  366. package/build/controls/ImageControl.js.map +0 -1
  367. package/build/controls/InspectorPanel.js +0 -26
  368. package/build/controls/InspectorPanel.js.map +0 -1
  369. package/build/controls/LazySuggestionsComboboxControl.js +0 -29
  370. package/build/controls/LazySuggestionsComboboxControl.js.map +0 -1
  371. package/build/controls/MultiSelectControl.js +0 -30
  372. package/build/controls/MultiSelectControl.js.map +0 -1
  373. package/build/controls/PickOne.js +0 -48
  374. package/build/controls/PickOne.js.map +0 -1
  375. package/build/controls/PromisableComponent.js.map +0 -1
  376. package/build/controls/ProperLinkControl.js +0 -56
  377. package/build/controls/ProperLinkControl.js.map +0 -1
  378. package/build/controls/SimpleToggle.js +0 -8
  379. package/build/controls/SimpleToggle.js.map +0 -1
  380. package/build/controls/SortableFlexibleItemsControl.js +0 -15
  381. package/build/controls/SortableFlexibleItemsControl.js.map +0 -1
  382. package/build/controls/SortableItemsControl.js +0 -12
  383. package/build/controls/SortableItemsControl.js.map +0 -1
  384. package/build/controls/basicNumericallyIdedItemPicker.js +0 -34
  385. package/build/controls/basicNumericallyIdedItemPicker.js.map +0 -1
  386. package/build/controls/hooks/useImprovedTokenManager.js.map +0 -1
  387. package/build/controls/hooks/useMultiSingleConversionLayer.js +0 -11
  388. package/build/controls/hooks/useMultiSingleConversionLayer.js.map +0 -1
  389. package/build/controls/hooks/useNonRenderingCounter.js +0 -6
  390. package/build/controls/hooks/useNonRenderingCounter.js.map +0 -1
  391. package/build/controls/hooks/useOutputMemoizingFilter.js.map +0 -1
  392. package/build/controls/hooks/useSortableItemsModel.js.map +0 -1
  393. package/build/controls/hooks/useSuggestions.js.map +0 -1
  394. package/build/controls/hooks/useTokenManager.js.map +0 -1
  395. package/build/controls/index.js.map +0 -1
  396. package/build/controls/shared.js.map +0 -1
  397. package/build/controls/types.js +0 -2
  398. package/build/editor/post-featured-image.js +0 -122
  399. package/build/editor/post-featured-image.js.map +0 -1
  400. package/build/editor/simple-gutenberg-endpoints-api.js +0 -22
  401. package/build/editor/simple-gutenberg-endpoints-api.js.map +0 -1
  402. package/build/editor/simple-gutenberg-endpoints-impl.js.map +0 -1
  403. package/build/index.js +0 -22
  404. package/build/index.js.map +0 -1
  405. package/build/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js +0 -23
  406. package/build/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.js.map +0 -1
  407. package/build/lib/gutenberg-api-extensions-state/general-logic.js.map +0 -1
  408. package/build/lib/gutenberg-api-extensions-state/layered-block-styles-logic.js.map +0 -1
  409. package/build/lib/gutenberg-api-extensions-state/snp-logic.js.map +0 -1
  410. package/build/lib/gutenberg-api-extensions-state.js +0 -48
  411. package/build/lib/gutenberg-api-extensions-state.js.map +0 -1
  412. package/build/lib/helpers.js.map +0 -1
  413. package/build/lib/plaudit-icons/column-1.js +0 -3
  414. package/build/lib/plaudit-icons/column-1.js.map +0 -1
  415. package/build/lib/plaudit-icons/column-2.js +0 -3
  416. package/build/lib/plaudit-icons/column-2.js.map +0 -1
  417. package/build/lib/plaudit-icons/column-3.js +0 -3
  418. package/build/lib/plaudit-icons/column-3.js.map +0 -1
  419. package/build/lib/plaudit-icons/placement-center.js +0 -3
  420. package/build/lib/plaudit-icons/placement-center.js.map +0 -1
  421. package/build/lib/plaudit-icons/placement-end.js +0 -3
  422. package/build/lib/plaudit-icons/placement-end.js.map +0 -1
  423. package/build/lib/plaudit-icons/placement-start.js +0 -3
  424. package/build/lib/plaudit-icons/placement-start.js.map +0 -1
  425. package/build/lib/plaudit-icons/placement-stretch.js +0 -3
  426. package/build/lib/plaudit-icons/placement-stretch.js.map +0 -1
  427. package/build/lib/plaudit-icons/plaudit-icon.js +0 -3
  428. package/build/lib/plaudit-icons/plaudit-icon.js.map +0 -1
  429. package/build/lib/plaudit-icons/reusable-block-marker.js +0 -3
  430. package/build/lib/plaudit-icons.js.map +0 -1
  431. package/build/lib/suspense/promise-handlers.js.map +0 -1
  432. package/build/lib/suspense.js +0 -14
  433. package/build/lib/suspense.js.map +0 -1
  434. package/build/lib/useful-types.js +0 -7
  435. package/build/lib/useful-types.js.map +0 -1
  436. /package/{build → dist}/blocks/MoveError.d.ts +0 -0
  437. /package/{build → dist}/blocks/PathError.d.ts +0 -0
  438. /package/{build → dist}/blocks/SNPTreeContext.d.ts +0 -0
  439. /package/{build → dist}/blocks/basic-custom-block-bindings-support.d.ts +0 -0
  440. /package/{build → dist}/blocks/conditions.d.ts +0 -0
  441. /package/{build → dist}/blocks/data-controller-manager.d.ts +0 -0
  442. /package/{build → dist}/blocks/data-controller.d.ts +0 -0
  443. /package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/select.d.ts +0 -0
  444. /package/{build → dist}/blocks/hooks/built-in-suspendable-option-protocols/settings.d.ts +0 -0
  445. /package/{build → dist}/blocks/index.d.ts +0 -0
  446. /package/{build → dist}/blocks/layered-styles-impl.d.ts +0 -0
  447. /package/{build → dist}/blocks/layout/LaidOutPropertyRow.d.ts +0 -0
  448. /package/{build → dist}/blocks/layout/PanelRoot.d.ts +0 -0
  449. /package/{build → dist}/blocks/layout/TabsRoot.d.ts +0 -0
  450. /package/{build → dist}/blocks/layout/ToolsPanelContext.d.ts +0 -0
  451. /package/{build → dist}/blocks/shared-exportable-types.d.ts +0 -0
  452. /package/{build → dist}/blocks/shared-exportable-types.js.map +0 -0
  453. /package/{build → dist}/blocks/shared-internal-types.d.ts +0 -0
  454. /package/{build → dist}/blocks/shared-internal-types.js.map +0 -0
  455. /package/{build → dist}/blocks/simple-native-property-impl.d.ts +0 -0
  456. /package/{build → dist}/blocks/simple-native-property-internal-shared.d.ts +0 -0
  457. /package/{build → dist}/blocks/snp-data-store.d.ts +0 -0
  458. /package/{build → dist}/controls/ExtendedPostPicker.d.ts +0 -0
  459. /package/{build → dist}/controls/ExtendedUserPicker.d.ts +0 -0
  460. /package/{build → dist}/controls/SimpleToggle.d.ts +0 -0
  461. /package/{build → dist}/controls/SortableFlexibleItemsControl.d.ts +0 -0
  462. /package/{build → dist}/controls/SortableItemsControl.d.ts +0 -0
  463. /package/{build → dist}/controls/hooks/useNonRenderingCounter.d.ts +0 -0
  464. /package/{build → dist}/controls/hooks/useOutputMemoizingFilter.d.ts +0 -0
  465. /package/{build → dist}/controls/hooks/useSortableItemsModel.d.ts +0 -0
  466. /package/{build → dist}/controls/hooks/useSuggestions.d.ts +0 -0
  467. /package/{build → dist}/controls/index.d.ts +0 -0
  468. /package/{build → dist}/controls/shared.d.ts +0 -0
  469. /package/{build → dist}/controls/types.d.ts +0 -0
  470. /package/{build → dist}/controls/types.js.map +0 -0
  471. /package/{build → dist}/editor/post-featured-image.d.ts +0 -0
  472. /package/{build → dist}/editor/simple-gutenberg-endpoints-api.d.ts +0 -0
  473. /package/{build → dist}/editor/simple-gutenberg-endpoints-impl.d.ts +0 -0
  474. /package/{build → dist}/index.d.ts +0 -0
  475. /package/{build → dist}/lib/gutenberg-api-extensions-state/custom-block-bindings-support-logic.d.ts +0 -0
  476. /package/{build → dist}/lib/gutenberg-api-extensions-state/general-logic.d.ts +0 -0
  477. /package/{build → dist}/lib/gutenberg-api-extensions-state/layered-block-styles-logic.d.ts +0 -0
  478. /package/{build → dist}/lib/gutenberg-api-extensions-state/snp-logic.d.ts +0 -0
  479. /package/{build → dist}/lib/plaudit-icons/column-1.d.ts +0 -0
  480. /package/{build → dist}/lib/plaudit-icons/column-2.d.ts +0 -0
  481. /package/{build → dist}/lib/plaudit-icons/column-3.d.ts +0 -0
  482. /package/{build → dist}/lib/plaudit-icons/placement-center.d.ts +0 -0
  483. /package/{build → dist}/lib/plaudit-icons/placement-end.d.ts +0 -0
  484. /package/{build → dist}/lib/plaudit-icons/placement-start.d.ts +0 -0
  485. /package/{build → dist}/lib/plaudit-icons/placement-stretch.d.ts +0 -0
  486. /package/{build → dist}/lib/plaudit-icons/plaudit-icon.d.ts +0 -0
  487. /package/{build → dist}/lib/plaudit-icons/reusable-block-marker.d.ts +0 -0
  488. /package/{build → dist}/lib/plaudit-icons.d.ts +0 -0
  489. /package/{build → dist}/lib/suspense/promise-handlers.d.ts +0 -0
@@ -0,0 +1,177 @@
1
+ import {useEffect, useState} from "@wordpress/element";
2
+
3
+ import {ValidationState} from "../AsynchronousFormTokenField";
4
+ import {isNumeric} from "../shared";
5
+ import type {Dict} from "../types";
6
+ import type {TokenItem} from "../../lib/useful-types";
7
+ import {useNonRenderingCounter} from "./useNonRenderingCounter";
8
+
9
+ import {useReducer} from "react";
10
+
11
+ type TokenManagerReturnType = {
12
+ currentTokens: TokenItem[];
13
+ dispatchValueUpdate: (value: (((prevState: (string|TokenItem)[]) => (string|TokenItem)[])|(string|TokenItem)[])) => void;
14
+ hasValidationError: boolean;
15
+ isInitializing: boolean;
16
+ isValidating: boolean;
17
+ tokenTitleMappings: Dict<string>
18
+ };
19
+
20
+ export function useTokenManager(
21
+ initialValue: string[], setComponentValue: (value: TokenItem[]) => void, validationQuery: (tokens: string[]) => Promise<TokenItem[]>,
22
+ stringToTokenConverter: (value: string) => TokenItem
23
+ ): TokenManagerReturnType {
24
+ const [validationRequestId, nextValidationRequestId] = useNonRenderingCounter(initialValue.length ? 0 : 1);
25
+ const [isValidating, setIsValidating] = useState(false);
26
+ const [hasValidationError, setHasValidationError] = useState(false);
27
+
28
+ const [latestResolvedRequest, dispatchLatestResolvedRequestUpdate] = useReducer<(prev: number, next: number) => number>(Math.max, validationRequestId.current);
29
+ const [validatedTokens, dispatchValidatedTokensUpdate] = useReducer(performValidationStateDictReductionUpdate, {});
30
+
31
+ const [currentValue, setCurrentValue] = useState<(string|TokenItem)[]>(initialValue);
32
+ const [currentTokens, updateCurrentTokens] = useReducer(currentTokensStateReducer, [],
33
+ (): TokenItem[] => initialValue.map(value => ({value, status: ValidationState.Validating})));
34
+ const [tokenTitleMappings, updateTokenTitleMappings] = useReducer(tokenTitleMappingsUpdater, {});
35
+
36
+ useEffect(() => {
37
+ const tokensInNeedOfValidation = currentTokens
38
+ .filter(token => token.status === ValidationState.Validating)
39
+ .filter(token => !(token.value in validatedTokens))
40
+ .map(token => token.value);
41
+
42
+ if (tokensInNeedOfValidation.length > 0) {
43
+ dispatchValidatedTokensUpdate({data: Object.fromEntries(tokensInNeedOfValidation.map(token => [token, ValidationState.Waiting]))});
44
+ }
45
+ }, [currentTokens]);
46
+
47
+ // I'm splitting out the useEffect call here in order to have one-to-one correspondence between effects and types of state updates
48
+ useEffect(() => {
49
+ const tokensInNeedOfValidation = Object.entries(validatedTokens)
50
+ .filter(([_,v]) => v === ValidationState.Waiting)
51
+ .map(([token]) => token);
52
+ if (tokensInNeedOfValidation.length === 0) {
53
+ return;
54
+ }
55
+
56
+ const myValidationRequestId = nextValidationRequestId();
57
+ setIsValidating(true);
58
+ setHasValidationError(false);
59
+ dispatchValidatedTokensUpdate({data: Object.fromEntries(tokensInNeedOfValidation.map(token => [token, ValidationState.Validating]))});
60
+
61
+ let timeoutId: ReturnType<typeof setTimeout>|undefined = setTimeout(() => {
62
+ timeoutId = undefined;
63
+ dispatchValidatedTokensUpdate({type: 'rollback', data: Object.fromEntries(tokensInNeedOfValidation.map(token => [token, ValidationState.Waiting]))});
64
+ }, 60_000);
65
+ validationQuery(tokensInNeedOfValidation)
66
+ .then(tokens => {
67
+ if (timeoutId === undefined) {
68
+ throw "Timeout";
69
+ }
70
+ dispatchValidatedTokensUpdate({
71
+ data: Object.fromEntries(tokens.map(token => [token.value, token.status === ValidationState.Valid ? ValidationState.Valid : ValidationState.Invalid]))
72
+ });
73
+ updateTokenTitleMappings(tokens);
74
+ })
75
+ .catch(err => {
76
+ console.error("Validation Error:", err);
77
+ setHasValidationError(true);
78
+ // We retry the validation after 30 seconds
79
+ setTimeout(() => dispatchValidatedTokensUpdate({
80
+ type: 'rollback',
81
+ data: Object.fromEntries(tokensInNeedOfValidation.map(token => [token, ValidationState.Waiting]))
82
+ }), 30_000);
83
+ })
84
+ .finally(() => {
85
+ clearTimeout(timeoutId);
86
+ dispatchLatestResolvedRequestUpdate(myValidationRequestId);
87
+ });
88
+ }, [validatedTokens]);
89
+
90
+ useEffect(() => {
91
+ updateCurrentTokens(currentValue.map<TokenItem>(token => {
92
+ if (typeof token === 'string') {
93
+ token = stringToTokenConverter(token);
94
+ if (token.status === undefined || token.status === ValidationState.Validating) {
95
+ const status = validatedTokens[token.value];
96
+ if (status !== undefined && status !== ValidationState.Waiting) {
97
+ token.status = status;
98
+ }
99
+ }
100
+ }
101
+ return token.title === undefined && token.value in tokenTitleMappings ? {...token, title: tokenTitleMappings[token.value]} : token;
102
+ }));
103
+ }, [currentValue]);
104
+
105
+ // This is split out into a useEffect call in order to take advantage of the Reducer's excess-update-reduction logic.
106
+ useEffect(() => {
107
+ updateTokenTitleMappings(currentTokens);
108
+ if (latestResolvedRequest > (initialValue.length ? 0 : 1)) {
109
+ setComponentValue(currentTokens);
110
+ }
111
+ }, [currentTokens]);
112
+ useEffect(() => {
113
+ if (currentTokens.some(token => token.value in tokenTitleMappings && tokenTitleMappings[token.value] !== token.title)) {
114
+ updateCurrentTokens(currentTokens.map(token => token.title === undefined && token.value in tokenTitleMappings
115
+ ? {...token, title: tokenTitleMappings[token.value]} : token));
116
+ }
117
+ }, [tokenTitleMappings]);
118
+
119
+ useEffect(() => {
120
+ const potentiallyUpdatableTokens = currentTokens.map((token): [TokenItem, ValidationState|undefined] => [token, validatedTokens[token.value]]);
121
+ // A token is worth updating if its status is undefined or validating and its new status is defined and neither waiting nor validating
122
+ const hasTokenWorthUpdating = potentiallyUpdatableTokens.some(([token, nvs]) => {
123
+ return (token.status === undefined || token.status === ValidationState.Validating)
124
+ && nvs !== undefined && nvs !== ValidationState.Validating && nvs !== ValidationState.Waiting;
125
+ });
126
+ if (hasTokenWorthUpdating) {
127
+ updateCurrentTokens(potentiallyUpdatableTokens.map(([token, status]) => {
128
+ return !status || status === ValidationState.Waiting ? token : ({...token, status});
129
+ }));
130
+ }
131
+ setIsValidating(latestResolvedRequest < validationRequestId.current);
132
+ }, [latestResolvedRequest]);
133
+
134
+ return {currentTokens, dispatchValueUpdate: setCurrentValue, hasValidationError, isInitializing: latestResolvedRequest === 0, isValidating, tokenTitleMappings};
135
+ }
136
+
137
+ type ValidationStateDictReductionUpdateAction = {type?: 'update'|'rollback', data: Dict<ValidationState>};
138
+ function performValidationStateDictReductionUpdate(prevState: Dict<ValidationState>, action: ValidationStateDictReductionUpdateAction): Dict<ValidationState> {
139
+ switch (action.type) {
140
+ case 'rollback':
141
+ return {...prevState, ...action.data};
142
+ default:
143
+ return {
144
+ ...prevState, ...Object.fromEntries(Object.entries(action.data)
145
+ .filter(([token, validationState]) => validationState !== ValidationState.Waiting || !(token in prevState)))
146
+ };
147
+ }
148
+ }
149
+ function currentTokensStateReducer(currentTokens: TokenItem[], newTokens: TokenItem[]): TokenItem[] {
150
+ if (newTokens.length !== currentTokens.length) {
151
+ return newTokens;
152
+ }
153
+ for (let i = 0; i < newTokens.length; i++) {
154
+ if (currentTokens[i]!.value !== newTokens[i]!.value || currentTokens[i]!.status !== newTokens[i]!.status || currentTokens[i]!.title !== newTokens[i]!.title) {
155
+ return newTokens;
156
+ }
157
+ }
158
+ return currentTokens;
159
+ }
160
+ function tokenTitleMappingsUpdater(state: Dict<string>, tokens: TokenItem[]): Dict<string> {
161
+ const titleWithIdRegex = /(.*)\(#([^)]+)\)$/;
162
+ const novelTokens = tokens
163
+ .map<[string, string|undefined]>(token => [token.value, token.title])
164
+ .filter((token): token is [string, string] => token[1] !== undefined && !isNumeric(token[1]))
165
+ .map<[string, string]>(token => {
166
+ const res = titleWithIdRegex.exec(token[1]);
167
+ return res && res[1] && res[1].trim().length < 30 ? token : [token[0], labelToDisplayableTitle(res?.[1] ?? token[1], res?.[2] ?? token[0])];
168
+ })
169
+ .filter(token => state[token[0]] !== token[1]);
170
+ if (novelTokens.length === 0) {
171
+ return state;
172
+ }
173
+ return {...state, ...Object.fromEntries(novelTokens)};
174
+ }
175
+ function labelToDisplayableTitle(label: string, id: string): string {
176
+ return `${label.length > 30 ? `${label.substring(0, 30).trim()}…` : label.trim()} (#${id})`;
177
+ }
@@ -1,4 +1,4 @@
1
- export { AsynchronousFormTokenField } from "./AsynchronousFormTokenField";
1
+ export {AsynchronousFormTokenField} from "./AsynchronousFormTokenField";
2
2
  export * from "./BaseSortableItemsControl";
3
3
  export * from "./ExtendedFormTokenField";
4
4
  export * from "./ExtendedPostPicker";
@@ -18,5 +18,6 @@ export * from "./ProperLinkControl";
18
18
  export * from "./SimpleToggle";
19
19
  export * from "./SortableFlexibleItemsControl";
20
20
  export * from "./SortableItemsControl";
21
+
21
22
  export { requestPostsFromAPI } from "./shared";
22
- //# sourceMappingURL=index.js.map
23
+ export type * from "./types";
@@ -0,0 +1,50 @@
1
+ import apiFetch from "@wordpress/api-fetch";
2
+ import {addQueryArgs} from "@wordpress/url";
3
+
4
+ import type {ObjectNormalizedPickableOptions, PairNormalizedPickableOptions, PickableOptions} from "./types";
5
+
6
+ export async function requestPostsFromAPI(data: {search?: string, ids?: string, postTypes?: string|undefined}) {
7
+ return (await apiFetch<Array<{ id: number, title: string, type: string }>>({path: addQueryArgs("/plaudit/common/v1/post-table-search", data)}))
8
+ .map(item => ({id: item.id.toString(), title: item.title, type: item.type}));
9
+ }
10
+
11
+ export function normalizePickableOptionsToObjects<V extends string|number, T extends Omit<object, 'text'|'value'> = {}>(
12
+ options: PickableOptions<V, T>
13
+ ): ObjectNormalizedPickableOptions<V, T> {
14
+ return options.map(option => {
15
+ if (Array.isArray(option)) {
16
+ if (typeof option[1] === 'string') {
17
+ return {value: option[0], label: option[1]} as ObjectNormalizedPickableOptions<V, T>[number];
18
+ }
19
+ const {text, ...rest} = option[1];
20
+ return {value: option[0], label: text, ...rest} as unknown as ObjectNormalizedPickableOptions<V, T>[number];
21
+ }
22
+ return option;
23
+ });
24
+ }
25
+ export function normalizePickableOptionsToPairs<V extends string|number, T extends Omit<object, 'text'|'value'|'tooltip'> = {}>(
26
+ options: PickableOptions<V, T>
27
+ ): PairNormalizedPickableOptions<V, T> {
28
+ return options.map(option => {
29
+ if (isPairPickableOption<V, T>(option)) {
30
+ return option;
31
+ }
32
+ const {value, label, ...rest} = option;
33
+ return [value, {text: label, ...rest}] as unknown as PairNormalizedPickableOptions<V, T>[number];
34
+ });
35
+ }
36
+ export function getLabel(option: PickableOptions<any>[number]): string {
37
+ return Array.isArray(option) ? (typeof option[1] === 'string' ? option[1] : option[1].text) : (option.label ?? option.value.toString());
38
+ }
39
+
40
+ function isPairPickableOption<V extends string|number, T extends Omit<object, 'text'|'value'|'tooltip'> = {}>(
41
+ option: PickableOptions<V, T>[number]
42
+ ): option is PairNormalizedPickableOptions<V, T>[number] {
43
+ return Array.isArray(option) && option.length === 2;
44
+ }
45
+
46
+ export function isNumeric(str: string|number) {
47
+ if (typeof str !== "string") return true; // we only process strings!
48
+ return !isNaN(str as any) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
49
+ !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
50
+ }
@@ -0,0 +1,18 @@
1
+ import type {BlockEditProps} from "@wordpress/blocks";
2
+
3
+ export type SpecificValueBlockProps<T extends string, V> = {
4
+ attribute: T, attributes: BlockEditProps<Record<T, V>&Record<string, unknown>>['attributes'],
5
+ setAttributes: BlockEditProps<any>['setAttributes']
6
+ }
7
+ export type SimpleBlockControlProps<T extends string, V> = SpecificValueBlockProps<T, V>&{
8
+ label: string,
9
+ help?: string
10
+ };
11
+
12
+ export type PairNormalizedPickableOptions<V extends string|number, T extends Omit<object, 'text'|'value'|'tooltip'> = {}> = Array<[V, string|({text: string, tooltip?: string|undefined}&T)]>;
13
+ export type ObjectNormalizedPickableOptions<V extends string|number, T extends Omit<object, 'text'|'value'|'tooltip'> = {}> = Array<{value: V, label?: string|undefined, tooltip?: string|undefined}&T>;
14
+ export type PickableOptions<V extends string|number, T extends Omit<object, 'text'|'value'|'tooltip'> = {}> = Array<PairNormalizedPickableOptions<V, T>[number]|ObjectNormalizedPickableOptions<V, T>[number]>;
15
+
16
+ export type Dict<V> = {[key: string]: V};
17
+
18
+ export type FlexibleItem<T extends string = string> = {type: T}&{[key: Exclude<string, 'type'>]: unknown};
@@ -0,0 +1,161 @@
1
+ import {Button, FocalPointPicker, Spinner} from "@wordpress/components";
2
+ import type {Attachment} from "@wordpress/core-data";
3
+ import {dispatch, select, useSelect} from "@wordpress/data";
4
+ import {PostFeaturedImageCheck, store as editorStore} from "@wordpress/editor";
5
+ import {memo, useCallback, useEffect, useMemo, useState} from "@wordpress/element";
6
+ import {addFilter, applyFilters} from "@wordpress/hooks";
7
+ import {__} from "@wordpress/i18n";
8
+
9
+ import type {ComponentType} from "react";
10
+
11
+ type MediaDetailsArgs = Omit<Attachment, 'media_details'>&{media_details: Record<string, any>};
12
+ function getMediaDetails(media: MediaDetailsArgs, postId: any) {
13
+ if (!media) {
14
+ return {};
15
+ }
16
+
17
+ const sizes = (media?.media_details?.['sizes'] ?? {}) as Record<string, {width: any, height: any, source_url: string}>;
18
+
19
+ const activeSize = sizes[getImageSize('large', media, postId)];
20
+ if (activeSize !== undefined) {
21
+ return {
22
+ mediaWidth: activeSize.width,
23
+ mediaHeight: activeSize.height,
24
+ mediaSourceUrl: activeSize.source_url,
25
+ };
26
+ }
27
+
28
+ // Use fallbackSize when defaultSize is not available.
29
+ const fallbackSize = sizes[getImageSize('thumbnail', media, postId)];
30
+ if (fallbackSize !== undefined) {
31
+ return {
32
+ mediaWidth: fallbackSize.width,
33
+ mediaHeight: fallbackSize.height,
34
+ mediaSourceUrl: fallbackSize.source_url,
35
+ };
36
+ }
37
+
38
+ // Use full image size when fallbackSize and defaultSize are not available.
39
+ return {
40
+ mediaWidth: media.media_details['width'],
41
+ mediaHeight: media.media_details['height'],
42
+ mediaSourceUrl: media.source_url,
43
+ };
44
+ }
45
+
46
+ type Position = {x: number, y: number};
47
+ function getLivePosition(selectFunction = select): Position {
48
+ const {x = 50, y = 50} = (selectFunction(editorStore).getEditedPostAttribute('meta')?.["plaudit_card-image_pos"] ?? {}) as Record<string, any>;
49
+ return {x: x / 100, y: y / 100};
50
+ }
51
+ function setLivePosition({x, y}: Position) {
52
+ dispatch(editorStore)
53
+ .editPost({
54
+ meta: {"plaudit_card-image_pos": {x: Math.round(x * 100), y: Math.round(y * 100)}}
55
+ })
56
+ .catch(e => {
57
+ console.error(e);
58
+ });
59
+ }
60
+
61
+ function getRawLivePosition() {
62
+ return {x: 50, y: 50, ...((select(editorStore).getEditedPostAttribute('meta')?.["plaudit_card-image_pos"] ?? {}) as Partial<Position>)};
63
+ }
64
+
65
+ function getImageSize(defaultSize: string, media: MediaDetailsArgs, postId: any): string {
66
+ let filteredSize = applyFilters('editor.PostFeaturedImage.imageSize', defaultSize, media.id, postId);
67
+ if (typeof filteredSize !== 'string') {
68
+ console.error(`The 'editor.PostFeaturedImage.imageSize' filter returned a non-string size (${filteredSize}).`, `Using '${defaultSize}' as a fallback.`);
69
+ return defaultSize;
70
+ }
71
+ return filteredSize;
72
+ }
73
+
74
+ function wrapPostFeaturedImage(OriginalComponent: ComponentType) {
75
+ return (props: Record<string, any>) => {
76
+ const [inFocusMode, setInFocusMode] = useState(false);
77
+ // This useMemo call makes it so that we only update restorablePosition when the state changes.
78
+ const restorablePosition = useMemo(getLivePosition, [inFocusMode]);
79
+
80
+ const {mediaSourceUrl} = getMediaDetails(props.media, props.currentPostId);
81
+
82
+ if (!mediaSourceUrl) {
83
+ if (select(editorStore).getEditedPostAttribute('featured_media')) {
84
+ return <Spinner/>;
85
+ }
86
+ return <OriginalComponent {...props} />;
87
+ } else if (!inFocusMode) {
88
+ return <NotInFocusMode OriginalComponent={OriginalComponent} props={props} setInFocusMode={setInFocusMode} />;
89
+ }
90
+ return <InFocusMode mediaSourceUrl={mediaSourceUrl} props={props} restorablePosition={restorablePosition} setInFocusMode={setInFocusMode} />;
91
+ };
92
+ }
93
+
94
+ type NotInFocusModeProps = {OriginalComponent: ComponentType, props: Record<string, any>, setInFocusMode(value: boolean): void};
95
+ const NotInFocusMode = memo(({OriginalComponent, props, setInFocusMode}: NotInFocusModeProps) => {
96
+ const {x, y} = getRawLivePosition();
97
+ useEffect(() => {
98
+ let sheet = document.adoptedStyleSheets.find(s => (s as any).identifier === '__POST_FEATURED_IMAGE__');
99
+ if (!sheet) {
100
+ sheet = new CSSStyleSheet();
101
+ (sheet as any).identifier = '__POST_FEATURED_IMAGE__';
102
+ }
103
+ sheet.replace(`.plauditPostFeaturedImageWithFocalPoint__wrapper .editor-post-featured-image__preview-image {object-fit: ${x}% ${y}% !important;}`)
104
+ .catch(e => {
105
+ console.error(e);
106
+ });
107
+ return () => {
108
+ const sheet = document.adoptedStyleSheets.findIndex(s => (s as any).identifier === '__POST_FEATURED_IMAGE__');
109
+ if (sheet) {
110
+ document.adoptedStyleSheets.splice(sheet, 1);
111
+ }
112
+ };
113
+ }, [x, y]);
114
+ return <PostFeaturedImageCheck>
115
+ <div className="plauditPostFeaturedImageWithFocalPoint__wrapper">
116
+ <div className="plauditPostFeaturedImageWithFocalPoint__toggle">
117
+ <Button onClick={useCallback(() => setInFocusMode(true), [setInFocusMode])} className="editor-post-featured-image__action" text={__("Change Focal Point", 'plaudit')} />
118
+ </div>
119
+ <OriginalComponent {...props} />
120
+ </div>
121
+ </PostFeaturedImageCheck>;
122
+ });
123
+
124
+ type InFocusModeProps = {mediaSourceUrl: string, props: Record<string, any>, restorablePosition: Position, setInFocusMode(value: boolean): void};
125
+ const InFocusMode = memo(({mediaSourceUrl, props, restorablePosition, setInFocusMode}: InFocusModeProps) => {
126
+ // 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
127
+ const {x, y} = useSelect(selectFunction => getLivePosition(selectFunction as typeof select), []);
128
+ const [position, setPosition] = useState({x, y});
129
+ useEffect(() => setPosition(getLivePosition()), [x, y]);
130
+
131
+ return <PostFeaturedImageCheck>
132
+ {props.noticeUI}
133
+ <div className="editor-post-featured-image">
134
+ <FocalPointPicker
135
+ onChange={useCallback(pos => {
136
+ setPosition(pos);
137
+ setLivePosition(pos);
138
+ }, [setPosition])}
139
+ url={mediaSourceUrl}
140
+ value={position}
141
+ />
142
+ <div>
143
+ <Button text={__("Done", 'plaudit')} onClick={useCallback(() => setInFocusMode(false), [setInFocusMode])} variant="primary" />
144
+ <Button text={__('Cancel', 'plaudit')} onClick={useCallback(() => {
145
+ setLivePosition(restorablePosition);
146
+ setInFocusMode(false);
147
+ }, [setInFocusMode])} isDestructive />
148
+ </div>
149
+ </div>
150
+ </PostFeaturedImageCheck>;
151
+ })
152
+
153
+ export function installPostFeaturedImageCardFocusTargeting() {
154
+ if (!installPostFeaturedImageCardFocusTargeting.called) {
155
+ installPostFeaturedImageCardFocusTargeting.called = true;
156
+ addFilter('editor.PostFeaturedImage', 'plaudit-gutenberg-api-extensions/inject-post-featured-image-card-focus-targeting', wrapPostFeaturedImage);
157
+ }
158
+ }
159
+ export namespace installPostFeaturedImageCardFocusTargeting {
160
+ export let called: boolean = false;
161
+ }
@@ -0,0 +1,31 @@
1
+ import apiFetch from "@wordpress/api-fetch";
2
+ import {dispatch, useSuspenseSelect} from "@wordpress/data";
3
+
4
+ import {installSimpleGutenbergApisSupport, store as endpointsStore} from "../editor/simple-gutenberg-endpoints-impl";
5
+
6
+ export type ApiCallArgs = [string, any][]|Record<string, any>|URLSearchParams|string|undefined;
7
+ export function registerSimpleGutenbergApiEndpoint<T>(
8
+ name: string, endpoint: ((args: ApiCallArgs, key: string) => Promise<T>)|Parameters<typeof apiFetch<T>>[0],
9
+ options?: {transformer?: (response: Awaited<T>, args: ApiCallArgs, key: string) => unknown, maxCachedResults?: number}
10
+ ): void {
11
+ installSimpleGutenbergApisSupport();
12
+ dispatch(endpointsStore).registerEndpoint(name, endpoint, options);
13
+ }
14
+
15
+ /**
16
+ * @param name the name of the endpoint
17
+ * @param args MUST be a value derived from useDeferredValue()
18
+ * @param config shared configuration logic
19
+ */
20
+ export function useEndpointResolver<R>(
21
+ name: string, args: ApiCallArgs, config: {immediateReturnOnEmpty?: boolean, dependencies?: readonly unknown[]} = {}
22
+ ) {
23
+ const {immediateReturnOnEmpty = true, dependencies = []} = config;
24
+ return useSuspenseSelect(select => {
25
+ if (!args && immediateReturnOnEmpty) {
26
+ return undefined;
27
+ }
28
+ const selector = select(endpointsStore);
29
+ return selector.get(name, args) as R|undefined;
30
+ }, [args, immediateReturnOnEmpty, ...dependencies]);
31
+ }
@@ -0,0 +1,119 @@
1
+ import apiFetch from "@wordpress/api-fetch";
2
+ import {type createReduxStore, register} from "@wordpress/data";
3
+ import {applyFilters} from "@wordpress/hooks";
4
+
5
+ import {clone, TemporalLRUCache} from "../lib/helpers";
6
+ import {use, useImmediately, useToPromise, type WrappedPromise, wrapPromise} from "../lib/suspense/promise-handlers";
7
+ import type {ApiCallArgs} from "./simple-gutenberg-endpoints-api";
8
+
9
+ type ResponseCacheEntry = {args: ApiCallArgs, promise: WrappedPromise<unknown>};
10
+
11
+ type EndpointOptions<P, R> = {transformer?: (response: P, args: ApiCallArgs, name: string) => R, maxCachedResults?: number};
12
+ type ApiEndpointConfig<T> = {
13
+ endpoint: ((args: ApiCallArgs, name: string) => Promise<T>)|Parameters<typeof apiFetch<T, boolean>>[0],
14
+ responseCache: TemporalLRUCache<string, ResponseCacheEntry>
15
+ }&ApiEndpointOptions<T>;
16
+ export type ApiEndpointOptions<T> = {transformer?: (response: Awaited<T>, args: ApiCallArgs, name: string) => unknown, maxCachedResults?: number};
17
+
18
+ function argsToKey(args: ApiCallArgs) {
19
+ return args instanceof URLSearchParams || typeof args !== 'object' ? args?.toString() ?? "" : JSON.stringify(args);
20
+ }
21
+
22
+ export function installSimpleGutenbergApisSupport() {
23
+ if (!installSimpleGutenbergApisSupport.called) {
24
+ installSimpleGutenbergApisSupport.called = true;
25
+ register(store);
26
+ }
27
+ }
28
+ export namespace installSimpleGutenbergApisSupport {
29
+ export let called: boolean = false;
30
+ }
31
+
32
+ type Selectors = {
33
+ get(name: string, args?: ApiCallArgs): unknown,
34
+ resolve(name: string, args?: ApiCallArgs): Promise<unknown>
35
+ };
36
+ type Actions = {
37
+ registerEndpoint(
38
+ name: string, endpoint: ((args: ApiCallArgs, name: string) => Promise<unknown>)|Parameters<typeof apiFetch>[0],
39
+ options?: EndpointOptions<any, unknown>
40
+ ): void
41
+ };
42
+ type AddBSStateArg<S extends {[name in string]: (...args: any[]) => any}> = {[name in keyof S]: (state: any, ...args: Parameters<S[name]>) => ReturnType<S[name]>};
43
+ export const store: ReturnType<typeof createReduxStore<{}, Actions, AddBSStateArg<Selectors>>> = {
44
+ name: 'plaudit/simple-gutenberg-apis',
45
+ instantiate: () => {
46
+ const listeners = new Set<() => void>();
47
+ const endpoints: {[name in string]: ApiEndpointConfig<any>} = {};
48
+
49
+ function storeChanged() {
50
+ for (const listener of listeners) {
51
+ listener();
52
+ }
53
+ }
54
+
55
+ function handleCacheMiss(name: string, args?: ApiCallArgs) {
56
+ const endpoint = endpoints[name];
57
+ if (!endpoint) {
58
+ throw new Error(`Attempted to fetch data from an unmapped endpoint: ${name}`);
59
+ }
60
+ const key = argsToKey(args);
61
+ const existingPromise = endpoint.responseCache.get(key)?.promise;
62
+ if (existingPromise) {
63
+ return existingPromise;
64
+ }
65
+ const res = wrapPromise(
66
+ (typeof endpoint.endpoint === 'function' ? endpoint.endpoint(args, name) : apiFetch(endpoint.endpoint))
67
+ .then(rawResponse => {
68
+ return applyFilters(`plaudit-common.simple-gutenberg-apis.endpoint.${name}.response`,
69
+ endpoint.transformer?.(rawResponse, args, name) ?? rawResponse, args, name);
70
+ })
71
+ );
72
+ res.finally(() => storeChanged());
73
+ endpoint.responseCache.set(key, {args, promise: res});
74
+ return res;
75
+ }
76
+
77
+ const actions: Actions = {
78
+ registerEndpoint(name, endpoint, options?) {
79
+ if (endpoints[name]?.responseCache instanceof TemporalLRUCache) {
80
+ endpoints[name].responseCache.cancelTimeout();
81
+ }
82
+ endpoints[name] = {
83
+ endpoint: clone(endpoint),
84
+ ...options,
85
+ responseCache: new TemporalLRUCache(options?.maxCachedResults ?? Number.MAX_SAFE_INTEGER)
86
+ };
87
+ storeChanged();
88
+ }
89
+ };
90
+
91
+ const selectors: Selectors = {
92
+ get(name, args?) {
93
+ return useImmediately(handleCacheMiss(name, args));
94
+ },
95
+ resolve(name, args?) {
96
+ return handleCacheMiss(name, args);
97
+ }
98
+ };
99
+ const suspendSelectors: Selectors = {
100
+ get(name, args?) {
101
+ return use(handleCacheMiss(name, args));
102
+ },
103
+ resolve(name, args?) {
104
+ return useToPromise(handleCacheMiss(name, args));
105
+ }
106
+ };
107
+
108
+ // noinspection JSUnusedGlobalSymbols
109
+ return {
110
+ getSelectors: () => selectors,
111
+ getSuspendSelectors: () => suspendSelectors, // This adds support for useSuspenseSelect. WordPress' typedefs are incomplete.
112
+ getActions: (): any => actions, // This is correctly typed, but WordPress' typedefs are broken.
113
+ subscribe: (listener: () => void) => {
114
+ listeners.add(listener);
115
+ return () => listeners.delete(listener);
116
+ }
117
+ };
118
+ }
119
+ };
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ import {installSimpleNativePropertiesSupport} from "./blocks/simple-native-property-impl";
2
+ import {installPostFeaturedImageCardFocusTargeting} from "./editor/post-featured-image";
3
+ import {installSimpleGutenbergApisSupport, type store as endpointStore} from "./editor/simple-gutenberg-endpoints-impl";
4
+ import {registerStore, type store as apiStore} from "./lib/gutenberg-api-extensions-state";
5
+
6
+ export * from "./blocks";
7
+ export * from "./controls";
8
+ export * from "./editor/simple-gutenberg-endpoints-api";
9
+ export * from "./lib/plaudit-icons";
10
+ export * from "./lib/suspense";
11
+ export type * from "./lib/useful-types";
12
+
13
+ export function installGutenbergExtensions() {
14
+ if (!installGutenbergExtensions.called) {
15
+ installGutenbergExtensions.called = true;
16
+ registerStore();
17
+ installSimpleNativePropertiesSupport();
18
+ installPostFeaturedImageCardFocusTargeting();
19
+ installSimpleGutenbergApisSupport();
20
+ }
21
+ }
22
+ export namespace installGutenbergExtensions {
23
+ export let called: boolean = false;
24
+ }
25
+
26
+ declare module "@wordpress/data" {
27
+ function select(key: 'plaudit/gutenberg-api-extensions'): ReturnType<typeof select<typeof apiStore>>;
28
+ function dispatch(key: 'plaudit/gutenberg-api-extensions'): ReturnType<typeof dispatch<typeof apiStore>>;
29
+
30
+ function select(key: 'plaudit/simple-gutenberg-apis'): ReturnType<typeof select<typeof endpointStore>>;
31
+ function dispatch(key: 'plaudit/simple-gutenberg-apis'): ReturnType<typeof dispatch<typeof endpointStore>>;
32
+ }
@@ -0,0 +1,34 @@
1
+ import {registerBlockBindingsSource} from "@wordpress/blocks";
2
+
3
+ import type {DbSource} from "../../blocks";
4
+ import type {WordPressMetaActions} from "../useful-types";
5
+ import {produce} from "immer";
6
+
7
+ export type CustomBlockBindingsSupportLogicActions = {type: 'ADD_CUSTOM_BLOCK_BINDINGS_SOURCE', name: string, value: {dbSources?: DbSource[]}};
8
+ export type CustomBlockBindingsSupportLogicState = {
9
+ customBlockBindingsSupport: {[name in string]?: {dbSources?: DbSource[]}}
10
+ };
11
+
12
+ export const customBlockBindingsSupportLogicActions = {
13
+ registerCustomBlockBindingsSource(args: Parameters<typeof registerBlockBindingsSource>[0]&{dbSources?: DbSource[]}) {
14
+ const {dbSources, ...actualArgs} = args;
15
+ registerBlockBindingsSource('getValue' in actualArgs ? actualArgs : {...actualArgs, getValue: () => ({})});
16
+ return {type: 'ADD_CUSTOM_BLOCK_BINDINGS_SOURCE', name: actualArgs.name, value: {dbSources}};
17
+ }
18
+ };
19
+ export const customBlockBindingsSupportLogicSelectors = {
20
+ customBlockBindingsSource(state: CustomBlockBindingsSupportLogicState, name: string) {
21
+ return state.customBlockBindingsSupport[name];
22
+ }
23
+ };
24
+
25
+ export function customBlockBindingsSupportLogic(
26
+ state: CustomBlockBindingsSupportLogicState, action: CustomBlockBindingsSupportLogicActions|WordPressMetaActions
27
+ ): typeof state {
28
+ if (action.type === "ADD_CUSTOM_BLOCK_BINDINGS_SOURCE") {
29
+ return produce(state, (draft: typeof state) => {
30
+ draft.customBlockBindingsSupport[action.name] = action.value;
31
+ });
32
+ }
33
+ return state;
34
+ }