@kaspernj/api-maker 1.0.2011 → 1.0.2012

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 (410) hide show
  1. package/{.eslintrc.cjs → .eslintrc.js} +10 -1
  2. package/README.md +35 -0
  3. package/android/build.gradle +43 -0
  4. package/android/src/main/AndroidManifest.xml +2 -0
  5. package/android/src/main/java/expo/modules/api_maker/ApiMakerModule.kt +50 -0
  6. package/android/src/main/java/expo/modules/api_maker/ApiMakerView.kt +30 -0
  7. package/build/api.js +120 -0
  8. package/build/attribute-not-loaded-error.js +2 -0
  9. package/build/base-component.js +5 -0
  10. package/build/base-error.js +33 -0
  11. package/build/base-model/attribute.js +25 -0
  12. package/build/base-model/column.js +11 -0
  13. package/build/base-model/reflection.js +14 -0
  14. package/build/base-model/scope.js +11 -0
  15. package/build/base-model.js +828 -0
  16. package/build/bootstrap/attribute-row.js +135 -0
  17. package/build/bootstrap/attribute-rows.js +31 -0
  18. package/build/bootstrap/card.js +138 -0
  19. package/build/bootstrap/checkbox.js +97 -0
  20. package/build/bootstrap/checkboxes.js +183 -0
  21. package/build/bootstrap/index.js +2 -0
  22. package/build/bootstrap/input.js +129 -0
  23. package/build/bootstrap/invalid-feedback.js +27 -0
  24. package/build/bootstrap/paginate.js +150 -0
  25. package/build/bootstrap/radio-buttons.js +72 -0
  26. package/build/bootstrap/select.js +88 -0
  27. package/build/bootstrap/sort-link.js +131 -0
  28. package/build/cable-connection-pool.js +128 -0
  29. package/build/cable-subscription-pool.js +207 -0
  30. package/build/cable-subscription.js +21 -0
  31. package/build/cache-key-generator.js +81 -0
  32. package/build/can-can.js +134 -0
  33. package/build/channels-consumer.js +9 -0
  34. package/build/collection-loader.js +48 -0
  35. package/build/collection.js +280 -0
  36. package/build/command-submit-data.js +81 -0
  37. package/build/commands-pool.js +195 -0
  38. package/build/compose.js +9 -0
  39. package/build/config.js +62 -0
  40. package/build/custom-error.js +5 -0
  41. package/build/data-set-to-attributes.js +10 -0
  42. package/build/deserializer.js +56 -0
  43. package/build/destroy-error.js +5 -0
  44. package/build/devise.js +112 -0
  45. package/build/draggable-sort/controller.js +136 -0
  46. package/build/draggable-sort/index.js +114 -0
  47. package/build/draggable-sort/item.js +188 -0
  48. package/build/error-logger.js +101 -0
  49. package/build/error-messages.js +13 -0
  50. package/build/event-connection.js +32 -0
  51. package/build/event-emitter-listener.js +15 -0
  52. package/build/event-model-class.js +24 -0
  53. package/build/events.js +5 -0
  54. package/build/flash-message.js +79 -0
  55. package/build/form.js +83 -0
  56. package/build/history-expo.js +20 -0
  57. package/build/history-react-native.js +20 -0
  58. package/build/history.js +3 -0
  59. package/build/index.js +3 -0
  60. package/build/inputs/attachment.js +133 -0
  61. package/build/inputs/auto-submit.js +36 -0
  62. package/build/inputs/checkbox.js +138 -0
  63. package/build/inputs/checkboxes.js +112 -0
  64. package/build/inputs/id-for-component.js +15 -0
  65. package/build/inputs/input-wrapper.js +19 -0
  66. package/build/inputs/input.js +243 -0
  67. package/build/inputs/money.js +179 -0
  68. package/build/inputs/name-for-component.js +13 -0
  69. package/build/inputs/select.js +93 -0
  70. package/build/instance-of-class-name.js +23 -0
  71. package/build/key-value-store.js +53 -0
  72. package/build/link.js +73 -0
  73. package/build/logger.js +30 -0
  74. package/build/modal.js +38 -0
  75. package/build/model-class-require.js +13 -0
  76. package/build/model-events.js +30 -0
  77. package/build/model-name.js +28 -0
  78. package/build/model-prop-type.js +101 -0
  79. package/build/model-recipes-loader.js +32 -0
  80. package/build/model-recipes-model-loader.js +357 -0
  81. package/build/models-response-reader.js +40 -0
  82. package/build/models.js +8 -0
  83. package/build/money-formatter.js +78 -0
  84. package/build/not-loaded-error.js +2 -0
  85. package/build/params.js +61 -0
  86. package/build/preloaded.js +38 -0
  87. package/build/resize-observer.js +11 -0
  88. package/build/result.js +13 -0
  89. package/build/router/route.js +270 -0
  90. package/build/router/switch.js +72 -0
  91. package/build/router.js +59 -0
  92. package/build/routes-native.js +202 -0
  93. package/build/routes.js +50 -0
  94. package/build/run-last.js +35 -0
  95. package/build/serializer.js +63 -0
  96. package/build/services.js +20 -0
  97. package/build/session-status-updater.js +134 -0
  98. package/build/source-maps-loader.js +184 -0
  99. package/build/super-admin/config-reader.js +85 -0
  100. package/build/super-admin/edit-page/edit-attribute-checkbox.js +85 -0
  101. package/build/super-admin/edit-page/edit-attribute-content.js +55 -0
  102. package/build/super-admin/edit-page/edit-attribute-input.js +79 -0
  103. package/build/super-admin/edit-page/edit-attribute.js +77 -0
  104. package/build/super-admin/edit-page.js +123 -0
  105. package/build/super-admin/has-edit-config.js +12 -0
  106. package/build/super-admin/index-page.js +25 -0
  107. package/build/super-admin/index.js +181 -0
  108. package/build/super-admin/layout/header/index.js +161 -0
  109. package/build/super-admin/layout/index.js +164 -0
  110. package/build/super-admin/layout/menu/index.js +206 -0
  111. package/build/super-admin/layout/menu/menu-content.js +46 -0
  112. package/build/super-admin/layout/menu/menu-item.js +84 -0
  113. package/build/super-admin/layout/no-access.js +27 -0
  114. package/build/super-admin/model-class-table.js +61 -0
  115. package/build/super-admin/models.js +8 -0
  116. package/build/super-admin/show-nav.js +51 -0
  117. package/build/super-admin/show-page/belongs-to-attribute-row.js +29 -0
  118. package/build/super-admin/show-page/index.js +141 -0
  119. package/build/super-admin/show-reflection-actions.js +47 -0
  120. package/build/super-admin/show-reflection-link.js +48 -0
  121. package/build/super-admin/show-reflection-page.js +48 -0
  122. package/build/table/column-content.js +117 -0
  123. package/build/table/column-identifier.js +18 -0
  124. package/build/table/column-visible.js +7 -0
  125. package/build/table/components/column.js +21 -0
  126. package/build/table/components/flat-list.js +21 -0
  127. package/build/table/components/header.js +26 -0
  128. package/build/table/components/row.js +26 -0
  129. package/build/table/filters/attribute-element.js +44 -0
  130. package/build/table/filters/filter-form.js +402 -0
  131. package/build/table/filters/filter.js +90 -0
  132. package/build/table/filters/index.js +184 -0
  133. package/build/table/filters/load-search-modal.js +175 -0
  134. package/build/table/filters/reflection-element.js +37 -0
  135. package/build/table/filters/save-search-modal.js +88 -0
  136. package/build/table/filters/scope-element.js +42 -0
  137. package/build/table/header-column-content.js +68 -0
  138. package/build/table/header-column.js +144 -0
  139. package/build/table/header-select.js +105 -0
  140. package/build/table/model-callback-args.js +10 -0
  141. package/build/table/model-column.js +97 -0
  142. package/build/table/model-row.js +193 -0
  143. package/build/table/select-calculator.js +63 -0
  144. package/build/table/settings/column-row.js +97 -0
  145. package/build/table/settings/download-action.js +79 -0
  146. package/build/table/settings/index.js +92 -0
  147. package/build/table/table-settings.js +219 -0
  148. package/build/table/table.js +972 -0
  149. package/build/table/use-sorting.js +34 -0
  150. package/build/table/widths.js +75 -0
  151. package/build/table/worker-plugins-check-all-checkbox.js +125 -0
  152. package/build/table/worker-plugins-checkbox.js +115 -0
  153. package/build/translated-attributes.js +10 -0
  154. package/build/translated-collections.js +12 -0
  155. package/build/updated-attribute.js +76 -0
  156. package/build/url-encode.js +15 -0
  157. package/build/use-breakpoint.js +62 -0
  158. package/build/use-can-can.js +55 -0
  159. package/build/use-collection.js +225 -0
  160. package/build/use-created-event.js +52 -0
  161. package/build/use-current-user.js +76 -0
  162. package/build/use-destroyed-event.js +60 -0
  163. package/build/use-event-emitter.js +13 -0
  164. package/build/use-event-listener.js +16 -0
  165. package/build/use-input.js +137 -0
  166. package/build/use-model-event.js +60 -0
  167. package/build/use-model.js +169 -0
  168. package/build/use-resize-observer.js +23 -0
  169. package/build/use-router.js +104 -0
  170. package/build/use-screen-layout.js +39 -0
  171. package/build/use-updated-event.js +60 -0
  172. package/build/use-validation-errors.js +30 -0
  173. package/build/utils/card.js +51 -0
  174. package/build/utils/checkbox.js +78 -0
  175. package/build/utils/checkboxes.js +163 -0
  176. package/build/utils/default-style.js +18 -0
  177. package/build/utils/icon.js +23 -0
  178. package/build/utils/invalid-feedback.js +19 -0
  179. package/build/utils/modal.js +62 -0
  180. package/build/utils/text.js +19 -0
  181. package/build/validation-error.js +28 -0
  182. package/build/validation-errors.js +98 -0
  183. package/build/with-api-maker.js +29 -0
  184. package/build/with-collection.js +14 -0
  185. package/build/with-current-user.js +10 -0
  186. package/build/with-model.js +15 -0
  187. package/build/with-router.js +22 -0
  188. package/expo-module.config.json +17 -0
  189. package/ios/ApiMaker.podspec +29 -0
  190. package/ios/ApiMakerModule.swift +48 -0
  191. package/ios/ApiMakerView.swift +38 -0
  192. package/link.sh +8 -0
  193. package/package.json +49 -46
  194. package/src/{api.mjs → api.js} +38 -37
  195. package/src/base-component.jsx +5 -0
  196. package/src/{base-error.mjs → base-error.js} +4 -6
  197. package/src/base-model/attribute.js +33 -0
  198. package/src/base-model/column.js +13 -0
  199. package/src/base-model/reflection.js +15 -0
  200. package/src/base-model/scope.js +12 -0
  201. package/src/{base-model.mjs → base-model.js} +302 -144
  202. package/src/bootstrap/attribute-row.jsx +135 -0
  203. package/src/bootstrap/attribute-rows.jsx +27 -0
  204. package/src/bootstrap/card.jsx +149 -0
  205. package/src/bootstrap/checkbox.jsx +86 -0
  206. package/src/bootstrap/checkboxes.jsx +185 -0
  207. package/src/bootstrap/index.js +0 -0
  208. package/src/bootstrap/input.jsx +173 -0
  209. package/src/bootstrap/invalid-feedback.jsx +31 -0
  210. package/src/bootstrap/paginate.jsx +187 -0
  211. package/src/bootstrap/radio-buttons.jsx +87 -0
  212. package/src/bootstrap/select.jsx +110 -0
  213. package/src/bootstrap/sort-link.jsx +106 -0
  214. package/src/{cable-connection-pool.mjs → cable-connection-pool.js} +16 -36
  215. package/src/{cable-subscription-pool.mjs → cable-subscription-pool.js} +26 -21
  216. package/src/{cable-subscription.mjs → cable-subscription.js} +6 -4
  217. package/src/cache-key-generator.js +100 -0
  218. package/src/{can-can.mjs → can-can.js} +13 -12
  219. package/src/channels-consumer.js +10 -0
  220. package/src/collection-loader.jsx +58 -224
  221. package/src/{collection.mjs → collection.js} +98 -44
  222. package/src/{command-submit-data.mjs → command-submit-data.js} +2 -7
  223. package/src/{commands-pool.mjs → commands-pool.js} +57 -41
  224. package/src/compose.js +11 -0
  225. package/src/{config.mjs → config.js} +6 -2
  226. package/src/{custom-error.mjs → custom-error.js} +1 -1
  227. package/src/data-set-to-attributes.js +13 -0
  228. package/src/{deserializer.mjs → deserializer.js} +3 -3
  229. package/src/destroy-error.js +7 -0
  230. package/src/devise.js +129 -0
  231. package/src/draggable-sort/controller.js +137 -0
  232. package/src/draggable-sort/index.jsx +108 -0
  233. package/src/draggable-sort/item.jsx +174 -0
  234. package/src/{error-logger.mjs → error-logger.js} +12 -7
  235. package/src/{error-messages.mjs → error-messages.js} +1 -0
  236. package/src/event-connection.jsx +1 -1
  237. package/src/event-emitter-listener.jsx +8 -27
  238. package/src/event-model-class.jsx +2 -4
  239. package/src/events.js +7 -0
  240. package/src/flash-message.js +70 -0
  241. package/src/form.jsx +91 -0
  242. package/src/history-expo.js +23 -0
  243. package/src/history-react-native.js +25 -0
  244. package/src/history.js +3 -0
  245. package/src/index.js +3 -0
  246. package/src/inputs/attachment.jsx +108 -0
  247. package/src/inputs/auto-submit.js +37 -0
  248. package/src/inputs/checkbox.jsx +125 -0
  249. package/src/inputs/checkboxes.jsx +116 -0
  250. package/src/inputs/id-for-component.js +15 -0
  251. package/src/inputs/input-wrapper.jsx +16 -0
  252. package/src/inputs/input.jsx +260 -0
  253. package/src/inputs/money.jsx +187 -0
  254. package/src/inputs/name-for-component.js +15 -0
  255. package/src/inputs/select.jsx +104 -0
  256. package/src/{key-value-store.mjs → key-value-store.js} +1 -1
  257. package/src/link.jsx +54 -9
  258. package/src/logger.js +38 -0
  259. package/src/modal.jsx +37 -0
  260. package/src/model-class-require.js +17 -0
  261. package/src/{model-events.mjs → model-events.js} +1 -1
  262. package/src/{model-name.mjs → model-name.js} +8 -8
  263. package/src/{model-recipes-loader.mjs → model-recipes-loader.js} +1 -1
  264. package/src/{model-recipes-model-loader.mjs → model-recipes-model-loader.js} +5 -5
  265. package/src/{models-response-reader.mjs → models-response-reader.js} +3 -4
  266. package/src/models.js +7 -0
  267. package/src/{models.mjs.erb → models.js.erb} +6 -3
  268. package/src/{money-formatter.mjs → money-formatter.js} +5 -4
  269. package/src/{params.mjs → params.js} +17 -7
  270. package/src/{preloaded.mjs → preloaded.js} +2 -2
  271. package/src/resize-observer.jsx +10 -0
  272. package/src/result.js +13 -0
  273. package/src/router/route.jsx +246 -0
  274. package/src/router/switch.jsx +76 -0
  275. package/src/router.jsx +23 -21
  276. package/src/{routes-native.mjs → routes-native.js} +12 -6
  277. package/src/{routes.mjs → routes.js} +1 -1
  278. package/src/run-last.js +39 -0
  279. package/src/{serializer.mjs → serializer.js} +2 -2
  280. package/src/{services.mjs → services.js} +1 -1
  281. package/src/session-status-updater.js +172 -0
  282. package/src/{source-maps-loader.mjs → source-maps-loader.js} +54 -28
  283. package/src/super-admin/config-reader.jsx +93 -0
  284. package/src/super-admin/edit-page/edit-attribute-checkbox.jsx +81 -0
  285. package/src/super-admin/edit-page/edit-attribute-content.jsx +57 -0
  286. package/src/super-admin/edit-page/edit-attribute-input.jsx +71 -0
  287. package/src/super-admin/edit-page/edit-attribute.jsx +81 -0
  288. package/src/super-admin/edit-page.jsx +117 -0
  289. package/src/super-admin/has-edit-config.js +15 -0
  290. package/src/super-admin/index-page.jsx +23 -0
  291. package/src/super-admin/index.jsx +197 -0
  292. package/src/super-admin/layout/header/index.jsx +144 -0
  293. package/src/super-admin/layout/header/style.scss +45 -0
  294. package/src/super-admin/layout/index.jsx +154 -0
  295. package/src/super-admin/layout/menu/index.jsx +171 -0
  296. package/src/super-admin/layout/menu/menu-content.jsx +43 -0
  297. package/src/super-admin/layout/menu/menu-item.jsx +70 -0
  298. package/src/super-admin/layout/menu/style.scss +11 -0
  299. package/src/super-admin/layout/no-access.jsx +26 -0
  300. package/src/super-admin/model-class-table.jsx +66 -0
  301. package/src/super-admin/models.js +11 -0
  302. package/src/super-admin/show-nav.jsx +44 -0
  303. package/src/super-admin/show-page/belongs-to-attribute-row.jsx +30 -0
  304. package/src/super-admin/show-page/index.jsx +141 -0
  305. package/src/super-admin/show-reflection-actions.jsx +49 -0
  306. package/src/super-admin/show-reflection-link.jsx +40 -0
  307. package/src/super-admin/show-reflection-page.jsx +47 -0
  308. package/src/super-admin/stylesheets/variables.scss +11 -0
  309. package/src/table/column-content.jsx +122 -0
  310. package/src/table/column-identifier.js +23 -0
  311. package/src/table/column-visible.js +7 -0
  312. package/src/table/components/column.jsx +19 -0
  313. package/src/table/components/flat-list.jsx +19 -0
  314. package/src/table/components/header.jsx +21 -0
  315. package/src/table/components/row.jsx +23 -0
  316. package/src/table/filters/attribute-element.jsx +47 -0
  317. package/src/table/filters/filter-form.jsx +407 -0
  318. package/src/table/filters/filter.jsx +70 -0
  319. package/src/table/filters/index.jsx +170 -0
  320. package/src/table/filters/load-search-modal.jsx +146 -0
  321. package/src/table/filters/reflection-element.jsx +38 -0
  322. package/src/table/filters/save-search-modal.jsx +74 -0
  323. package/src/table/filters/scope-element.jsx +44 -0
  324. package/src/table/header-column-content.jsx +55 -0
  325. package/src/table/header-column.jsx +129 -0
  326. package/src/table/header-select.jsx +73 -0
  327. package/src/table/model-callback-args.js +10 -0
  328. package/src/table/model-column.jsx +82 -0
  329. package/src/table/model-row.jsx +136 -0
  330. package/src/table/select-calculator.js +65 -0
  331. package/src/table/settings/column-row.jsx +93 -0
  332. package/src/table/settings/download-action.jsx +68 -0
  333. package/src/table/settings/index.jsx +65 -0
  334. package/src/table/table-settings.js +263 -0
  335. package/src/table/table.jsx +950 -0
  336. package/src/table/use-sorting.js +35 -0
  337. package/src/table/variables.scss +11 -0
  338. package/src/table/widths.jsx +87 -0
  339. package/src/table/worker-plugins-check-all-checkbox.jsx +112 -0
  340. package/src/table/worker-plugins-checkbox.jsx +104 -0
  341. package/src/translated-attributes.js +11 -0
  342. package/src/{translated-collections.mjs → translated-collections.js} +3 -2
  343. package/src/updated-attribute.jsx +1 -1
  344. package/src/url-encode.js +18 -0
  345. package/src/use-breakpoint.js +76 -0
  346. package/src/use-can-can.js +55 -0
  347. package/src/use-collection.js +280 -0
  348. package/src/use-created-event.js +55 -0
  349. package/src/use-current-user.js +88 -0
  350. package/src/use-destroyed-event.js +60 -0
  351. package/src/use-event-emitter.js +15 -0
  352. package/src/use-event-listener.js +19 -0
  353. package/src/use-input.js +157 -0
  354. package/src/use-model-event.js +60 -0
  355. package/src/use-model.js +189 -0
  356. package/src/use-resize-observer.js +24 -0
  357. package/src/use-router.jsx +128 -0
  358. package/src/use-screen-layout.js +49 -0
  359. package/src/use-updated-event.js +60 -0
  360. package/src/use-validation-errors.js +33 -0
  361. package/src/utils/card.jsx +49 -0
  362. package/src/utils/checkbox.jsx +80 -0
  363. package/src/utils/checkboxes.jsx +158 -0
  364. package/src/utils/default-style.jsx +25 -0
  365. package/src/utils/icon.jsx +21 -0
  366. package/src/utils/invalid-feedback.jsx +20 -0
  367. package/src/utils/modal.jsx +60 -0
  368. package/src/utils/text.jsx +16 -0
  369. package/src/{validation-error.mjs → validation-error.js} +9 -5
  370. package/src/{validation-errors.mjs → validation-errors.js} +15 -27
  371. package/src/with-api-maker.jsx +31 -0
  372. package/src/with-collection.jsx +17 -0
  373. package/src/with-current-user.jsx +7 -25
  374. package/src/with-model.jsx +16 -0
  375. package/src/with-router.jsx +7 -129
  376. package/__tests__/base-model.test.js +0 -71
  377. package/__tests__/cable-connection-pool.test.js +0 -227
  378. package/__tests__/cable-subscription-pool.test.js +0 -26
  379. package/__tests__/can-can.test.js +0 -34
  380. package/__tests__/collection.test.js +0 -51
  381. package/__tests__/custom-error.test.js +0 -13
  382. package/__tests__/model-name.test.js +0 -34
  383. package/__tests__/model-prop-type.test.js +0 -113
  384. package/__tests__/params.test.js +0 -40
  385. package/__tests__/routes-native.test.js +0 -103
  386. package/__tests__/routes.test.js +0 -46
  387. package/__tests__/serializer.test.js +0 -30
  388. package/__tests__/support/task.js +0 -27
  389. package/__tests__/support/user.js +0 -32
  390. package/index.js +0 -1
  391. package/jest.config.js +0 -4
  392. package/src/can-can-loader.jsx +0 -54
  393. package/src/channels-consumer.mjs +0 -3
  394. package/src/destroy-error.mjs +0 -7
  395. package/src/devise.mjs +0 -122
  396. package/src/event-created.jsx +0 -65
  397. package/src/event-destroyed.jsx +0 -29
  398. package/src/event-listener.jsx +0 -38
  399. package/src/event-updated.jsx +0 -74
  400. package/src/logger.mjs +0 -25
  401. package/src/model-class-require.mjs +0 -10
  402. package/src/model-load-wrapper.jsx +0 -116
  403. package/src/result.mjs +0 -29
  404. package/src/session-status-updater.mjs +0 -116
  405. package/webpack.config.js +0 -15
  406. /package/src/{attribute-not-loaded-error.mjs → attribute-not-loaded-error.js} +0 -0
  407. /package/src/{instance-of-class-name.mjs → instance-of-class-name.js} +0 -0
  408. /package/src/{model-prop-type.mjs → model-prop-type.js} +0 -0
  409. /package/src/{not-loaded-error.mjs → not-loaded-error.js} +0 -0
  410. /package/src/{translated-collections-data.mjs.erb → translated-collections-data.js.erb} +0 -0
@@ -0,0 +1,60 @@
1
+ import {useCallback, useLayoutEffect, useMemo} from "react"
2
+ import debounceFunction from "debounce"
3
+ import ModelEvents from "./model-events"
4
+ import useShape from "set-state-compare/src/use-shape"
5
+
6
+ const apiMakerUseModelEvent = (model, event, onCallback, props) => {
7
+ const {active = true, debounce, onConnected, ...restProps} = props || {}
8
+
9
+ if (Object.keys(restProps).length > 0) {
10
+ throw new Error(`Unknown props given to apiMakerUseModelEvent: ${Object.keys(restProps).join(", ")}`)
11
+ }
12
+
13
+ const s = useShape({active, debounce, model, onCallback})
14
+
15
+ const debounceCallback = useMemo(() => {
16
+ if (typeof debounce == "number") {
17
+ return debounceFunction(s.p.onCallback, debounce)
18
+ } else {
19
+ return debounceFunction(s.p.onCallback)
20
+ }
21
+ }, [debounce])
22
+
23
+ s.updateMeta({debounceCallback})
24
+
25
+ const onCallbackCallback = useCallback((...args) => {
26
+ if (!s.p.active) {
27
+ return
28
+ }
29
+
30
+ if (s.p.debounce) {
31
+ s.m.debounceCallback(...args)
32
+ } else {
33
+ s.p.onCallback(...args)
34
+ }
35
+ }, [])
36
+
37
+ useLayoutEffect(() => {
38
+ let connectEvent, onConnectedListener
39
+
40
+ if (model) {
41
+ connectEvent = ModelEvents.connect(model, event, onCallbackCallback)
42
+
43
+ if (onConnected) {
44
+ onConnectedListener = connectEvent.events.addListener("connected", onConnected)
45
+ }
46
+ }
47
+
48
+ return () => {
49
+ if (onConnectedListener) {
50
+ connectEvent.events.removeListener("connected", onConnected)
51
+ }
52
+
53
+ if (connectEvent) {
54
+ connectEvent.unsubscribe()
55
+ }
56
+ }
57
+ }, [model?.id()])
58
+ }
59
+
60
+ export default apiMakerUseModelEvent
@@ -0,0 +1,189 @@
1
+ import {useCallback, useLayoutEffect, useMemo} from "react"
2
+ import Devise from "./devise"
3
+ import * as inflection from "inflection"
4
+ import ModelEvents from "./model-events"
5
+ import useQueryParams from "on-location-changed/build/use-query-params"
6
+ import useShape from "set-state-compare/src/use-shape"
7
+
8
+ const useModel = (modelClassArg, argsArg = {}) => {
9
+ const queryParams = useQueryParams()
10
+ let args, modelClass
11
+
12
+ if (typeof argsArg == "function") {
13
+ args = argsArg({modelClass})
14
+ } else {
15
+ args = argsArg
16
+ }
17
+
18
+ const s = useShape(args)
19
+
20
+ s.useStates({
21
+ model: undefined,
22
+ notFound: undefined
23
+ })
24
+
25
+ if ("active" in s.props && !s.props.active) {
26
+ s.meta.active = false
27
+ } else {
28
+ s.meta.active = true
29
+ }
30
+
31
+ if (typeof modelClassArg == "object") {
32
+ modelClass = modelClassArg.callback({queryParams})
33
+ } else {
34
+ modelClass = modelClassArg
35
+ }
36
+
37
+ const paramsVariableName = `${modelClass.modelName().paramKey()}_id`
38
+ let modelId
39
+
40
+ if (args.loadByQueryParam) {
41
+ modelId = args.loadByQueryParam({queryParams})
42
+ } else if (!args.query) {
43
+ if (!args.match) throw new Error("Both 'loadByQueryParam' and 'match' wasn't given")
44
+
45
+ modelId = args.match.params[paramsVariableName] || args.match.params.id
46
+ }
47
+
48
+ const modelVariableName = inflection.camelize(modelClass.modelClassData().name, true)
49
+ const cacheArgs = [modelId]
50
+
51
+ const loadExistingModel = useCallback(async () => {
52
+ let query
53
+
54
+ if (s.m.modelId) {
55
+ query = modelClass.ransack({id_eq: s.m.modelId})
56
+ } else if (s.m.args.query) {
57
+ query = s.m.args.query.clone()
58
+ } else {
59
+ throw new Error(`No model ID was given: ${s.m.modelId} by '${paramsVariableName}' in query params: ${Object.keys(s.props.match.params).join(", ")}`)
60
+ }
61
+
62
+ if (s.props.abilities) query.abilities(s.p.abilities)
63
+ if (s.props.preload) query.preload(s.p.preload)
64
+ if (s.props.select) query.select(s.p.select)
65
+
66
+ const model = await query.first()
67
+
68
+ s.set({model, notFound: !model})
69
+ }, [])
70
+
71
+ const loadNewModel = useCallback(async () => {
72
+ const ModelClass = modelClass
73
+ const paramKey = ModelClass.modelName().paramKey()
74
+ const modelDataFromParams = s.m.queryParams[paramKey] || {}
75
+
76
+ let defaults = {}
77
+
78
+ if (s.props.newIfNoId?.defaults) {
79
+ defaults = await s.props.newIfNoId.defaults()
80
+ }
81
+
82
+ const modelData = Object.assign(defaults, s.props.newAttributes, modelDataFromParams)
83
+ const model = new ModelClass({
84
+ isNewRecord: true,
85
+ data: {a: modelData}
86
+ })
87
+
88
+ s.set({model})
89
+ }, [])
90
+
91
+ const loadModel = useCallback(async () => {
92
+ if (!s.m.active) {
93
+ // Not active - don't do anything
94
+ } else if (s.props.newIfNoId && !s.m.modelId) {
95
+ return await loadNewModel()
96
+ } else if (!s.props.optional || s.m.modelId | s.m.args.query) {
97
+ return await loadExistingModel()
98
+ }
99
+ }, [])
100
+
101
+ const onDestroyed = useCallback(({model}) => {
102
+ const forwardArgs = {model}
103
+
104
+ forwardArgs[s.m.modelVariableName] = model
105
+
106
+ s.p.onDestroyed(forwardArgs)
107
+ }, [])
108
+
109
+ const onSignedIn = useCallback(() => {
110
+ loadModel()
111
+ }, [])
112
+
113
+ const onSignedOut = useCallback(() => {
114
+ loadModel()
115
+ }, [])
116
+
117
+ if (args.cacheArgs) {
118
+ cacheArgs.push(...args.cacheArgs)
119
+ }
120
+
121
+ s.updateMeta({args, modelId, modelVariableName, queryParams})
122
+
123
+ useMemo(
124
+ () => { loadModel() },
125
+ cacheArgs
126
+ )
127
+
128
+ useLayoutEffect(() => {
129
+ let reloadModelCallback
130
+
131
+ if (args.events) {
132
+ reloadModelCallback = args.events.addListener("reloadModel", loadModel)
133
+ }
134
+
135
+ return () => {
136
+ if (reloadModelCallback) {
137
+ args.events.removeListener("reloadModel", loadModel)
138
+ }
139
+ }
140
+ }, [args.events])
141
+
142
+ useLayoutEffect(() => {
143
+ let connectUpdated
144
+
145
+ if (s.s.model && args.eventUpdated) {
146
+ connectUpdated = ModelEvents.connectUpdated(s.s.model, loadModel)
147
+ }
148
+
149
+ return () => {
150
+ connectUpdated?.unsubscribe()
151
+ }
152
+ }, [args.eventUpdated, s.s.model?.id()])
153
+
154
+ useLayoutEffect(() => {
155
+ Devise.events().addListener("onDeviseSignIn", onSignedIn)
156
+ Devise.events().addListener("onDeviseSignOut", onSignedOut)
157
+
158
+ return () => {
159
+ Devise.events().removeListener("onDeviseSignIn", onSignedIn)
160
+ Devise.events().removeListener("onDeviseSignOut", onSignedOut)
161
+ }
162
+ })
163
+
164
+ useLayoutEffect(() => {
165
+ let connectDestroyed
166
+
167
+ if (s.s.model && args.onDestroyed) {
168
+ connectDestroyed = ModelEvents.connectDestroyed(s.s.model, onDestroyed)
169
+ }
170
+
171
+ return () => {
172
+ connectDestroyed?.unsubscribe()
173
+ }
174
+ }, [args.onDestroyed, s.s.model?.id()])
175
+
176
+ const result = {
177
+ model: s.s.model,
178
+ modelId,
179
+ notFound: s.s.notFound
180
+ }
181
+
182
+ result[modelVariableName] = s.s.model
183
+ result[`${modelVariableName}Id`] = modelId
184
+ result[`${modelVariableName}NotFound`] = s.s.notFound
185
+
186
+ return result
187
+ }
188
+
189
+ export default useModel
@@ -0,0 +1,24 @@
1
+ import {useCallback, useLayoutEffect, useMemo} from "react"
2
+ import useShape from "set-state-compare/src/use-shape"
3
+
4
+ const useResizeObserver = (element, callback) => {
5
+ const s = useShape({callback})
6
+ const onResize = useCallback((...args) => {
7
+ s.p.callback(...args)
8
+ }, [])
9
+ const observer = useMemo(() => new ResizeObserver(onResize), [])
10
+
11
+ useLayoutEffect(() => {
12
+ if (element) {
13
+ observer.observe(element)
14
+ }
15
+
16
+ return () => {
17
+ if (element) {
18
+ observer.disconnect()
19
+ }
20
+ }
21
+ }, [element])
22
+ }
23
+
24
+ export default useResizeObserver
@@ -0,0 +1,128 @@
1
+ import config from "./config"
2
+ import escapeStringRegexp from "escape-string-regexp"
3
+ import * as inflection from "inflection"
4
+ import PropTypes from "prop-types"
5
+ import propTypesExact from "prop-types-exact"
6
+ import {useCallback, useMemo} from "react"
7
+ import useShape from "set-state-compare/src/use-shape"
8
+
9
+ const useRouterPropTypes = propTypesExact({
10
+ locales: PropTypes.array.isRequired,
11
+ path: PropTypes.string,
12
+ routeDefinitions: PropTypes.object.isRequired,
13
+ routes: PropTypes.object.isRequired
14
+ })
15
+
16
+ const useRouter = (props) => {
17
+ PropTypes.checkPropTypes(useRouterPropTypes, props, "prop", "useRouter")
18
+
19
+ const s = useShape(props)
20
+
21
+ const findRouteParams = useCallback((routeDefinition) => {
22
+ const result = []
23
+ const parts = routeDefinition.path.split("/")
24
+
25
+ for (const part of parts) {
26
+ if (part.match(/^:([a-z_]+)$/))
27
+ result.push(part)
28
+ }
29
+
30
+ return result
31
+ }, [])
32
+
33
+ const getPath = useCallback(() => {
34
+ let path = s.p.path || window.location.pathname
35
+
36
+ path = path.replace(/[/]+$/, "")
37
+
38
+ return path
39
+ }, [])
40
+
41
+ const getRouteDefinitions = useCallback(() => s.p.routeDefinitions || config.getRouteDefinitions(), [])
42
+ const getRoutes = useCallback(() => s.p.routes || config.getRoutes(), [])
43
+
44
+ const parseRouteDefinitions = useCallback(() => {
45
+ const routeDefinitions = getRouteDefinitions()
46
+ const routes = getRoutes()
47
+ const regex = /:([A-z\d_]+)/
48
+ const parsedRouteDefinitions = []
49
+
50
+ for (const locale of s.p.locales) {
51
+ for (const routeDefinition of routeDefinitions.routes) {
52
+ const routePathName = `${inflection.camelize(routeDefinition.name, true)}Path`
53
+ const params = findRouteParams(routeDefinition)
54
+
55
+ params.push({locale})
56
+
57
+ if (!(routePathName in routes))
58
+ throw new Error(`${routePathName} not found in routes: ${Object.keys(routes, ", ")}`)
59
+
60
+ const routePath = routes[routePathName](...params).replace(/[/]+$/, "")
61
+ const groups = []
62
+ let pathRegexString = "^"
63
+
64
+ pathRegexString += escapeStringRegexp(routePath)
65
+
66
+ while (true) {
67
+ const match = pathRegexString.match(regex)
68
+
69
+ if (!match) break
70
+
71
+ const variableName = match[1]
72
+
73
+ groups.push(variableName)
74
+
75
+ pathRegexString = pathRegexString.replace(match[0], "([^/]+)")
76
+ }
77
+
78
+ pathRegexString += "$"
79
+
80
+ const pathRegex = new RegExp(pathRegexString)
81
+
82
+ parsedRouteDefinitions.push({groups, pathRegex, routeDefinition})
83
+ }
84
+ }
85
+
86
+ return parsedRouteDefinitions
87
+ }, [])
88
+
89
+ const parsedRouteDefinitions = useMemo(() => parseRouteDefinitions(), [])
90
+
91
+ s.updateMeta({parsedRouteDefinitions})
92
+
93
+ const findMatchingRoute = useCallback(() => {
94
+ const path = getPath()
95
+
96
+ for (const parsedRouteDefinition of s.m.parsedRouteDefinitions) {
97
+ const match = path.match(parsedRouteDefinition.pathRegex)
98
+ let matched, params
99
+
100
+ if (match) {
101
+ matched = true
102
+ params = {}
103
+
104
+ for (const groupKey in parsedRouteDefinition.groups) {
105
+ const groupName = parsedRouteDefinition.groups[groupKey]
106
+
107
+ params[groupName] = match[Number(groupKey) + 1]
108
+ }
109
+ }
110
+
111
+ if (path == "" && parsedRouteDefinition.routeDefinition.path == "/") matched = true
112
+ if (matched) {
113
+ return {params, parsedRouteDefinition}
114
+ }
115
+ }
116
+ }, [])
117
+
118
+ const matchingRoute = findMatchingRoute()
119
+ const params = matchingRoute?.params || {}
120
+ const match = {
121
+ matchingRoute,
122
+ params
123
+ }
124
+
125
+ return {match}
126
+ }
127
+
128
+ export default useRouter
@@ -0,0 +1,49 @@
1
+ import {Platform, useWindowDimensions} from "react-native"
2
+
3
+ const getWindowLayout = (width) => {
4
+ if (width <= 575) {
5
+ return "xs"
6
+ } else if (width <= 767) {
7
+ return "sm"
8
+ } else if (width <= 991) {
9
+ return "md"
10
+ } else if (width <= 1199) {
11
+ return "lg"
12
+ } else if (width <= 1399) {
13
+ return "xl"
14
+ } else if (width >= 1400) {
15
+ return "xxl"
16
+ } else {
17
+ console.error(`Couldn't determine window layout from width: ${width}`)
18
+ }
19
+ }
20
+
21
+ const useScreenLayout = () => {
22
+ if (Platform.OS == "web") {
23
+ const shared = useMemo(() => ({}))
24
+
25
+ shared.width = window.innerWidth
26
+
27
+ const [screenLayout, setScreenLayout] = useState(() => getWindowLayout(shared.width))
28
+
29
+ const onResize = useCallback(() => {
30
+ const newWindowLayout = getWindowLayout(window.innerWidth)
31
+
32
+ if (shared.screenlayout != newWindowLayout) {
33
+ setScreenLayout(newWindowLayout)
34
+ }
35
+ }, [])
36
+
37
+ useEventListener(window, "resize", onResize)
38
+
39
+ shared.screenLayout = screenLayout
40
+
41
+ return shared.screenLayout
42
+ } else {
43
+ const windowDimensions = useWindowDimensions()
44
+
45
+ return getWindowLayout(windowDimensions.width)
46
+ }
47
+ }
48
+
49
+ export default useScreenLayout
@@ -0,0 +1,60 @@
1
+ import {useCallback, useLayoutEffect, useMemo} from "react"
2
+ import debounceFunction from "debounce"
3
+ import ModelEvents from "./model-events"
4
+ import useShape from "set-state-compare/src/use-shape"
5
+
6
+ const apiMakerUseUpdatedEvent = (model, onUpdated, props = {}) => {
7
+ const {active = true, debounce, onConnected, ...restProps} = props
8
+
9
+ if (Object.keys(restProps).length > 0) {
10
+ throw new Error(`Unknown props given to useUpdatedEvent: ${Object.keys(restProps).join(", ")}`)
11
+ }
12
+
13
+ const s = useShape({active, debounce, model, onUpdated})
14
+
15
+ const debounceCallback = useMemo(() => {
16
+ if (typeof debounce == "number") {
17
+ return debounceFunction(s.p.onUpdated, debounce)
18
+ } else {
19
+ return debounceFunction(s.p.onUpdated)
20
+ }
21
+ }, [debounce])
22
+
23
+ s.updateMeta({debounceCallback})
24
+
25
+ const onUpdatedCallback = useCallback((...args) => {
26
+ if (!s.p.active) {
27
+ return
28
+ }
29
+
30
+ if (s.p.debounce) {
31
+ s.m.debounceCallback(...args)
32
+ } else {
33
+ s.p.onUpdated(...args)
34
+ }
35
+ }, [])
36
+
37
+ useLayoutEffect(() => {
38
+ let connectUpdated, onConnectedListener
39
+
40
+ if (model) {
41
+ connectUpdated = ModelEvents.connectUpdated(model, onUpdatedCallback)
42
+
43
+ if (onConnected) {
44
+ onConnectedListener = connectUpdated.events.addListener("connected", onConnected)
45
+ }
46
+ }
47
+
48
+ return () => {
49
+ if (onConnectedListener) {
50
+ connectUpdated.events.removeListener("connected", onConnected)
51
+ }
52
+
53
+ if (connectUpdated) {
54
+ connectUpdated.unsubscribe()
55
+ }
56
+ }
57
+ }, [model?.id()])
58
+ }
59
+
60
+ export default apiMakerUseUpdatedEvent
@@ -0,0 +1,33 @@
1
+ import events from "./events"
2
+ import {useCallback} from "react"
3
+ import useEventEmitter from "./use-event-emitter"
4
+ import useShape from "set-state-compare/src/use-shape"
5
+
6
+ const useValidationErrors = (callback) => {
7
+ const s = useShape({callback})
8
+
9
+ s.useStates({validationErrors: []})
10
+
11
+ const onValidationErrors = useCallback((validationErrors) => {
12
+ const matchedValidationErrors = []
13
+
14
+ for (const validationError of validationErrors.getValidationErrors()) {
15
+ if (s.p.callback(validationError)) {
16
+ validationError.setHandled()
17
+ matchedValidationErrors.push(validationError)
18
+ }
19
+ }
20
+
21
+ s.set({
22
+ validationErrors: matchedValidationErrors
23
+ })
24
+ }, [])
25
+
26
+ useEventEmitter(events, "onValidationErrors", onValidationErrors)
27
+
28
+ return {
29
+ validationErrors: s.s.validationErrors
30
+ }
31
+ }
32
+
33
+ export default useValidationErrors
@@ -0,0 +1,49 @@
1
+ import BaseComponent from "../base-component"
2
+ import memo from "set-state-compare/src/memo"
3
+ import PropTypes from "prop-types"
4
+ import propTypesExact from "prop-types-exact"
5
+ import {shapeComponent} from "set-state-compare/src/shape-component"
6
+ import Text from "./text"
7
+
8
+ export default memo(shapeComponent(class ApiMakerUtilsCard extends BaseComponent {
9
+ static propTypes = propTypesExact({
10
+ children: PropTypes.node,
11
+ controls: PropTypes.node,
12
+ dataSet: PropTypes.object,
13
+ header: PropTypes.string,
14
+ style: PropTypes.object
15
+ })
16
+
17
+ render() {
18
+ const {children, controls, dataSet, header, style} = this.props
19
+ const {component, ...restDataSet} = dataSet || {}
20
+ const actualDataSet = Object.assign(
21
+ {component: classNames("api-maker/utils/card", component)},
22
+ restDataSet
23
+ )
24
+ const actualStyle = Object.assign(
25
+ {
26
+ backgroundColor: "#fff",
27
+ borderRadius: 15,
28
+ padding: 30
29
+ },
30
+ style
31
+ )
32
+
33
+ return (
34
+ <View dataSet={actualDataSet} style={actualStyle}>
35
+ {controls &&
36
+ <View style={{position: "absolute", top: 15, right: 15}}>
37
+ {controls}
38
+ </View>
39
+ }
40
+ {header &&
41
+ <Text style={{fontSize: 24}}>
42
+ {header}
43
+ </Text>
44
+ }
45
+ {children}
46
+ </View>
47
+ )
48
+ }
49
+ }))
@@ -0,0 +1,80 @@
1
+ import BaseComponent from "../base-component"
2
+ import {CheckBox, Pressable, View} from "react-native"
3
+ import memo from "set-state-compare/src/memo"
4
+ import PropTypes from "prop-types"
5
+ import propTypesExact from "prop-types-exact"
6
+ import React from "react"
7
+ import {shapeComponent} from "set-state-compare/src/shape-component"
8
+ import Text from "./text"
9
+
10
+ export default memo(shapeComponent(class ApiMakerUtilsCheckbox extends BaseComponent {
11
+ static defaultProps = {
12
+ label: undefined
13
+ }
14
+
15
+ static propTypes = propTypesExact({
16
+ checked: PropTypes.bool,
17
+ dataSet: PropTypes.object,
18
+ defaultChecked: PropTypes.bool,
19
+ label: PropTypes.string,
20
+ onCheckedChange: PropTypes.func,
21
+ style: PropTypes.object
22
+ })
23
+
24
+ setup() {
25
+ this.useStates({
26
+ checked: this.props.defaultChecked
27
+ })
28
+ this.isChecked = this.calculateChecked()
29
+ }
30
+
31
+ calculateChecked() {
32
+ if ("checked" in this.props) {
33
+ return this.p.checked
34
+ } else {
35
+ return this.s.checked
36
+ }
37
+ }
38
+
39
+ render() {
40
+ const {isChecked} = this.tt
41
+ const {label} = this.p
42
+ const {dataSet} = this.props
43
+ const actualStyle = Object.assign(
44
+ {flexDirection: "row", alignItems: "center"},
45
+ this.props.style
46
+ )
47
+ const actualDataSet = Object.assign(
48
+ {
49
+ checked: isChecked
50
+ },
51
+ dataSet
52
+ )
53
+
54
+ return (
55
+ <View
56
+ dataSet={{component: "api-maker/utils/checkbox"}}
57
+ style={actualStyle}
58
+ >
59
+ <CheckBox dataSet={actualDataSet} onValueChange={this.tt.onValueChange} value={isChecked} />
60
+ {label &&
61
+ <Pressable onPress={this.tt.onLabelPressed}>
62
+ <Text style={{marginLeft: 3}}>
63
+ {label}
64
+ </Text>
65
+ </Pressable>
66
+ }
67
+ </View>
68
+ )
69
+ }
70
+
71
+ onLabelPressed = () => this.p.onCheckedChange(!this.tt.isChecked)
72
+
73
+ onValueChange = (e) => {
74
+ if (this.props.onCheckedChange) {
75
+ this.p.onCheckedChange(e)
76
+ }
77
+
78
+ this.setState({checked: !this.tt.isChecked})
79
+ }
80
+ }))