Browse Source

Upgrade Storybook to v10 (#30442)

GitOrigin-RevId: 9f51624bc2b34b6746d1854969173b44c9c9cf9a
Alf Eaton 3 months ago
parent
commit
ce4ca192ee
63 changed files with 274 additions and 719 deletions
  1. 172 632
      package-lock.json
  2. 1 0
      services/web/.eslintrc.js
  3. 2 0
      services/web/.gitignore
  4. 15 6
      services/web/.storybook/main.ts
  5. 2 2
      services/web/.storybook/manager.ts
  6. 1 1
      services/web/.storybook/preview.tsx
  7. 1 1
      services/web/.storybook/utils/with-split-tests.tsx
  8. 1 1
      services/web/cypress/support/shared/commands/intercept-async.ts
  9. 1 3
      services/web/cypress/support/shared/commands/linked-file.ts
  10. 4 5
      services/web/cypress/support/shared/commands/upload.ts
  11. 4 2
      services/web/frontend/js/features/ide-react/components/resize/horizontal-resize-handle.tsx
  12. 4 2
      services/web/frontend/js/features/ide-react/components/resize/vertical-resize-handle.tsx
  13. 1 1
      services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts
  14. 1 1
      services/web/frontend/js/features/source-editor/extensions/visual/utils/typeset-content.ts
  15. 1 1
      services/web/frontend/js/features/utils/ciam-icon.ts
  16. 4 2
      services/web/frontend/js/infrastructure/error-boundary.tsx
  17. 1 1
      services/web/frontend/stories/decorators/ide-redesign.tsx
  18. 1 1
      services/web/frontend/stories/deprecated-browser.stories.tsx
  19. 1 1
      services/web/frontend/stories/docs/cloud-builds.mdx
  20. 2 2
      services/web/frontend/stories/docs/feature-flags.mdx
  21. 1 1
      services/web/frontend/stories/docs/foundations.mdx
  22. 1 1
      services/web/frontend/stories/editor/pdf-compile-button.stories.tsx
  23. 1 1
      services/web/frontend/stories/editor/synctex-toasts.stories.tsx
  24. 1 1
      services/web/frontend/stories/loading/loading.stories.tsx
  25. 1 1
      services/web/frontend/stories/modals/unsaved-docs-locked-modal.stories.tsx
  26. 1 1
      services/web/frontend/stories/online-users.stories.tsx
  27. 1 1
      services/web/frontend/stories/pdf-log-entry.stories.tsx
  28. 1 1
      services/web/frontend/stories/shared/autocomplete.stories.tsx
  29. 1 1
      services/web/frontend/stories/shared/badge.stories.tsx
  30. 1 1
      services/web/frontend/stories/shared/billing-period-toggle.stories.tsx
  31. 1 1
      services/web/frontend/stories/shared/button.stories.tsx
  32. 1 1
      services/web/frontend/stories/shared/buttons.stories.tsx
  33. 1 1
      services/web/frontend/stories/shared/dropdown-menu.stories.tsx
  34. 1 1
      services/web/frontend/stories/shared/ds/ds-button.stories.tsx
  35. 1 1
      services/web/frontend/stories/shared/ds/ds-form-check.stories.tsx
  36. 1 1
      services/web/frontend/stories/shared/ds/ds-form-control.stories.tsx
  37. 1 1
      services/web/frontend/stories/shared/ds/ds-form-radio.stories.tsx
  38. 1 1
      services/web/frontend/stories/shared/ds/ds-selection-group.stories.tsx
  39. 1 1
      services/web/frontend/stories/shared/ds/ds-six-digits-input.stories.tsx
  40. 1 1
      services/web/frontend/stories/shared/form/form-check.stories.tsx
  41. 1 1
      services/web/frontend/stories/shared/form/form-input.stories.tsx
  42. 1 1
      services/web/frontend/stories/shared/form/form-radio.stories.tsx
  43. 1 1
      services/web/frontend/stories/shared/form/form-select.stories.tsx
  44. 1 1
      services/web/frontend/stories/shared/form/form-textarea.stories.tsx
  45. 1 1
      services/web/frontend/stories/shared/icon-button.stories.tsx
  46. 1 1
      services/web/frontend/stories/shared/labeled-divider.stories.tsx
  47. 1 1
      services/web/frontend/stories/shared/loading-spinner.stories.tsx
  48. 1 1
      services/web/frontend/stories/shared/menu-bar.stories.tsx
  49. 1 1
      services/web/frontend/stories/shared/modal.stories.tsx
  50. 1 1
      services/web/frontend/stories/shared/row.stories.tsx
  51. 1 1
      services/web/frontend/stories/shared/select.stories.tsx
  52. 1 1
      services/web/frontend/stories/shared/split-button.stories.tsx
  53. 1 1
      services/web/frontend/stories/shared/split-test-badge.stories.tsx
  54. 1 1
      services/web/frontend/stories/shared/start-free-trial-button.stories.tsx
  55. 1 1
      services/web/frontend/stories/shared/tag.stories.tsx
  56. 1 1
      services/web/frontend/stories/shared/tooltip.stories.tsx
  57. 1 1
      services/web/frontend/stories/shared/upgrade-prompt.stories.tsx
  58. 1 1
      services/web/frontend/stories/source-editor/source-editor.stories.tsx
  59. 1 1
      services/web/frontend/stories/subscription/active-subscription.stories.tsx
  60. 1 1
      services/web/frontend/stories/word-count-modal.stories.tsx
  61. 1 1
      services/web/modules/full-project-search/stories/full-project-search.stories.tsx
  62. 12 12
      services/web/package.json
  63. 1 1
      services/web/tsconfig.json

File diff suppressed because it is too large
+ 172 - 632
package-lock.json


+ 1 - 0
services/web/.eslintrc.js

@@ -10,6 +10,7 @@ module.exports = {
     'plugin:@typescript-eslint/recommended',
     'standard',
     'prettier',
+    'plugin:storybook/recommended',
   ],
   plugins: ['@overleaf'],
   env: {

+ 2 - 0
services/web/.gitignore

@@ -33,3 +33,5 @@ frontend/js/features/source-editor/lezer-bibtex/bibtex.mjs
 frontend/js/features/source-editor/lezer-bibtex/bibtex.terms.mjs
 
 !**/fixtures/**/*.log
+
+debug-storybook.log

+ 15 - 6
services/web/.storybook/main.ts

@@ -1,7 +1,14 @@
+// This file has been automatically migrated to valid ESM format by Storybook.
+import { fileURLToPath } from 'node:url'
+import { createRequire } from 'node:module'
 import type { StorybookConfig } from '@storybook/react-webpack5'
-import path from 'node:path'
+import path, { dirname } from 'node:path'
 import MiniCssExtractPlugin from 'mini-css-extract-plugin'
 
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = dirname(__filename)
+const require = createRequire(import.meta.url)
+
 const rootDir = path.resolve(__dirname, '..')
 
 // NOTE: must be set before webpack config is imported
@@ -20,17 +27,18 @@ const config: StorybookConfig = {
   core: {
     disableTelemetry: true,
   },
+
   staticDirs: [path.join(rootDir, 'public')],
+
   stories: [
     path.join(rootDir, 'frontend/stories/**/*.stories.{js,jsx,ts,tsx}'),
     path.join(rootDir, 'modules/**/stories/**/*.stories.{js,jsx,ts,tsx}'),
     path.join(rootDir, 'frontend/stories/**/*.mdx'),
     path.join(rootDir, 'modules/**/stories/**/*.mdx'),
   ],
+
   addons: [
     getAbsolutePath('@storybook/addon-links'),
-    getAbsolutePath('@storybook/addon-essentials'),
-    getAbsolutePath('@storybook/addon-interactions'),
     getAbsolutePath('@storybook/addon-a11y'),
     getAbsolutePath('@storybook/addon-designs'),
     getAbsolutePath('@storybook/addon-webpack5-compiler-babel'),
@@ -76,14 +84,14 @@ const config: StorybookConfig = {
         plugins: [new MiniCssExtractPlugin()],
       },
     },
+    getAbsolutePath('@storybook/addon-docs'),
   ],
+
   framework: {
     name: getAbsolutePath('@storybook/react-webpack5'),
     options: {},
   },
-  docs: {
-    autodocs: 'tag',
-  },
+
   babel: (options: Record<string, any>) => {
     return {
       ...options,
@@ -95,6 +103,7 @@ const config: StorybookConfig = {
       ],
     }
   },
+
   webpackFinal: storybookConfig => {
     return {
       ...storybookConfig,

+ 2 - 2
services/web/.storybook/manager.ts

@@ -1,5 +1,5 @@
-import { addons } from '@storybook/manager-api'
-import { create } from '@storybook/theming/create'
+import { addons } from 'storybook/manager-api'
+import { create } from 'storybook/theming/create'
 
 import './manager.css'
 

+ 1 - 1
services/web/.storybook/preview.tsx

@@ -1,4 +1,4 @@
-import type { Preview } from '@storybook/react'
+import type { Preview } from '@storybook/react-webpack5'
 
 // Storybook does not (currently) support async loading of "stories". Therefore
 // the strategy in frontend/js/i18n.ts does not work (because we cannot wait on

+ 1 - 1
services/web/.storybook/utils/with-split-tests.tsx

@@ -1,4 +1,4 @@
-import type { Meta } from '@storybook/react'
+import type { Meta } from '@storybook/react-webpack5'
 import _ from 'lodash'
 import { SplitTestContext } from '@/shared/context/split-test-context'
 

+ 1 - 1
services/web/cypress/support/shared/commands/intercept-async.ts

@@ -1,4 +1,4 @@
-import { RouteHandler, RouteMatcher } from 'cypress/types/net-stubbing'
+import type { RouteMatcher, RouteHandler } from 'cypress/types/net-stubbing'
 
 export const interceptAsync = (route: RouteMatcher, alias: string) => {
   const deferred: { resolve: (value: RouteHandler) => void } = {

+ 1 - 3
services/web/cypress/support/shared/commands/linked-file.ts

@@ -1,10 +1,8 @@
-import { HttpRequestInterceptor } from 'cypress/types/net-stubbing'
-
 export const interceptLinkedFile = () => {
   cy.intercept(
     { method: 'POST', url: '/project/*/linked_file' },
     cy
-      .spy((req: Parameters<HttpRequestInterceptor>[0]) => {
+      .spy(req => {
         req.reply({ statusCode: 200, body: { success: true } })
       })
       .as('linked-file-request')

+ 4 - 5
services/web/cypress/support/shared/commands/upload.ts

@@ -1,17 +1,16 @@
-import { HttpRequestInterceptor } from 'cypress/types/net-stubbing'
-
 export const interceptFileUpload = () => {
   cy.intercept(
     { method: 'POST', url: /\/project\/.*\/upload/ },
     cy
-      .spy((req: Parameters<HttpRequestInterceptor>[0]) => {
+      .spy(req => {
         const folderMatch = req.url.match(
           /project\/.*\/upload\?folder_id=[a-f0-9]{24}/
         )
-        if (!folderMatch) {
+        if (folderMatch) {
+          req.reply({ statusCode: 200, body: { success: true } })
+        } else {
           req.reply({ statusCode: 500, body: { success: false } })
         }
-        req.reply({ statusCode: 200, body: { success: true } })
       })
       .as('uploadRequest')
   )

+ 4 - 2
services/web/frontend/js/features/ide-react/components/resize/horizontal-resize-handle.tsx

@@ -1,7 +1,9 @@
-import { PanelResizeHandle } from 'react-resizable-panels'
+import {
+  PanelResizeHandle,
+  PanelResizeHandleProps,
+} from 'react-resizable-panels'
 import { FC, useEffect, useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import { PanelResizeHandleProps } from 'react-resizable-panels/dist/declarations/src/PanelResizeHandle'
 import classNames from 'classnames'
 
 type HorizontalResizeHandleOwnProps = {

+ 4 - 2
services/web/frontend/js/features/ide-react/components/resize/vertical-resize-handle.tsx

@@ -1,6 +1,8 @@
-import { PanelResizeHandle } from 'react-resizable-panels'
+import {
+  PanelResizeHandle,
+  PanelResizeHandleProps,
+} from 'react-resizable-panels'
 import { useTranslation } from 'react-i18next'
-import { PanelResizeHandleProps } from 'react-resizable-panels/dist/declarations/src/PanelResizeHandle'
 import classNames from 'classnames'
 
 export function VerticalResizeHandle(props: PanelResizeHandleProps) {

+ 1 - 1
services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts

@@ -583,7 +583,7 @@ type ElementSelector<T extends string, E extends HTMLElement = HTMLElement> = {
 const createSelector = <
   T extends string,
   E extends HTMLElement = T extends keyof HTMLElementTagNameMap
-    ? HTMLElementTagNameMap[T]
+    ? Extract<HTMLElementTagNameMap[T], HTMLElement>
     : HTMLElement,
 >({
   selector,

+ 1 - 1
services/web/frontend/js/features/source-editor/extensions/visual/utils/typeset-content.ts

@@ -78,7 +78,7 @@ export function typesetNodeIntoElement(
   let from = node.from
 
   const addMarkup = (markup: Markup, childNode: SyntaxNode) => {
-    const element = document.createElement(markup.elementType)
+    const element = document.createElement(markup.elementType) as HTMLElement
     if (markup.className) {
       element.classList.add(markup.className)
     }

+ 1 - 1
services/web/frontend/js/features/utils/ciam-icon.ts

@@ -1,6 +1,6 @@
 export function ciamIcon(type: 'error' | 'info', className?: string) {
   const elName = type === 'error' ? 'ph-warning-circle' : 'ph-info'
-  const icon = document.createElement(elName)
+  const icon = document.createElement(elName) as HTMLElement
   if (className) {
     icon.className = className
   }

+ 4 - 2
services/web/frontend/js/infrastructure/error-boundary.tsx

@@ -1,7 +1,9 @@
 import { captureException } from './error-reporter'
-import { withErrorBoundary as rebWithErrorBoundary } from 'react-error-boundary'
+import {
+  withErrorBoundary as rebWithErrorBoundary,
+  FallbackProps,
+} from 'react-error-boundary'
 import { ComponentType, ErrorInfo } from 'react'
-import { FallbackProps } from 'react-error-boundary/dist/declarations/src/types'
 
 function errorHandler(error: Error, errorInfo: ErrorInfo) {
   captureException(error, {

+ 1 - 1
services/web/frontend/stories/decorators/ide-redesign.tsx

@@ -1,4 +1,4 @@
-import { Decorator } from '@storybook/react'
+import { Decorator } from '@storybook/react-webpack5'
 
 export const IdeRedesign: Decorator = Story => (
   <div className="ide-redesign-main">

+ 1 - 1
services/web/frontend/stories/deprecated-browser.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, StoryObj } from '@storybook/react'
+import { Meta, StoryObj } from '@storybook/react-webpack5'
 import { DeprecatedBrowser } from '@/shared/components/deprecated-browser'
 
 const meta: Meta = {

+ 1 - 1
services/web/frontend/stories/docs/cloud-builds.mdx

@@ -1,4 +1,4 @@
-import { Meta } from '@storybook/blocks'
+import { Meta } from '@storybook/addon-docs/blocks'
 
 <Meta title="Storybook Guideline / Storybook builds" />
 

+ 2 - 2
services/web/frontend/stories/docs/feature-flags.mdx

@@ -1,4 +1,4 @@
-import { Canvas, Controls, Meta } from '@storybook/blocks'
+import { Canvas, Controls, Meta } from '@storybook/addon-docs/blocks'
 import * as FormatCurrency from './format-currency.stories'
 
 <Meta title="Storybook Guideline / Feature flags" />
@@ -22,7 +22,7 @@ export const splitTestsArgTypes = {
 
 2. Wrap your story with `withSplitTests`.
 
-Import `withSplitTests` and `Meta` from '@storybook/react' in your stories.
+Import `withSplitTests` and `Meta` from '@storybook/react-webpack5' in your stories.
 
 ```js
 export default {

+ 1 - 1
services/web/frontend/stories/docs/foundations.mdx

@@ -4,7 +4,7 @@ import {
   ColorPalette,
   Title,
   Typeset,
-} from '@storybook/blocks'
+} from '@storybook/addon-docs/blocks'
 import colors from '../../stylesheets/foundations/tokens/colors.json'
 import typography from '../../stylesheets/foundations/tokens/typography.json'
 import borderRadius from '../../stylesheets/foundations/tokens/borderRadius.json'

+ 1 - 1
services/web/frontend/stories/editor/pdf-compile-button.stories.tsx

@@ -1,5 +1,5 @@
 import { FC } from 'react'
-import type { Meta } from '@storybook/react'
+import type { Meta } from '@storybook/react-webpack5'
 import PdfCompileButton from '@/features/pdf-preview/components/pdf-compile-button'
 import { ScopeDecorator } from '../decorators/scope'
 import { CompileContext } from '@/shared/context/local-compile-context'

+ 1 - 1
services/web/frontend/stories/editor/synctex-toasts.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, StoryObj } from '@storybook/react'
+import { Meta, StoryObj } from '@storybook/react-webpack5'
 import { OLToast } from '@/shared/components/ol/ol-toast'
 import { SynctexFileErrorToast } from '@/features/pdf-preview/components/synctex-toasts'
 

+ 1 - 1
services/web/frontend/stories/loading/loading.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import { LoadingUI } from '@/features/ide-react/components/loading'
 import { EditorProviders } from '../../../test/frontend/helpers/editor-providers'
 import { PartialMeta } from '@/utils/meta'

+ 1 - 1
services/web/frontend/stories/modals/unsaved-docs-locked-modal.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, StoryObj } from '@storybook/react'
+import { Meta, StoryObj } from '@storybook/react-webpack5'
 import { UnsavedDocsLockedAlert } from '@/features/ide-react/components/unsaved-docs/unsaved-docs-locked-alert'
 import { ScopeDecorator } from '../decorators/scope'
 

+ 1 - 1
services/web/frontend/stories/online-users.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 import { OnlineUser } from '@/features/ide-react/context/online-users-context'
 import { OnlineUsersWidget } from '@/features/editor-navigation-toolbar/components/online-users-widget'
 

+ 1 - 1
services/web/frontend/stories/pdf-log-entry.stories.tsx

@@ -1,5 +1,5 @@
 import PdfLogEntry from '@/features/pdf-preview/components/pdf-log-entry'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import { ruleIds } from '@/ide/human-readable-logs/HumanReadableLogsHints'
 import { ScopeDecorator } from './decorators/scope'
 import { useMeta } from './hooks/use-meta'

+ 1 - 1
services/web/frontend/stories/shared/autocomplete.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, StoryObj } from '@storybook/react'
+import { Meta, StoryObj } from '@storybook/react-webpack5'
 import { useState } from 'react'
 import OLAutocomplete from '@/shared/components/ol/ol-autocomplete'
 

+ 1 - 1
services/web/frontend/stories/shared/badge.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import classnames from 'classnames'
 import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
 import Badge from '@/shared/components/badge/badge'

+ 1 - 1
services/web/frontend/stories/shared/billing-period-toggle.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import { useState } from 'react'
 import BillingPeriodToggle, {
   type BillingPeriod,

+ 1 - 1
services/web/frontend/stories/shared/button.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
 import OLButton from '@/shared/components/ol/ol-button'
 

+ 1 - 1
services/web/frontend/stories/shared/buttons.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, StoryObj } from '@storybook/react'
+import { Meta, StoryObj } from '@storybook/react-webpack5'
 import OLButton from '@/shared/components/ol/ol-button'
 import { ButtonProps } from '@/shared/components/types/button-props'
 

+ 1 - 1
services/web/frontend/stories/shared/dropdown-menu.stories.tsx

@@ -4,7 +4,7 @@ import {
   DropdownDivider,
   DropdownHeader,
 } from '@/shared/components/dropdown/dropdown-menu'
-import type { Meta } from '@storybook/react'
+import type { Meta } from '@storybook/react-webpack5'
 import OLDropdownMenuItem from '@/shared/components/ol/ol-dropdown-menu-item'
 import { IdeRedesign } from '../decorators/ide-redesign'
 

+ 1 - 1
services/web/frontend/stories/shared/ds/ds-button.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 import DSButton from '@/shared/components/ds/ds-button'
 

+ 1 - 1
services/web/frontend/stories/shared/ds/ds-form-check.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import DSFormCheckbox from '@/shared/components/ds/ds-form-checkbox'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 

+ 1 - 1
services/web/frontend/stories/shared/ds/ds-form-control.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 import DSFormControl from '@/shared/components/ds/ds-form-control'
 import DSFormText from '@/shared/components/ds/ds-form-text'

+ 1 - 1
services/web/frontend/stories/shared/ds/ds-form-radio.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import DSFormRadio from '@/shared/components/ds/ds-form-radio'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 

+ 1 - 1
services/web/frontend/stories/shared/ds/ds-selection-group.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, type StoryObj } from '@storybook/react'
+import { Meta, type StoryObj } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 import DSSelectionGroup from '@/shared/components/ds/ds-selection-group'
 import DSSelectionGroupItem from '@/shared/components/ds/ds-selection-group-item'

+ 1 - 1
services/web/frontend/stories/shared/ds/ds-six-digits-input.stories.tsx

@@ -1,5 +1,5 @@
 import { ComponentProps, useEffect, useState } from 'react'
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 import DSFormGroup from '@/shared/components/ds/ds-form-group'
 import DSFormLabel from '@/shared/components/ds/ds-form-label'

+ 1 - 1
services/web/frontend/stories/shared/form/form-check.stories.tsx

@@ -1,6 +1,6 @@
 import { useRef, useLayoutEffect } from 'react'
 import { Form } from 'react-bootstrap'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 import OLFormCheckbox from '@/shared/components/ol/ol-form-checkbox'
 

+ 1 - 1
services/web/frontend/stories/shared/form/form-input.stories.tsx

@@ -1,5 +1,5 @@
 import { Form } from 'react-bootstrap'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import FormGroup from '@/shared/components/form/form-group'
 import FormText from '@/shared/components/form/form-text'
 import FormControl from '@/shared/components/form/form-control'

+ 1 - 1
services/web/frontend/stories/shared/form/form-radio.stories.tsx

@@ -1,5 +1,5 @@
 import { Form } from 'react-bootstrap'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'
 
 const meta: Meta<(typeof Form)['Check']> = {

+ 1 - 1
services/web/frontend/stories/shared/form/form-select.stories.tsx

@@ -1,5 +1,5 @@
 import { Form, FormSelectProps } from 'react-bootstrap'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import FormGroup from '@/shared/components/form/form-group'
 import FormText from '@/shared/components/form/form-text'
 import { figmaDesignUrl } from '../../../../.storybook/utils/figma-design-url'

+ 1 - 1
services/web/frontend/stories/shared/form/form-textarea.stories.tsx

@@ -1,5 +1,5 @@
 import { Form } from 'react-bootstrap'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import FormGroup from '@/shared/components/form/form-group'
 import FormText from '@/shared/components/form/form-text'
 import FormControl from '@/shared/components/form/form-control'

+ 1 - 1
services/web/frontend/stories/shared/icon-button.stories.tsx

@@ -1,5 +1,5 @@
 import IconButton from '@/shared/components/button/icon-button'
-import type { Meta } from '@storybook/react'
+import type { Meta } from '@storybook/react-webpack5'
 import { useTranslation } from 'react-i18next'
 import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
 

+ 1 - 1
services/web/frontend/stories/shared/labeled-divider.stories.tsx

@@ -1,5 +1,5 @@
 import LabeledDivider from '@/shared/components/labeled-divider'
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 
 type Args = React.ComponentProps<typeof LabeledDivider>
 

+ 1 - 1
services/web/frontend/stories/shared/loading-spinner.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import LoadingSpinner, {
   FullSizeLoadingSpinner,
 } from '@/shared/components/loading-spinner'

+ 1 - 1
services/web/frontend/stories/shared/menu-bar.stories.tsx

@@ -2,7 +2,7 @@ import { DropdownDivider } from '@/shared/components/dropdown/dropdown-menu'
 import { MenuBar } from '@/shared/components/menu-bar/menu-bar'
 import { MenuBarDropdown } from '@/shared/components/menu-bar/menu-bar-dropdown'
 import { MenuBarOption } from '@/shared/components/menu-bar/menu-bar-option'
-import { Meta } from '@storybook/react/*'
+import { Meta } from '@storybook/react-webpack5'
 
 export const Default = () => {
   return (

+ 1 - 1
services/web/frontend/stories/shared/modal.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from './../../../.storybook/utils/figma-design-url'
 import {
   OLModal,

+ 1 - 1
services/web/frontend/stories/shared/row.stories.tsx

@@ -1,5 +1,5 @@
 import { Container, Row, Col } from 'react-bootstrap'
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 
 type Args = React.ComponentProps<typeof Row>
 

+ 1 - 1
services/web/frontend/stories/shared/select.stories.tsx

@@ -1,5 +1,5 @@
 import { Select } from '@/shared/components/select'
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 
 type Args = Pick<
   React.ComponentProps<typeof Select>,

+ 1 - 1
services/web/frontend/stories/shared/split-button.stories.tsx

@@ -1,5 +1,5 @@
 import { Fragment } from 'react'
-import type { Meta } from '@storybook/react'
+import type { Meta } from '@storybook/react-webpack5'
 import { useTranslation } from 'react-i18next'
 import {
   Dropdown,

+ 1 - 1
services/web/frontend/stories/shared/split-test-badge.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import SplitTestBadge from '../../js/shared/components/split-test-badge'
 import { SplitTestContext } from '../../js/shared/context/split-test-context'
 

+ 1 - 1
services/web/frontend/stories/shared/start-free-trial-button.stories.tsx

@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import StartFreeTrialButton from '../../js/shared/components/start-free-trial-button'
 import type { ButtonProps } from '../../js/shared/components/types/button-props'
 

+ 1 - 1
services/web/frontend/stories/shared/tag.stories.tsx

@@ -1,6 +1,6 @@
 import OLTagIcon from '@/shared/components/ol/ol-tag-icon'
 import Tag from '@/shared/components/tag'
-import type { Meta, StoryObj } from '@storybook/react'
+import type { Meta, StoryObj } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
 
 const meta: Meta<typeof Tag> = {

+ 1 - 1
services/web/frontend/stories/shared/tooltip.stories.tsx

@@ -1,6 +1,6 @@
 import OLButton from '@/shared/components/ol/ol-button'
 import OLTooltip from '@/shared/components/ol/ol-tooltip'
-import { Meta } from '@storybook/react'
+import { Meta } from '@storybook/react-webpack5'
 import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
 
 export const Tooltips = () => {

+ 1 - 1
services/web/frontend/stories/shared/upgrade-prompt.stories.tsx

@@ -1,5 +1,5 @@
 import { UpgradePrompt } from '@/shared/components/upgrade-prompt'
-import { StoryObj } from '@storybook/react/*'
+import { StoryObj } from '@storybook/react-webpack5'
 
 type Story = StoryObj<typeof UpgradePrompt>
 

+ 1 - 1
services/web/frontend/stories/source-editor/source-editor.stories.tsx

@@ -8,7 +8,7 @@ import RangesTracker from '@overleaf/ranges-tracker'
 import useExposedState from '@/shared/hooks/use-exposed-state'
 import { EditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
 import { DocId } from '../../../types/project-settings'
-import { StoryObj } from '@storybook/react'
+import { StoryObj } from '@storybook/react-webpack5'
 import { DocumentContainer } from '@/features/ide-react/editor/document-container'
 import { EditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
 

+ 1 - 1
services/web/frontend/stories/subscription/active-subscription.stories.tsx

@@ -18,7 +18,7 @@ import {
 import { SubscriptionDashboardProvider } from '../../js/features/subscription/context/subscription-dashboard-context'
 import { SplitTestProvider } from '@/shared/context/split-test-context'
 import { PaidSubscription } from '@ol-types/subscription/dashboard/subscription'
-import type { StoryFn } from '@storybook/react'
+import type { StoryFn } from '@storybook/react-webpack5'
 import { setupSubscriptionDashContext } from '../../../test/frontend/features/subscription/helpers/setup-subscription-dash-context'
 
 export default {

+ 1 - 1
services/web/frontend/stories/word-count-modal.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, StoryObj } from '@storybook/react'
+import { Meta, StoryObj } from '@storybook/react-webpack5'
 import WordCountModal from '@/features/word-count-modal/components/word-count-modal'
 import { ScopeDecorator } from './decorators/scope'
 import useFetchMock from './hooks/use-fetch-mock'

+ 1 - 1
services/web/modules/full-project-search/stories/full-project-search.stories.tsx

@@ -1,4 +1,4 @@
-import { Meta, StoryObj } from '@storybook/react'
+import { Meta, StoryObj } from '@storybook/react-webpack5'
 import { ScopeDecorator } from '../../../frontend/stories/decorators/scope'
 import useFetchMock from '../../../frontend/stories/hooks/use-fetch-mock'
 import FullProjectSearchUI from '../frontend/js/components/full-project-search-ui'

+ 12 - 12
services/web/package.json

@@ -233,17 +233,14 @@
     "@replit/codemirror-indentation-markers": "overleaf/codemirror-indentation-markers#371ce3b56f453a392eb0d3b85ab019c185c68e1f",
     "@replit/codemirror-vim": "overleaf/codemirror-vim#1bef138382d948018f3f9b8a4d7a70ab61774e4b",
     "@sentry/browser": "7.46.0",
-    "@storybook/addon-a11y": "^8.6.17",
-    "@storybook/addon-designs": "^8.2.1",
-    "@storybook/addon-essentials": "^8.6.17",
-    "@storybook/addon-interactions": "^8.6.17",
-    "@storybook/addon-links": "^8.6.17",
-    "@storybook/addon-styling-webpack": "^1.0.1",
-    "@storybook/addon-webpack5-compiler-babel": "^3.0.6",
-    "@storybook/cli": "^8.6.17",
-    "@storybook/react": "^8.6.17",
-    "@storybook/react-webpack5": "^8.6.17",
-    "@storybook/theming": "^8.6.17",
+    "@storybook/addon-a11y": "10.3.5",
+    "@storybook/addon-designs": "^11.1.3",
+    "@storybook/addon-docs": "10.3.5",
+    "@storybook/addon-links": "10.3.5",
+    "@storybook/addon-styling-webpack": "^3.0.2",
+    "@storybook/addon-webpack5-compiler-babel": "^4.0.1",
+    "@storybook/cli": "10.3.5",
+    "@storybook/react-webpack5": "10.3.5",
     "@streamdown/cjk": "^1.0.2",
     "@streamdown/math": "^1.0.2",
     "@tailwindcss/container-queries": "^0.1.1",
@@ -287,6 +284,7 @@
     "@uppy/xhr-upload": "^3.6.0",
     "@vitest/coverage-istanbul": "^4.0.17",
     "@vitest/eslint-plugin": "1.6.6",
+    "@vitest/mocker": "^4.0.15",
     "@writefull/core": "^1.27.27",
     "@writefull/ui": "^1.27.27",
     "@writefull/utils": "^1.27.27",
@@ -330,6 +328,7 @@
     "eslint-plugin-jsx-a11y": "^6.7.1",
     "eslint-plugin-react": "^7.32.2",
     "eslint-plugin-react-hooks": "^4.6.0",
+    "eslint-plugin-storybook": "10.3.5",
     "eslint-plugin-testing-library": "^7.1.1",
     "eslint-plugin-unicorn": "^56.0.0",
     "events": "^3.3.0",
@@ -403,8 +402,9 @@
     "sinon": "^7.5.0",
     "sinon-chai": "^3.7.0",
     "sinon-mongoose": "^2.3.0",
-    "storybook": "^8.6.17",
+    "storybook": "10.3.5",
     "streamdown": "^2.2.0",
+    "style-loader": "^4.0.0",
     "stylelint": "^16.26.1",
     "stylelint-config-standard-scss": "^13.1.0",
     "tailwindcss": "^3.4.4",

+ 1 - 1
services/web/tsconfig.json

@@ -8,7 +8,7 @@
     "jsx": "preserve" /* Specify JSX code generation */,
     "noEmit": true /* Do not emit outputs. */,
     "strict": true /* Enable all strict type-checking options. */,
-    "moduleResolution": "node" /* Specify module resolution strategy */,
+    "moduleResolution": "bundler" /* Specify module resolution strategy */,
     "isolatedModules": true,
     "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
     "skipLibCheck": true /* Skip type checking of declaration files. */,

Some files were not shown because too many files changed in this diff