Yuki Takei 5 месяцев назад
Родитель
Сommit
a154a904b4
82 измененных файлов с 242 добавлено и 127 удалено
  1. 2 2
      .serena/memories/apps-app-modal-performance-optimization-v3-completion-summary.md
  2. 1 1
      apps/app/src/client/components/CreateTemplateModal/dynamic.tsx
  3. 1 1
      apps/app/src/client/components/DeleteBookmarkFolderModal/dynamic.tsx
  4. 1 1
      apps/app/src/client/components/DescendantsPageListModal/dynamic.tsx
  5. 1 1
      apps/app/src/client/components/EmptyTrashModal/dynamic.tsx
  6. 1 1
      apps/app/src/client/components/GrantedGroupsInheritanceSelectModal/dynamic.tsx
  7. 1 1
      apps/app/src/client/components/PageAccessoriesModal/dynamic.tsx
  8. 1 1
      apps/app/src/client/components/PageAttachment/dynamic.tsx
  9. 1 1
      apps/app/src/client/components/PageComment/DeleteCommentModal/dynamic.tsx
  10. 1 1
      apps/app/src/client/components/PageDeleteModal/dynamic.tsx
  11. 1 1
      apps/app/src/client/components/PageDuplicateModal/dynamic.tsx
  12. 1 1
      apps/app/src/client/components/PageEditor/ConflictDiffModal/dynamic.tsx
  13. 1 1
      apps/app/src/client/components/PageEditor/DrawioModal/dynamic.tsx
  14. 1 1
      apps/app/src/client/components/PageEditor/HandsontableModal/dynamic.tsx
  15. 1 1
      apps/app/src/client/components/PageEditor/LinkEditModal/dynamic.tsx
  16. 1 1
      apps/app/src/client/components/PagePresentationModal/dynamic.tsx
  17. 1 1
      apps/app/src/client/components/PageRenameModal/dynamic.tsx
  18. 1 1
      apps/app/src/client/components/PageSelectModal/dynamic.tsx
  19. 1 1
      apps/app/src/client/components/PageTags/TagEditModal/dynamic.tsx
  20. 1 1
      apps/app/src/client/components/PutbackPageModal/dynamic.tsx
  21. 1 1
      apps/app/src/client/components/ShortcutsModal/dynamic.tsx
  22. 1 1
      apps/app/src/client/components/TemplateModal/dynamic.tsx
  23. 1 0
      apps/app/src/components/Common/PagePathNav/PagePathNavLayout.tsx
  24. 1 0
      apps/app/src/components/Common/PagePathNavTitle/PagePathNavTitle.tsx
  25. 3 1
      apps/app/src/components/Layout/AdminLayout.tsx
  26. 5 0
      apps/app/src/components/Layout/BasicLayout.tsx
  27. 3 2
      apps/app/src/components/Layout/ShareLinkLayout.tsx
  28. 3 0
      apps/app/src/components/PageView/PageAlerts/FixPageGrantAlert/FixPageGrantModal.tsx
  29. 1 1
      apps/app/src/components/PageView/PageAlerts/FixPageGrantAlert/dynamic.tsx
  30. 1 1
      apps/app/src/components/PageView/PageAlerts/FullTextSearchNotCoverAlert/dynamic.tsx
  31. 2 0
      apps/app/src/components/PageView/PageAlerts/PageRedirectedAlert/PageRedirectedAlert.tsx
  32. 1 1
      apps/app/src/components/PageView/PageAlerts/PageRedirectedAlert/dynamic.tsx
  33. 2 0
      apps/app/src/components/PageView/PageAlerts/TrashPageAlert/TrashPageAlert.tsx
  34. 1 1
      apps/app/src/components/PageView/PageAlerts/TrashPageAlert/dynamic.tsx
  35. 3 0
      apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx
  36. 1 0
      apps/app/src/components/PageView/PageContentFooter.tsx
  37. 2 0
      apps/app/src/components/PageView/PageView.tsx
  38. 2 0
      apps/app/src/components/ShareLinkPageView/ShareLinkPageView.tsx
  39. 77 33
      apps/app/src/components/utils/use-lazy-loader.spec.tsx
  40. 13 7
      apps/app/src/components/utils/use-lazy-loader.ts
  41. 1 1
      apps/app/src/features/openai/client/components/AiAssistant/AiAssistantManagementModal/dynamic.tsx
  42. 1 1
      apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/dynamic.tsx
  43. 1 1
      apps/app/src/features/openai/client/components/AiAssistant/Sidebar/DeleteAiAssistantModal/dynamic.tsx
  44. 1 1
      apps/app/src/features/page-bulk-export/client/components/dynamic.tsx
  45. 1 1
      apps/app/src/features/search/client/components/SearchPage/SearchOptionModal/dynamic.tsx
  46. 6 11
      apps/app/src/pages/[[...path]]/index.page.tsx
  47. 1 0
      apps/app/src/pages/_private-legacy-pages/index.page.tsx
  48. 1 1
      apps/app/src/pages/_search/index.page.tsx
  49. 1 0
      apps/app/src/pages/admin/[...path].page.tsx
  50. 1 0
      apps/app/src/pages/admin/_shared/AdminPageFrame.tsx
  51. 2 0
      apps/app/src/pages/admin/ai-integration.page.tsx
  52. 4 3
      apps/app/src/pages/admin/app.page.tsx
  53. 1 0
      apps/app/src/pages/admin/audit-log.page.tsx
  54. 2 0
      apps/app/src/pages/admin/customize.page.tsx
  55. 4 3
      apps/app/src/pages/admin/data-transfer.page.tsx
  56. 4 3
      apps/app/src/pages/admin/export.page.tsx
  57. 5 3
      apps/app/src/pages/admin/global-notification/[globalNotificationId].page.tsx
  58. 4 3
      apps/app/src/pages/admin/global-notification/new.page.tsx
  59. 4 3
      apps/app/src/pages/admin/importer.page.tsx
  60. 4 3
      apps/app/src/pages/admin/index.page.tsx
  61. 4 3
      apps/app/src/pages/admin/markdown.page.tsx
  62. 4 3
      apps/app/src/pages/admin/notification.page.tsx
  63. 4 3
      apps/app/src/pages/admin/plugins.page.tsx
  64. 1 0
      apps/app/src/pages/admin/search.page.tsx
  65. 3 0
      apps/app/src/pages/admin/security.page.tsx
  66. 5 3
      apps/app/src/pages/admin/slack-integration-legacy.page.tsx
  67. 1 0
      apps/app/src/pages/admin/slack-integration.page.tsx
  68. 1 0
      apps/app/src/pages/admin/user-group-detail/[userGroupId].page.tsx
  69. 1 0
      apps/app/src/pages/admin/user-groups.page.tsx
  70. 5 3
      apps/app/src/pages/admin/users/external-accounts.page.tsx
  71. 4 3
      apps/app/src/pages/admin/users/index.page.tsx
  72. 1 1
      apps/app/src/pages/forgot-password/index.page.tsx
  73. 2 0
      apps/app/src/pages/installer/index.page.tsx
  74. 1 0
      apps/app/src/pages/invited/index.page.tsx
  75. 1 0
      apps/app/src/pages/login/index.page.tsx
  76. 1 0
      apps/app/src/pages/maintenance/index.page.tsx
  77. 2 0
      apps/app/src/pages/me/index.page.tsx
  78. 1 0
      apps/app/src/pages/reset-password/index.page.tsx
  79. 1 0
      apps/app/src/pages/share/[[...path]]/index.page.tsx
  80. 2 0
      apps/app/src/pages/tags/index.page.tsx
  81. 2 0
      apps/app/src/pages/trash/index.page.tsx
  82. 1 0
      apps/app/src/pages/user-activation/index.page.tsx

+ 2 - 2
.serena/memories/apps-app-modal-performance-optimization-v3-completion-summary.md

@@ -128,7 +128,7 @@ apps/app/.../[ComponentName]/
 **dynamic.tsx**:
 ```tsx
 import type { JSX } from 'react';
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useShortcutsModalStatus } from '~/states/ui/modal/shortcuts';
 
 export const ShortcutsModalLazyLoaded = (): JSX.Element => {
@@ -297,7 +297,7 @@ AiAssistantSidebar/
 ```tsx
 import type { FC } from 'react';
 import { memo } from 'react';
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useAiAssistantSidebarStatus } from '../../../states';
 
 export const AiAssistantSidebarLazyLoaded: FC = memo(() => {

+ 1 - 1
apps/app/src/client/components/CreateTemplateModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '../../util/use-lazy-loader';
+import { useLazyLoader } from '../../../components/utils/use-lazy-loader';
 
 type CreateTemplateModalProps = {
   path: string;

+ 1 - 1
apps/app/src/client/components/DeleteBookmarkFolderModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useDeleteBookmarkFolderModalStatus } from '~/states/ui/modal/delete-bookmark-folder';
 
 type DeleteBookmarkFolderModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/DescendantsPageListModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useDescendantsPageListModalStatus } from '~/states/ui/modal/descendants-page-list';
 
 type DescendantsPageListModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/EmptyTrashModal/dynamic.tsx

@@ -2,7 +2,7 @@ import type { JSX } from 'react';
 
 import { useEmptyTrashModalStatus } from '~/states/ui/modal/empty-trash';
 
-import { useLazyLoader } from '../../util/use-lazy-loader';
+import { useLazyLoader } from '../../../components/utils/use-lazy-loader';
 
 type EmptyTrashModalProps = Record<string, unknown>;
 

+ 1 - 1
apps/app/src/client/components/GrantedGroupsInheritanceSelectModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useGrantedGroupsInheritanceSelectModalStatus } from '~/states/ui/modal/granted-groups-inheritance-select';
 
 type GrantedGroupsInheritanceSelectModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageAccessoriesModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { usePageAccessoriesModalStatus } from '~/states/ui/modal/page-accessories';
 
 type PageAccessoriesModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageAttachment/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useDeleteAttachmentModalStatus } from '~/states/ui/modal/delete-attachment';
 
 type DeleteAttachmentModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageComment/DeleteCommentModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '../../../util/use-lazy-loader';
+import { useLazyLoader } from '../../../../components/utils/use-lazy-loader';
 
 import type { DeleteCommentModalProps } from './DeleteCommentModal';
 

+ 1 - 1
apps/app/src/client/components/PageDeleteModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { usePageDeleteModalStatus } from '~/states/ui/modal/page-delete';
 
 type PageDeleteModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageDuplicateModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { usePageDuplicateModalStatus } from '~/states/ui/modal/page-duplicate';
 
 type PageDuplicateModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageEditor/ConflictDiffModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useConflictDiffModalStatus } from '~/states/ui/modal/conflict-diff';
 
 type ConflictDiffModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageEditor/DrawioModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useDrawioModalStatus } from '~/states/ui/modal/drawio';
 
 type DrawioModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageEditor/HandsontableModal/dynamic.tsx

@@ -2,7 +2,7 @@ import type { JSX } from 'react';
 
 import { useHandsontableModalForEditorStatus } from '@growi/editor';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useHandsontableModalStatus } from '~/states/ui/modal/handsontable';
 
 type HandsontableModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageEditor/LinkEditModal/dynamic.tsx

@@ -2,7 +2,7 @@ import type { JSX } from 'react';
 
 import { useLinkEditModalStatus } from '@growi/editor/dist/states/modal/link-edit';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 type LinkEditModalProps = Record<string, unknown>;
 

+ 1 - 1
apps/app/src/client/components/PagePresentationModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { usePresentationModalStatus } from '~/states/ui/modal/page-presentation';
 
 type PagePresentationModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageRenameModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { usePageRenameModalStatus } from '~/states/ui/modal/page-rename';
 
 type PageRenameModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageSelectModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { usePageSelectModalStatus } from '~/states/ui/modal/page-select';
 
 type PageSelectModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PageTags/TagEditModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useTagEditModalStatus } from '~/states/ui/modal/tag-edit';
 
 type TagEditModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/PutbackPageModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { usePutBackPageModalStatus } from '~/states/ui/modal/put-back-page';
 
 type PutBackPageModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/ShortcutsModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useShortcutsModalStatus } from '~/states/ui/modal/shortcuts';
 
 type ShortcutsModalProps = Record<string, unknown>;

+ 1 - 1
apps/app/src/client/components/TemplateModal/dynamic.tsx

@@ -2,7 +2,7 @@ import type { JSX } from 'react';
 
 import { useTemplateModalStatus } from '@growi/editor';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 type TemplateModalProps = Record<string, unknown>;
 

+ 1 - 0
apps/app/src/components/Common/PagePathNav/PagePathNavLayout.tsx

@@ -25,6 +25,7 @@ type Props = PagePathNavLayoutProps & {
 
 const CopyDropdown = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Common/CopyDropdown').then(
       (mod) => mod.CopyDropdown,
     ),

+ 1 - 0
apps/app/src/components/Common/PagePathNavTitle/PagePathNavTitle.tsx

@@ -14,6 +14,7 @@ const PagePathNavSticky = withLoadingProps<PagePathNavLayoutProps>(
   (useLoadingProps) =>
     dynamic(
       () =>
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
         import('~/client/components/PagePathNavSticky').then(
           (mod) => mod.PagePathNavSticky,
         ),

+ 3 - 1
apps/app/src/components/Layout/AdminLayout.tsx

@@ -1,5 +1,4 @@
 import type { JSX, ReactNode } from 'react';
-import React from 'react';
 import dynamic from 'next/dynamic';
 import Link from 'next/link';
 
@@ -17,14 +16,17 @@ const AdminNavigation = dynamic(
   { ssr: false },
 );
 const PageCreateModal = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/PageCreateModal'),
   { ssr: false },
 );
 const SystemVersion = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/SystemVersion'),
   { ssr: false },
 );
 const HotkeysManager = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Hotkeys/HotkeysManager'),
   { ssr: false },
 );

+ 5 - 0
apps/app/src/components/Layout/BasicLayout.tsx

@@ -1,6 +1,7 @@
 import type { JSX, ReactNode } from 'react';
 import dynamic from 'next/dynamic';
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem lazy loaded components
 import { AlertSiteUrlUndefined } from '~/client/components/AlertSiteUrlUndefined';
 import { DeleteBookmarkFolderModalLazyLoaded } from '~/client/components/DeleteBookmarkFolderModal';
 import { GrantedGroupsInheritanceSelectModalLazyLoaded } from '~/client/components/GrantedGroupsInheritanceSelectModal';
@@ -17,12 +18,15 @@ import { AiAssistantManagementModalLazyLoaded } from '~/features/openai/client/c
 import { AiAssistantSidebarLazyLoaded } from '~/features/openai/client/components/AiAssistant/AiAssistantSidebar';
 import { PageBulkExportSelectModalLazyLoaded } from '~/features/page-bulk-export/client/components';
 
+// biome-ignore-end lint/style/noRestrictedImports: no-problem lazy loaded components
+
 import { RawLayout } from './RawLayout';
 
 import styles from './BasicLayout.module.scss';
 
 const moduleClass = styles['grw-basic-layout'] ?? '';
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 const Sidebar = dynamic(
   () => import('~/client/components/Sidebar').then((mod) => mod.Sidebar),
   { ssr: false },
@@ -52,6 +56,7 @@ const SearchModal = dynamic(
   () => import('~/features/search/client/components/SearchModal'),
   { ssr: false },
 );
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 type Props = {
   children?: ReactNode;

+ 3 - 2
apps/app/src/components/Layout/ShareLinkLayout.tsx

@@ -1,12 +1,12 @@
 import type { JSX, ReactNode } from 'react';
-import React from 'react';
 import dynamic from 'next/dynamic';
 
-// eslint-disable-next-line no-restricted-imports
+// biome-ignore lint/style/noRestrictedImports: no-problem lazy loaded components
 import { ShortcutsModalLazyLoaded } from '~/client/components/ShortcutsModal';
 
 import { RawLayout } from './RawLayout';
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 const PageCreateModal = dynamic(
   () => import('~/client/components/PageCreateModal'),
   { ssr: false },
@@ -22,6 +22,7 @@ const SystemVersion = dynamic(
   () => import('~/client/components/SystemVersion'),
   { ssr: false },
 );
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 type Props = {
   children?: ReactNode;

+ 3 - 0
apps/app/src/components/PageView/PageAlerts/FixPageGrantAlert/FixPageGrantModal.tsx

@@ -79,6 +79,7 @@ export const FixPageGrantModal = (props: ModalProps): JSX.Element => {
     close();
 
     try {
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       const apiv3Put = (await import('~/client/util/apiv3-client')).apiv3Put;
       await apiv3Put(`/page/${pageId}/grant`, {
         grant: selectedGrant,
@@ -90,9 +91,11 @@ export const FixPageGrantModal = (props: ModalProps): JSX.Element => {
             : null,
       });
 
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       const toastSuccess = (await import('~/client/util/toastr')).toastSuccess;
       toastSuccess(t('Successfully updated'));
     } catch {
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       const toastError = (await import('~/client/util/toastr')).toastError;
       toastError(t('Failed to update'));
     }

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/FixPageGrantAlert/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useCurrentUser } from '~/states/global';
 import { useCurrentPageData, usePageNotFound } from '~/states/page';
 import { useSWRxCurrentGrantData } from '~/stores/page';

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/FullTextSearchNotCoverAlert/dynamic.tsx

@@ -1,7 +1,7 @@
 import type { JSX } from 'react';
 import { useAtomValue } from 'jotai';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useCurrentPageData } from '~/states/page';
 import { elasticsearchMaxBodyLengthToIndexAtom } from '~/states/server-configurations';
 

+ 2 - 0
apps/app/src/components/PageView/PageAlerts/PageRedirectedAlert/PageRedirectedAlert.tsx

@@ -20,11 +20,13 @@ const PageRedirectedAlertSubstance = React.memo(
         return;
       }
       try {
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
         const unlink = (await import('~/client/services/page-operation'))
           .unlink;
         await unlink(currentPagePath);
         setIsUnlinked(true);
       } catch (err) {
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
         const toastError = (await import('~/client/util/toastr')).toastError;
         toastError(err);
       }

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/PageRedirectedAlert/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useRedirectFrom } from '~/states/page';
 
 export const PageRedirectedAlertLazyLoaded = (): JSX.Element => {

+ 2 - 0
apps/app/src/components/PageView/PageAlerts/TrashPageAlert/TrashPageAlert.tsx

@@ -59,6 +59,7 @@ const TrashPageAlertSubstance = (props: SubstanceProps): JSX.Element => {
         return;
       }
       try {
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
         const unlink = (await import('~/client/services/page-operation'))
           .unlink;
         unlink(currentPagePath);
@@ -67,6 +68,7 @@ const TrashPageAlertSubstance = (props: SubstanceProps): JSX.Element => {
         fetchCurrentPage();
         mutateRecentlyUpdated();
       } catch (err) {
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
         const toastError = (await import('~/client/util/toastr')).toastError;
         toastError(err);
       }

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/TrashPageAlert/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 import { useIsTrashPage } from '~/states/page';
 
 export const TrashPageAlertLazyLoaded = (): JSX.Element => {

+ 3 - 0
apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx

@@ -16,6 +16,7 @@ export const WipPageAlert = (): JSX.Element => {
     }
 
     try {
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       const publish = (await import('~/client/services/page-operation'))
         .publish;
       await publish(pageId);
@@ -30,9 +31,11 @@ export const WipPageAlert = (): JSX.Element => {
         .mutateRecentlyUpdated;
       await mutateRecentlyUpdated();
 
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       const toastSuccess = (await import('~/client/util/toastr')).toastSuccess;
       toastSuccess(t('wip_page.success_publish_page'));
     } catch {
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       const toastError = (await import('~/client/util/toastr')).toastError;
       toastError(t('wip_page.fail_publish_page'));
     }

+ 1 - 0
apps/app/src/components/PageView/PageContentFooter.tsx

@@ -5,6 +5,7 @@ import type { IPage, IPagePopulatedToShowRevision } from '@growi/core';
 import styles from './PageContentFooter.module.scss';
 
 const AuthorInfo = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/AuthorInfo').then((mod) => mod.AuthorInfo),
   { ssr: false },
 );

+ 2 - 0
apps/app/src/components/PageView/PageView.tsx

@@ -23,6 +23,7 @@ import { PageContentFooter } from './PageContentFooter';
 import { PageViewLayout } from './PageViewLayout';
 import RevisionRenderer from './RevisionRenderer';
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 const NotCreatablePage = dynamic(
   () =>
     import('~/client/components/NotCreatablePage').then(
@@ -76,6 +77,7 @@ const SlideRenderer = dynamic(
     ),
   { ssr: false },
 );
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 type Props = {
   pagePath: string;

+ 2 - 0
apps/app/src/components/ShareLinkPageView/ShareLinkPageView.tsx

@@ -18,6 +18,7 @@ import ShareLinkAlert from './ShareLinkAlert';
 
 const logger = loggerFactory('growi:components:ShareLinkPageView');
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 const PageSideContents = dynamic(
   () =>
     import('~/client/components/PageSideContents').then(
@@ -36,6 +37,7 @@ const SlideRenderer = dynamic(
     ),
   { ssr: false },
 );
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 type Props = {
   pagePath: string;

+ 77 - 33
apps/app/src/client/util/use-lazy-loader.spec.tsx → apps/app/src/components/utils/use-lazy-loader.spec.tsx

@@ -1,11 +1,7 @@
-import React from 'react';
-
 import { renderHook, waitFor } from '@testing-library/react';
-import {
-  describe, it, expect, vi, beforeEach,
-} from 'vitest';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
 
-import { useLazyLoader, clearComponentCache } from './use-lazy-loader';
+import { clearComponentCache, useLazyLoader } from './use-lazy-loader';
 
 describe('useLazyLoader', () => {
   beforeEach(() => {
@@ -21,7 +17,9 @@ describe('useLazyLoader', () => {
       const mockImport = vi.fn().mockResolvedValue({ default: MockComponent });
 
       // Act
-      const { result } = renderHook(() => useLazyLoader('test-key', mockImport, true));
+      const { result } = renderHook(() =>
+        useLazyLoader('test-key', mockImport, true),
+      );
 
       // Assert
       await waitFor(() => {
@@ -35,7 +33,9 @@ describe('useLazyLoader', () => {
       const mockImport = vi.fn();
 
       // Act
-      const { result } = renderHook(() => useLazyLoader('test-key', mockImport, false));
+      const { result } = renderHook(() =>
+        useLazyLoader('test-key', mockImport, false),
+      );
 
       // Assert
       expect(result.current).toBeNull();
@@ -48,7 +48,9 @@ describe('useLazyLoader', () => {
       const mockImport = vi.fn().mockResolvedValue({ default: MockComponent });
 
       // Act
-      const { result } = renderHook(() => useLazyLoader('async-key', mockImport, true));
+      const { result } = renderHook(() =>
+        useLazyLoader('async-key', mockImport, true),
+      );
 
       // Assert - Initially null
       expect(result.current).toBeNull();
@@ -67,14 +69,18 @@ describe('useLazyLoader', () => {
       const mockImport = vi.fn().mockResolvedValue({ default: MockComponent });
 
       // Act - First call
-      const { result: result1 } = renderHook(() => useLazyLoader('cached-key', mockImport, true));
+      const { result: result1 } = renderHook(() =>
+        useLazyLoader('cached-key', mockImport, true),
+      );
 
       await waitFor(() => {
         expect(result1.current).toBe(MockComponent);
       });
 
       // Act - Second call with same key
-      const { result: result2 } = renderHook(() => useLazyLoader('cached-key', mockImport, true));
+      const { result: result2 } = renderHook(() =>
+        useLazyLoader('cached-key', mockImport, true),
+      );
 
       await waitFor(() => {
         expect(result2.current).toBe(MockComponent);
@@ -92,9 +98,13 @@ describe('useLazyLoader', () => {
       const mockImport2 = vi.fn().mockResolvedValue({ default: Component2 });
 
       // Act
-      const { result: result1 } = renderHook(() => useLazyLoader('key1', mockImport1, true));
+      const { result: result1 } = renderHook(() =>
+        useLazyLoader('key1', mockImport1, true),
+      );
 
-      const { result: result2 } = renderHook(() => useLazyLoader('key2', mockImport2, true));
+      const { result: result2 } = renderHook(() =>
+        useLazyLoader('key2', mockImport2, true),
+      );
 
       // Assert
       await waitFor(() => {
@@ -191,11 +201,17 @@ describe('useLazyLoader', () => {
       const mockImport3 = vi.fn().mockResolvedValue({ default: Component3 });
 
       // Act
-      const { result: result1 } = renderHook(() => useLazyLoader('multi-key1', mockImport1, true));
+      const { result: result1 } = renderHook(() =>
+        useLazyLoader('multi-key1', mockImport1, true),
+      );
 
-      const { result: result2 } = renderHook(() => useLazyLoader('multi-key2', mockImport2, true));
+      const { result: result2 } = renderHook(() =>
+        useLazyLoader('multi-key2', mockImport2, true),
+      );
 
-      const { result: result3 } = renderHook(() => useLazyLoader('multi-key3', mockImport3, false));
+      const { result: result3 } = renderHook(() =>
+        useLazyLoader('multi-key3', mockImport3, false),
+      );
 
       // Assert
       await waitFor(() => {
@@ -215,9 +231,13 @@ describe('useLazyLoader', () => {
       const mockImport = vi.fn().mockResolvedValue({ default: MockComponent });
 
       // Act - Render two hooks with same key simultaneously
-      const { result: result1 } = renderHook(() => useLazyLoader('concurrent-key', mockImport, true));
+      const { result: result1 } = renderHook(() =>
+        useLazyLoader('concurrent-key', mockImport, true),
+      );
 
-      const { result: result2 } = renderHook(() => useLazyLoader('concurrent-key', mockImport, true));
+      const { result: result2 } = renderHook(() =>
+        useLazyLoader('concurrent-key', mockImport, true),
+      );
 
       // Assert - Both should resolve to same component
       await waitFor(() => {
@@ -233,12 +253,16 @@ describe('useLazyLoader', () => {
   describe('Error handling', () => {
     it('should handle import failure gracefully', async () => {
       // Arrange
-      const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
+      const consoleErrorSpy = vi
+        .spyOn(console, 'error')
+        .mockImplementation(() => {});
       const mockError = new Error('Import failed');
       const mockImport = vi.fn().mockRejectedValue(mockError);
 
       // Act
-      const { result } = renderHook(() => useLazyLoader('error-key', mockImport, true));
+      const { result } = renderHook(() =>
+        useLazyLoader('error-key', mockImport, true),
+      );
 
       // Assert - Should remain null on error
       expect(result.current).toBeNull();
@@ -267,10 +291,14 @@ describe('useLazyLoader', () => {
           {title}: {count}
         </div>
       );
-      const mockImport = vi.fn().mockResolvedValue({ default: MockComponentWithProps });
+      const mockImport = vi
+        .fn()
+        .mockResolvedValue({ default: MockComponentWithProps });
 
       // Act
-      const { result } = renderHook(() => useLazyLoader<TestProps>('typed-key', mockImport, true));
+      const { result } = renderHook(() =>
+        useLazyLoader<TestProps>('typed-key', mockImport, true),
+      );
 
       // Assert
       await waitFor(() => {
@@ -303,14 +331,18 @@ describe('useLazyLoader', () => {
       const mockImport2 = vi.fn().mockResolvedValue({ default: Component2 });
 
       // Act - First hook with Component1
-      const { result: result1 } = renderHook(() => useLazyLoader('duplicate-key', mockImport1, true));
+      const { result: result1 } = renderHook(() =>
+        useLazyLoader('duplicate-key', mockImport1, true),
+      );
 
       await waitFor(() => {
         expect(result1.current).toBe(Component1);
       });
 
       // Act - Second hook with same key but different import function
-      const { result: result2 } = renderHook(() => useLazyLoader('duplicate-key', mockImport2, true));
+      const { result: result2 } = renderHook(() =>
+        useLazyLoader('duplicate-key', mockImport2, true),
+      );
 
       await waitFor(() => {
         expect(result2.current).toBe(Component1); // Should still get Component1 from cache
@@ -323,11 +355,15 @@ describe('useLazyLoader', () => {
 
     it('should handle import function returning null', async () => {
       // Arrange
-      const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
+      const consoleErrorSpy = vi
+        .spyOn(console, 'error')
+        .mockImplementation(() => {});
       const mockImport = vi.fn().mockResolvedValue(null);
 
       // Act
-      const { result } = renderHook(() => useLazyLoader('null-key', mockImport, true));
+      const { result } = renderHook(() =>
+        useLazyLoader('null-key', mockImport, true),
+      );
 
       // Assert - Should remain null
       await waitFor(() => {
@@ -335,7 +371,7 @@ describe('useLazyLoader', () => {
       });
 
       // Wait a bit to ensure state update attempts have been processed
-      await new Promise(resolve => setTimeout(resolve, 50));
+      await new Promise((resolve) => setTimeout(resolve, 50));
 
       // Component should be null since the import resolved to null
       expect(result.current).toBeNull();
@@ -348,11 +384,17 @@ describe('useLazyLoader', () => {
 
     it('should handle import function returning object without default property', async () => {
       // Arrange
-      const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
-      const mockImport = vi.fn().mockResolvedValue({ notDefault: () => <div>Wrong</div> });
+      const consoleErrorSpy = vi
+        .spyOn(console, 'error')
+        .mockImplementation(() => {});
+      const mockImport = vi
+        .fn()
+        .mockResolvedValue({ notDefault: () => <div>Wrong</div> });
 
       // Act
-      const { result } = renderHook(() => useLazyLoader('no-default-key', mockImport, true));
+      const { result } = renderHook(() =>
+        useLazyLoader('no-default-key', mockImport, true),
+      );
 
       // Assert - Should remain null since there's no default export
       await waitFor(() => {
@@ -360,7 +402,7 @@ describe('useLazyLoader', () => {
       });
 
       // Wait a bit to ensure state update attempts have been processed
-      await new Promise(resolve => setTimeout(resolve, 50));
+      await new Promise((resolve) => setTimeout(resolve, 50));
 
       expect(result.current).toBeNull();
       expect(consoleErrorSpy).toHaveBeenCalledWith(
@@ -399,7 +441,9 @@ describe('useLazyLoader', () => {
 
     it('should not call import function when isActive is false initially and remains false', async () => {
       // Arrange
-      const mockImport = vi.fn().mockResolvedValue({ default: () => <div>Test</div> });
+      const mockImport = vi
+        .fn()
+        .mockResolvedValue({ default: () => <div>Test</div> });
 
       // Act
       const { result, rerender } = renderHook(
@@ -413,7 +457,7 @@ describe('useLazyLoader', () => {
       rerender({ isActive: false });
 
       // Wait a bit to ensure no async operations are triggered
-      await new Promise(resolve => setTimeout(resolve, 100));
+      await new Promise((resolve) => setTimeout(resolve, 100));
 
       // Assert
       expect(result.current).toBeNull();

+ 13 - 7
apps/app/src/client/util/use-lazy-loader.ts → apps/app/src/components/utils/use-lazy-loader.ts

@@ -1,5 +1,5 @@
 import type React from 'react';
-import { useState, useEffect, useCallback } from 'react';
+import { useCallback, useEffect, useState } from 'react';
 
 type ComponentModule<T> = { default: React.ComponentType<T> };
 
@@ -55,9 +55,11 @@ export const useLazyLoader = <T extends Record<string, unknown>>(
   importFn: () => Promise<{ default: React.ComponentType<T> }>,
   isActive: boolean,
 ): React.ComponentType<T> | null => {
-  const [Component, setComponent] = useState<React.ComponentType<T> | null>(null);
+  const [Component, setComponent] = useState<React.ComponentType<T> | null>(
+    null,
+  );
 
-  const memoizedImportFn = useCallback(importFn, [importFn, importKey]);
+  const memoizedImportFn = useCallback(importFn, []);
 
   useEffect(() => {
     if (isActive && !Component) {
@@ -65,15 +67,19 @@ export const useLazyLoader = <T extends Record<string, unknown>>(
         .then((mod) => {
           if (mod?.default) {
             setComponent(() => mod.default);
-          }
-          else {
+          } else {
             // eslint-disable-next-line no-console
-            console.error(`Failed to load component with key "${importKey}": Module or default export is missing`);
+            console.error(
+              `Failed to load component with key "${importKey}": Module or default export is missing`,
+            );
           }
         })
         .catch((error) => {
           // eslint-disable-next-line no-console
-          console.error(`Failed to load component with key "${importKey}":`, error);
+          console.error(
+            `Failed to load component with key "${importKey}":`,
+            error,
+          );
         });
     }
   }, [isActive, Component, importKey, memoizedImportFn]);

+ 1 - 1
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantManagementModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 import { useAiAssistantManagementModalStatus } from '../../../states/modal/ai-assistant-management';
 

+ 1 - 1
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/dynamic.tsx

@@ -1,7 +1,7 @@
 import type { FC } from 'react';
 import { memo } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 import { useAiAssistantSidebarStatus } from '../../../states';
 

+ 1 - 1
apps/app/src/features/openai/client/components/AiAssistant/Sidebar/DeleteAiAssistantModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 import type { DeleteAiAssistantModalProps } from './DeleteAiAssistantModal';
 

+ 1 - 1
apps/app/src/features/page-bulk-export/client/components/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 import { usePageBulkExportSelectModalStatus } from '../states/modal';
 

+ 1 - 1
apps/app/src/features/search/client/components/SearchPage/SearchOptionModal/dynamic.tsx

@@ -1,6 +1,6 @@
 import type { JSX } from 'react';
 
-import { useLazyLoader } from '~/client/util/use-lazy-loader';
+import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 type SearchOptionModalProps = {
   isOpen: boolean;

+ 6 - 11
apps/app/src/pages/[[...path]]/index.page.tsx

@@ -7,20 +7,17 @@ import Head from 'next/head';
 import { isClient } from '@growi/core/dist/utils';
 import EventEmitter from 'events';
 
-// eslint-disable-next-line no-restricted-imports
+// biome-ignore-start lint/style/noRestrictedImports: no-problem lazy loaded components
 import { DescendantsPageListModalLazyLoaded } from '~/client/components/DescendantsPageListModal';
-// eslint-disable-next-line no-restricted-imports
 import { ConflictDiffModalLazyLoaded } from '~/client/components/PageEditor/ConflictDiffModal';
-// eslint-disable-next-line no-restricted-imports
 import { DrawioModalLazyLoaded } from '~/client/components/PageEditor/DrawioModal';
-// eslint-disable-next-line no-restricted-imports
 import { HandsontableModalLazyLoaded } from '~/client/components/PageEditor/HandsontableModal';
-// eslint-disable-next-line no-restricted-imports
 import { LinkEditModalLazyLoaded } from '~/client/components/PageEditor/LinkEditModal';
-// eslint-disable-next-line no-restricted-imports
 import { TagEditModalLazyLoaded } from '~/client/components/PageTags/TagEditModal';
-// eslint-disable-next-line no-restricted-imports
 import { TemplateModalLazyLoaded } from '~/client/components/TemplateModal';
+
+// biome-ignore-end lint/style/noRestrictedImports: no-problem lazy loaded components
+
 import { BasicLayout } from '~/components/Layout/BasicLayout';
 import { PageView } from '~/components/PageView/PageView';
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
@@ -63,11 +60,11 @@ declare global {
   var globalEmitter: EventEmitter;
 }
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 const GrowiContextualSubNavigation = dynamic(
   () => import('~/client/components/Navbar/GrowiContextualSubNavigation'),
   { ssr: false },
 );
-
 const GrowiPluginsActivator = dynamic(
   () =>
     import(
@@ -75,7 +72,6 @@ const GrowiPluginsActivator = dynamic(
     ).then((mod) => mod.GrowiPluginsActivator),
   { ssr: false },
 );
-
 const DisplaySwitcher = dynamic(
   () =>
     import('~/client/components/Page/DisplaySwitcher').then(
@@ -90,12 +86,10 @@ const PageStatusAlert = dynamic(
     ),
   { ssr: false },
 );
-
 const UnsavedAlertDialog = dynamic(
   () => import('~/client/components/UnsavedAlertDialog'),
   { ssr: false },
 );
-
 const EditablePageEffects = dynamic(
   () =>
     import('~/client/components/Page/EditablePageEffects').then(
@@ -103,6 +97,7 @@ const EditablePageEffects = dynamic(
     ),
   { ssr: false },
 );
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 type Props = EachProps | InitialProps;
 

+ 1 - 0
apps/app/src/pages/_private-legacy-pages/index.page.tsx

@@ -31,6 +31,7 @@ const PrivateLegacyPage: NextPage<Props> = (props: Props) => {
   const { t } = useTranslation();
 
   const PrivateLegacyPages = dynamic(
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     () => import('~/features/search/client/components/PrivateLegacyPages'),
     { ssr: false },
   );

+ 1 - 1
apps/app/src/pages/_search/index.page.tsx

@@ -1,7 +1,6 @@
 import { useEffect } from 'react';
 import dynamic from 'next/dynamic';
 import Head from 'next/head';
-import { useRouter } from 'next/router';
 import { useTranslation } from 'next-i18next';
 
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
@@ -23,6 +22,7 @@ const SearchResultLayout = dynamic(
 );
 const SearchPage = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/features/search/client/components/SearchPage').then(
       (mod) => mod.SearchPage,
     ),

+ 1 - 0
apps/app/src/pages/admin/[...path].page.tsx

@@ -8,6 +8,7 @@ import {
 
 const AdminNotFoundPage = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/NotFoundPage').then(
       (mod) => mod.AdminNotFoundPage,
     ),

+ 1 - 0
apps/app/src/pages/admin/_shared/AdminPageFrame.tsx

@@ -12,6 +12,7 @@ const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), {
 });
 const ForbiddenPage = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/ForbiddenPage').then(
       (mod) => mod.ForbiddenPage,
     ),

+ 2 - 0
apps/app/src/pages/admin/ai-integration.page.tsx

@@ -16,6 +16,7 @@ import {
 const AiIntegration = dynamic(
   () =>
     import(
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       '~/features/openai/client/components/AiIntegration/AiIntegration'
     ).then((mod) => mod.AiIntegration),
   { ssr: false },
@@ -23,6 +24,7 @@ const AiIntegration = dynamic(
 const AiIntegrationDisableMode = dynamic(
   () =>
     import(
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       '~/features/openai/client/components/AiIntegration/AiIntegrationDisableMode'
     ).then((mod) => mod.AiIntegrationDisableMode),
   { ssr: false },

+ 4 - 3
apps/app/src/pages/admin/app.page.tsx

@@ -9,6 +9,7 @@ import {
 } from './_shared';
 
 const AppSettingsPageContents = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/App/AppSettingsPageContents'),
   { ssr: false },
 );
@@ -23,9 +24,9 @@ AdminAppPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('headers.app_settings', { ns: 'commons' }),
   containerFactories: [
     async () => {
-      const AdminAppContainer = (
-        await import('~/client/services/AdminAppContainer')
-      ).default;
+      const AdminAppContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminAppContainer')).default;
       return new AdminAppContainer();
     },
   ],

+ 1 - 0
apps/app/src/pages/admin/audit-log.page.tsx

@@ -20,6 +20,7 @@ import {
 
 const AuditLogManagement = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/AuditLogManagement').then(
       (mod) => mod.AuditLogManagement,
     ),

+ 2 - 0
apps/app/src/pages/admin/customize.page.tsx

@@ -15,6 +15,7 @@ import {
 } from './_shared';
 
 const CustomizeSettingContents = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/Customize/Customize'),
   { ssr: false },
 );
@@ -47,6 +48,7 @@ AdminCustomizeSettingsPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('customize_settings.customize_settings'),
   containerFactories: [
     async () => {
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       const C = (await import('~/client/services/AdminCustomizeContainer'))
         .default;
       return new C();

+ 4 - 3
apps/app/src/pages/admin/data-transfer.page.tsx

@@ -9,6 +9,7 @@ import {
 } from './_shared';
 
 const G2GDataTransferPage = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/G2GDataTransfer'),
   { ssr: false },
 );
@@ -23,9 +24,9 @@ DataTransferPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('g2g_data_transfer.data_transfer', { ns: 'commons' }),
   containerFactories: [
     async () => {
-      const AdminAppContainer = (
-        await import('~/client/services/AdminAppContainer')
-      ).default;
+      const AdminAppContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminAppContainer')).default;
       return new AdminAppContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/export.page.tsx

@@ -9,6 +9,7 @@ import {
 } from './_shared';
 
 const ExportArchiveDataPage = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/ExportArchiveDataPage'),
   { ssr: false },
 );
@@ -23,9 +24,9 @@ AdminExportDataArchivePage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('export_management.export_archive_data'),
   containerFactories: [
     async () => {
-      const AdminAppContainer = (
-        await import('~/client/services/AdminAppContainer')
-      ).default;
+      const AdminAppContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminAppContainer')).default;
       return new AdminAppContainer();
     },
   ],

+ 5 - 3
apps/app/src/pages/admin/global-notification/[globalNotificationId].page.tsx

@@ -12,6 +12,7 @@ import {
 
 const ManageGlobalNotification = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/Notification/ManageGlobalNotification'),
   { ssr: false },
 );
@@ -26,6 +27,7 @@ const AdminGlobalNotificationDetailPage: NextPageWithLayout<Props> = () => {
     : globalNotificationId;
 
   useEffect(() => {
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     const toastErrorPromise = import('~/client/util/toastr').then(
       (mod) => mod.toastError,
     );
@@ -55,9 +57,9 @@ AdminGlobalNotificationDetailPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('external_notification.external_notification'),
   containerFactories: [
     async () => {
-      const AdminNotificationContainer = (
-        await import('~/client/services/AdminNotificationContainer')
-      ).default;
+      const AdminNotificationContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminNotificationContainer')).default;
       return new AdminNotificationContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/global-notification/new.page.tsx

@@ -10,6 +10,7 @@ import {
 
 const ManageGlobalNotification = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/Notification/ManageGlobalNotification'),
   { ssr: false },
 );
@@ -24,9 +25,9 @@ AdminGlobalNotificationNewPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('external_notification.external_notification'),
   containerFactories: [
     async () => {
-      const AdminNotificationContainer = (
-        await import('~/client/services/AdminNotificationContainer')
-      ).default;
+      const AdminNotificationContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminNotificationContainer')).default;
       return new AdminNotificationContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/importer.page.tsx

@@ -9,6 +9,7 @@ import {
 } from './_shared';
 
 const DataImportPageContents = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/ImportData/ImportDataPageContents'),
   { ssr: false },
 );
@@ -23,9 +24,9 @@ AdminDataImportPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('importer_management.import_data'),
   containerFactories: [
     async () => {
-      const AdminImportContainer = (
-        await import('~/client/services/AdminImportContainer')
-      ).default;
+      const AdminImportContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminImportContainer')).default;
       return new AdminImportContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/index.page.tsx

@@ -14,6 +14,7 @@ import {
 } from './_shared';
 
 const AdminHome = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/AdminHome/AdminHome'),
   { ssr: false },
 );
@@ -45,9 +46,9 @@ AdminHomepage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('wiki_management_homepage'),
   containerFactories: [
     async () => {
-      const AdminHomeContainer = (
-        await import('~/client/services/AdminHomeContainer')
-      ).default;
+      const AdminHomeContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminHomeContainer')).default;
       return new AdminHomeContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/markdown.page.tsx

@@ -10,6 +10,7 @@ import {
 
 const MarkDownSettingContents = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/MarkdownSetting/MarkDownSettingContents'),
   { ssr: false },
 );
@@ -24,9 +25,9 @@ AdminMarkdownPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('markdown_settings.markdown_settings'),
   containerFactories: [
     async () => {
-      const AdminMarkDownContainer = (
-        await import('~/client/services/AdminMarkDownContainer')
-      ).default;
+      const AdminMarkDownContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminMarkDownContainer')).default;
       return new AdminMarkDownContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/notification.page.tsx

@@ -9,6 +9,7 @@ import {
 } from './_shared';
 
 const NotificationSetting = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/Notification/NotificationSetting'),
   { ssr: false },
 );
@@ -23,9 +24,9 @@ AdminExternalNotificationPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('external_notification.external_notification'),
   containerFactories: [
     async () => {
-      const AdminNotificationContainer = (
-        await import('~/client/services/AdminNotificationContainer')
-      ).default;
+      const AdminNotificationContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminNotificationContainer')).default;
       return new AdminNotificationContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/plugins.page.tsx

@@ -10,6 +10,7 @@ import {
 
 const PluginsExtensionPageContents = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/features/growi-plugin/client/Admin/components').then(
       (mod) => mod.PluginsExtensionPageContents,
     ),
@@ -26,9 +27,9 @@ AdminAppPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('plugins.plugins'),
   containerFactories: [
     async () => {
-      const AdminAppContainer = (
-        await import('~/client/services/AdminAppContainer')
-      ).default;
+      const AdminAppContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminAppContainer')).default;
       return new AdminAppContainer();
     },
   ],

+ 1 - 0
apps/app/src/pages/admin/search.page.tsx

@@ -20,6 +20,7 @@ import {
 
 const FullTextSearchManagement = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/FullTextSearchManagement').then(
       (mod) => mod.FullTextSearchManagement,
     ),

+ 3 - 0
apps/app/src/pages/admin/security.page.tsx

@@ -15,6 +15,7 @@ import {
 } from './_shared';
 
 const SecurityManagement = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/Security/SecurityManagement'),
   { ssr: false },
 );
@@ -37,6 +38,7 @@ const AdminSecuritySettingsPage: NextPageWithLayout<Props> = (props: Props) => {
   return <SecurityManagement />;
 };
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 AdminSecuritySettingsPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('security_settings.security_settings'),
   containerFactories: [
@@ -84,6 +86,7 @@ AdminSecuritySettingsPage.getLayout = createAdminPageLayout<Props>({
     },
   ],
 });
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 export const getServerSideProps: GetServerSideProps<Props> = async (
   context: GetServerSidePropsContext,

+ 5 - 3
apps/app/src/pages/admin/slack-integration-legacy.page.tsx

@@ -10,6 +10,7 @@ import {
 const LegacySlackIntegration = dynamic(
   () =>
     import(
+      // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
       '~/client/components/Admin/LegacySlackIntegration/LegacySlackIntegration'
     ),
   { ssr: false },
@@ -25,9 +26,10 @@ AdminLegacySlackIntegrationPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('slack_integration_legacy.slack_integration_legacy'),
   containerFactories: [
     async () => {
-      const AdminSlackIntegrationLegacyContainer = (
-        await import('~/client/services/AdminSlackIntegrationLegacyContainer')
-      ).default;
+      const AdminSlackIntegrationLegacyContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminSlackIntegrationLegacyContainer'))
+          .default;
       return new AdminSlackIntegrationLegacyContainer();
     },
   ],

+ 1 - 0
apps/app/src/pages/admin/slack-integration.page.tsx

@@ -13,6 +13,7 @@ import {
 
 const SlackIntegration = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/SlackIntegration/SlackIntegration').then(
       (mod) => mod.SlackIntegration,
     ),

+ 1 - 0
apps/app/src/pages/admin/user-group-detail/[userGroupId].page.tsx

@@ -13,6 +13,7 @@ import {
 } from '../_shared';
 
 const UserGroupDetailPage = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/UserGroupDetail/UserGroupDetailPage'),
   { ssr: false },
 );

+ 1 - 0
apps/app/src/pages/admin/user-groups.page.tsx

@@ -15,6 +15,7 @@ import {
 
 const UserGroupPage = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Admin/UserGroup/UserGroupPage').then(
       (mod) => mod.UserGroupPage,
     ),

+ 5 - 3
apps/app/src/pages/admin/users/external-accounts.page.tsx

@@ -8,6 +8,7 @@ import {
 } from '../_shared';
 
 const ManageExternalAccount = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/ManageExternalAccount'),
   { ssr: false },
 );
@@ -22,9 +23,10 @@ AdminExternalAccountsPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('user_management.external_account'),
   containerFactories: [
     async () => {
-      const AdminExternalAccountsContainer = (
-        await import('~/client/services/AdminExternalAccountsContainer')
-      ).default;
+      const AdminExternalAccountsContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminExternalAccountsContainer'))
+          .default;
       return new AdminExternalAccountsContainer();
     },
   ],

+ 4 - 3
apps/app/src/pages/admin/users/index.page.tsx

@@ -14,6 +14,7 @@ import {
 } from '../_shared';
 
 const UserManagement = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Admin/UserManagement'),
   { ssr: false },
 );
@@ -33,9 +34,9 @@ AdminUserManagementPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('user_management.user_management'),
   containerFactories: [
     async () => {
-      const AdminUsersContainer = (
-        await import('~/client/services/AdminUsersContainer')
-      ).default;
+      const AdminUsersContainer =
+        // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
+        (await import('~/client/services/AdminUsersContainer')).default;
       return new AdminUsersContainer();
     },
   ],

+ 1 - 1
apps/app/src/pages/forgot-password/index.page.tsx

@@ -1,4 +1,3 @@
-import React from 'react';
 import type {
   GetServerSideProps,
   GetServerSidePropsContext,
@@ -20,6 +19,7 @@ import type { ServerConfigurationProps } from './types';
 import { useHydrateServerConfigurationAtoms } from './use-hydrate-server-configurations';
 
 const PasswordResetRequestForm = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/PasswordResetRequestForm'),
   { ssr: false },
 );

+ 2 - 0
apps/app/src/pages/installer/index.page.tsx

@@ -20,6 +20,7 @@ import {
 import { useCustomTitle } from '../utils/page-title-customization';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 const InstallerForm = dynamic(
   () => import('~/client/components/InstallerForm'),
   { ssr: false },
@@ -32,6 +33,7 @@ const CustomNavAndContents = dynamic(
   () => import('~/client/components/CustomNavigation/CustomNavAndContents'),
   { ssr: false },
 );
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 type ServerConfigurationProps = {
   minPasswordLength: number;

+ 1 - 0
apps/app/src/pages/invited/index.page.tsx

@@ -23,6 +23,7 @@ import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 
 const InvitedForm = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/InvitedForm').then((mod) => mod.InvitedForm),
   { ssr: false },
 );

+ 1 - 0
apps/app/src/pages/login/index.page.tsx

@@ -31,6 +31,7 @@ import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import styles from './index.module.scss';
 
 const LoginForm = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/LoginForm').then((mod) => mod.LoginForm),
   { ssr: false },
 );

+ 1 - 0
apps/app/src/pages/maintenance/index.page.tsx

@@ -15,6 +15,7 @@ import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 
 const Maintenance = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/Maintenance').then((mod) => mod.Maintenance),
   { ssr: false },
 );

+ 2 - 0
apps/app/src/pages/me/index.page.tsx

@@ -28,12 +28,14 @@ import { useHydrateServerConfigurationAtoms } from './use-hydrate-server-configu
 const logger = loggerFactory('growi:pages:me');
 
 const PersonalSettings = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Me/PersonalSettings'),
   { ssr: false },
 );
 // const MyDraftList = dynamic(() => import('~/components/MyDraftList/MyDraftList'), { ssr: false });
 const InAppNotificationPage = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/InAppNotification/InAppNotificationPage').then(
       (mod) => mod.InAppNotificationPage,
     ),

+ 1 - 0
apps/app/src/pages/reset-password/index.page.tsx

@@ -23,6 +23,7 @@ type Props = CommonInitialProps &
   };
 
 const PasswordResetExecutionForm = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/PasswordResetExecutionForm'),
   { ssr: false },
 );

+ 1 - 0
apps/app/src/pages/share/[[...path]]/index.page.tsx

@@ -35,6 +35,7 @@ import type { InitialProps } from './types';
 registerPageToShowRevisionWithMeta();
 
 const GrowiContextualSubNavigation = dynamic(
+  // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
   () => import('~/client/components/Navbar/GrowiContextualSubNavigation'),
   { ssr: false },
 );

+ 2 - 0
apps/app/src/pages/tags/index.page.tsx

@@ -32,12 +32,14 @@ import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 
 const PAGING_LIMIT = 10;
 
+// biome-ignore-start lint/style/noRestrictedImports: no-problem dynamic import
 const TagList = dynamic(() => import('~/client/components/TagList'), {
   ssr: false,
 });
 const TagCloudBox = dynamic(() => import('~/client/components/TagCloudBox'), {
   ssr: false,
 });
+// biome-ignore-end lint/style/noRestrictedImports: no-problem dynamic import
 
 type Props = CommonInitialProps &
   CommonEachProps &

+ 2 - 0
apps/app/src/pages/trash/index.page.tsx

@@ -8,6 +8,7 @@ import {
   isUsersTopPage,
 } from '@growi/core/dist/utils/page-path-utils';
 
+// biome-ignore lint/style/noRestrictedImports: no-problem lazy loaded components
 import { EmptyTrashModalLazyLoaded } from '~/client/components/EmptyTrashModal';
 import { PagePathNavTitle } from '~/components/Common/PagePathNavTitle';
 import { BasicLayout } from '~/components/Layout/BasicLayout';
@@ -32,6 +33,7 @@ import { useHydrateServerConfigurationAtoms } from './use-hydrate-server-configu
 
 const TrashPageList = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/TrashPageList').then(
       (mod) => mod.TrashPageList,
     ),

+ 1 - 0
apps/app/src/pages/user-activation/index.page.tsx

@@ -24,6 +24,7 @@ import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 
 const CompleteUserRegistrationForm = dynamic(
   () =>
+    // biome-ignore lint/style/noRestrictedImports: no-problem dynamic import
     import('~/client/components/CompleteUserRegistrationForm').then(
       (mod) => mod.CompleteUserRegistrationForm,
     ),