@strapi/admin 4.15.0-alpha.0 → 4.15.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 (472) hide show
  1. package/.eslintrc.js +4 -1
  2. package/admin/.eslintrc.js +28 -0
  3. package/admin/custom.d.ts +28 -0
  4. package/admin/src/StrapiApp.js +27 -28
  5. package/admin/src/components/AuthenticatedApp.tsx +187 -0
  6. package/admin/src/components/ConfigurationProvider.tsx +68 -0
  7. package/admin/src/components/{DragLayer/DragLayer.js → DragLayer.tsx} +18 -10
  8. package/admin/src/components/GuidedTour/Homepage.tsx +111 -0
  9. package/admin/src/components/GuidedTour/Modal.tsx +303 -0
  10. package/admin/src/components/GuidedTour/Ornaments.tsx +74 -0
  11. package/admin/src/components/GuidedTour/Provider.tsx +253 -0
  12. package/admin/src/components/GuidedTour/{layout.js → constants.ts} +13 -3
  13. package/admin/src/components/LanguageProvider.tsx +130 -0
  14. package/admin/src/components/{LeftMenu/index.js → LeftMenu.tsx} +23 -18
  15. package/admin/src/components/{NpsSurvey/index.js → NpsSurvey.tsx} +68 -21
  16. package/admin/src/components/PluginsInitializer.tsx +124 -0
  17. package/admin/src/components/PrivateRoute.tsx +42 -0
  18. package/admin/src/components/Providers.tsx +125 -0
  19. package/admin/src/components/RBACProvider.tsx +124 -0
  20. package/admin/src/components/Theme.tsx +41 -0
  21. package/admin/src/components/ThemeToggleProvider.tsx +64 -0
  22. package/admin/src/components/{UnauthenticatedLogo/index.js → UnauthenticatedLogo.tsx} +3 -5
  23. package/admin/src/components/{LocalesProvider/__mocks__/useLocalesProvider.js → __mocks__/LanguageProvider.ts} +3 -1
  24. package/admin/src/{constants.js → constants.ts} +48 -0
  25. package/admin/src/content-manager/components/BlocksEditor/BlocksInput/index.js +68 -9
  26. package/admin/src/content-manager/components/BlocksEditor/Toolbar/index.js +433 -202
  27. package/admin/src/content-manager/components/BlocksEditor/hooks/useBlocksStore.js +463 -135
  28. package/admin/src/content-manager/components/BlocksEditor/hooks/useModifiersStore.js +23 -6
  29. package/admin/src/content-manager/components/BlocksEditor/index.js +97 -20
  30. package/admin/src/content-manager/components/BlocksEditor/plugins/index.js +4 -0
  31. package/admin/src/content-manager/components/BlocksEditor/plugins/withLinks.js +61 -0
  32. package/admin/src/content-manager/components/BlocksEditor/plugins/withStrapiSchema.js +33 -0
  33. package/admin/src/content-manager/components/BlocksEditor/utils/links.js +90 -0
  34. package/admin/src/content-manager/components/InputUID/index.js +1 -1
  35. package/admin/src/content-manager/hooks/useAllowedAttributes.js +9 -1
  36. package/admin/src/content-manager/pages/App/selectors.js +1 -1
  37. package/admin/src/content-manager/pages/App/useContentManagerInitData.js +3 -1
  38. package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -0
  39. package/admin/src/content-manager/pages/EditSettingsView/utils/createPossibleMainFieldsForModelsAndComponents.js +1 -0
  40. package/admin/src/content-manager/pages/EditView/selectors.js +1 -1
  41. package/admin/src/content-manager/pages/EditViewLayoutManager/index.js +3 -1
  42. package/admin/src/content-manager/pages/ListSettingsView/constants.js +1 -0
  43. package/admin/src/content-manager/pages/ListView/components/Body/index.js +53 -56
  44. package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +5 -3
  45. package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
  46. package/admin/src/content-manager/pages/ListView/index.js +35 -51
  47. package/admin/src/content-manager/pages/ListView/selectors.js +1 -1
  48. package/admin/src/content-manager/utils/checkIfAttributeIsDisplayable.js +1 -1
  49. package/admin/src/content-manager/utils/schema.js +2 -2
  50. package/admin/src/contexts/admin.ts +19 -0
  51. package/admin/src/contexts/apiTokenPermissions.tsx +64 -0
  52. package/admin/src/contexts/configuration.ts +25 -0
  53. package/admin/src/contexts/themeToggle.ts +18 -0
  54. package/admin/src/core/store/configure.ts +91 -0
  55. package/admin/src/core/store/hooks.ts +15 -0
  56. package/admin/src/hooks/{useConfigurations/__mocks__/index.js → __mocks__/useConfigurations.ts} +4 -2
  57. package/admin/src/hooks/index.js +0 -8
  58. package/admin/src/hooks/{useAdminRoles/index.js → useAdminRoles.ts} +26 -10
  59. package/admin/src/hooks/useAdminUsers.ts +64 -0
  60. package/admin/src/hooks/useConfiguration.ts +5 -0
  61. package/admin/src/hooks/{useContentTypes/useContentTypes.js → useContentTypes.ts} +39 -16
  62. package/admin/src/hooks/useDebounce.ts +17 -0
  63. package/admin/src/hooks/{useEnterprise/useEnterprise.js → useEnterprise.ts} +15 -5
  64. package/admin/src/hooks/useLicenseLimitNotification.ts +3 -0
  65. package/admin/src/hooks/useMenu.ts +153 -0
  66. package/admin/src/hooks/useSettingsForm/index.js +14 -2
  67. package/admin/src/hooks/useSettingsMenu/constants.js +39 -0
  68. package/admin/src/hooks/useThemeToggle.ts +9 -0
  69. package/admin/src/index.js +7 -6
  70. package/admin/src/layouts/{AppLayout/index.js → AppLayout.tsx} +7 -10
  71. package/admin/src/layouts/UnauthenticatedLayout.tsx +77 -0
  72. package/admin/src/pages/Admin/index.js +15 -8
  73. package/admin/src/pages/App/index.js +13 -8
  74. package/admin/src/pages/App/selectors.js +1 -1
  75. package/admin/src/pages/AuthPage/components/ForgotPassword/index.js +3 -2
  76. package/admin/src/pages/AuthPage/components/ForgotPasswordSuccess/index.js +3 -2
  77. package/admin/src/pages/AuthPage/components/Login/BaseLogin.js +1 -1
  78. package/admin/src/pages/AuthPage/components/Login/index.js +1 -1
  79. package/admin/src/pages/AuthPage/components/Oops/index.js +3 -2
  80. package/admin/src/pages/AuthPage/components/Register/index.js +30 -35
  81. package/admin/src/pages/AuthPage/components/ResetPassword/index.js +3 -2
  82. package/admin/src/pages/AuthPage/index.js +4 -5
  83. package/admin/src/pages/HomePage/index.js +6 -3
  84. package/admin/src/pages/{InternalErrorPage/index.js → InternalErrorPage.tsx} +10 -6
  85. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/index.js +0 -2
  86. package/admin/src/pages/MarketplacePage/hooks/__mocks__/useNavigatorOnline.ts +1 -0
  87. package/admin/src/{hooks/useNavigatorOnLine/index.js → pages/MarketplacePage/hooks/useNavigatorOnline.ts} +4 -6
  88. package/admin/src/pages/MarketplacePage/index.js +3 -3
  89. package/admin/src/pages/{NotFoundPage/index.js → NotFoundPage.tsx} +9 -7
  90. package/admin/src/pages/ProfilePage/components/Preferences/index.js +23 -9
  91. package/admin/src/pages/ProfilePage/index.js +4 -4
  92. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +20 -0
  93. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +1 -1
  94. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +119 -87
  95. package/admin/src/pages/SettingsPage/constants.js +33 -0
  96. package/admin/src/{hooks/useRegenerate/index.js → pages/SettingsPage/hooks/useRegenerate.ts} +13 -7
  97. package/admin/src/pages/SettingsPage/index.js +2 -2
  98. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +1 -1
  99. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +1 -1
  100. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +1 -1
  101. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +1 -1
  102. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -2
  103. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/CustomizationInfos/index.js +2 -2
  104. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +2 -2
  105. package/admin/src/pages/SettingsPage/pages/AuditLogs/SalesPage.js +50 -0
  106. package/admin/src/pages/SettingsPage/pages/ReviewWorkflows/SalesPage.js +53 -0
  107. package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +1 -1
  108. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +1 -1
  109. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +1 -1
  110. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/index.js +1 -1
  111. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/index.js +1 -1
  112. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/index.js +1 -1
  113. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PermissionsDataManagerProvider/index.js +1 -1
  114. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/index.js +1 -1
  115. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/hooks/usePermissionsDataManager.ts +28 -0
  116. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +1 -1
  117. package/admin/src/{hooks/useAdminRolePermissions/index.js → pages/SettingsPage/pages/Roles/hooks/useAdminRolePermissions.ts} +13 -6
  118. package/admin/src/pages/SettingsPage/pages/SingleSignOn/SalesPage.js +53 -0
  119. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
  120. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +3 -5
  121. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -1
  122. package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
  123. package/admin/src/pages/{UseCasePage/index.js → UseCasePage.tsx} +10 -12
  124. package/admin/src/shared/hooks/index.js +0 -1
  125. package/admin/src/shared/hooks/useInjectionZone/index.js +2 -2
  126. package/admin/src/translations/en.json +13 -0
  127. package/admin/src/types/adminAPI.ts +29 -0
  128. package/admin/src/utils/createRoute.tsx +54 -0
  129. package/admin/src/utils/formatAPIErrors.ts +18 -0
  130. package/admin/src/utils/getFullName.ts +3 -0
  131. package/admin/src/utils/{uniqueAdminHash.js → hashAdminUserEmail.ts} +6 -3
  132. package/admin/src/utils/makeUniqueRoutes.ts +11 -0
  133. package/admin/tsconfig.build.json +4 -0
  134. package/admin/tsconfig.json +11 -0
  135. package/build/0cd5f8915b265d5b1856.png +0 -0
  136. package/build/1049.ecc10c97.chunk.js +1 -0
  137. package/build/1217.96155682.chunk.js +35 -0
  138. package/build/1227.947ceaf9.chunk.js +1 -0
  139. package/build/1306.2699df52.chunk.js +79 -0
  140. package/build/135.ad267b59.chunk.js +1 -0
  141. package/build/1386.eabd8a1e.chunk.js +7 -0
  142. package/build/1727.b49f0713.chunk.js +1 -0
  143. package/build/1835.eaa696ba.chunk.js +1 -0
  144. package/build/19eb2dfcf2603eb55733.png +0 -0
  145. package/build/2325.d705b39a.chunk.js +1 -0
  146. package/build/2379.7ce8e110.chunk.js +1 -0
  147. package/build/2395.acb961a8.chunk.js +26 -0
  148. package/build/2421.79e5b3d0.chunk.js +1 -0
  149. package/build/267.073a3bcb.chunk.js +1 -0
  150. package/build/27d16aefee06412db90a.png +0 -0
  151. package/build/2801.4711ea5a.chunk.js +1 -0
  152. package/build/2878.145ebf7c.chunk.js +1 -0
  153. package/build/2950.216f2e89.chunk.js +1 -0
  154. package/build/2953.284a63c0.chunk.js +1 -0
  155. package/build/3019.fde2e1be.chunk.js +181 -0
  156. package/build/3100.2ba4df95.chunk.js +1 -0
  157. package/build/311.cb0884bb.chunk.js +1 -0
  158. package/build/3460.8644e608.chunk.js +146 -0
  159. package/build/3483.db8c1520.chunk.js +1 -0
  160. package/build/3911.488fbde3.chunk.js +95 -0
  161. package/build/4174.49cedb6a.chunk.js +1 -0
  162. package/build/4429.7f044dc7.chunk.js +1 -0
  163. package/build/4555.c883d697.chunk.js +1 -0
  164. package/build/4663.b906cc10.chunk.js +1 -0
  165. package/build/4732.149f5f8f.chunk.js +1 -0
  166. package/build/4916.480053a6.chunk.js +1 -0
  167. package/build/4996.d285c30b.chunk.js +1 -0
  168. package/build/502.f536f78b.chunk.js +1 -0
  169. package/build/570.2f3b4c56.chunk.js +1 -0
  170. package/build/5858.493b31ec.chunk.js +1 -0
  171. package/build/6158.c3c13c20.chunk.js +1 -0
  172. package/build/6345.334e7678.chunk.js +1 -0
  173. package/build/6453.4160b5b7.chunk.js +1 -0
  174. package/build/7030.b98dcedf.chunk.js +1 -0
  175. package/build/70674f63fc3904c20de0.svg +7 -0
  176. package/build/7448.6fd14dd3.chunk.js +1 -0
  177. package/build/7464.579564ac.chunk.js +1 -0
  178. package/build/7735.9e7c9fdd.chunk.js +10 -0
  179. package/build/78.dcc6df5c.chunk.js +1 -0
  180. package/build/7811.fdbe09af.chunk.js +103 -0
  181. package/build/782.7243b183.chunk.js +1 -0
  182. package/build/7849.2a500ed8.chunk.js +1 -0
  183. package/build/7897.63ba0a00.chunk.js +6 -0
  184. package/build/7e9af4fb7e723fcebf1f.svg +48 -0
  185. package/build/8162.7d1100a0.chunk.js +1 -0
  186. package/build/8276.9abe4679.chunk.js +26 -0
  187. package/build/8773.ee67141c.chunk.js +48 -0
  188. package/build/8980.f0045cc1.chunk.js +1 -0
  189. package/build/9077.2cc01ac8.chunk.js +105 -0
  190. package/build/9153.42c1428a.chunk.js +1 -0
  191. package/build/918.54414509.chunk.js +1 -0
  192. package/build/9218.b2d367f8.chunk.js +1 -0
  193. package/build/9285.5f174057.chunk.js +1 -0
  194. package/build/9547.62987774.chunk.js +1 -0
  195. package/build/9754.b4e73779.chunk.js +1 -0
  196. package/build/9d5d788027e86620c234.svg +5 -0
  197. package/build/Admin-authenticatedApp.059dc48f.chunk.js +79 -0
  198. package/build/Admin_InternalErrorPage.06eeef20.chunk.js +1 -0
  199. package/build/Admin_homePage.56b9eb3f.chunk.js +81 -0
  200. package/build/Admin_marketplace.d693a435.chunk.js +44 -0
  201. package/build/Admin_pluginsPage.ae2c872a.chunk.js +6 -0
  202. package/build/Admin_profilePage.89099d5b.chunk.js +13 -0
  203. package/build/Admin_settingsPage.88c45586.chunk.js +12 -0
  204. package/build/Upload_ConfigureTheView.44f28145.chunk.js +1 -0
  205. package/build/admin-app.990e112f.chunk.js +69 -0
  206. package/build/admin-edit-roles-page.4e1eb4a9.chunk.js +267 -0
  207. package/build/admin-edit-users.5b91404e.chunk.js +10 -0
  208. package/build/admin-roles-list.89dd94fe.chunk.js +22 -0
  209. package/build/admin-users.7be4fc5f.chunk.js +11 -0
  210. package/build/api-tokens-create-page.571920e5.chunk.js +1 -0
  211. package/build/api-tokens-edit-page.cbdc81b1.chunk.js +1 -0
  212. package/build/api-tokens-list-page.de0c49e8.chunk.js +16 -0
  213. package/build/ar-json.74e40bc7.chunk.js +1 -0
  214. package/build/audit-logs-sales-page.2955db88.chunk.js +1 -0
  215. package/build/audit-logs-settings-page.b0cb5164.chunk.js +1 -0
  216. package/build/bb3108f7fd1e6179bde1.svg +1 -0
  217. package/build/bb4d0d527bdfb161bc5a.svg +1 -0
  218. package/build/ca-json.fc6001d3.chunk.js +1 -0
  219. package/build/content-manager.de7ae330.chunk.js +1241 -0
  220. package/build/content-type-builder-list-view.6c8d3213.chunk.js +211 -0
  221. package/build/content-type-builder-translation-ar-json.3e808e2f.chunk.js +1 -0
  222. package/build/content-type-builder-translation-cs-json.1ef9e106.chunk.js +1 -0
  223. package/build/content-type-builder-translation-de-json.63fcff7b.chunk.js +1 -0
  224. package/build/content-type-builder-translation-dk-json.fd626b67.chunk.js +1 -0
  225. package/build/content-type-builder-translation-en-json.74d80f18.chunk.js +1 -0
  226. package/build/content-type-builder-translation-es-json.a4a361a9.chunk.js +1 -0
  227. package/build/content-type-builder-translation-fr-json.499c3a46.chunk.js +1 -0
  228. package/build/content-type-builder-translation-id-json.65255f93.chunk.js +1 -0
  229. package/build/content-type-builder-translation-it-json.e268ab74.chunk.js +1 -0
  230. package/build/content-type-builder-translation-ja-json.9be0d5b2.chunk.js +1 -0
  231. package/build/content-type-builder-translation-ko-json.04cb309d.chunk.js +1 -0
  232. package/build/content-type-builder-translation-ms-json.f6b743b9.chunk.js +1 -0
  233. package/build/content-type-builder-translation-nl-json.997fe8cc.chunk.js +1 -0
  234. package/build/content-type-builder-translation-pl-json.634f638b.chunk.js +1 -0
  235. package/build/content-type-builder-translation-pt-BR-json.6a95dc71.chunk.js +1 -0
  236. package/build/content-type-builder-translation-pt-json.ddb44f8c.chunk.js +1 -0
  237. package/build/content-type-builder-translation-ru-json.3af65503.chunk.js +1 -0
  238. package/build/content-type-builder-translation-sk-json.c6078082.chunk.js +1 -0
  239. package/build/content-type-builder-translation-sv-json.a6df2462.chunk.js +1 -0
  240. package/build/content-type-builder-translation-th-json.122277cc.chunk.js +1 -0
  241. package/build/content-type-builder-translation-tr-json.41f44f77.chunk.js +1 -0
  242. package/build/content-type-builder-translation-uk-json.e1315acd.chunk.js +1 -0
  243. package/build/content-type-builder-translation-zh-Hans-json.6ff57db6.chunk.js +1 -0
  244. package/build/content-type-builder-translation-zh-json.3532b962.chunk.js +1 -0
  245. package/build/content-type-builder.0bc97051.chunk.js +136 -0
  246. package/build/cs-json.4b44411c.chunk.js +1 -0
  247. package/build/de-json.e72545cf.chunk.js +1 -0
  248. package/build/dk-json.e77140ef.chunk.js +1 -0
  249. package/build/email-settings-page.07712efc.chunk.js +11 -0
  250. package/build/en-json.5b907f67.chunk.js +1 -0
  251. package/build/es-json.b1f2284b.chunk.js +1 -0
  252. package/build/eu-json.63d0a898.chunk.js +1 -0
  253. package/build/fr-json.33c6428b.chunk.js +1 -0
  254. package/build/gu-json.7efe8cc2.chunk.js +1 -0
  255. package/build/he-json.3cf0b48a.chunk.js +1 -0
  256. package/build/hi-json.0d633692.chunk.js +1 -0
  257. package/build/highlight.js.28a1547e.chunk.js +85 -0
  258. package/build/hu-json.c74b6a1e.chunk.js +1 -0
  259. package/build/i18n-settings-page.5c34f012.chunk.js +9 -0
  260. package/build/i18n-translation-de-json.362384a6.chunk.js +1 -0
  261. package/build/i18n-translation-dk-json.89401417.chunk.js +1 -0
  262. package/build/i18n-translation-en-json.1ec7becf.chunk.js +1 -0
  263. package/build/i18n-translation-es-json.87b494d1.chunk.js +1 -0
  264. package/build/i18n-translation-fr-json.57ddc77e.chunk.js +1 -0
  265. package/build/i18n-translation-ko-json.ef4f9471.chunk.js +1 -0
  266. package/build/i18n-translation-pl-json.dfac513d.chunk.js +1 -0
  267. package/build/i18n-translation-ru-json.a3dbc125.chunk.js +1 -0
  268. package/build/i18n-translation-tr-json.3bfc812f.chunk.js +1 -0
  269. package/build/i18n-translation-zh-Hans-json.757ce62d.chunk.js +1 -0
  270. package/build/i18n-translation-zh-json.bef2dc07.chunk.js +1 -0
  271. package/build/id-json.41e07c46.chunk.js +1 -0
  272. package/build/index.html +1 -0
  273. package/build/it-json.bfe27ed8.chunk.js +1 -0
  274. package/build/ja-json.e1959a1c.chunk.js +1 -0
  275. package/build/ko-json.ce5d6d94.chunk.js +1 -0
  276. package/build/main.f84563f1.js +2665 -0
  277. package/build/ml-json.940d7ace.chunk.js +1 -0
  278. package/build/ms-json.0eddffd9.chunk.js +1 -0
  279. package/build/nl-json.fe38f0fb.chunk.js +1 -0
  280. package/build/no-json.19a2dbfa.chunk.js +1 -0
  281. package/build/pl-json.d55e8e78.chunk.js +1 -0
  282. package/build/pt-BR-json.ae0a0d2e.chunk.js +1 -0
  283. package/build/pt-json.ee554a41.chunk.js +1 -0
  284. package/build/review-workflows-sales-page.f46a8f00.chunk.js +1 -0
  285. package/build/review-workflows-settings-create-view.d0544fb0.chunk.js +1 -0
  286. package/build/review-workflows-settings-edit-view.aabf49ef.chunk.js +1 -0
  287. package/build/review-workflows-settings-list-view.8b0525ab.chunk.js +56 -0
  288. package/build/ru-json.1c976644.chunk.js +1 -0
  289. package/build/runtime~main.270fd45f.js +2 -0
  290. package/build/sa-json.2c03ef4e.chunk.js +1 -0
  291. package/build/sk-json.b41847e8.chunk.js +1 -0
  292. package/build/sso-sales-page.ef22e469.chunk.js +1 -0
  293. package/build/sso-settings-page.21e16ae4.chunk.js +1 -0
  294. package/build/sv-json.568cb7ae.chunk.js +1 -0
  295. package/build/th-json.5f659396.chunk.js +1 -0
  296. package/build/tr-json.c9f22432.chunk.js +1 -0
  297. package/build/transfer-tokens-create-page.3366204d.chunk.js +1 -0
  298. package/build/transfer-tokens-edit-page.15cf0f73.chunk.js +1 -0
  299. package/build/transfer-tokens-list-page.0bc0e682.chunk.js +16 -0
  300. package/build/uk-json.b7e38370.chunk.js +1 -0
  301. package/build/upload-settings.1319dca0.chunk.js +14 -0
  302. package/build/upload-translation-ca-json.57954414.chunk.js +1 -0
  303. package/build/upload-translation-de-json.420c943b.chunk.js +1 -0
  304. package/build/upload-translation-dk-json.bbb2fa05.chunk.js +1 -0
  305. package/build/upload-translation-en-json.8b7573ce.chunk.js +1 -0
  306. package/build/upload-translation-es-json.ba2eb03a.chunk.js +1 -0
  307. package/build/upload-translation-fr-json.baab9911.chunk.js +1 -0
  308. package/build/upload-translation-he-json.0a830937.chunk.js +1 -0
  309. package/build/upload-translation-it-json.e87d7966.chunk.js +1 -0
  310. package/build/upload-translation-ja-json.44b88e7a.chunk.js +1 -0
  311. package/build/upload-translation-ko-json.a52eab64.chunk.js +1 -0
  312. package/build/upload-translation-ms-json.74f6d746.chunk.js +1 -0
  313. package/build/upload-translation-pl-json.426f31c9.chunk.js +1 -0
  314. package/build/upload-translation-pt-BR-json.d1704f0b.chunk.js +1 -0
  315. package/build/upload-translation-pt-json.6b937fdf.chunk.js +1 -0
  316. package/build/upload-translation-ru-json.675f6b93.chunk.js +1 -0
  317. package/build/upload-translation-sk-json.483a18f6.chunk.js +1 -0
  318. package/build/upload-translation-th-json.98d35574.chunk.js +1 -0
  319. package/build/upload-translation-tr-json.74117e5c.chunk.js +1 -0
  320. package/build/upload-translation-uk-json.9950466a.chunk.js +1 -0
  321. package/build/upload-translation-zh-Hans-json.db163b6b.chunk.js +1 -0
  322. package/build/upload-translation-zh-json.e1dd6eb2.chunk.js +1 -0
  323. package/build/upload.1ced11be.chunk.js +58 -0
  324. package/build/users-advanced-settings-page.8e657084.chunk.js +9 -0
  325. package/build/users-email-settings-page.e57745e5.chunk.js +9 -0
  326. package/build/users-permissions-translation-ar-json.7d87d54d.chunk.js +1 -0
  327. package/build/users-permissions-translation-cs-json.7e23424a.chunk.js +1 -0
  328. package/build/users-permissions-translation-de-json.a6fb670f.chunk.js +1 -0
  329. package/build/users-permissions-translation-dk-json.60e50f48.chunk.js +1 -0
  330. package/build/users-permissions-translation-en-json.4b302272.chunk.js +1 -0
  331. package/build/users-permissions-translation-es-json.35007573.chunk.js +1 -0
  332. package/build/users-permissions-translation-fr-json.7e55bbbb.chunk.js +1 -0
  333. package/build/users-permissions-translation-id-json.a5a0fb59.chunk.js +1 -0
  334. package/build/users-permissions-translation-it-json.0705465d.chunk.js +1 -0
  335. package/build/users-permissions-translation-ja-json.891fe76e.chunk.js +1 -0
  336. package/build/users-permissions-translation-ko-json.357d7a33.chunk.js +1 -0
  337. package/build/users-permissions-translation-ms-json.c83f87c4.chunk.js +1 -0
  338. package/build/users-permissions-translation-nl-json.c9f92a3c.chunk.js +1 -0
  339. package/build/users-permissions-translation-pl-json.0a7287d1.chunk.js +1 -0
  340. package/build/users-permissions-translation-pt-BR-json.1b6d2920.chunk.js +1 -0
  341. package/build/users-permissions-translation-pt-json.a7eda429.chunk.js +1 -0
  342. package/build/users-permissions-translation-ru-json.8e883c67.chunk.js +1 -0
  343. package/build/users-permissions-translation-sk-json.7f37180f.chunk.js +1 -0
  344. package/build/users-permissions-translation-sv-json.17187818.chunk.js +1 -0
  345. package/build/users-permissions-translation-th-json.1e9c0247.chunk.js +1 -0
  346. package/build/users-permissions-translation-tr-json.2bd7ff98.chunk.js +1 -0
  347. package/build/users-permissions-translation-uk-json.6a0a1572.chunk.js +1 -0
  348. package/build/users-permissions-translation-vi-json.6722a8a2.chunk.js +1 -0
  349. package/build/users-permissions-translation-zh-Hans-json.8d82c809.chunk.js +1 -0
  350. package/build/users-permissions-translation-zh-json.7978eaa6.chunk.js +1 -0
  351. package/build/users-providers-settings-page.55796d13.chunk.js +14 -0
  352. package/build/users-roles-settings-page.57079245.chunk.js +55 -0
  353. package/build/vi-json.ee4c5537.chunk.js +1 -0
  354. package/build/webhook-edit-page.3a28b2e7.chunk.js +33 -0
  355. package/build/webhook-list-page.ee80767b.chunk.js +63 -0
  356. package/build/zh-Hans-json.97efd015.chunk.js +1 -0
  357. package/build/zh-json.bfc2e036.chunk.js +1 -0
  358. package/ee/admin/hooks/{useLicenseLimitNotification.js → useLicenseLimitNotification.ts} +4 -4
  359. package/ee/admin/pages/AuthPage/components/Login/index.js +1 -1
  360. package/ee/admin/pages/AuthPage/components/Providers/index.js +3 -2
  361. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/selectors.js +1 -1
  362. package/ee/admin/pages/SettingsPage/pages/Users/ListPage/index.js +1 -3
  363. package/ee/server/bootstrap.js +1 -1
  364. package/ee/server/controllers/admin.js +1 -1
  365. package/ee/server/controllers/user.js +1 -1
  366. package/ee/server/destroy.js +1 -1
  367. package/ee/server/register.js +1 -1
  368. package/ee/server/routes/utils.js +1 -1
  369. package/ee/server/services/audit-logs.js +1 -1
  370. package/ee/server/services/passport/sso.js +1 -1
  371. package/ee/server/services/passport.js +1 -1
  372. package/ee/server/services/seat-enforcement.js +1 -1
  373. package/ee/server/utils/sso-lock.js +1 -1
  374. package/ee/server/validation/role.js +1 -1
  375. package/ee/server/validation/user.js +1 -1
  376. package/jest.config.front.js +4 -0
  377. package/package.json +28 -22
  378. package/scripts/build.js +6 -2
  379. package/server/controllers/admin.js +4 -3
  380. package/shared/entities.ts +33 -0
  381. package/shared/permissions.ts +52 -0
  382. package/shared/schema.ts +9 -0
  383. package/webpack.config.js +1 -0
  384. package/admin/src/components/AuthenticatedApp/index.js +0 -120
  385. package/admin/src/components/AuthenticatedApp/utils/api.js +0 -85
  386. package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +0 -11
  387. package/admin/src/components/ConfigurationsProvider/index.js +0 -66
  388. package/admin/src/components/ConfigurationsProvider/reducer.js +0 -29
  389. package/admin/src/components/DragLayer/index.js +0 -1
  390. package/admin/src/components/GlobalStyle/index.js +0 -9
  391. package/admin/src/components/GuidedTour/Homepage/components/Step.js +0 -61
  392. package/admin/src/components/GuidedTour/Homepage/components/Stepper.js +0 -61
  393. package/admin/src/components/GuidedTour/Homepage/index.js +0 -71
  394. package/admin/src/components/GuidedTour/Modal/components/Content.js +0 -66
  395. package/admin/src/components/GuidedTour/Modal/components/Modal.js +0 -72
  396. package/admin/src/components/GuidedTour/Modal/components/StepNumberWithPadding.js +0 -26
  397. package/admin/src/components/GuidedTour/Modal/components/Stepper.js +0 -118
  398. package/admin/src/components/GuidedTour/Modal/index.js +0 -94
  399. package/admin/src/components/GuidedTour/Modal/reducer.js +0 -29
  400. package/admin/src/components/GuidedTour/Stepper/StepLine.js +0 -29
  401. package/admin/src/components/GuidedTour/Stepper/StepNumber.js +0 -71
  402. package/admin/src/components/GuidedTour/constants.js +0 -3
  403. package/admin/src/components/GuidedTour/index.js +0 -102
  404. package/admin/src/components/GuidedTour/init.js +0 -37
  405. package/admin/src/components/GuidedTour/reducer.js +0 -50
  406. package/admin/src/components/GuidedTour/utils/arePreviousSectionsDone.js +0 -13
  407. package/admin/src/components/GuidedTour/utils/arePreviousStepsDone.js +0 -12
  408. package/admin/src/components/GuidedTour/utils/isGuidedTourCompleted.js +0 -6
  409. package/admin/src/components/GuidedTour/utils/persistStateToLocaleStorage.js +0 -34
  410. package/admin/src/components/LanguageProvider/index.js +0 -54
  411. package/admin/src/components/LanguageProvider/init.js +0 -13
  412. package/admin/src/components/LanguageProvider/reducer.js +0 -30
  413. package/admin/src/components/LanguageProvider/utils/localStorageKey.js +0 -3
  414. package/admin/src/components/LocalesProvider/context.js +0 -5
  415. package/admin/src/components/LocalesProvider/index.js +0 -21
  416. package/admin/src/components/LocalesProvider/useLocalesProvider.js +0 -11
  417. package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +0 -17
  418. package/admin/src/components/PluginsInitializer/index.js +0 -68
  419. package/admin/src/components/PluginsInitializer/init.js +0 -11
  420. package/admin/src/components/PluginsInitializer/reducer.js +0 -22
  421. package/admin/src/components/PrivateRoute/index.js +0 -46
  422. package/admin/src/components/Providers/index.js +0 -156
  423. package/admin/src/components/RBACProvider/actions.js +0 -10
  424. package/admin/src/components/RBACProvider/constants.js +0 -2
  425. package/admin/src/components/RBACProvider/index.js +0 -39
  426. package/admin/src/components/RBACProvider/reducer.js +0 -51
  427. package/admin/src/components/Theme/index.js +0 -26
  428. package/admin/src/components/ThemeToggleProvider/index.js +0 -79
  429. package/admin/src/contexts/Admin/index.js +0 -5
  430. package/admin/src/contexts/ApiTokenPermissions/index.js +0 -25
  431. package/admin/src/contexts/Configurations/index.js +0 -5
  432. package/admin/src/contexts/MarketPlace/index.js +0 -18
  433. package/admin/src/contexts/PermisssionsDataManagerContext/index.js +0 -5
  434. package/admin/src/contexts/ThemeToggle/index.js +0 -5
  435. package/admin/src/contexts/index.js +0 -4
  436. package/admin/src/core/store/configureStore.js +0 -47
  437. package/admin/src/exposedHooks.js +0 -27
  438. package/admin/src/hooks/useAdminRoles/__mocks__/index.js +0 -5
  439. package/admin/src/hooks/useAdminUsers/index.js +0 -1
  440. package/admin/src/hooks/useAdminUsers/useAdminUsers.js +0 -47
  441. package/admin/src/hooks/useConfigurations/index.js +0 -11
  442. package/admin/src/hooks/useContentTypes/index.js +0 -1
  443. package/admin/src/hooks/useDebounce/index.js +0 -19
  444. package/admin/src/hooks/useEnterprise/index.js +0 -1
  445. package/admin/src/hooks/useLicenseLimitNotification/index.js +0 -5
  446. package/admin/src/hooks/useMenu/index.js +0 -86
  447. package/admin/src/hooks/useMenu/utils/checkPermissions.js +0 -13
  448. package/admin/src/hooks/useMenu/utils/getGeneralLinks.js +0 -31
  449. package/admin/src/hooks/useMenu/utils/getPluginSectionLinks.js +0 -17
  450. package/admin/src/hooks/usePermissionsDataManager/index.js +0 -7
  451. package/admin/src/hooks/useReleaseNotification/index.js +0 -31
  452. package/admin/src/hooks/useReleaseNotification/utils/api.js +0 -20
  453. package/admin/src/hooks/useReleaseNotification/utils/checkLatestStrapiVersion.js +0 -11
  454. package/admin/src/hooks/useThemeToggle/index.js +0 -11
  455. package/admin/src/injectionZones.js +0 -25
  456. package/admin/src/layouts/UnauthenticatedLayout/LocaleToggle/index.js +0 -29
  457. package/admin/src/layouts/UnauthenticatedLayout/index.js +0 -55
  458. package/admin/src/reducers.js +0 -23
  459. package/admin/src/shared/hooks/useAdminProvider/index.js +0 -11
  460. package/admin/src/tsconfig.json +0 -10
  461. package/admin/src/utils/checkFormValidity.js +0 -15
  462. package/admin/src/utils/createRoute.js +0 -47
  463. package/admin/src/utils/formatAPIErrors.js +0 -17
  464. package/admin/src/utils/getAttributesToDisplay.js +0 -19
  465. package/admin/src/utils/getExistingActions.js +0 -32
  466. package/admin/src/utils/getFullName.js +0 -9
  467. package/admin/src/utils/index.js +0 -9
  468. package/admin/src/utils/makeUniqueRoutes.js +0 -6
  469. package/admin/src/utils/sortLinks.js +0 -5
  470. /package/admin/src/hooks/{useAdminUsers/__mocks__/index.js → __mocks__/useAdminUsers.ts} +0 -0
  471. /package/admin/src/hooks/{useContentTypes/__mocks__/index.js → __mocks__/useContentTypes.ts} +0 -0
  472. /package/admin/src/{hooks/useAdminRolePermissions/__mocks__/index.js → pages/SettingsPage/pages/Roles/hooks/__mocks__/useAdminRolePermissions.ts} +0 -0
@@ -1,6 +1,18 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { Box, Typography, BaseLink } from '@strapi/design-system';
3
+ import {
4
+ Box,
5
+ Icon,
6
+ Typography,
7
+ BaseLink,
8
+ Popover,
9
+ Field,
10
+ FieldLabel,
11
+ FieldInput,
12
+ Flex,
13
+ Button,
14
+ Tooltip,
15
+ } from '@strapi/design-system';
4
16
  import {
5
17
  Code,
6
18
  Quote,
@@ -12,11 +24,24 @@ import {
12
24
  HeadingFour,
13
25
  HeadingFive,
14
26
  HeadingSix,
27
+ Trash,
28
+ Pencil,
29
+ BulletList,
30
+ NumberList,
15
31
  } from '@strapi/icons';
16
32
  import PropTypes from 'prop-types';
17
- import { Editor, Path, Transforms } from 'slate';
33
+ import { useIntl } from 'react-intl';
34
+ import { Editor, Path, Transforms, Range } from 'slate';
35
+ import { useSlate, ReactEditor } from 'slate-react';
18
36
  import styled, { css } from 'styled-components';
19
37
 
38
+ import { composeRefs } from '../../../utils';
39
+ import { editLink, removeLink } from '../utils/links';
40
+
41
+ const StyledBaseLink = styled(BaseLink)`
42
+ text-decoration: none;
43
+ `;
44
+
20
45
  const H1 = styled(Typography).attrs({ as: 'h1' })`
21
46
  font-size: ${42 / 16}rem;
22
47
  line-height: ${({ theme }) => theme.lineHeights[1]};
@@ -47,53 +72,28 @@ const H6 = styled(Typography).attrs({ as: 'h6' })`
47
72
  line-height: ${({ theme }) => theme.lineHeights[1]};
48
73
  `;
49
74
 
50
- const Heading = ({ attributes, children, element }) => {
51
- switch (element.level) {
52
- case 1:
53
- return <H1 {...attributes}>{children}</H1>;
54
- case 2:
55
- return <H2 {...attributes}>{children}</H2>;
56
- case 3:
57
- return <H3 {...attributes}>{children}</H3>;
58
- case 4:
59
- return <H4 {...attributes}>{children}</H4>;
60
- case 5:
61
- return <H5 {...attributes}>{children}</H5>;
62
- case 6:
63
- return <H6 {...attributes}>{children}</H6>;
64
- default: // do nothing
65
- return null;
66
- }
67
- };
68
-
69
- Heading.propTypes = {
70
- attributes: PropTypes.object.isRequired,
71
- children: PropTypes.node.isRequired,
72
- element: PropTypes.shape({
73
- level: PropTypes.oneOf([1, 2, 3, 4, 5, 6]).isRequired,
74
- }).isRequired,
75
- };
76
-
77
75
  const CodeBlock = styled.pre.attrs({ role: 'code' })`
78
76
  border-radius: ${({ theme }) => theme.borderRadius};
79
- background-color: #32324d; // since the color is same between the themes
77
+ background-color: ${({ theme }) => theme.colors.neutral100};
80
78
  max-width: 100%;
81
79
  overflow: auto;
82
- padding: ${({ theme }) => theme.spaces[2]};
80
+ padding: ${({ theme }) => `${theme.spaces[3]} ${theme.spaces[4]}`};
81
+ flex-shrink: 0;
83
82
  & > code {
84
- color: #839496; // TODO: to confirm with design and get theme color
83
+ font-family: 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono', Menlo, Consolas,
84
+ monospace;
85
+ color: ${({ theme }) => theme.colors.neutral800};
85
86
  overflow: auto;
86
87
  max-width: 100%;
87
- padding: ${({ theme }) => theme.spaces[2]};
88
88
  }
89
89
  `;
90
90
 
91
91
  const Blockquote = styled.blockquote.attrs({ role: 'blockquote' })`
92
- margin: ${({ theme }) => `${theme.spaces[6]} 0`};
92
+ margin: ${({ theme }) => `${theme.spaces[4]} 0`};
93
93
  font-weight: ${({ theme }) => theme.fontWeights.regular};
94
- border-left: ${({ theme }) => `${theme.spaces[1]} solid ${theme.colors.neutral150}`};
95
- font-style: italic;
94
+ border-left: ${({ theme }) => `${theme.spaces[1]} solid ${theme.colors.neutral200}`};
96
95
  padding: ${({ theme }) => theme.spaces[2]} ${({ theme }) => theme.spaces[5]};
96
+ color: ${({ theme }) => theme.colors.neutral600};
97
97
  `;
98
98
 
99
99
  const listStyle = css`
@@ -134,35 +134,63 @@ List.propTypes = {
134
134
  }).isRequired,
135
135
  };
136
136
 
137
- const Img = styled.img`
138
- max-width: 100%;
139
- `;
140
-
141
- const Image = ({ attributes, children, element }) => {
142
- if (!element.image) return null;
143
- const { url, alternativeText, width, height } = element.image;
137
+ /**
138
+ * @param {import('slate').Editor} editor
139
+ * @param {Path} currentListPath
140
+ */
141
+ const replaceListWithEmptyBlock = (editor, currentListPath) => {
142
+ // Delete the empty list
143
+ Transforms.removeNodes(editor, { at: currentListPath });
144
144
 
145
- return (
146
- <Box {...attributes}>
147
- {children}
148
- <Box contentEditable={false}>
149
- <Img src={url} alt={alternativeText} width={width} height={height} />
150
- </Box>
151
- </Box>
152
- );
145
+ if (currentListPath[0] === 0) {
146
+ // If the list was the only (or first) block element then insert empty paragraph as editor needs default value
147
+ Transforms.insertNodes(
148
+ editor,
149
+ {
150
+ type: 'paragraph',
151
+ children: [{ type: 'text', text: '' }],
152
+ },
153
+ { at: currentListPath }
154
+ );
155
+ Transforms.select(editor, currentListPath);
156
+ }
153
157
  };
154
158
 
155
- Image.propTypes = {
156
- attributes: PropTypes.object.isRequired,
157
- children: PropTypes.node.isRequired,
158
- element: PropTypes.shape({
159
- image: PropTypes.shape({
160
- url: PropTypes.string.isRequired,
161
- alternativeText: PropTypes.string,
162
- width: PropTypes.number,
163
- height: PropTypes.number,
164
- }),
165
- }).isRequired,
159
+ /**
160
+ * Common handler for the backspace event on ordered and unordered lists
161
+ * @param {import('slate').Editor} editor
162
+ * @param {Event} event
163
+ */
164
+ const handleBackspaceKeyOnList = (editor, event) => {
165
+ const [currentListItem, currentListItemPath] = Editor.parent(editor, editor.selection.anchor);
166
+ const [currentList, currentListPath] = Editor.parent(editor, currentListItemPath);
167
+ const isListEmpty = currentList.children.length === 1 && currentListItem.children[0].text === '';
168
+ const isNodeStart = Editor.isStart(editor, editor.selection.anchor, currentListItemPath);
169
+ const isFocusAtTheBeginningOfAChild =
170
+ editor.selection.focus.offset === 0 && editor.selection.focus.path.at(-1) === 0;
171
+
172
+ if (isListEmpty) {
173
+ event.preventDefault();
174
+ replaceListWithEmptyBlock(editor, currentListPath);
175
+ } else if (isNodeStart) {
176
+ Transforms.liftNodes(editor, {
177
+ match: (n) => n.type === 'list-item',
178
+ });
179
+ // Transforms the list item into a paragraph
180
+ Transforms.setNodes(
181
+ editor,
182
+ { type: 'paragraph' },
183
+ {
184
+ hanging: true,
185
+ }
186
+ );
187
+ } else if (isFocusAtTheBeginningOfAChild) {
188
+ Transforms.liftNodes(editor, {
189
+ match: (n) => n.type === 'list-item',
190
+ });
191
+ // If the focus is at the beginning of a child node we need to replace it with a paragraph
192
+ Transforms.setNodes(editor, { type: 'paragraph' });
193
+ }
166
194
  };
167
195
 
168
196
  /**
@@ -170,18 +198,21 @@ Image.propTypes = {
170
198
  * @param {import('slate').Editor} editor
171
199
  */
172
200
  const handleEnterKeyOnList = (editor) => {
173
- // Check if the selected list item is empty
174
201
  const [currentListItem, currentListItemPath] = Editor.above(editor, {
175
202
  matchNode: (node) => node.type === 'list-item',
176
203
  });
177
- const isEmptyListItem =
204
+ const [currentList, currentListPath] = Editor.parent(editor, currentListItemPath);
205
+ const isListEmpty = currentList.children.length === 1 && currentListItem.children[0].text === '';
206
+ const isListItemEmpty =
178
207
  currentListItem.children.length === 1 && currentListItem.children[0].text === '';
179
208
 
180
- if (isEmptyListItem) {
209
+ if (isListEmpty) {
210
+ replaceListWithEmptyBlock(editor, currentListPath);
211
+ } else if (isListItemEmpty) {
181
212
  // Delete the empty list item
182
213
  Transforms.removeNodes(editor, { at: currentListItemPath });
183
214
 
184
- // And create a new paragraph below the parent list
215
+ // Create a new paragraph below the parent list
185
216
  const listNodeEntry = Editor.above(editor, { match: (n) => n.type === 'list' });
186
217
  const createdParagraphPath = Path.next(listNodeEntry[1]);
187
218
  Transforms.insertNodes(
@@ -193,14 +224,249 @@ const handleEnterKeyOnList = (editor) => {
193
224
  { at: createdParagraphPath }
194
225
  );
195
226
 
196
- // Move selection to the newly created paragraph
227
+ // Move the selection to the newly created paragraph
197
228
  Transforms.select(editor, createdParagraphPath);
198
229
  } else {
199
- // Otherwise just create a new list item by splitting the current one
200
- Transforms.splitNodes(editor, { always: true });
230
+ // Check if the cursor is at the end of the list item
231
+ const isNodeEnd = Editor.isEnd(editor, editor.selection.anchor, currentListItemPath);
232
+
233
+ if (isNodeEnd) {
234
+ // If there was nothing after the cursor, create a fresh new list item,
235
+ // in order to avoid carrying over the modifiers from the previous list item
236
+ Transforms.insertNodes(editor, { type: 'list-item', children: [{ type: 'text', text: '' }] });
237
+ } else {
238
+ // If there is something after the cursor, split the current list item,
239
+ // so that we keep the content and the modifiers
240
+ Transforms.splitNodes(editor);
241
+ }
201
242
  }
202
243
  };
203
244
 
245
+ // The max-height is decided with the design team, the 56px is the height of the toolbar
246
+ const Img = styled.img`
247
+ max-height: calc(512px - 56px);
248
+ max-width: 100%;
249
+ object-fit: contain;
250
+ `;
251
+
252
+ // Added a background color to the image wrapper to make it easier to recognize the image block
253
+ const Image = ({ attributes, children, element }) => {
254
+ if (!element.image) return null;
255
+ const { url, alternativeText, width, height } = element.image;
256
+
257
+ return (
258
+ <Box {...attributes}>
259
+ {children}
260
+ <Flex background="neutral100" contentEditable={false} justifyContent="center">
261
+ <Img src={url} alt={alternativeText} width={width} height={height} />
262
+ </Flex>
263
+ </Box>
264
+ );
265
+ };
266
+
267
+ Image.propTypes = {
268
+ attributes: PropTypes.object.isRequired,
269
+ children: PropTypes.node.isRequired,
270
+ element: PropTypes.shape({
271
+ image: PropTypes.shape({
272
+ url: PropTypes.string.isRequired,
273
+ alternativeText: PropTypes.string,
274
+ width: PropTypes.number,
275
+ height: PropTypes.number,
276
+ }),
277
+ }).isRequired,
278
+ };
279
+
280
+ // Make sure the tooltip is above the popover
281
+ const TooltipCustom = styled(Tooltip)`
282
+ z-index: 6;
283
+ `;
284
+
285
+ // Used for the Edit and Cancel buttons in the link popover
286
+ const CustomButton = styled(Button)`
287
+ & > span {
288
+ line-height: normal;
289
+ }
290
+ `;
291
+
292
+ const Link = React.forwardRef(({ element, children, ...attributes }, forwardedRef) => {
293
+ const { formatMessage } = useIntl();
294
+ const editor = useSlate();
295
+ const path = ReactEditor.findPath(editor, element);
296
+ const [popoverOpen, setPopoverOpen] = React.useState(
297
+ editor.lastInsertedLinkPath ? Path.equals(path, editor.lastInsertedLinkPath) : false
298
+ );
299
+ const [isEditing, setIsEditing] = React.useState(element.url === '');
300
+ const linkRef = React.useRef(null);
301
+ const elementText = element.children.map((child) => child.text).join('');
302
+ const [linkText, setLinkText] = React.useState(elementText);
303
+ const [linkUrl, setLinkUrl] = React.useState(element.url);
304
+
305
+ const handleOpenEditPopover = (e) => {
306
+ e.preventDefault();
307
+ setPopoverOpen(true);
308
+ };
309
+
310
+ const handleSave = (e) => {
311
+ e.stopPropagation();
312
+
313
+ // If the selection is collapsed, we select the parent node because we want all the link to be replaced
314
+ if (Range.isCollapsed(editor.selection)) {
315
+ const [, parentPath] = Editor.parent(editor, editor.selection.focus?.path);
316
+ Transforms.select(editor, parentPath);
317
+ }
318
+
319
+ editLink(editor, { url: linkUrl, text: linkText });
320
+ setIsEditing(false);
321
+ };
322
+
323
+ const handleCancel = () => {
324
+ setIsEditing(false);
325
+
326
+ if (element.url === '') {
327
+ removeLink(editor);
328
+ }
329
+ };
330
+
331
+ const handleDismiss = () => {
332
+ setPopoverOpen(false);
333
+
334
+ if (element.url === '') {
335
+ removeLink(editor);
336
+ }
337
+
338
+ ReactEditor.focus(editor);
339
+ };
340
+
341
+ const composedRefs = composeRefs(linkRef, forwardedRef);
342
+
343
+ return (
344
+ <>
345
+ <StyledBaseLink
346
+ {...attributes}
347
+ ref={composedRefs}
348
+ href={element.url}
349
+ onClick={handleOpenEditPopover}
350
+ color="primary600"
351
+ >
352
+ {children}
353
+ </StyledBaseLink>
354
+ {popoverOpen && (
355
+ <Popover source={linkRef} onDismiss={handleDismiss} padding={4} contentEditable={false}>
356
+ {isEditing ? (
357
+ <Flex as="form" onSubmit={handleSave} direction="column" gap={4}>
358
+ <Field width="300px">
359
+ <FieldLabel>
360
+ {formatMessage({
361
+ id: 'components.Blocks.popover.text',
362
+ defaultMessage: 'Text',
363
+ })}
364
+ </FieldLabel>
365
+ <FieldInput
366
+ name="text"
367
+ placeholder={formatMessage({
368
+ id: 'components.Blocks.popover.text.placeholder',
369
+ defaultMessage: 'Enter link text',
370
+ })}
371
+ value={linkText}
372
+ onChange={(e) => setLinkText(e.target.value)}
373
+ />
374
+ </Field>
375
+ <Field width="300px">
376
+ <FieldLabel>
377
+ {formatMessage({
378
+ id: 'components.Blocks.popover.link',
379
+ defaultMessage: 'Link',
380
+ })}
381
+ </FieldLabel>
382
+ <FieldInput
383
+ name="url"
384
+ placeholder="https://strapi.io"
385
+ value={linkUrl}
386
+ onChange={(e) => setLinkUrl(e.target.value)}
387
+ />
388
+ </Field>
389
+ <Flex justifyContent="end" width="100%" gap={2}>
390
+ <Button variant="tertiary" onClick={handleCancel}>
391
+ {formatMessage({
392
+ id: 'components.Blocks.popover.cancel',
393
+ defaultMessage: 'Cancel',
394
+ })}
395
+ </Button>
396
+ <Button type="submit" disabled={!linkText || !linkUrl}>
397
+ {formatMessage({
398
+ id: 'components.Blocks.popover.save',
399
+ defaultMessage: 'Save',
400
+ })}
401
+ </Button>
402
+ </Flex>
403
+ </Flex>
404
+ ) : (
405
+ <Flex direction="column" gap={4} alignItems="start" width="400px">
406
+ <Typography>{elementText}</Typography>
407
+ <Typography>
408
+ <StyledBaseLink href={element.url} target="_blank" color="primary600">
409
+ {element.url}
410
+ </StyledBaseLink>
411
+ </Typography>
412
+ <Flex justifyContent="end" width="100%" gap={2}>
413
+ <TooltipCustom
414
+ description={formatMessage({
415
+ id: 'components.Blocks.popover.delete',
416
+ defaultMessage: 'Delete',
417
+ })}
418
+ >
419
+ <CustomButton
420
+ size="S"
421
+ width="2rem"
422
+ variant="danger-light"
423
+ onClick={() => removeLink(editor)}
424
+ aria-label={formatMessage({
425
+ id: 'components.Blocks.popover.delete',
426
+ defaultMessage: 'Delete',
427
+ })}
428
+ type="button"
429
+ justifyContent="center"
430
+ >
431
+ <Icon width={3} height={3} as={Trash} />
432
+ </CustomButton>
433
+ </TooltipCustom>
434
+
435
+ <TooltipCustom
436
+ description={formatMessage({
437
+ id: 'components.Blocks.popover.edit',
438
+ defaultMessage: 'Edit',
439
+ })}
440
+ >
441
+ <CustomButton
442
+ size="S"
443
+ width="2rem"
444
+ variant="tertiary"
445
+ onClick={() => setIsEditing(true)}
446
+ aria-label={formatMessage({
447
+ id: 'components.Blocks.popover.edit',
448
+ defaultMessage: 'Edit',
449
+ })}
450
+ type="button"
451
+ justifyContent="center"
452
+ >
453
+ <Icon width={3} height={3} as={Pencil} />
454
+ </CustomButton>
455
+ </TooltipCustom>
456
+ </Flex>
457
+ </Flex>
458
+ )}
459
+ </Popover>
460
+ )}
461
+ </>
462
+ );
463
+ });
464
+
465
+ Link.propTypes = {
466
+ element: PropTypes.object.isRequired,
467
+ children: PropTypes.node.isRequired,
468
+ };
469
+
204
470
  /**
205
471
  * Manages a store of all the available blocks.
206
472
  *
@@ -213,6 +479,7 @@ const handleEnterKeyOnList = (editor) => {
213
479
  * matchNode: (node: Object) => boolean,
214
480
  * isInBlocksSelector: true,
215
481
  * handleEnterKey: (editor: import('slate').Editor) => void,
482
+ * handleBackspaceKey?:(editor: import('slate').Editor, event: Event) => void,
216
483
  * }
217
484
  * }} an object containing rendering functions and metadata for different blocks, indexed by name.
218
485
  */
@@ -235,18 +502,25 @@ export function useBlocksStore() {
235
502
  matchNode: (node) => node.type === 'paragraph',
236
503
  isInBlocksSelector: true,
237
504
  handleEnterKey(editor) {
505
+ // We need to keep track of the initial position of the cursor
506
+ const anchorPathInitialPosition = editor.selection.anchor.path;
238
507
  /**
239
508
  * Split the nodes where the cursor is. This will create a new paragraph with the content
240
509
  * after the cursor, while retaining all the children, modifiers etc.
241
510
  */
242
511
  Transforms.splitNodes(editor, {
243
- /**
244
- * Makes sure we always create a new node,
245
- * even if there's nothing to the right of the cursor in the node.
246
- */
512
+ // Makes sure we always create a new node,
513
+ // even if there's nothing to the right of the cursor in the node.
247
514
  always: true,
248
515
  });
249
516
 
517
+ // Check if the created node is empty (if there was no text after the cursor in the node)
518
+ // This lets us know if we need to carry over the modifiers from the previous node
519
+ const [, parentBlockPath] = Editor.above(editor, {
520
+ match: (n) => n.type !== 'text',
521
+ });
522
+ const isNodeEnd = Editor.isEnd(editor, editor.selection.anchor, parentBlockPath);
523
+
250
524
  /**
251
525
  * Delete and recreate the node that was created at the right of the cursor.
252
526
  * This is to avoid node pollution
@@ -254,12 +528,25 @@ export function useBlocksStore() {
254
528
  * Select the parent of the selection because we want the full block, not the leaf.
255
529
  * And copy its children to make sure we keep the modifiers.
256
530
  */
257
- const [createdNode] = Editor.parent(editor, editor.selection.anchor.path);
531
+ const [fragmentedNode] = Editor.parent(editor, editor.selection.anchor.path);
258
532
  Transforms.removeNodes(editor, editor.selection);
259
- Transforms.insertNodes(editor, {
260
- type: 'paragraph',
261
- children: createdNode.children,
262
- });
533
+
534
+ // Check if after the current position there is another node
535
+ const hasNextNode = editor.children.length - anchorPathInitialPosition[0] > 1;
536
+
537
+ // Insert the new node at the right position.
538
+ // The next line after the editor selection if present or otherwise at the end of the editor.
539
+ Transforms.insertNodes(
540
+ editor,
541
+ {
542
+ type: 'paragraph',
543
+ // Don't carry over the modifiers from the previous node if there was no text after the cursor
544
+ children: isNodeEnd ? [{ type: 'text', text: '' }] : fragmentedNode.children,
545
+ },
546
+ {
547
+ at: hasNextNode ? [anchorPathInitialPosition[0] + 1] : [editor.children.length],
548
+ }
549
+ );
263
550
 
264
551
  /**
265
552
  * The new selection will by default be at the end of the created node.
@@ -267,11 +554,11 @@ export function useBlocksStore() {
267
554
  * Use slice(0, -1) to go 1 level higher in the tree,
268
555
  * so we go to the start of the node and not the start of the leaf.
269
556
  */
270
- Transforms.select(editor, editor.start(editor.selection.anchor.path.slice(0, -1)));
557
+ Transforms.select(editor, editor.start([anchorPathInitialPosition[0] + 1]));
271
558
  },
272
559
  },
273
560
  'heading-one': {
274
- renderElement: (props) => <Heading {...props} />,
561
+ renderElement: (props) => <H1 {...props.attributes}>{props.children}</H1>,
275
562
  icon: HeadingOne,
276
563
  label: {
277
564
  id: 'components.Blocks.blocks.heading1',
@@ -285,7 +572,7 @@ export function useBlocksStore() {
285
572
  isInBlocksSelector: true,
286
573
  },
287
574
  'heading-two': {
288
- renderElement: (props) => <Heading {...props} />,
575
+ renderElement: (props) => <H2 {...props.attributes}>{props.children}</H2>,
289
576
  icon: HeadingTwo,
290
577
  label: {
291
578
  id: 'components.Blocks.blocks.heading2',
@@ -299,7 +586,7 @@ export function useBlocksStore() {
299
586
  isInBlocksSelector: true,
300
587
  },
301
588
  'heading-three': {
302
- renderElement: (props) => <Heading {...props} />,
589
+ renderElement: (props) => <H3 {...props.attributes}>{props.children}</H3>,
303
590
  icon: HeadingThree,
304
591
  label: {
305
592
  id: 'components.Blocks.blocks.heading3',
@@ -313,7 +600,7 @@ export function useBlocksStore() {
313
600
  isInBlocksSelector: true,
314
601
  },
315
602
  'heading-four': {
316
- renderElement: (props) => <Heading {...props} />,
603
+ renderElement: (props) => <H4 {...props.attributes}>{props.children}</H4>,
317
604
  icon: HeadingFour,
318
605
  label: {
319
606
  id: 'components.Blocks.blocks.heading4',
@@ -327,7 +614,7 @@ export function useBlocksStore() {
327
614
  isInBlocksSelector: true,
328
615
  },
329
616
  'heading-five': {
330
- renderElement: (props) => <Heading {...props} />,
617
+ renderElement: (props) => <H5 {...props.attributes}>{props.children}</H5>,
331
618
  icon: HeadingFive,
332
619
  label: {
333
620
  id: 'components.Blocks.blocks.heading5',
@@ -341,7 +628,7 @@ export function useBlocksStore() {
341
628
  isInBlocksSelector: true,
342
629
  },
343
630
  'heading-six': {
344
- renderElement: (props) => <Heading {...props} />,
631
+ renderElement: (props) => <H6 {...props.attributes}>{props.children}</H6>,
345
632
  icon: HeadingSix,
346
633
  label: {
347
634
  id: 'components.Blocks.blocks.heading6',
@@ -354,73 +641,37 @@ export function useBlocksStore() {
354
641
  matchNode: (node) => node.type === 'heading' && node.level === 6,
355
642
  isInBlocksSelector: true,
356
643
  },
357
- link: {
358
- renderElement: (props) => (
359
- <BaseLink href={props.element.url} {...props.attributes}>
360
- {props.children}
361
- </BaseLink>
362
- ),
363
- value: {
364
- type: 'link',
365
- },
366
- matchNode: (node) => node.type === 'link',
367
- isInBlocksSelector: false,
368
- },
369
- code: {
370
- renderElement: (props) => (
371
- <CodeBlock {...props.attributes}>
372
- <code>{props.children}</code>
373
- </CodeBlock>
374
- ),
375
- icon: Code,
376
- label: {
377
- id: 'components.Blocks.blocks.code',
378
- defaultMessage: 'Code',
379
- },
380
- value: {
381
- type: 'code',
382
- },
383
- matchNode: (node) => node.type === 'code',
384
- isInBlocksSelector: true,
385
- handleEnterKey(editor) {
386
- // Insert a new line within the block
387
- Transforms.insertText(editor, '\n');
388
- },
389
- },
390
- quote: {
391
- renderElement: (props) => <Blockquote {...props.attributes}>{props.children}</Blockquote>,
392
- icon: Quote,
393
- label: {
394
- id: 'components.Blocks.blocks.quote',
395
- defaultMessage: 'Quote',
396
- },
397
- value: {
398
- type: 'quote',
399
- },
400
- matchNode: (node) => node.type === 'quote',
401
- isInBlocksSelector: true,
402
- },
403
644
  'list-ordered': {
404
645
  renderElement: (props) => <List {...props} />,
646
+ label: {
647
+ id: 'components.Blocks.blocks.orderedList',
648
+ defaultMessage: 'Numbered list',
649
+ },
405
650
  value: {
406
651
  type: 'list',
407
652
  format: 'ordered',
408
653
  },
654
+ icon: NumberList,
409
655
  matchNode: (node) => node.type === 'list' && node.format === 'ordered',
410
- // TODO add icon and label and set isInBlocksEditor to true
411
- isInBlocksSelector: false,
656
+ isInBlocksSelector: true,
412
657
  handleEnterKey: handleEnterKeyOnList,
658
+ handleBackspaceKey: handleBackspaceKeyOnList,
413
659
  },
414
660
  'list-unordered': {
415
661
  renderElement: (props) => <List {...props} />,
662
+ label: {
663
+ id: 'components.Blocks.blocks.unorderedList',
664
+ defaultMessage: 'Bulleted list',
665
+ },
416
666
  value: {
417
667
  type: 'list',
418
668
  format: 'unordered',
419
669
  },
670
+ icon: BulletList,
420
671
  matchNode: (node) => node.type === 'list' && node.format === 'unordered',
421
- // TODO add icon and label and set isInBlocksEditor to true
422
- isInBlocksSelector: false,
672
+ isInBlocksSelector: true,
423
673
  handleEnterKey: handleEnterKeyOnList,
674
+ handleBackspaceKey: handleBackspaceKeyOnList,
424
675
  },
425
676
  'list-item': {
426
677
  renderElement: (props) => (
@@ -434,6 +685,18 @@ export function useBlocksStore() {
434
685
  matchNode: (node) => node.type === 'list-item',
435
686
  isInBlocksSelector: false,
436
687
  },
688
+ link: {
689
+ renderElement: (props) => (
690
+ <Link element={props.element} {...props.attributes}>
691
+ {props.children}
692
+ </Link>
693
+ ),
694
+ value: {
695
+ type: 'link',
696
+ },
697
+ matchNode: (node) => node.type === 'link',
698
+ isInBlocksSelector: false,
699
+ },
437
700
  image: {
438
701
  renderElement: (props) => <Image {...props} />,
439
702
  icon: Picture,
@@ -447,5 +710,70 @@ export function useBlocksStore() {
447
710
  matchNode: (node) => node.type === 'image',
448
711
  isInBlocksSelector: true,
449
712
  },
713
+ quote: {
714
+ renderElement: (props) => <Blockquote {...props.attributes}>{props.children}</Blockquote>,
715
+ icon: Quote,
716
+ label: {
717
+ id: 'components.Blocks.blocks.quote',
718
+ defaultMessage: 'Quote',
719
+ },
720
+ value: {
721
+ type: 'quote',
722
+ },
723
+ matchNode: (node) => node.type === 'quote',
724
+ isInBlocksSelector: true,
725
+ handleEnterKey(editor) {
726
+ /**
727
+ * To determine if we should break out of the quote node, check 2 things:
728
+ * 1. If the cursor is at the end of the quote node
729
+ * 2. If the last line of the quote node is empty
730
+ */
731
+ const [quoteNode, quoteNodePath] = Editor.above(editor, {
732
+ match: (n) => n.type === 'quote',
733
+ });
734
+ const isNodeEnd = Editor.isEnd(editor, editor.selection.anchor, quoteNodePath);
735
+ const isEmptyLine = quoteNode.children.at(-1).text.endsWith('\n');
736
+
737
+ if (isNodeEnd && isEmptyLine) {
738
+ // Remove the last line break
739
+ Transforms.delete(editor, { distance: 1, unit: 'character', reverse: true });
740
+ // Break out of the quote node new paragraph
741
+ Transforms.insertNodes(editor, {
742
+ type: 'paragraph',
743
+ children: [{ type: 'text', text: '' }],
744
+ });
745
+ } else {
746
+ // Otherwise insert a new line within the quote node
747
+ Transforms.insertText(editor, '\n');
748
+
749
+ // If there's nothing after the cursor, disable modifiers
750
+ if (isNodeEnd) {
751
+ Editor.removeMark(editor, 'bold');
752
+ Editor.removeMark(editor, 'italic');
753
+ }
754
+ }
755
+ },
756
+ },
757
+ code: {
758
+ renderElement: (props) => (
759
+ <CodeBlock {...props.attributes}>
760
+ <code>{props.children}</code>
761
+ </CodeBlock>
762
+ ),
763
+ icon: Code,
764
+ label: {
765
+ id: 'components.Blocks.blocks.code',
766
+ defaultMessage: 'Code',
767
+ },
768
+ value: {
769
+ type: 'code',
770
+ },
771
+ matchNode: (node) => node.type === 'code',
772
+ isInBlocksSelector: true,
773
+ handleEnterKey(editor) {
774
+ // Insert a new line within the block
775
+ Transforms.insertText(editor, '\n');
776
+ },
777
+ },
450
778
  };
451
779
  }