Skip to content

release: major v43 (test)#4655

Closed
Richard-Shen (RichardSyq) wants to merge 35 commits into
mainfrom
release/major-43-test
Closed

release: major v43 (test)#4655
Richard-Shen (RichardSyq) wants to merge 35 commits into
mainfrom
release/major-43-test

Conversation

@RichardSyq

Copy link
Copy Markdown
Contributor

Major Release v43 Regression PR (Test)

Combines a subset of currently open PRs labelled `major` into one branch for the upcoming major release.

Merged PRs (in merge order)

Notes

This PR was generated by the `major-regression` skill. Conflicts in PRs #4464 and #4553 were resolved manually before this PR was opened. PRs were merged in ascending PR-number order; commit hashes are visible in this branch's history.

This PR is opened as a draft. Mark it ready for review once you've validated the combined diff.

adamwilson-ss and others added 30 commits March 24, 2026 15:25
  Run preset-19 minus refobject-defaults and useRef-required-initial —
  those two emit code that only typechecks against @types/react@19, so
  defer to the future bump PR.

  34 files. ReactElement -> ReactElement<any>, scoped JSX imports, and
  deprecated-* type aliases replaced. License headers preserved.

  Manual fixups: array-type lint rule (3 sites: ReactElement<any>[] ->
  Array<ReactElement<any>>) and single-quote style on 2 new JSX imports.
  Custom jscodeshift transform at scripts/react-19/transforms/strip-proptypes.js,
  applied in two passes:
  - .ts/.tsx (--parser=tsx): remove prop-types imports, .propTypes assignments,
    static propTypes class fields, AND migrate function-component .defaultProps
    into ES6 destructure defaults.
  - .js/.jsx (--parser=babylon): only the defaultProps migration. Keep prop-types
    in place; the project's react/prop-types rule wants validation and most .js
    components rely on prop-types. React 19 ignores propTypes silently so this
    is safe; full removal happens in the future TS migration.

  Skipped (manual follow-up):
  - 26 .tsx class components with static defaultProps (Phase C reports them).
  - ~38 implicit-return story arrow components with .defaultProps left in place.
  - Files where PropTypes is used as a const export (e.g. common-types.ts).

  Manual fixups: 1 eslint-disable for an unused destructured rest sibling
  (ignoreRestSiblings only allows when there's no default), and 2 dead-import
  cleanups in tsx files.

  License headers preserved everywhere. 27 files: +70 / -243. Lint 0 errors,
  typecheck clean, jest 172 tests pass on touched packages.
  packages/package.json: peerDep range narrowed-and-shifted from "17.0.2 -
  18.3.1" to "18.3.1 - 19.2.5" (drops React 17, adds 19; lockfile updated).
  React 17 is unsupported upstream and has no consumers; dropping it shrinks
  the test/CI surface.

  .github/workflows/_build.yml: new React19 job runs typecheck + jest with
  react@19.2.5 and @types/react@19 installed --no-save into the cached
  node_modules. continue-on-error: true while the migration lands; flip to
  required once Repo 1 is released and consumers can opt in.

  packages/react-version-test.js: regex widened from /^18/ to /^(18|19)\./
  so the runtime version test passes under both supported versions.

  REACT_19_MIGRATION.md: documents the peerDep decision + a runbook note
  on the drop-17 call vs the widen-to-3 default.

  Verified on React 18.3.1: typecheck clean, lint clean, check-react-versions
  + check-bpk-dependencies pass, full jest suite (2402 tests, 380 suites,
  825 snapshots) passes.
  Removes codemod@1.9.1 and types-react-codemod@3.5.3 from devDependencies
  (step 11 of the master plan recipe). The custom transform at
  scripts/react-19/transforms/strip-proptypes.js stays in the repo for
  reviewer traceability; scripts/react-19/README.md explains how to
  re-install jscodeshift on demand and notes the long-term home in
  web-migration-scripts/migrations/2026-05-react-19/.

  REACT_19_MIGRATION.md: recipe checklist marked complete; new "Deferred
  to follow-up PRs" section captures the 35 class-component static
  defaultProps migrations, 13 .js story/HOC files with leftover
  .defaultProps, full .js (Flow) prop-types removal, the @types/react@19
  bump (which unlocks refobject-defaults + useRef-required-initial), the
  React19 CI matrix failure tracking, and moving the transform to
  web-migration-scripts.

  2402 tests pass on React 18.3.1 after the uninstall.
  RefObject<T | null>), add @types/prop-types to the override install
  (R19's @types/react no longer pulls it in transitively), and overlay
  the React 19 install into packages/node_modules so jest sees a single
  React version across both module trees.

  Remaining R19 jest failures (continue-on-error: true) are
  react-transition-group findDOMNode usage and useId() snapshot format
  drift — separate migration work.
…serializer and rewrites R19's _r_X_ useId format back to R18's :rX: so a single set of snapshots serves both versions
…o destructure defaults

Coupled-calendar pair, first commit of the class-component defaultProps migration:

- BpkCalendarContainer: extract DEFAULT_MARK_TODAY / DEFAULT_MAX_DATE / DEFAULT_MIN_DATE
  as exported module-level constants (preserving the prior 'frozen at module load'
  semantics — moving new Date() into per-render destructure defaults would re-evaluate
  on every render). Apply destructure-with-defaults at every access site (constructor,
  componentDidUpdate, handleDateFocus, handleDateSelect, render).
- BpkDatepicker: import the calendar defaults instead of reading
  DefaultCalendar.defaultProps.{markToday,maxDate,minDate}; migrate own defaults to
  destructure pattern. Make calendarComponent / inputComponent / nextMonthLabel /
  previousMonthLabel optional in Props (they were typed required but defaultProps was
  silently filling them in).
- BpkCalendarWeek: migrate; hoist DEFAULT_SELECTION_CONFIGURATION and a noop helper
  to module scope so destructure defaults don't allocate per render.
- BpkCalendarWeek-test.tsx + BpkCalendar.stories.js: drop ...BpkCalendarWeek.defaultProps
  spread (the migrated class applies the same defaults internally now).

R18 typecheck clean, jest green for both packages (60 tests / 23 snapshots).
The 5 composeCalendar-test snapshot failures are a pre-existing timezone-locale
string drift on this machine ('Coordinated Universal Time' vs 'Greenwich Mean Time'),
not caused by this change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ucture defaults

Eight class components whose defaulted props are read only inside render() (or
trivially null-safe lifecycle paths). Mechanical migration matching the function-
component pattern from #4455:

- withAccordionItemState
- BpkCalendarDate (lifecycle reads also gain destructure-defaults; isToday is
  filtered out via the existing buttonProps delete pattern)
- BpkCalendarGridHeader
- withLazyLoading
- BpkInput (defaults sourced from common-types: type, valid, large, docked*,
  inputRef, clearButton*; type now passed to <input> explicitly since the
  destructure pulls it out of {...rest})
- BpkInputField
- BpkSplitInput (multi-method reads of inputLength, type, large, placeholder
  use destructure-defaults at each access site)
- withInteractiveStarRatingState (Flow)

Where Props had previously-required fields kept alive only by static defaultProps,
they're typed optional now (consistent with the destructure default).

Typecheck clean. Tests green: 98/98 with 72 snapshots.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mponent defaultProps

Symmetric edits to the four near-identical class components shared between
banner-alert and info-banner:

- AnimateAndFade (both packages): destructure-defaults at constructor and render
  for animateOnEnter / animateOnLeave; Props makes both optional.
- withBannerAlertState (both packages): destructure-defaults at render for
  animateOnLeave / children; constructor uses ?? false for the expanded init
  (the existing if-guards in onDismiss/onExpandToggle/onHide already handle
  undefined callbacks safely).

R18 typecheck clean, jest green: 71 tests / 50 snapshots.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Thirteen files (9 .tsx + 4 Flow .js external-assignment patterns):

TypeScript:
- BpkCalendarGrid (local DEFAULT_MAX_DATE / DEFAULT_MIN_DATE constants — keeping
  module-eval-frozen semantics; can't import from BpkCalendarContainer because
  that creates an import cycle via BpkCalendarGridWithTransition)
- BpkCalendarGridTransition (only static defaultProps removal — destructure-defaults
  were already in place from a prior pass)
- BpkBackgroundImage, BpkImage (lifecycle reads of inView gain destructure-defaults)
- withOpenEvents (HAS_TOUCH_SUPPORT hoisted to module-level const so the destructure
  default doesn't re-evaluate per render)
- BpkMobileScrollContainer
- withScrim (DEFAULT_IS_IPHONE / DEFAULT_IS_IPAD module-level consts; dialogRef +
  closeOnScrimClick already-handled-as-truthy semantics preserved)

Flow .js (external Component.defaultProps = {...} assignment pattern):
- BpkBarchart (computed defaults hoisted to module-level: DEFAULT_X/Y_AXIS_MARGIN,
  DEFAULT_Y_AXIS_DOMAIN, DEFAULT_GET_BAR_LABEL, DEFAULT_GET_BAR_SELECTION — preserves
  function-reference stability that downstream sCU/memo may rely on)
- withInfiniteScroll (Flow `Config<Props, typeof defaultProps>` external type
  preserved; internal access sites use `?? defaultProps.X` to apply defaults at
  runtime since static defaultProps no longer fills them in)
- BpkGridToggle, BpkHorizontalNav, BpkHorizontalNavItem
- BpkProgress (componentDidUpdate restructured: `onComplete` was previously truthy-
  checked because the static default was () => null; without the default it was
  undefined and `onCompleteTransitionEnd` never fired. Restructured to call
  destructure-defaulted onComplete unconditionally, then conditional
  onCompleteTransitionEnd as before — fixes a test failure caught by the existing
  suite)

R18 typecheck clean, lint clean, jest green for all touched packages
(228 tests / 111 snapshots, plus the pre-existing composeCalendar-test
timezone-locale failure that's unrelated to this migration).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…aults

Largest single migration in the class-component sweep. ~22 this.props reads
across 5 methods (componentDidMount, componentDidUpdate, onDocumentMouseUp,
onDocumentKeyDown, open).

- Module-level `noop = () => null` for the three callable defaults
  (onClose / onOpen / onRender) — the original `static defaultProps`
  value was the same shared `() => null`, so a single hoisted reference
  preserves identity-equality semantics.
- Destructure-defaults applied at every method that calls these: must call
  unconditionally without a default would TypeError on undefined.
- closeOnEscPressed default `true` is load-bearing — without the destructure
  default, omitting the prop would mean ESC never closes the portal.
- Props type widened: required fields with prior static defaults are now
  optional. Affects 7 fields; consumers (BpkTooltip, BpkScrim, BpkModalV3,
  withScrimmedPortal) all already omit one or more of these.

R18 typecheck clean, lint clean, jest green for Portal + all its consumers
(174 tests / 31 snapshots).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The prop relied on scrollIntoView from a useEffect on mount, which
silently no-ops when the carousel is rendered inside a parent that
hasn't laid out yet (e.g. AnimateHeight at display: none). The sole
intended consumer (ExpandedPricingOption in web-platform) hit exactly
this and has since switched to a manual ref-based scroll triggered
after its parent's animation completes (IRN-6568). No other consumers
exist, so the prop is dead weight with a misleading API.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix package-lock.json resolved URLs: replace all Artifactory registry hosts
with registry.npmjs.org so that `npm ci` in CI does not request packages
blocked by Artifactory's security policy (e.g. websocket-extensions@0.1.4).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add Apache 2.0 license header to scripts/react-19/transforms/strip-proptypes.js (Danger was flagging its absence)
- Add build:gulp script back to package.json (React19 CI step calls `npm run build:gulp` to generate icons/flare/spinners, but the script was dropped when the build system was refactored)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Pt 2 (LOOM-2442_B) was written before the Nx consolidation (#4494) moved
all component source files from packages/bpk-component-*/ to
packages/backpack-web/src/bpk-component-*/. The nodeRef and act() fixes
existed only at the old paths, leaving the React19 CI failing.

Apply the identical changes to the correct consolidated locations:
- BpkDrawerContent: nodeRef + setRefs to avoid findDOMNode in Transition
- AnimateAndFade (banner-alert + info-banner): nodeRef class-field +
  cloneElement to forward ref to CSSTransition child
- BpkFloatingNotification: nodeRef wired to CSSTransition + wrapping div
- withInfiniteScroll-test: wrap updateData/intersect calls in act(async)
  so state flushes deterministically; update 3 stale snapshots

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@skyscanner-backpack-bot

Copy link
Copy Markdown
Contributor

Visit https://backpack.github.io/storybook-prs/4655 to see this build running in a browser.

@RichardSyq Richard-Shen (RichardSyq) marked this pull request as ready for review June 1, 2026 07:03
Copilot AI review requested due to automatic review settings June 1, 2026 07:03
@skyscanner-backpack-bot

Copy link
Copy Markdown
Contributor

Visit https://backpack.github.io/storybook-prs/4655 to see this build running in a browser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@skyscanner-backpack-bot

Copy link
Copy Markdown
Contributor

Visit https://backpack.github.io/storybook-prs/4655 to see this build running in a browser.

@skyscanner-backpack-bot

Copy link
Copy Markdown
Contributor

Browser support

If this is a visual change, make sure you've tested it in multiple browsers.

Generated by 🚫 dangerJS against a531c2d

@RichardSyq Richard-Shen (RichardSyq) deleted the release/major-43-test branch June 1, 2026 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants