@plaudit/gutenberg-api-extensions 2.79.0 → 2.80.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 (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 -3
  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 +22 -30
  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 +121 -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 +157 -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 +114 -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,35 @@
1
+ import {Button, SelectControl} from "@wordpress/components";
2
+ import {useCallback, useState} from "@wordpress/element";
3
+
4
+ import {BaseSortableItemsControl, type BaseSortableItemsControlProps} from "./BaseSortableItemsControl";
5
+ import type {NonEmptyArray} from "../lib/useful-types";
6
+ import type {FlexibleItem} from "./types";
7
+
8
+ import type {ReactNode} from "react";
9
+
10
+ type SortableFlexibleItemsControlSpecificProps<T extends string> = {
11
+ availableTypes: NonEmptyArray<{label: string, value: T}>,
12
+ emptyValueBuilder: (type: T) => FlexibleItem<T>
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>) {
16
+ const buttonsArea = useCallback<BaseSortableItemsControlProps<FlexibleItem<T>>['buttonsArea']>(
17
+ // Unfortunately, the typedefs for React memo components don't allow us to properly check the emptyValueBuilder function
18
+ args => <ButtonsArea {...args} availableTypes={availableTypes} emptyValueBuilder={emptyValueBuilder} />, [availableTypes, emptyValueBuilder]);
19
+ return <BaseSortableItemsControl {...baseProps} buttonsArea={buttonsArea} />;
20
+ }
21
+
22
+ type ButtonsAreaProps<T extends string> = Parameters<BaseSortableItemsControlProps<FlexibleItem<T>>['buttonsArea']>[0]&SortableFlexibleItemsControlSpecificProps<T>;
23
+ function ButtonsArea<T extends string>({addHandler, disabled, availableTypes, emptyValueBuilder}: ButtonsAreaProps<T>): ReactNode {
24
+ const [selectedType, setSelectedType] = useState(availableTypes[0].value);
25
+ return <div className="plaudit-sortable-items-buttons flexible-items">
26
+ <Button icon="insert" disabled={disabled} onClick={() => addHandler(emptyValueBuilder(selectedType))}>Add</Button>
27
+ <SelectControl
28
+ label="Type"
29
+ hideLabelFromVision={true}
30
+ value={selectedType}
31
+ options={availableTypes}
32
+ onChange={setSelectedType}
33
+ />
34
+ </div>;
35
+ }
@@ -0,0 +1,18 @@
1
+ import {Button} from "@wordpress/components";
2
+ import {useCallback} from "@wordpress/element";
3
+
4
+ import {BaseSortableItemsControl, type BaseSortableItemsControlProps} from "./BaseSortableItemsControl";
5
+
6
+ export type SortableItemsControlProps<D> = Omit<BaseSortableItemsControlProps<D>, 'buttonsArea'|'emptyValue'>&{emptyValue: D, addRowText?: string};
7
+ export function SortableItemsControl<D>({emptyValue, addRowText, ...baseProps}: SortableItemsControlProps<D>) {
8
+ const buttonsArea = useCallback<BaseSortableItemsControlProps<D>['buttonsArea']>(
9
+ args => <ButtonsArea {...args} emptyValue={emptyValue} addRowText={addRowText} />, [emptyValue, addRowText]);
10
+ return <BaseSortableItemsControl {...baseProps} buttonsArea={buttonsArea} emptyValue={emptyValue} />;
11
+ }
12
+
13
+ type ButtonsAreaProps<D = any> = Parameters<BaseSortableItemsControlProps<D>['buttonsArea']>[0]&{emptyValue: D, addRowText?: string};
14
+ function ButtonsArea<D>({addHandler, disabled, emptyValue, addRowText}: ButtonsAreaProps<D>) {
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>
17
+ </div>
18
+ }
@@ -0,0 +1,76 @@
1
+ import {select as dataSelect} from "@wordpress/data";
2
+ import {useCallback} from "@wordpress/element";
3
+
4
+ import type {SNPControlSlots} from "../blocks";
5
+ import {ExtendedFormTokenField, unpackDisplayedTokenText, ValidationState} from "./ExtendedFormTokenField";
6
+ import {isNumeric} from "./shared";
7
+ import type {TokenItem} from "../lib/useful-types";
8
+
9
+ import type {ReactNode} from "react";
10
+
11
+ type BasicNumericallyIdedItemPickerPropsBase = {
12
+ label?: string;
13
+ help?: ReactNode;
14
+ placeholder?: string;
15
+ }&Partial<Pick<SNPControlSlots, 'Messages'>>;
16
+ type BasicNumericallyIdedItemPickerPropsSingle = BasicNumericallyIdedItemPickerPropsBase&{
17
+ onChange(value: string): void;
18
+ value?: string;
19
+ multiple: false;
20
+ };
21
+ type BasicNumericallyIdedItemPickerPropsMultiple = BasicNumericallyIdedItemPickerPropsBase&{
22
+ onChange(value: string[]): void;
23
+ value?: string[];
24
+ multiple?: true|undefined;
25
+ };
26
+ export type BasicNumericallyIdedItemPickerProps = BasicNumericallyIdedItemPickerPropsSingle|BasicNumericallyIdedItemPickerPropsMultiple;
27
+
28
+ export function basicNumericallyIdedItemPicker(props: BasicNumericallyIdedItemPickerProps, endpoint: string, queryProps: {[key: string]: any}) {
29
+ const {multiple, value, ...remainder} = props;
30
+
31
+ const suggestionQuery = useCallback((input: string, select: typeof dataSelect) => {
32
+ return select('plaudit/simple-gutenberg-apis')
33
+ .get(endpoint + "-options", {search: input, ...queryProps}) as TokenItem[]|undefined;
34
+ }, [queryProps]);
35
+ const validationQuery = useCallback((idsBeingValidated: string[], select: typeof dataSelect) => {
36
+ return (select('plaudit/simple-gutenberg-apis')
37
+ .get(endpoint + "-validation", {ids: idsBeingValidated.join(','), ...queryProps}) as TokenItem[]|undefined);
38
+ }, [queryProps]);
39
+
40
+ if (props.multiple === false) {
41
+ return <ExtendedFormTokenField
42
+ {...remainder}
43
+ value={props.value}
44
+ multiple={false}
45
+ onChange={props.onChange}
46
+ stringToTokenConverter={makeTokenFromSuggestion}
47
+ suggestionQuery={suggestionQuery}
48
+ validationQuery={validationQuery}
49
+ validator={validator}
50
+ />;
51
+ } else {
52
+ return <ExtendedFormTokenField
53
+ {...remainder}
54
+ value={props.value}
55
+ multiple={true}
56
+ onChange={props.onChange}
57
+ stringToTokenConverter={makeTokenFromSuggestion}
58
+ suggestionQuery={suggestionQuery}
59
+ validationQuery={validationQuery}
60
+ validator={validator}
61
+ />;
62
+ }
63
+ }
64
+
65
+ function makeTokenFromSuggestion(token: string): TokenItem {
66
+ if (isNumeric(token)) {
67
+ return {value: token, status: ValidationState.Validating};
68
+ } else {
69
+ const {value, title} = unpackDisplayedTokenText(token);
70
+ return {value, status: isNumeric(value) ? ValidationState.Validating : ValidationState.Invalid, title};
71
+ }
72
+ }
73
+
74
+ function validator(token: string) {
75
+ return /\(#([0-9]+)\)$/.exec(token)?.[1] !== undefined;
76
+ }
@@ -0,0 +1,157 @@
1
+ import {useSelect} from "@wordpress/data";
2
+ import type {MapSelect} from "@wordpress/data/types";
3
+ import {useEffect, useMemo, useRef, useState} from "@wordpress/element";
4
+
5
+ import type {TokenItem} from "../../lib/useful-types";
6
+
7
+ export function packDisplayTokenText(token: TokenItem) {
8
+ return `${token.title || token.value} (#${token.value})`;
9
+ }
10
+ export function unpackDisplayedTokenText(token: string) {
11
+ const result = /(.+) \(#([^)]+)\)$/.exec(token);
12
+ return {title: result?.[1], value: result?.[2] ?? token};
13
+ }
14
+
15
+ // The strange values correspond to the literals that are expected by TokenItem.status, which allows the assignment code to be cleaner
16
+ export const enum ValidationState {
17
+ Valid = 'success',
18
+ Invalid = 'error',
19
+ Validating = 'validating'
20
+ }
21
+
22
+ export type TokenManagementCallbacks = {
23
+ validationQuery(tokens: string[], ...args: Parameters<MapSelect>): TokenItem[]|undefined;
24
+ suggestionQuery(input: string, ...args: Parameters<MapSelect>): TokenItem[]|undefined;
25
+ stringToTokenConverter(suggestion: string): TokenItem;
26
+ }
27
+
28
+ type ImprovedTokenManagerReturnType = {
29
+ currentTokens: TokenItem[];
30
+ isValidating: boolean;
31
+ updateComponentValue: (value: (((prevState: (string | TokenItem)[]) => (string|TokenItem)[])|(string|TokenItem)[])) => void;
32
+ tokenStatusCache: Map<TokenItem["value"], TokenItem["status"]>
33
+ };
34
+
35
+ export function useImprovedTokenManager(
36
+ initialValue: (string|TokenItem)[]|undefined,
37
+ writeBackingValue: (value: TokenItem[]) => void,
38
+ validationQuery: TokenManagementCallbacks['validationQuery'],
39
+ makeTokenFromString: TokenManagementCallbacks['stringToTokenConverter'],
40
+ tokenTitleCache: Map<TokenItem['value'], TokenItem['title']>
41
+ ): ImprovedTokenManagerReturnType {
42
+ const [componentValue, updateComponentValue] = useState<(string|TokenItem)[]>(
43
+ () => initialValue?.map(item => typeof item === 'string' ? makeTokenFromString(item) : item) ?? []);
44
+
45
+ const tokenStatusCacheRef = useRef<Map<TokenItem['value'], TokenItem['status']>|undefined>(undefined);
46
+ if (tokenStatusCacheRef.current === undefined) {
47
+ tokenStatusCacheRef.current = new Map();
48
+ }
49
+
50
+ const convertedTokens = useTokenConverter(componentValue, makeTokenFromString, tokenStatusCacheRef.current);
51
+ const {isValidating, validatedTokens} = useTokenValidator(convertedTokens, validationQuery, tokenStatusCacheRef.current)
52
+ const titledTokens = useTokenTitleApplier(validatedTokens, tokenTitleCache);
53
+
54
+ useEffect(() => {
55
+ if (!isValidating) {
56
+ writeBackingValue(titledTokens);
57
+ }
58
+ }, [titledTokens, isValidating]);
59
+
60
+ return {currentTokens: titledTokens, isValidating, updateComponentValue, tokenStatusCache: tokenStatusCacheRef.current};
61
+ }
62
+ function syncTokenTitles(token: TokenItem, cache: Map<TokenItem['value'], TokenItem['title']>): TokenItem {
63
+ return {...token, title: cache.get(token.value) ?? addTokenTitleToCache(token, cache) ?? packDisplayTokenText(token)};
64
+ }
65
+ function addTokenTitleToCache(token: TokenItem, cache: Map<TokenItem['value'], TokenItem['title']>) {
66
+ let label = token.title?.trim();
67
+ if (!label) {
68
+ return;
69
+ }
70
+ const valueSuffix = `(#${token.value})`;
71
+ if (label.endsWith(valueSuffix)) {
72
+ label = label.substring(0, label.length - valueSuffix.length).trim();
73
+ }
74
+ const res = `${label.length > 30 ? `${label.substring(0, 30).trim()}…` : label} ${valueSuffix}`;
75
+ cache.set(token.value, res);
76
+ return res;
77
+ }
78
+
79
+ function isAllValidTokens(arr: (string|TokenItem)[]): arr is (Omit<TokenItem, 'title'|'status'>&Required<Pick<TokenItem, 'title'|'status'>>)[] {
80
+ return arr.every(token => typeof token !== 'string' && token.status !== undefined && token.status !== ValidationState.Validating && token.title !== undefined);
81
+ }
82
+
83
+ function useTokenConverter(
84
+ componentValue: (string|TokenItem)[], makeTokenFromString: (token: string) => TokenItem, tokenStatusCache: Map<TokenItem['value'], TokenItem['status']>
85
+ ) {
86
+ const priorComponentValue = useRef<(string|TokenItem)[]>([]);
87
+ const alreadyConvertedTokens = useRef<TokenItem[]>([]);
88
+ if (priorComponentValue.current === componentValue) {
89
+ return alreadyConvertedTokens.current;
90
+ }
91
+
92
+ const newlyConvertedTokens = isAllValidTokens(componentValue) ? componentValue
93
+ : componentValue.map(token => {
94
+ if (typeof token === 'string') {
95
+ const res = makeTokenFromString(token);
96
+ if (res.status === undefined) {
97
+ res.status = tokenStatusCache.get(res.value);
98
+ }
99
+ return res;
100
+ } else {
101
+ if (token.status === undefined || token.status === ValidationState.Validating) {
102
+ token.status = tokenStatusCache.get(token.value);
103
+ }
104
+ return token;
105
+ }
106
+ });
107
+
108
+ const convertedTokens = alreadyConvertedTokens.current;
109
+ if (newlyConvertedTokens.length !== convertedTokens.length) {
110
+ priorComponentValue.current = componentValue;
111
+ alreadyConvertedTokens.current = newlyConvertedTokens;
112
+ return newlyConvertedTokens;
113
+ }
114
+ for (let i = 0; i < newlyConvertedTokens.length; i++) {
115
+ if (newlyConvertedTokens[i]?.value !== convertedTokens[i]?.value || newlyConvertedTokens[i]?.status !== convertedTokens[i]?.status) {
116
+ priorComponentValue.current = componentValue;
117
+ alreadyConvertedTokens.current = newlyConvertedTokens;
118
+ return newlyConvertedTokens;
119
+ }
120
+ }
121
+ return convertedTokens;
122
+ }
123
+
124
+ function useTokenValidator(
125
+ convertedTokens: TokenItem[], validationQuery: TokenManagementCallbacks['validationQuery'], tokenStatusCache: Map<TokenItem['value'], TokenItem['status']>
126
+ ) {
127
+ const [statusUpdatedConvertedTokens, statusUpdatedConvertedTokenValues] = useMemo(() => {
128
+ const res = convertedTokens
129
+ .map(token => {
130
+ return (token.status === undefined || token.status === ValidationState.Validating) && tokenStatusCache.has(token.value)
131
+ ? {...token, status: tokenStatusCache.get(token.value)} : token;
132
+ });
133
+ return [res, res.map(token => token.value)];
134
+ }, [convertedTokens, tokenStatusCache]);
135
+
136
+ return useSelect((select, registry) => {
137
+ if (statusUpdatedConvertedTokens.some(token => token.status === undefined || token.status === ValidationState.Validating)) {
138
+ const res = validationQuery(statusUpdatedConvertedTokenValues, select, registry);
139
+ if (res !== undefined) {
140
+ const validTokens = new Map(res.map(token => [token.value, token]));
141
+ const validatedTokens = convertedTokens.map(token => validTokens.get(token.value) ?? {...token, status: ValidationState.Invalid});
142
+ for (const token of validatedTokens) {
143
+ tokenStatusCache.set(token.value, token.status);
144
+ }
145
+ return {validatedTokens: res, isValidating: false};
146
+ } else {
147
+ return {validatedTokens: statusUpdatedConvertedTokens, isValidating: true};
148
+ }
149
+ } else {
150
+ return {validatedTokens: statusUpdatedConvertedTokens, isValidating: false};
151
+ }
152
+ }, [convertedTokens, statusUpdatedConvertedTokens, statusUpdatedConvertedTokenValues, validationQuery, tokenStatusCache]);
153
+ }
154
+
155
+ function useTokenTitleApplier(convertedTokens: TokenItem[], tokenTitleCache: Map<TokenItem['value'], TokenItem['title']>) {
156
+ return useMemo(() => convertedTokens.map(token => syncTokenTitles(token, tokenTitleCache)), [convertedTokens, tokenTitleCache]);
157
+ }
@@ -0,0 +1,17 @@
1
+ import {useCallback, useMemo} from "@wordpress/element";
2
+
3
+ import type {TokenItem} from "../../lib/useful-types";
4
+
5
+ export type ValueConverter = [string[], (value: TokenItem[]) => void];
6
+ export function useMultiSingleConversionLayer(
7
+ value: string|string[]|undefined, onChange: ((tokens: string[]) => void)|((token: string) => void),
8
+ makeTokenFromSuggestion: (suggestion: string) => TokenItem, multiple = true
9
+ ): ValueConverter {
10
+ return [
11
+ useMemo(() => value === undefined ? [] : (Array.isArray(value) ? value : [value]), [value]),
12
+ useCallback(tokens => {
13
+ const bareTokens = tokens.filter(token => token.status === 'success').map(token => token.value);
14
+ onChange((multiple ? bareTokens : bareTokens[0]) as any);
15
+ }, [onChange, makeTokenFromSuggestion, multiple])
16
+ ];
17
+ }
@@ -0,0 +1,6 @@
1
+ import {useRef} from "@wordpress/element";
2
+
3
+ export function useNonRenderingCounter(initialValue = 0): [{ readonly current: number }, () => number] {
4
+ const count = useRef(initialValue);
5
+ return [count, () => ++count.current];
6
+ }
@@ -0,0 +1,16 @@
1
+ import {useCallback, useRef} from "@wordpress/element";
2
+
3
+ export function useOutputMemoizingFilter<A extends any[], R>(filter: (...args: A) => R, externals?: any[]): typeof filter {
4
+ const existingState = useRef<undefined|[typeof filter, A, R]>(undefined);
5
+ const memoizedFilter = useCallback((...args: A): R => {
6
+ if (existingState.current !== undefined && existingState.current[0] === memoizedFilter
7
+ && (existingState.current[1] === args || args.every((a, i) => existingState.current![1][i] === a))
8
+ ) {
9
+ return existingState.current[2];
10
+ }
11
+ const res = filter(...args);
12
+ existingState.current = [memoizedFilter, args, res];
13
+ return res;
14
+ }, externals ? [filter, ...externals] : [filter]);
15
+ return memoizedFilter;
16
+ }
@@ -0,0 +1,196 @@
1
+ import {useEffect, useMemo, useState} from "@wordpress/element";
2
+
3
+ import {Immer} from "immer";
4
+ import {clone} from "../../lib/helpers";
5
+
6
+ type Listeners<D> = {
7
+ onAdd?: (index: number, value: D) => void,
8
+ onChange?: (value: D[]) => void,
9
+ onRemove?: (index: number) => void,
10
+ onReorder?: (oldIndex: number, newIndex: number) => void
11
+ };
12
+ type SortableItemsModelArgs<D> = Listeners<D>&{
13
+ emptyValue?: D,
14
+ value?: D[]
15
+ }
16
+ export type SortableItemsModelKey = ReturnType<typeof crypto.randomUUID>;
17
+ export type KeyedValue<D> = {value: D, key: SortableItemsModelKey};
18
+ export type KeyedValues<D> = KeyedValue<D>[];
19
+ type ActionDefs<D> = {
20
+ add(args: {index?: number, value: D}): void,
21
+ remove(args: {key: SortableItemsModelKey}): void,
22
+ move(args: {oldIndex: number, newIndex: number}): void,
23
+ change(args: {value: D, index: number}): void,
24
+
25
+ commit(args: {keyedValues: KeyedValues<D>}): void,
26
+ refresh(args: {listeners: Listeners<D>, value?: D[]}): void
27
+ };
28
+
29
+ type State<D> = {
30
+ listeners: Listeners<D>,
31
+ keyedValues: KeyedValues<D>,
32
+ value?: D[] // This is only used to avoid updating keyedValues on refresh wherever possible
33
+ };
34
+
35
+ export type IndexedItemActions<D> = {
36
+ add(value: D): void,
37
+ remove(): void,
38
+ moveUp(): void,
39
+ moveDown(): void,
40
+ change(value: D): void
41
+ };
42
+ export type IndexedItemActionsMaker<D> = (index: number, key: SortableItemsModelKey) => IndexedItemActions<D>;
43
+
44
+ type Actions<D> = {add(value: D, index?: number): void, commit(keyedValues: KeyedValues<D>): void, makeIndexedItemActions: IndexedItemActionsMaker<D>};
45
+ export function useSortableItemsModel<D>(args: SortableItemsModelArgs<D>) {
46
+ const {mutators, state} = usePseudoReducerBasedStateManagement<D>(args);
47
+
48
+ const {emptyValue} = args;
49
+ // We use a separate memo for the actions because dispatch should change significantly less-often than state
50
+ const actions = useMemo<Actions<D>>(() => {
51
+ return ({
52
+ add: (value: D, index?: number) => {
53
+ mutators.add({value, index});
54
+ },
55
+ commit: (keyedValues: KeyedValues<D>) => {
56
+ mutators.commit({keyedValues});
57
+ },
58
+ addEmptyValue: emptyValue !== undefined && emptyValue !== null ? (index?: number) => {
59
+ mutators.add({value: typeof emptyValue === 'object' ? {...emptyValue} : emptyValue, index});
60
+ } : undefined,
61
+ makeIndexedItemActions(index: number, key: SortableItemsModelKey) {
62
+ return useMemo(() => ({
63
+ add: (value: D) => {
64
+ mutators.add({value, index});
65
+ },
66
+ remove: () => {
67
+ mutators.remove({key});
68
+ },
69
+ moveUp: () => {
70
+ mutators.move({oldIndex: index, newIndex: index - 1});
71
+ },
72
+ moveDown: () => {
73
+ mutators.move({oldIndex: index, newIndex: index + 1});
74
+ },
75
+ change: (value: D) => {
76
+ mutators.change({value, index});
77
+ }
78
+ }), [index, key, mutators]);
79
+ }
80
+ });
81
+ }, [emptyValue, mutators]);
82
+
83
+ return {...actions, keyedValues: state.keyedValues};
84
+ }
85
+
86
+ function swap<T>(value: T[], newIndex: number, oldIndex: number): T[] {
87
+ const splicedValue = [...value];
88
+ if (newIndex > oldIndex) {
89
+ splicedValue.splice(newIndex + 1, 0, splicedValue[oldIndex]!);
90
+ splicedValue.splice(oldIndex, 1);
91
+ } else {
92
+ splicedValue.splice(newIndex, 0, ...splicedValue.splice(oldIndex, 1));
93
+ }
94
+ return splicedValue;
95
+ }
96
+
97
+ function usePseudoReducerBasedStateManagement<D>({value, onAdd, onChange, onRemove, onReorder}: SortableItemsModelArgs<D>) {
98
+ const [state, setState] = useState<State<D>>({keyedValues: [], listeners: {}});
99
+
100
+ const mutators = useMemo<ActionDefs<D>>(() => {
101
+ return {
102
+ add({value, index}) {
103
+ const newItemIndex = index ?? state.value?.length ?? 0;
104
+ const newValue = state.value?.toSpliced(newItemIndex, 0, value) ?? [value];
105
+ onAdd?.(newItemIndex, value);
106
+ onChange?.(newValue);
107
+ setState({
108
+ ...state,
109
+ value: newValue,
110
+ keyedValues: state.keyedValues.toSpliced(newItemIndex, 0, {value: value, key: crypto.randomUUID()})
111
+ });
112
+ },
113
+ remove({key}) {
114
+ const actionIndex = state.keyedValues?.findIndex(({key: k}) => k === key) ?? -1;
115
+ if (actionIndex === -1) {
116
+ return;
117
+ }
118
+ const newValue = state.value?.toSpliced(actionIndex, 1) ?? [];
119
+ onRemove?.(actionIndex);
120
+ onChange?.(newValue);
121
+ setState({
122
+ ...state,
123
+ value: newValue,
124
+ keyedValues: state.keyedValues.toSpliced(actionIndex, 1)
125
+ });
126
+ },
127
+ move({oldIndex, newIndex}) {
128
+ if (newIndex === oldIndex) {
129
+ return;
130
+ }
131
+ const newValue = swap(state.value ?? [], newIndex, oldIndex);
132
+ const changesStart = Math.min(newIndex, oldIndex);
133
+ newValue.splice(changesStart, newValue.length, ...newValue.slice(changesStart).map(v => clone(v)));
134
+ onReorder?.(oldIndex, newIndex);
135
+ onChange?.(newValue);
136
+ setState({
137
+ ...state,
138
+ value: newValue,
139
+ keyedValues: swap(state.keyedValues, newIndex, oldIndex).map(({key}, i) => ({
140
+ value: newValue[i]!,
141
+ key
142
+ }))
143
+ });
144
+ },
145
+ change({value, index}) {
146
+ const newValue = (state.value ?? []).toSpliced(index, 1, value);
147
+ onChange?.(newValue);
148
+ setState({
149
+ ...state,
150
+ value: newValue,
151
+ keyedValues: state.keyedValues.toSpliced(index, 1, {...state.keyedValues[index]!, value})
152
+ });
153
+ },
154
+ commit({keyedValues}) {
155
+ const newValue = keyedValues.map(({value}) => value);
156
+ onChange?.(newValue);
157
+ setState({
158
+ ...state,
159
+ value: newValue,
160
+ keyedValues
161
+ });
162
+ },
163
+ refresh(args) {
164
+ const prevState = state;
165
+ setState((new Immer({autoFreeze: false})).produce(prevState, (draft: State<D>) => {
166
+ for (const [key, value] of Object.entries(args.listeners) as [keyof Listeners<D>, any][]) {
167
+ draft.listeners[key] = value;
168
+ }
169
+ if (prevState.value !== args.value) {
170
+ draft.value = args.value;
171
+ if (args.value !== undefined) {
172
+ if (args.value.length !== prevState.keyedValues.length) {
173
+ draft.keyedValues = args.value.map((v, i) => {
174
+ return {
175
+ value: v,
176
+ key: prevState.keyedValues[i] !== undefined && prevState.keyedValues[i].value === v ? prevState.keyedValues[i].key : crypto.randomUUID()
177
+ };
178
+ });
179
+ } else {
180
+ for (let i = 0; i < args.value.length; i++) {
181
+ draft.keyedValues[i]!.value = args.value[i]!;
182
+ }
183
+ }
184
+ }
185
+ }
186
+ }));
187
+ }
188
+ };
189
+ }, [state, onAdd, onChange, onRemove, onReorder]);
190
+
191
+ useEffect(() => {
192
+ mutators.refresh({listeners: {onAdd, onChange, onRemove, onReorder}, value});
193
+ }, [value, onAdd, onChange, onRemove, onReorder, mutators]);
194
+
195
+ return {mutators, state};
196
+ }
@@ -0,0 +1,91 @@
1
+ import {useCallback, useEffect, useRef, useState} from "@wordpress/element";
2
+
3
+ import {useNonRenderingCounter} from "./useNonRenderingCounter";
4
+
5
+ import {useReducer} from "react";
6
+
7
+ type UseSuggestionsArgs<T> = {
8
+ expandOnFocus?: boolean,
9
+ getOption?: (value?: string) => Promise<T|undefined>,
10
+ getSuggestions(filterValue: string): Promise<T[]>
11
+ };
12
+ type SuggestionState<T> = {
13
+ hasLoadingError: boolean,
14
+ suggestions: T[],
15
+ requestId: number
16
+ };
17
+ function useSimpleDebouncer(delay: number) {
18
+ const timerId = useRef<ReturnType<typeof window['setTimeout']>|undefined>(undefined);
19
+ return useCallback((action: () => void) => {
20
+ if (timerId.current !== undefined) {
21
+ clearTimeout(timerId.current);
22
+ }
23
+ timerId.current = setTimeout(() => {
24
+ timerId.current = undefined;
25
+ action();
26
+ }, delay);
27
+ }, [timerId]);
28
+ }
29
+
30
+ export function useSuggestions<T>(initialValue: string|null|undefined, {expandOnFocus, getOption, getSuggestions}: UseSuggestionsArgs<T>) {
31
+ const suggestionRequestDebouncer = useSimpleDebouncer(200);
32
+ const [requestId, nextRequestId] = useNonRenderingCounter();
33
+ const [isLoading, setIsLoading] = useState(false);
34
+ const [latestSuggestions, dispatchSuggestionsUpdate] = useReducer(useSuggestionSuggestionUpdateReducer<T>,
35
+ {hasLoadingError: false, requestId: 0, suggestions: []});
36
+ const [input, setInput] = useState(initialValue ?? "");
37
+
38
+ useEffect(() => {
39
+ const myRequestId = nextRequestId();
40
+ if (getOption === undefined) {
41
+ dispatchSuggestionsUpdate({hasLoadingError: false, suggestions: [], requestId: myRequestId});
42
+ return;
43
+ }
44
+ if (!expandOnFocus && input.length < 2) {
45
+ dispatchSuggestionsUpdate({hasLoadingError: false, suggestions: [], requestId: myRequestId});
46
+ } else {
47
+ setIsLoading(true);
48
+ getOption(input)
49
+ .then(option => dispatchSuggestionsUpdate({hasLoadingError: false, suggestions: option ? [option] : [], requestId: myRequestId}))
50
+ .catch(err => {
51
+ dispatchSuggestionsUpdate({hasLoadingError: true, suggestions: [], requestId: myRequestId});
52
+ console.error("An error occurred while loading options:", err);
53
+ });
54
+ }
55
+ }, [expandOnFocus, getOption]);
56
+
57
+ useEffect(() => {
58
+ const myRequestId = nextRequestId();
59
+ if (!expandOnFocus && input.length < 2) {
60
+ dispatchSuggestionsUpdate({hasLoadingError: false, suggestions: [], requestId: myRequestId});
61
+ } else {
62
+ const myRequestId = nextRequestId();
63
+ setIsLoading(true);
64
+ suggestionRequestDebouncer(() => {
65
+ getSuggestions(input)
66
+ .then(suggestions => dispatchSuggestionsUpdate({hasLoadingError: false, suggestions, requestId: myRequestId}))
67
+ .catch(err => {
68
+ dispatchSuggestionsUpdate({hasLoadingError: true, suggestions: [], requestId: myRequestId});
69
+ console.error("An error occurred while loading options:", err);
70
+ });
71
+ });
72
+ }
73
+ }, [input, suggestionRequestDebouncer]);
74
+
75
+ // This is a separate useEffect hook because we don't necessarily want to update the rendered state when a new request is sent out.
76
+ useEffect(() => setIsLoading(latestSuggestions.requestId < requestId.current), [latestSuggestions.requestId]);
77
+
78
+ return {
79
+ hasLoadingError: latestSuggestions.hasLoadingError, isInitializing: latestSuggestions.requestId === 0, isLoading,
80
+ input, setInput, suggestions: latestSuggestions.suggestions
81
+ }
82
+ }
83
+ function useSuggestionSuggestionUpdateReducer<T>(state: SuggestionState<T>, action: SuggestionState<T>): SuggestionState<T> {
84
+ if (action.requestId <= state.requestId) {
85
+ return state;
86
+ }
87
+ if (action.hasLoadingError) {
88
+ return {hasLoadingError: true, requestId: action.requestId, suggestions: [...state.suggestions]};
89
+ }
90
+ return action;
91
+ }