@transferwise/components 46.160.1 → 46.160.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/build/Calendar/Calendar.js +9 -3
  2. package/build/Calendar/Calendar.js.map +1 -1
  3. package/build/Calendar/Calendar.mjs +9 -3
  4. package/build/Calendar/Calendar.mjs.map +1 -1
  5. package/build/Carousel/Carousel.js +17 -10
  6. package/build/Carousel/Carousel.js.map +1 -1
  7. package/build/Carousel/Carousel.mjs +17 -10
  8. package/build/Carousel/Carousel.mjs.map +1 -1
  9. package/build/SegmentedControl/SegmentedControl.js +9 -2
  10. package/build/SegmentedControl/SegmentedControl.js.map +1 -1
  11. package/build/SegmentedControl/SegmentedControl.mjs +9 -2
  12. package/build/SegmentedControl/SegmentedControl.mjs.map +1 -1
  13. package/build/Tooltip/Tooltip.js +6 -1
  14. package/build/Tooltip/Tooltip.js.map +1 -1
  15. package/build/Tooltip/Tooltip.mjs +6 -1
  16. package/build/Tooltip/Tooltip.mjs.map +1 -1
  17. package/build/i18n/tr.json +5 -0
  18. package/build/i18n/tr.json.js +5 -0
  19. package/build/i18n/tr.json.js.map +1 -1
  20. package/build/i18n/tr.json.mjs +5 -0
  21. package/build/i18n/tr.json.mjs.map +1 -1
  22. package/build/i18n/zh-CN.json +5 -0
  23. package/build/i18n/zh-CN.json.js +5 -0
  24. package/build/i18n/zh-CN.json.js.map +1 -1
  25. package/build/i18n/zh-CN.json.mjs +5 -0
  26. package/build/i18n/zh-CN.json.mjs.map +1 -1
  27. package/build/main.css +34 -22
  28. package/build/styles/AvatarLayout/AvatarLayout.css +26 -9
  29. package/build/styles/SegmentedControl/SegmentedControl.css +2 -1
  30. package/build/styles/Tooltip/Tooltip.css +0 -6
  31. package/build/styles/common/Panel/Panel.css +6 -6
  32. package/build/styles/main.css +34 -22
  33. package/build/types/Calendar/Calendar.d.ts.map +1 -1
  34. package/build/types/Carousel/Carousel.d.ts.map +1 -1
  35. package/build/types/Carousel/_stories/constants.d.ts +3 -0
  36. package/build/types/Carousel/_stories/constants.d.ts.map +1 -0
  37. package/build/types/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  38. package/build/types/Tooltip/Tooltip.d.ts.map +1 -1
  39. package/package.json +4 -4
  40. package/src/AvatarLayout/AvatarLayout.css +26 -9
  41. package/src/AvatarLayout/AvatarLayout.less +46 -22
  42. package/src/AvatarLayout/_stories/AvatarLayout.test.story.tsx +17 -42
  43. package/src/Calendar/Calendar.test.tsx +82 -0
  44. package/src/Calendar/Calendar.tsx +6 -3
  45. package/src/Carousel/Carousel.test.tsx +50 -2
  46. package/src/Carousel/Carousel.tsx +13 -10
  47. package/src/Carousel/_stories/Carousel.story.tsx +12 -52
  48. package/src/Carousel/_stories/Carousel.test.story.tsx +7 -43
  49. package/src/Carousel/_stories/constants.tsx +46 -0
  50. package/src/DateLookup/_stories/DateLookup.rtl.test.story.tsx +59 -48
  51. package/src/Field/_stories/Field.test.story.tsx +48 -37
  52. package/src/FlowNavigation/_stories/FlowNavigation.rtl.test.story.tsx +78 -0
  53. package/src/FlowNavigation/_stories/FlowNavigation.test.story.tsx +0 -44
  54. package/src/Label/_stories/Label.test.story.tsx +35 -22
  55. package/src/Popover/_stories/Popover.rtl.test.story.tsx +40 -50
  56. package/src/SegmentedControl/SegmentedControl.css +2 -1
  57. package/src/SegmentedControl/SegmentedControl.less +4 -2
  58. package/src/SegmentedControl/SegmentedControl.tsx +8 -2
  59. package/src/SegmentedControl/_stories/SegmentedControl.test.story.tsx +16 -8
  60. package/src/Tooltip/Tooltip.css +0 -6
  61. package/src/Tooltip/Tooltip.less +0 -12
  62. package/src/Tooltip/Tooltip.test.tsx +51 -0
  63. package/src/Tooltip/Tooltip.tsx +11 -1
  64. package/src/Tooltip/_stories/Tooltip.rtl.test.story.tsx +16 -34
  65. package/src/common/Panel/Panel.css +6 -6
  66. package/src/common/Panel/Panel.less +6 -6
  67. package/src/i18n/tr.json +5 -0
  68. package/src/i18n/zh-CN.json +5 -0
  69. package/src/main.css +34 -22
@@ -28,6 +28,8 @@ require('@transferwise/icons');
28
28
  require('clsx');
29
29
  require('../common/CloseButton/CloseButton.messages.js');
30
30
  var jsxRuntime = require('react/jsx-runtime');
31
+ require('@transferwise/neptune-validation');
32
+ var useDirection = require('../common/hooks/useDirection/useDirection.js');
31
33
  var moveToWithinRange = require('../common/DateUtils/moveToWithinRange/moveToWithinRange.js');
32
34
  var isWithinRange = require('../common/DateUtils/isWithinRange/isWithinRange.js');
33
35
  var getDateView = require('../common/DateUtils/getDateView/getDateView.js');
@@ -56,6 +58,9 @@ const Calendar = ({
56
58
  onChange
57
59
  }) => {
58
60
  const intl = reactIntl.useIntl();
61
+ const {
62
+ isRTL
63
+ } = useDirection.useDirection();
59
64
  const selectedDate = GetStartOfDay.getStartOfDay(value);
60
65
  const min = GetStartOfDay.getStartOfDay(minProp);
61
66
  const max = GetStartOfDay.getStartOfDay(maxProp);
@@ -160,9 +165,10 @@ const Calendar = ({
160
165
  }
161
166
  }, [focusedDate, onDateFocus]);
162
167
  const handleKeyDown = React.useCallback(event => {
168
+ const orientationSign = isRTL ? -1 : 1;
163
169
  switch (event.key) {
164
170
  case 'ArrowLeft':
165
- adjustDate(-1, -1, -1);
171
+ adjustDate(-1 * orientationSign, -1 * orientationSign, -1 * orientationSign);
166
172
  event.preventDefault();
167
173
  break;
168
174
  case 'ArrowUp':
@@ -170,7 +176,7 @@ const Calendar = ({
170
176
  event.preventDefault();
171
177
  break;
172
178
  case 'ArrowRight':
173
- adjustDate(1, 1, 1);
179
+ adjustDate(1 * orientationSign, 1 * orientationSign, 1 * orientationSign);
174
180
  event.preventDefault();
175
181
  break;
176
182
  case 'ArrowDown':
@@ -185,7 +191,7 @@ const Calendar = ({
185
191
  }
186
192
  break;
187
193
  }
188
- }, [adjustDate, focusedDate, mode, handleSelectedDateUpdate]);
194
+ }, [adjustDate, focusedDate, mode, handleSelectedDateUpdate, isRTL]);
189
195
  const focusedDateOutOfRange = focusedDate ? !isWithinRange.isWithinRange(focusedDate, min, max) : false;
190
196
  const formatDateForPrompt = date => formatting.formatDate(date, intl.locale, Calendar_constants.LONG_DAY_FORMAT);
191
197
  const outOfRangePromptText = min && max ? intl.formatMessage(Calendar_messages.default.outOfRangeBetween, {
@@ -1 +1 @@
1
- {"version":3,"file":"Calendar.js","sources":["../../src/Calendar/Calendar.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useId, useRef, KeyboardEvent } from 'react';\nimport { useIntl } from 'react-intl';\nimport { formatDate } from '@transferwise/formatting';\n\nimport { MonthFormat } from '../common';\nimport { isWithinRange, moveToWithinRange, returnDateView } from '../common/DateUtils';\nimport { clampToDayViewBoundary, isDateDisabled, hasDisabledDatesInMonth } from './_helpers';\nimport { LONG_DAY_FORMAT } from './Calendar.constants';\nimport { InlinePrompt } from '../Prompt/InlinePrompt';\nimport type { DateChangeMeta, DisabledRules } from './Calendar.types';\nimport DayCalendar from './DayCalendar';\nimport { getStartOfDay } from './GetStartOfDay';\nimport messages from './Calendar.messages';\nimport MonthCalendar from './MonthCalendar';\nimport YearCalendar from './YearCalendar';\n\nexport interface CalendarProps {\n /** The currently selected date, or `null` for no selection. */\n value: Date | null;\n /** Earliest selectable date (inclusive). Dates before this are interactive but not selectable, and show a boundary prompt. */\n min?: Date | null;\n /** Latest selectable date (inclusive). Dates after this are interactive but not selectable, and show a boundary prompt. */\n max?: Date | null;\n /** Month name format in the header. Defaults to `'long'` (e.g. \"January\"). */\n monthFormat?: `${MonthFormat}`;\n /** Placeholder text shown in the month/year cells when no date is selected. */\n placeholder?: string;\n /** Rules for disabling specific weekdays, individual dates, or date ranges. The required `reason` is shown in an inline prompt and linked to disabled cells via `aria-describedby` for screen reader accessibility. */\n disabledRules?: DisabledRules;\n /** Called whenever the focused date changes — including disabled and out-of-range dates. `meta.isEnabled` is `false` when the date is not selectable. */\n onDateFocus?: (date: Date | null, meta: DateChangeMeta) => void;\n /** Called when a date is confirmed (click or Enter). Only fires for enabled dates. */\n onChange?: (date: Date | null) => void;\n}\n\n/**\n * Temporary toggle — set `true` to restore strict min/max keyboard clamping.\n * @see https://transferwise.atlassian.net/browse/DS-8518\n */\nconst STRICT_KEYBOARD_CLAMPING = false;\n\n/**\n * Inline calendar for selecting a single date. Powers [DateLookup](?path=/docs/forms-datelookup--docs).\n */\nconst Calendar = ({\n value,\n min: minProp = null,\n max: maxProp = null,\n monthFormat = MonthFormat.LONG,\n placeholder,\n disabledRules,\n onDateFocus,\n onChange,\n}: CalendarProps) => {\n const intl = useIntl();\n const selectedDate = getStartOfDay(value);\n const min = getStartOfDay(minProp);\n const max = getStartOfDay(maxProp);\n const disabledReasonId = useId();\n const disabledRulesRef = useRef(disabledRules);\n useEffect(() => {\n disabledRulesRef.current = disabledRules;\n });\n\n const [hasInteracted, setHasInteracted] = useState(false);\n const [focusedDate, setFocusedDate] = useState<Date | null>(selectedDate);\n\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setFocusedDate(selectedDate);\n }, [selectedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const checkIsEnabled = (date: Date | null) => {\n if (!date) return true;\n return isWithinRange(date, min, max) && !isDateDisabled(date, disabledRulesRef.current);\n };\n\n const focusedDateDisabled = focusedDate\n ? !isWithinRange(focusedDate, min, max) || isDateDisabled(focusedDate, disabledRules)\n : false;\n\n useEffect(() => {\n if (selectedDate && !isWithinRange(selectedDate, min, max)) {\n const clamped = moveToWithinRange(selectedDate, min, max);\n setFocusedDate(clamped); // eslint-disable-line react-hooks/set-state-in-effect\n onDateFocus?.(clamped, { isEnabled: checkIsEnabled(clamped) });\n }\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime(), onDateFocus]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const dateView = returnDateView(selectedDate, min, max);\n const [viewMonth, setViewMonth] = useState(dateView.getMonth());\n const [viewYear, setViewYear] = useState(dateView.getFullYear());\n const [mode, setMode] = useState<'day' | 'month' | 'year'>('day');\n\n useEffect(() => {\n const view = returnDateView(selectedDate, min, max);\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(view.getMonth());\n\n setViewYear(view.getFullYear());\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n if (focusedDate) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(focusedDate.getMonth());\n setViewYear(focusedDate.getFullYear());\n }\n }, [focusedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleViewDateUpdate = useCallback(\n // eslint-disable-next-line react-hooks/preserve-manual-memoization\n ({ month, year }: { month?: number; year?: number }) => {\n if (month !== undefined) setViewMonth(month);\n if (year !== undefined) setViewYear(year);\n setHasInteracted(false);\n },\n [],\n );\n\n const switchToDays = useCallback(() => setMode('day'), []);\n const switchToMonths = useCallback(() => setMode('month'), []);\n const switchToYears = useCallback(() => setMode('year'), []);\n\n const handleSelectedDateUpdate = useCallback(\n (date: Date) => {\n if (!hasInteracted) setHasInteracted(true);\n const isEnabled = checkIsEnabled(date);\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled });\n if (isEnabled && onChange) {\n onChange(date);\n }\n },\n [onDateFocus, onChange], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const adjustDate = useCallback(\n (daysToAdd: number, monthsToAdd: number, yearsToAdd: number) => {\n const base = focusedDate ?? selectedDate;\n let date: Date | null;\n if (base) {\n date = new Date(\n mode === 'year' ? base.getFullYear() + yearsToAdd : base.getFullYear(),\n mode === 'month' ? base.getMonth() + monthsToAdd : base.getMonth(),\n mode === 'day' ? base.getDate() + daysToAdd : base.getDate(),\n );\n } else {\n date = getStartOfDay(new Date());\n }\n date &&=\n STRICT_KEYBOARD_CLAMPING || mode !== 'day'\n ? moveToWithinRange(date, min, max)\n : clampToDayViewBoundary(date, min, max);\n if (date?.getTime() !== focusedDate?.getTime()) {\n const monthChanged = date\n ? date.getMonth() !== focusedDate?.getMonth() ||\n date.getFullYear() !== focusedDate?.getFullYear()\n : false;\n setFocusedDate(date);\n if (date) {\n setViewMonth(date.getMonth());\n setViewYear(date.getFullYear());\n }\n if (monthChanged) {\n setHasInteracted(false);\n } else if (!hasInteracted) {\n setHasInteracted(true);\n }\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, selectedDate, min, max, mode, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleDayFocus = useCallback(\n (date: Date) => {\n if (date.getTime() !== focusedDate?.getTime()) {\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n switch (event.key) {\n case 'ArrowLeft':\n adjustDate(-1, -1, -1);\n event.preventDefault();\n break;\n case 'ArrowUp':\n adjustDate(-7, -4, -4);\n event.preventDefault();\n break;\n case 'ArrowRight':\n adjustDate(1, 1, 1);\n event.preventDefault();\n break;\n case 'ArrowDown':\n adjustDate(7, 4, 4);\n event.preventDefault();\n break;\n case 'Enter':\n case ' ':\n if (\n mode === 'day' &&\n focusedDate &&\n (event.target as HTMLElement).hasAttribute('data-calendar-cell')\n ) {\n handleSelectedDateUpdate(focusedDate);\n event.preventDefault();\n }\n break;\n default:\n break;\n }\n },\n [adjustDate, focusedDate, mode, handleSelectedDateUpdate],\n );\n\n const focusedDateOutOfRange = focusedDate ? !isWithinRange(focusedDate, min, max) : false;\n\n const formatDateForPrompt = (date: Date) => formatDate(date, intl.locale, LONG_DAY_FORMAT);\n\n const outOfRangePromptText =\n min && max\n ? intl.formatMessage(messages.outOfRangeBetween, {\n min: formatDateForPrompt(min),\n max: formatDateForPrompt(max),\n })\n : min\n ? intl.formatMessage(messages.outOfRangeAfter, { min: formatDateForPrompt(min) })\n : max\n ? intl.formatMessage(messages.outOfRangeBefore, { max: formatDateForPrompt(max) })\n : '';\n\n const hasOutOfRangeDates = mode === 'day' && !!(min || max);\n const showRulesPrompt =\n mode === 'day' &&\n !!disabledRules &&\n hasDisabledDatesInMonth(viewMonth, viewYear, disabledRules, min, max);\n const showOutOfRangePrompt = mode === 'day' && focusedDateOutOfRange;\n const showPrompt = hasOutOfRangeDates || showRulesPrompt;\n\n const promptText = showOutOfRangePrompt\n ? outOfRangePromptText\n : (disabledRules?.reason ?? outOfRangePromptText);\n const promptSentiment = showOutOfRangePrompt || focusedDateDisabled ? 'negative' : 'neutral';\n // Visible when there's an actionable message; sr-only when only hasOutOfRangeDates is true\n // (prompt exists for aria-describedby but no visual cue needed until an out-of-range date is focused)\n const promptClassName = showOutOfRangePrompt || showRulesPrompt ? 'm-t-1' : 'sr-only';\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div onKeyDown={handleKeyDown}>\n {mode === 'day' && (\n <DayCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewMonth={viewMonth}\n viewYear={viewYear}\n monthFormat={monthFormat}\n disabledRules={disabledRules}\n disabledReasonId={showPrompt ? disabledReasonId : undefined}\n announceReasonOnFocus={!hasInteracted}\n onSelect={handleSelectedDateUpdate}\n onDayFocus={handleDayFocus}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'month' && (\n <MonthCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToDays}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'year' && (\n <YearCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToMonths}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {showPrompt && (\n <InlinePrompt\n sentiment={promptSentiment}\n width=\"full\"\n id={disabledReasonId}\n className={promptClassName}\n >\n {promptText}\n </InlinePrompt>\n )}\n </div>\n );\n};\n\nexport default Calendar;\n"],"names":["Calendar","value","min","minProp","max","maxProp","monthFormat","MonthFormat","LONG","placeholder","disabledRules","onDateFocus","onChange","intl","useIntl","selectedDate","getStartOfDay","disabledReasonId","useId","disabledRulesRef","useRef","useEffect","current","hasInteracted","setHasInteracted","useState","focusedDate","setFocusedDate","getTime","checkIsEnabled","date","isWithinRange","isDateDisabled","focusedDateDisabled","clamped","moveToWithinRange","isEnabled","dateView","returnDateView","viewMonth","setViewMonth","getMonth","viewYear","setViewYear","getFullYear","mode","setMode","view","handleViewDateUpdate","useCallback","month","year","undefined","switchToDays","switchToMonths","switchToYears","handleSelectedDateUpdate","adjustDate","daysToAdd","monthsToAdd","yearsToAdd","base","Date","getDate","clampToDayViewBoundary","monthChanged","handleDayFocus","handleKeyDown","event","key","preventDefault","target","hasAttribute","focusedDateOutOfRange","formatDateForPrompt","formatDate","locale","LONG_DAY_FORMAT","outOfRangePromptText","formatMessage","messages","outOfRangeBetween","outOfRangeAfter","outOfRangeBefore","hasOutOfRangeDates","showRulesPrompt","hasDisabledDatesInMonth","showOutOfRangePrompt","showPrompt","promptText","reason","promptSentiment","promptClassName","_jsxs","onKeyDown","children","_jsx","DayCalendar","announceReasonOnFocus","onSelect","onDayFocus","onLabelClick","onViewDateUpdate","MonthCalendar","YearCalendar","InlinePrompt","sentiment","width","id","className"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA;;AAEG;AACH,MAAMA,QAAQ,GAAGA,CAAC;EAChBC,KAAK;EACLC,GAAG,EAAEC,OAAO,GAAG,IAAI;EACnBC,GAAG,EAAEC,OAAO,GAAG,IAAI;eACnBC,aAAW,GAAGC,uBAAW,CAACC,IAAI;EAC9BC,WAAW;EACXC,aAAa;EACbC,WAAW;AACXC,EAAAA;AAAQ,CACM,KAAI;AAClB,EAAA,MAAMC,IAAI,GAAGC,iBAAO,EAAE;AACtB,EAAA,MAAMC,YAAY,GAAGC,2BAAa,CAACf,KAAK,CAAC;AACzC,EAAA,MAAMC,GAAG,GAAGc,2BAAa,CAACb,OAAO,CAAC;AAClC,EAAA,MAAMC,GAAG,GAAGY,2BAAa,CAACX,OAAO,CAAC;AAClC,EAAA,MAAMY,gBAAgB,GAAGC,WAAK,EAAE;AAChC,EAAA,MAAMC,gBAAgB,GAAGC,YAAM,CAACV,aAAa,CAAC;AAC9CW,EAAAA,eAAS,CAAC,MAAK;IACbF,gBAAgB,CAACG,OAAO,GAAGZ,aAAa;AAC1C,EAAA,CAAC,CAAC;EAEF,MAAM,CAACa,aAAa,EAAEC,gBAAgB,CAAC,GAAGC,cAAQ,CAAC,KAAK,CAAC;EACzD,MAAM,CAACC,WAAW,EAAEC,cAAc,CAAC,GAAGF,cAAQ,CAAcV,YAAY,CAAC;AAEzEM,EAAAA,eAAS,CAAC,MAAK;AACb;IACAM,cAAc,CAACZ,YAAY,CAAC;EAC9B,CAAC,EAAE,CAACA,YAAY,EAAEa,OAAO,EAAE,CAAC,CAAC,CAAC;EAE9B,MAAMC,cAAc,GAAIC,IAAiB,IAAI;AAC3C,IAAA,IAAI,CAACA,IAAI,EAAE,OAAO,IAAI;AACtB,IAAA,OAAOC,2BAAa,CAACD,IAAI,EAAE5B,GAAG,EAAEE,GAAG,CAAC,IAAI,CAAC4B,6BAAc,CAACF,IAAI,EAAEX,gBAAgB,CAACG,OAAO,CAAC;EACzF,CAAC;EAED,MAAMW,mBAAmB,GAAGP,WAAW,GACnC,CAACK,2BAAa,CAACL,WAAW,EAAExB,GAAG,EAAEE,GAAG,CAAC,IAAI4B,6BAAc,CAACN,WAAW,EAAEhB,aAAa,CAAC,GACnF,KAAK;AAETW,EAAAA,eAAS,CAAC,MAAK;IACb,IAAIN,YAAY,IAAI,CAACgB,2BAAa,CAAChB,YAAY,EAAEb,GAAG,EAAEE,GAAG,CAAC,EAAE;MAC1D,MAAM8B,OAAO,GAAGC,mCAAiB,CAACpB,YAAY,EAAEb,GAAG,EAAEE,GAAG,CAAC;AACzDuB,MAAAA,cAAc,CAACO,OAAO,CAAC,CAAC;MACxBvB,WAAW,GAAGuB,OAAO,EAAE;QAAEE,SAAS,EAAEP,cAAc,CAACK,OAAO;AAAC,OAAE,CAAC;AAChE,IAAA;EACF,CAAC,EAAE,CAACnB,YAAY,EAAEa,OAAO,EAAE,EAAE1B,GAAG,EAAE0B,OAAO,EAAE,EAAExB,GAAG,EAAEwB,OAAO,EAAE,EAAEjB,WAAW,CAAC,CAAC,CAAC;EAE3E,MAAM0B,QAAQ,GAAGC,0BAAc,CAACvB,YAAY,EAAEb,GAAG,EAAEE,GAAG,CAAC;AACvD,EAAA,MAAM,CAACmC,SAAS,EAAEC,YAAY,CAAC,GAAGf,cAAQ,CAACY,QAAQ,CAACI,QAAQ,EAAE,CAAC;AAC/D,EAAA,MAAM,CAACC,QAAQ,EAAEC,WAAW,CAAC,GAAGlB,cAAQ,CAACY,QAAQ,CAACO,WAAW,EAAE,CAAC;EAChE,MAAM,CAACC,IAAI,EAAEC,OAAO,CAAC,GAAGrB,cAAQ,CAA2B,KAAK,CAAC;AAEjEJ,EAAAA,eAAS,CAAC,MAAK;IACb,MAAM0B,IAAI,GAAGT,0BAAc,CAACvB,YAAY,EAAEb,GAAG,EAAEE,GAAG,CAAC;AACnD;AACAoC,IAAAA,YAAY,CAACO,IAAI,CAACN,QAAQ,EAAE,CAAC;AAE7BE,IAAAA,WAAW,CAACI,IAAI,CAACH,WAAW,EAAE,CAAC;EACjC,CAAC,EAAE,CAAC7B,YAAY,EAAEa,OAAO,EAAE,EAAE1B,GAAG,EAAE0B,OAAO,EAAE,EAAExB,GAAG,EAAEwB,OAAO,EAAE,CAAC,CAAC,CAAC;AAE9DP,EAAAA,eAAS,CAAC,MAAK;AACb,IAAA,IAAIK,WAAW,EAAE;AACf;AACAc,MAAAA,YAAY,CAACd,WAAW,CAACe,QAAQ,EAAE,CAAC;AACpCE,MAAAA,WAAW,CAACjB,WAAW,CAACkB,WAAW,EAAE,CAAC;AACxC,IAAA;EACF,CAAC,EAAE,CAAClB,WAAW,EAAEE,OAAO,EAAE,CAAC,CAAC,CAAC;EAE7B,MAAMoB,oBAAoB,GAAGC,iBAAW;AACtC;EACA,CAAC;IAAEC,KAAK;AAAEC,IAAAA;AAAI,GAAqC,KAAI;AACrD,IAAA,IAAID,KAAK,KAAKE,SAAS,EAAEZ,YAAY,CAACU,KAAK,CAAC;AAC5C,IAAA,IAAIC,IAAI,KAAKC,SAAS,EAAET,WAAW,CAACQ,IAAI,CAAC;IACzC3B,gBAAgB,CAAC,KAAK,CAAC;EACzB,CAAC,EACD,EAAE,CACH;EAED,MAAM6B,YAAY,GAAGJ,iBAAW,CAAC,MAAMH,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;EAC1D,MAAMQ,cAAc,GAAGL,iBAAW,CAAC,MAAMH,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;EAC9D,MAAMS,aAAa,GAAGN,iBAAW,CAAC,MAAMH,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;AAE5D,EAAA,MAAMU,wBAAwB,GAAGP,iBAAW,CACzCnB,IAAU,IAAI;AACb,IAAA,IAAI,CAACP,aAAa,EAAEC,gBAAgB,CAAC,IAAI,CAAC;AAC1C,IAAA,MAAMY,SAAS,GAAGP,cAAc,CAACC,IAAI,CAAC;IACtCH,cAAc,CAACG,IAAI,CAAC;IACpBnB,WAAW,GAAGmB,IAAI,EAAE;AAAEM,MAAAA;AAAS,KAAE,CAAC;IAClC,IAAIA,SAAS,IAAIxB,QAAQ,EAAE;MACzBA,QAAQ,CAACkB,IAAI,CAAC;AAChB,IAAA;AACF,EAAA,CAAC,EACD,CAACnB,WAAW,EAAEC,QAAQ,CAAC,CACxB;EAED,MAAM6C,UAAU,GAAGR,iBAAW,CAC5B,CAACS,SAAiB,EAAEC,WAAmB,EAAEC,UAAkB,KAAI;AAC7D,IAAA,MAAMC,IAAI,GAAGnC,WAAW,IAAIX,YAAY;AACxC,IAAA,IAAIe,IAAiB;AACrB,IAAA,IAAI+B,IAAI,EAAE;MACR/B,IAAI,GAAG,IAAIgC,IAAI,CACbjB,IAAI,KAAK,MAAM,GAAGgB,IAAI,CAACjB,WAAW,EAAE,GAAGgB,UAAU,GAAGC,IAAI,CAACjB,WAAW,EAAE,EACtEC,IAAI,KAAK,OAAO,GAAGgB,IAAI,CAACpB,QAAQ,EAAE,GAAGkB,WAAW,GAAGE,IAAI,CAACpB,QAAQ,EAAE,EAClEI,IAAI,KAAK,KAAK,GAAGgB,IAAI,CAACE,OAAO,EAAE,GAAGL,SAAS,GAAGG,IAAI,CAACE,OAAO,EAAE,CAC7D;AACH,IAAA,CAAC,MAAM;AACLjC,MAAAA,IAAI,GAAGd,2BAAa,CAAC,IAAI8C,IAAI,EAAE,CAAC;AAClC,IAAA;IACAhC,IAAI,KAC0Be,IAAI,KAAK,KAAK,GACtCV,mCAAiB,CAACL,IAAI,EAAE5B,GAAG,EAAEE,GAAG,CAAC,GACjC4D,6CAAsB,CAAClC,IAAI,EAAE5B,GAAG,EAAEE,GAAG,CAAC;IAC5C,IAAI0B,IAAI,EAAEF,OAAO,EAAE,KAAKF,WAAW,EAAEE,OAAO,EAAE,EAAE;AAC9C,MAAA,MAAMqC,YAAY,GAAGnC,IAAI,GACrBA,IAAI,CAACW,QAAQ,EAAE,KAAKf,WAAW,EAAEe,QAAQ,EAAE,IAC3CX,IAAI,CAACc,WAAW,EAAE,KAAKlB,WAAW,EAAEkB,WAAW,EAAE,GACjD,KAAK;MACTjB,cAAc,CAACG,IAAI,CAAC;AACpB,MAAA,IAAIA,IAAI,EAAE;AACRU,QAAAA,YAAY,CAACV,IAAI,CAACW,QAAQ,EAAE,CAAC;AAC7BE,QAAAA,WAAW,CAACb,IAAI,CAACc,WAAW,EAAE,CAAC;AACjC,MAAA;AACA,MAAA,IAAIqB,YAAY,EAAE;QAChBzC,gBAAgB,CAAC,KAAK,CAAC;AACzB,MAAA,CAAC,MAAM,IAAI,CAACD,aAAa,EAAE;QACzBC,gBAAgB,CAAC,IAAI,CAAC;AACxB,MAAA;MACAb,WAAW,GAAGmB,IAAI,EAAE;QAAEM,SAAS,EAAEP,cAAc,CAACC,IAAI;AAAC,OAAE,CAAC;AAC1D,IAAA;AACF,EAAA,CAAC,EACD,CAACJ,WAAW,EAAEX,YAAY,EAAEb,GAAG,EAAEE,GAAG,EAAEyC,IAAI,EAAElC,WAAW,CAAC,CACzD;AAED,EAAA,MAAMuD,cAAc,GAAGjB,iBAAW,CAC/BnB,IAAU,IAAI;IACb,IAAIA,IAAI,CAACF,OAAO,EAAE,KAAKF,WAAW,EAAEE,OAAO,EAAE,EAAE;MAC7CD,cAAc,CAACG,IAAI,CAAC;MACpBnB,WAAW,GAAGmB,IAAI,EAAE;QAAEM,SAAS,EAAEP,cAAc,CAACC,IAAI;AAAC,OAAE,CAAC;AAC1D,IAAA;AACF,EAAA,CAAC,EACD,CAACJ,WAAW,EAAEf,WAAW,CAAC,CAC3B;AAED,EAAA,MAAMwD,aAAa,GAAGlB,iBAAW,CAC9BmB,KAAoC,IAAI;IACvC,QAAQA,KAAK,CAACC,GAAG;AACf,MAAA,KAAK,WAAW;QACdZ,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QACtBW,KAAK,CAACE,cAAc,EAAE;AACtB,QAAA;AACF,MAAA,KAAK,SAAS;QACZb,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QACtBW,KAAK,CAACE,cAAc,EAAE;AACtB,QAAA;AACF,MAAA,KAAK,YAAY;AACfb,QAAAA,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnBW,KAAK,CAACE,cAAc,EAAE;AACtB,QAAA;AACF,MAAA,KAAK,WAAW;AACdb,QAAAA,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnBW,KAAK,CAACE,cAAc,EAAE;AACtB,QAAA;AACF,MAAA,KAAK,OAAO;AACZ,MAAA,KAAK,GAAG;AACN,QAAA,IACEzB,IAAI,KAAK,KAAK,IACdnB,WAAW,IACV0C,KAAK,CAACG,MAAsB,CAACC,YAAY,CAAC,oBAAoB,CAAC,EAChE;UACAhB,wBAAwB,CAAC9B,WAAW,CAAC;UACrC0C,KAAK,CAACE,cAAc,EAAE;AACxB,QAAA;AACA,QAAA;AAGJ;EACF,CAAC,EACD,CAACb,UAAU,EAAE/B,WAAW,EAAEmB,IAAI,EAAEW,wBAAwB,CAAC,CAC1D;AAED,EAAA,MAAMiB,qBAAqB,GAAG/C,WAAW,GAAG,CAACK,2BAAa,CAACL,WAAW,EAAExB,GAAG,EAAEE,GAAG,CAAC,GAAG,KAAK;AAEzF,EAAA,MAAMsE,mBAAmB,GAAI5C,IAAU,IAAK6C,qBAAU,CAAC7C,IAAI,EAAEjB,IAAI,CAAC+D,MAAM,EAAEC,kCAAe,CAAC;AAE1F,EAAA,MAAMC,oBAAoB,GACxB5E,GAAG,IAAIE,GAAG,GACNS,IAAI,CAACkE,aAAa,CAACC,yBAAQ,CAACC,iBAAiB,EAAE;AAC7C/E,IAAAA,GAAG,EAAEwE,mBAAmB,CAACxE,GAAG,CAAC;IAC7BE,GAAG,EAAEsE,mBAAmB,CAACtE,GAAG;GAC7B,CAAC,GACFF,GAAG,GACDW,IAAI,CAACkE,aAAa,CAACC,yBAAQ,CAACE,eAAe,EAAE;IAAEhF,GAAG,EAAEwE,mBAAmB,CAACxE,GAAG;GAAG,CAAC,GAC/EE,GAAG,GACDS,IAAI,CAACkE,aAAa,CAACC,yBAAQ,CAACG,gBAAgB,EAAE;IAAE/E,GAAG,EAAEsE,mBAAmB,CAACtE,GAAG;GAAG,CAAC,GAChF,EAAE;EAEZ,MAAMgF,kBAAkB,GAAGvC,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE3C,GAAG,IAAIE,GAAG,CAAC;EAC3D,MAAMiF,eAAe,GACnBxC,IAAI,KAAK,KAAK,IACd,CAAC,CAACnC,aAAa,IACf4E,+CAAuB,CAAC/C,SAAS,EAAEG,QAAQ,EAAEhC,aAAa,EAAER,GAAG,EAAEE,GAAG,CAAC;AACvE,EAAA,MAAMmF,oBAAoB,GAAG1C,IAAI,KAAK,KAAK,IAAI4B,qBAAqB;AACpE,EAAA,MAAMe,UAAU,GAAGJ,kBAAkB,IAAIC,eAAe;EAExD,MAAMI,UAAU,GAAGF,oBAAoB,GACnCT,oBAAoB,GACnBpE,aAAa,EAAEgF,MAAM,IAAIZ,oBAAqB;EACnD,MAAMa,eAAe,GAAGJ,oBAAoB,IAAItD,mBAAmB,GAAG,UAAU,GAAG,SAAS;AAC5F;AACA;EACA,MAAM2D,eAAe,GAAGL,oBAAoB,IAAIF,eAAe,GAAG,OAAO,GAAG,SAAS;AAErF,EAAA;AAAA;AACE;IACAQ,eAAA,CAAA,KAAA,EAAA;AAAKC,MAAAA,SAAS,EAAE3B,aAAc;AAAA4B,MAAAA,QAAA,GAC3BlD,IAAI,KAAK,KAAK,iBACbmD,cAAA,CAACC,mBAAW,EAAA;AACVlF,QAAAA,YAAY,EAAEA,YAAa;AAC3BW,QAAAA,WAAW,EAAEA,WAAY;AACzBxB,QAAAA,GAAG,EAAEA,GAAI;AACTE,QAAAA,GAAG,EAAEA,GAAI;AACTmC,QAAAA,SAAS,EAAEA,SAAU;AACrBG,QAAAA,QAAQ,EAAEA,QAAS;AACnBpC,QAAAA,WAAW,EAAEA,aAAY;AACzBI,QAAAA,aAAa,EAAEA,aAAc;AAC7BO,QAAAA,gBAAgB,EAAEuE,UAAU,GAAGvE,gBAAgB,GAAGmC,SAAU;QAC5D8C,qBAAqB,EAAE,CAAC3E,aAAc;AACtC4E,QAAAA,QAAQ,EAAE3C,wBAAyB;AACnC4C,QAAAA,UAAU,EAAElC,cAAe;AAC3BmC,QAAAA,YAAY,EAAE9C,aAAc;AAC5B+C,QAAAA,gBAAgB,EAAEtD;OAAqB,CAE1C,EACAH,IAAI,KAAK,OAAO,iBACfmD,cAAA,CAACO,qBAAa,EAAA;AACZxF,QAAAA,YAAY,EAAEA,YAAa;AAC3BW,QAAAA,WAAW,EAAEA,WAAY;AACzBxB,QAAAA,GAAG,EAAEA,GAAI;AACTE,QAAAA,GAAG,EAAEA,GAAI;AACTsC,QAAAA,QAAQ,EAAEA,QAAS;QAAA,IACdjC,WAAW,IAAI,IAAI,IAAI;AAAEA,UAAAA;SAAa,CAAA;AAC3C0F,QAAAA,QAAQ,EAAE9C,YAAa;AACvBgD,QAAAA,YAAY,EAAE9C,aAAc;AAC5B+C,QAAAA,gBAAgB,EAAEtD;OAAqB,CAE1C,EACAH,IAAI,KAAK,MAAM,iBACdmD,cAAA,CAACQ,oBAAY,EAAA;AACXzF,QAAAA,YAAY,EAAEA,YAAa;AAC3BW,QAAAA,WAAW,EAAEA,WAAY;AACzBxB,QAAAA,GAAG,EAAEA,GAAI;AACTE,QAAAA,GAAG,EAAEA,GAAI;AACTsC,QAAAA,QAAQ,EAAEA,QAAS;QAAA,IACdjC,WAAW,IAAI,IAAI,IAAI;AAAEA,UAAAA;SAAa,CAAA;AAC3C0F,QAAAA,QAAQ,EAAE7C,cAAe;AACzBgD,QAAAA,gBAAgB,EAAEtD;AAAqB,OAAA,CAE1C,EACAwC,UAAU,iBACTQ,cAAA,CAACS,yBAAY,EAAA;AACXC,QAAAA,SAAS,EAAEf,eAAgB;AAC3BgB,QAAAA,KAAK,EAAC,MAAM;AACZC,QAAAA,EAAE,EAAE3F,gBAAiB;AACrB4F,QAAAA,SAAS,EAAEjB,eAAgB;AAAAG,QAAAA,QAAA,EAE1BN;AAAU,OACC,CACf;KACE;AAAC;AAEV;;;;"}
1
+ {"version":3,"file":"Calendar.js","sources":["../../src/Calendar/Calendar.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useId, useRef, KeyboardEvent } from 'react';\nimport { useIntl } from 'react-intl';\nimport { formatDate } from '@transferwise/formatting';\n\nimport { MonthFormat } from '../common';\nimport { useDirection } from '../common/hooks';\nimport { isWithinRange, moveToWithinRange, returnDateView } from '../common/DateUtils';\nimport { clampToDayViewBoundary, isDateDisabled, hasDisabledDatesInMonth } from './_helpers';\nimport { LONG_DAY_FORMAT } from './Calendar.constants';\nimport { InlinePrompt } from '../Prompt/InlinePrompt';\nimport type { DateChangeMeta, DisabledRules } from './Calendar.types';\nimport DayCalendar from './DayCalendar';\nimport { getStartOfDay } from './GetStartOfDay';\nimport messages from './Calendar.messages';\nimport MonthCalendar from './MonthCalendar';\nimport YearCalendar from './YearCalendar';\n\nexport interface CalendarProps {\n /** The currently selected date, or `null` for no selection. */\n value: Date | null;\n /** Earliest selectable date (inclusive). Dates before this are interactive but not selectable, and show a boundary prompt. */\n min?: Date | null;\n /** Latest selectable date (inclusive). Dates after this are interactive but not selectable, and show a boundary prompt. */\n max?: Date | null;\n /** Month name format in the header. Defaults to `'long'` (e.g. \"January\"). */\n monthFormat?: `${MonthFormat}`;\n /** Placeholder text shown in the month/year cells when no date is selected. */\n placeholder?: string;\n /** Rules for disabling specific weekdays, individual dates, or date ranges. The required `reason` is shown in an inline prompt and linked to disabled cells via `aria-describedby` for screen reader accessibility. */\n disabledRules?: DisabledRules;\n /** Called whenever the focused date changes — including disabled and out-of-range dates. `meta.isEnabled` is `false` when the date is not selectable. */\n onDateFocus?: (date: Date | null, meta: DateChangeMeta) => void;\n /** Called when a date is confirmed (click or Enter). Only fires for enabled dates. */\n onChange?: (date: Date | null) => void;\n}\n\n/**\n * Temporary toggle — set `true` to restore strict min/max keyboard clamping.\n * @see https://transferwise.atlassian.net/browse/DS-8518\n */\nconst STRICT_KEYBOARD_CLAMPING = false;\n\n/**\n * Inline calendar for selecting a single date. Powers [DateLookup](?path=/docs/forms-datelookup--docs).\n */\nconst Calendar = ({\n value,\n min: minProp = null,\n max: maxProp = null,\n monthFormat = MonthFormat.LONG,\n placeholder,\n disabledRules,\n onDateFocus,\n onChange,\n}: CalendarProps) => {\n const intl = useIntl();\n const { isRTL } = useDirection();\n const selectedDate = getStartOfDay(value);\n const min = getStartOfDay(minProp);\n const max = getStartOfDay(maxProp);\n const disabledReasonId = useId();\n const disabledRulesRef = useRef(disabledRules);\n useEffect(() => {\n disabledRulesRef.current = disabledRules;\n });\n\n const [hasInteracted, setHasInteracted] = useState(false);\n const [focusedDate, setFocusedDate] = useState<Date | null>(selectedDate);\n\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setFocusedDate(selectedDate);\n }, [selectedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const checkIsEnabled = (date: Date | null) => {\n if (!date) return true;\n return isWithinRange(date, min, max) && !isDateDisabled(date, disabledRulesRef.current);\n };\n\n const focusedDateDisabled = focusedDate\n ? !isWithinRange(focusedDate, min, max) || isDateDisabled(focusedDate, disabledRules)\n : false;\n\n useEffect(() => {\n if (selectedDate && !isWithinRange(selectedDate, min, max)) {\n const clamped = moveToWithinRange(selectedDate, min, max);\n setFocusedDate(clamped); // eslint-disable-line react-hooks/set-state-in-effect\n onDateFocus?.(clamped, { isEnabled: checkIsEnabled(clamped) });\n }\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime(), onDateFocus]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const dateView = returnDateView(selectedDate, min, max);\n const [viewMonth, setViewMonth] = useState(dateView.getMonth());\n const [viewYear, setViewYear] = useState(dateView.getFullYear());\n const [mode, setMode] = useState<'day' | 'month' | 'year'>('day');\n\n useEffect(() => {\n const view = returnDateView(selectedDate, min, max);\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(view.getMonth());\n\n setViewYear(view.getFullYear());\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n if (focusedDate) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(focusedDate.getMonth());\n setViewYear(focusedDate.getFullYear());\n }\n }, [focusedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleViewDateUpdate = useCallback(\n // eslint-disable-next-line react-hooks/preserve-manual-memoization\n ({ month, year }: { month?: number; year?: number }) => {\n if (month !== undefined) setViewMonth(month);\n if (year !== undefined) setViewYear(year);\n setHasInteracted(false);\n },\n [],\n );\n\n const switchToDays = useCallback(() => setMode('day'), []);\n const switchToMonths = useCallback(() => setMode('month'), []);\n const switchToYears = useCallback(() => setMode('year'), []);\n\n const handleSelectedDateUpdate = useCallback(\n (date: Date) => {\n if (!hasInteracted) setHasInteracted(true);\n const isEnabled = checkIsEnabled(date);\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled });\n if (isEnabled && onChange) {\n onChange(date);\n }\n },\n [onDateFocus, onChange], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const adjustDate = useCallback(\n (daysToAdd: number, monthsToAdd: number, yearsToAdd: number) => {\n const base = focusedDate ?? selectedDate;\n let date: Date | null;\n if (base) {\n date = new Date(\n mode === 'year' ? base.getFullYear() + yearsToAdd : base.getFullYear(),\n mode === 'month' ? base.getMonth() + monthsToAdd : base.getMonth(),\n mode === 'day' ? base.getDate() + daysToAdd : base.getDate(),\n );\n } else {\n date = getStartOfDay(new Date());\n }\n date &&=\n STRICT_KEYBOARD_CLAMPING || mode !== 'day'\n ? moveToWithinRange(date, min, max)\n : clampToDayViewBoundary(date, min, max);\n if (date?.getTime() !== focusedDate?.getTime()) {\n const monthChanged = date\n ? date.getMonth() !== focusedDate?.getMonth() ||\n date.getFullYear() !== focusedDate?.getFullYear()\n : false;\n setFocusedDate(date);\n if (date) {\n setViewMonth(date.getMonth());\n setViewYear(date.getFullYear());\n }\n if (monthChanged) {\n setHasInteracted(false);\n } else if (!hasInteracted) {\n setHasInteracted(true);\n }\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, selectedDate, min, max, mode, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleDayFocus = useCallback(\n (date: Date) => {\n if (date.getTime() !== focusedDate?.getTime()) {\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n const orientationSign = isRTL ? -1 : 1;\n switch (event.key) {\n case 'ArrowLeft':\n adjustDate(-1 * orientationSign, -1 * orientationSign, -1 * orientationSign);\n event.preventDefault();\n break;\n case 'ArrowUp':\n adjustDate(-7, -4, -4);\n event.preventDefault();\n break;\n case 'ArrowRight':\n adjustDate(1 * orientationSign, 1 * orientationSign, 1 * orientationSign);\n event.preventDefault();\n break;\n case 'ArrowDown':\n adjustDate(7, 4, 4);\n event.preventDefault();\n break;\n case 'Enter':\n case ' ':\n if (\n mode === 'day' &&\n focusedDate &&\n (event.target as HTMLElement).hasAttribute('data-calendar-cell')\n ) {\n handleSelectedDateUpdate(focusedDate);\n event.preventDefault();\n }\n break;\n default:\n break;\n }\n },\n [adjustDate, focusedDate, mode, handleSelectedDateUpdate, isRTL],\n );\n\n const focusedDateOutOfRange = focusedDate ? !isWithinRange(focusedDate, min, max) : false;\n\n const formatDateForPrompt = (date: Date) => formatDate(date, intl.locale, LONG_DAY_FORMAT);\n\n const outOfRangePromptText =\n min && max\n ? intl.formatMessage(messages.outOfRangeBetween, {\n min: formatDateForPrompt(min),\n max: formatDateForPrompt(max),\n })\n : min\n ? intl.formatMessage(messages.outOfRangeAfter, { min: formatDateForPrompt(min) })\n : max\n ? intl.formatMessage(messages.outOfRangeBefore, { max: formatDateForPrompt(max) })\n : '';\n\n const hasOutOfRangeDates = mode === 'day' && !!(min || max);\n const showRulesPrompt =\n mode === 'day' &&\n !!disabledRules &&\n hasDisabledDatesInMonth(viewMonth, viewYear, disabledRules, min, max);\n const showOutOfRangePrompt = mode === 'day' && focusedDateOutOfRange;\n const showPrompt = hasOutOfRangeDates || showRulesPrompt;\n\n const promptText = showOutOfRangePrompt\n ? outOfRangePromptText\n : (disabledRules?.reason ?? outOfRangePromptText);\n const promptSentiment = showOutOfRangePrompt || focusedDateDisabled ? 'negative' : 'neutral';\n // Visible when there's an actionable message; sr-only when only hasOutOfRangeDates is true\n // (prompt exists for aria-describedby but no visual cue needed until an out-of-range date is focused)\n const promptClassName = showOutOfRangePrompt || showRulesPrompt ? 'm-t-1' : 'sr-only';\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div onKeyDown={handleKeyDown}>\n {mode === 'day' && (\n <DayCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewMonth={viewMonth}\n viewYear={viewYear}\n monthFormat={monthFormat}\n disabledRules={disabledRules}\n disabledReasonId={showPrompt ? disabledReasonId : undefined}\n announceReasonOnFocus={!hasInteracted}\n onSelect={handleSelectedDateUpdate}\n onDayFocus={handleDayFocus}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'month' && (\n <MonthCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToDays}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'year' && (\n <YearCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToMonths}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {showPrompt && (\n <InlinePrompt\n sentiment={promptSentiment}\n width=\"full\"\n id={disabledReasonId}\n className={promptClassName}\n >\n {promptText}\n </InlinePrompt>\n )}\n </div>\n );\n};\n\nexport default Calendar;\n"],"names":["Calendar","value","min","minProp","max","maxProp","monthFormat","MonthFormat","LONG","placeholder","disabledRules","onDateFocus","onChange","intl","useIntl","isRTL","useDirection","selectedDate","getStartOfDay","disabledReasonId","useId","disabledRulesRef","useRef","useEffect","current","hasInteracted","setHasInteracted","useState","focusedDate","setFocusedDate","getTime","checkIsEnabled","date","isWithinRange","isDateDisabled","focusedDateDisabled","clamped","moveToWithinRange","isEnabled","dateView","returnDateView","viewMonth","setViewMonth","getMonth","viewYear","setViewYear","getFullYear","mode","setMode","view","handleViewDateUpdate","useCallback","month","year","undefined","switchToDays","switchToMonths","switchToYears","handleSelectedDateUpdate","adjustDate","daysToAdd","monthsToAdd","yearsToAdd","base","Date","getDate","clampToDayViewBoundary","monthChanged","handleDayFocus","handleKeyDown","event","orientationSign","key","preventDefault","target","hasAttribute","focusedDateOutOfRange","formatDateForPrompt","formatDate","locale","LONG_DAY_FORMAT","outOfRangePromptText","formatMessage","messages","outOfRangeBetween","outOfRangeAfter","outOfRangeBefore","hasOutOfRangeDates","showRulesPrompt","hasDisabledDatesInMonth","showOutOfRangePrompt","showPrompt","promptText","reason","promptSentiment","promptClassName","_jsxs","onKeyDown","children","_jsx","DayCalendar","announceReasonOnFocus","onSelect","onDayFocus","onLabelClick","onViewDateUpdate","MonthCalendar","YearCalendar","InlinePrompt","sentiment","width","id","className"],"mappings":"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"}
@@ -24,6 +24,8 @@ import '@transferwise/icons';
24
24
  import 'clsx';
25
25
  import '../common/CloseButton/CloseButton.messages.mjs';
26
26
  import { jsxs, jsx } from 'react/jsx-runtime';
27
+ import '@transferwise/neptune-validation';
28
+ import { useDirection } from '../common/hooks/useDirection/useDirection.mjs';
27
29
  import { moveToWithinRange } from '../common/DateUtils/moveToWithinRange/moveToWithinRange.mjs';
28
30
  import { isWithinRange } from '../common/DateUtils/isWithinRange/isWithinRange.mjs';
29
31
  import { returnDateView } from '../common/DateUtils/getDateView/getDateView.mjs';
@@ -52,6 +54,9 @@ const Calendar = ({
52
54
  onChange
53
55
  }) => {
54
56
  const intl = useIntl();
57
+ const {
58
+ isRTL
59
+ } = useDirection();
55
60
  const selectedDate = getStartOfDay(value);
56
61
  const min = getStartOfDay(minProp);
57
62
  const max = getStartOfDay(maxProp);
@@ -156,9 +161,10 @@ const Calendar = ({
156
161
  }
157
162
  }, [focusedDate, onDateFocus]);
158
163
  const handleKeyDown = useCallback(event => {
164
+ const orientationSign = isRTL ? -1 : 1;
159
165
  switch (event.key) {
160
166
  case 'ArrowLeft':
161
- adjustDate(-1, -1, -1);
167
+ adjustDate(-1 * orientationSign, -1 * orientationSign, -1 * orientationSign);
162
168
  event.preventDefault();
163
169
  break;
164
170
  case 'ArrowUp':
@@ -166,7 +172,7 @@ const Calendar = ({
166
172
  event.preventDefault();
167
173
  break;
168
174
  case 'ArrowRight':
169
- adjustDate(1, 1, 1);
175
+ adjustDate(1 * orientationSign, 1 * orientationSign, 1 * orientationSign);
170
176
  event.preventDefault();
171
177
  break;
172
178
  case 'ArrowDown':
@@ -181,7 +187,7 @@ const Calendar = ({
181
187
  }
182
188
  break;
183
189
  }
184
- }, [adjustDate, focusedDate, mode, handleSelectedDateUpdate]);
190
+ }, [adjustDate, focusedDate, mode, handleSelectedDateUpdate, isRTL]);
185
191
  const focusedDateOutOfRange = focusedDate ? !isWithinRange(focusedDate, min, max) : false;
186
192
  const formatDateForPrompt = date => formatDate(date, intl.locale, LONG_DAY_FORMAT);
187
193
  const outOfRangePromptText = min && max ? intl.formatMessage(messages.outOfRangeBetween, {
@@ -1 +1 @@
1
- {"version":3,"file":"Calendar.mjs","sources":["../../src/Calendar/Calendar.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useId, useRef, KeyboardEvent } from 'react';\nimport { useIntl } from 'react-intl';\nimport { formatDate } from '@transferwise/formatting';\n\nimport { MonthFormat } from '../common';\nimport { isWithinRange, moveToWithinRange, returnDateView } from '../common/DateUtils';\nimport { clampToDayViewBoundary, isDateDisabled, hasDisabledDatesInMonth } from './_helpers';\nimport { LONG_DAY_FORMAT } from './Calendar.constants';\nimport { InlinePrompt } from '../Prompt/InlinePrompt';\nimport type { DateChangeMeta, DisabledRules } from './Calendar.types';\nimport DayCalendar from './DayCalendar';\nimport { getStartOfDay } from './GetStartOfDay';\nimport messages from './Calendar.messages';\nimport MonthCalendar from './MonthCalendar';\nimport YearCalendar from './YearCalendar';\n\nexport interface CalendarProps {\n /** The currently selected date, or `null` for no selection. */\n value: Date | null;\n /** Earliest selectable date (inclusive). Dates before this are interactive but not selectable, and show a boundary prompt. */\n min?: Date | null;\n /** Latest selectable date (inclusive). Dates after this are interactive but not selectable, and show a boundary prompt. */\n max?: Date | null;\n /** Month name format in the header. Defaults to `'long'` (e.g. \"January\"). */\n monthFormat?: `${MonthFormat}`;\n /** Placeholder text shown in the month/year cells when no date is selected. */\n placeholder?: string;\n /** Rules for disabling specific weekdays, individual dates, or date ranges. The required `reason` is shown in an inline prompt and linked to disabled cells via `aria-describedby` for screen reader accessibility. */\n disabledRules?: DisabledRules;\n /** Called whenever the focused date changes — including disabled and out-of-range dates. `meta.isEnabled` is `false` when the date is not selectable. */\n onDateFocus?: (date: Date | null, meta: DateChangeMeta) => void;\n /** Called when a date is confirmed (click or Enter). Only fires for enabled dates. */\n onChange?: (date: Date | null) => void;\n}\n\n/**\n * Temporary toggle — set `true` to restore strict min/max keyboard clamping.\n * @see https://transferwise.atlassian.net/browse/DS-8518\n */\nconst STRICT_KEYBOARD_CLAMPING = false;\n\n/**\n * Inline calendar for selecting a single date. Powers [DateLookup](?path=/docs/forms-datelookup--docs).\n */\nconst Calendar = ({\n value,\n min: minProp = null,\n max: maxProp = null,\n monthFormat = MonthFormat.LONG,\n placeholder,\n disabledRules,\n onDateFocus,\n onChange,\n}: CalendarProps) => {\n const intl = useIntl();\n const selectedDate = getStartOfDay(value);\n const min = getStartOfDay(minProp);\n const max = getStartOfDay(maxProp);\n const disabledReasonId = useId();\n const disabledRulesRef = useRef(disabledRules);\n useEffect(() => {\n disabledRulesRef.current = disabledRules;\n });\n\n const [hasInteracted, setHasInteracted] = useState(false);\n const [focusedDate, setFocusedDate] = useState<Date | null>(selectedDate);\n\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setFocusedDate(selectedDate);\n }, [selectedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const checkIsEnabled = (date: Date | null) => {\n if (!date) return true;\n return isWithinRange(date, min, max) && !isDateDisabled(date, disabledRulesRef.current);\n };\n\n const focusedDateDisabled = focusedDate\n ? !isWithinRange(focusedDate, min, max) || isDateDisabled(focusedDate, disabledRules)\n : false;\n\n useEffect(() => {\n if (selectedDate && !isWithinRange(selectedDate, min, max)) {\n const clamped = moveToWithinRange(selectedDate, min, max);\n setFocusedDate(clamped); // eslint-disable-line react-hooks/set-state-in-effect\n onDateFocus?.(clamped, { isEnabled: checkIsEnabled(clamped) });\n }\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime(), onDateFocus]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const dateView = returnDateView(selectedDate, min, max);\n const [viewMonth, setViewMonth] = useState(dateView.getMonth());\n const [viewYear, setViewYear] = useState(dateView.getFullYear());\n const [mode, setMode] = useState<'day' | 'month' | 'year'>('day');\n\n useEffect(() => {\n const view = returnDateView(selectedDate, min, max);\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(view.getMonth());\n\n setViewYear(view.getFullYear());\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n if (focusedDate) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(focusedDate.getMonth());\n setViewYear(focusedDate.getFullYear());\n }\n }, [focusedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleViewDateUpdate = useCallback(\n // eslint-disable-next-line react-hooks/preserve-manual-memoization\n ({ month, year }: { month?: number; year?: number }) => {\n if (month !== undefined) setViewMonth(month);\n if (year !== undefined) setViewYear(year);\n setHasInteracted(false);\n },\n [],\n );\n\n const switchToDays = useCallback(() => setMode('day'), []);\n const switchToMonths = useCallback(() => setMode('month'), []);\n const switchToYears = useCallback(() => setMode('year'), []);\n\n const handleSelectedDateUpdate = useCallback(\n (date: Date) => {\n if (!hasInteracted) setHasInteracted(true);\n const isEnabled = checkIsEnabled(date);\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled });\n if (isEnabled && onChange) {\n onChange(date);\n }\n },\n [onDateFocus, onChange], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const adjustDate = useCallback(\n (daysToAdd: number, monthsToAdd: number, yearsToAdd: number) => {\n const base = focusedDate ?? selectedDate;\n let date: Date | null;\n if (base) {\n date = new Date(\n mode === 'year' ? base.getFullYear() + yearsToAdd : base.getFullYear(),\n mode === 'month' ? base.getMonth() + monthsToAdd : base.getMonth(),\n mode === 'day' ? base.getDate() + daysToAdd : base.getDate(),\n );\n } else {\n date = getStartOfDay(new Date());\n }\n date &&=\n STRICT_KEYBOARD_CLAMPING || mode !== 'day'\n ? moveToWithinRange(date, min, max)\n : clampToDayViewBoundary(date, min, max);\n if (date?.getTime() !== focusedDate?.getTime()) {\n const monthChanged = date\n ? date.getMonth() !== focusedDate?.getMonth() ||\n date.getFullYear() !== focusedDate?.getFullYear()\n : false;\n setFocusedDate(date);\n if (date) {\n setViewMonth(date.getMonth());\n setViewYear(date.getFullYear());\n }\n if (monthChanged) {\n setHasInteracted(false);\n } else if (!hasInteracted) {\n setHasInteracted(true);\n }\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, selectedDate, min, max, mode, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleDayFocus = useCallback(\n (date: Date) => {\n if (date.getTime() !== focusedDate?.getTime()) {\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n switch (event.key) {\n case 'ArrowLeft':\n adjustDate(-1, -1, -1);\n event.preventDefault();\n break;\n case 'ArrowUp':\n adjustDate(-7, -4, -4);\n event.preventDefault();\n break;\n case 'ArrowRight':\n adjustDate(1, 1, 1);\n event.preventDefault();\n break;\n case 'ArrowDown':\n adjustDate(7, 4, 4);\n event.preventDefault();\n break;\n case 'Enter':\n case ' ':\n if (\n mode === 'day' &&\n focusedDate &&\n (event.target as HTMLElement).hasAttribute('data-calendar-cell')\n ) {\n handleSelectedDateUpdate(focusedDate);\n event.preventDefault();\n }\n break;\n default:\n break;\n }\n },\n [adjustDate, focusedDate, mode, handleSelectedDateUpdate],\n );\n\n const focusedDateOutOfRange = focusedDate ? !isWithinRange(focusedDate, min, max) : false;\n\n const formatDateForPrompt = (date: Date) => formatDate(date, intl.locale, LONG_DAY_FORMAT);\n\n const outOfRangePromptText =\n min && max\n ? intl.formatMessage(messages.outOfRangeBetween, {\n min: formatDateForPrompt(min),\n max: formatDateForPrompt(max),\n })\n : min\n ? intl.formatMessage(messages.outOfRangeAfter, { min: formatDateForPrompt(min) })\n : max\n ? intl.formatMessage(messages.outOfRangeBefore, { max: formatDateForPrompt(max) })\n : '';\n\n const hasOutOfRangeDates = mode === 'day' && !!(min || max);\n const showRulesPrompt =\n mode === 'day' &&\n !!disabledRules &&\n hasDisabledDatesInMonth(viewMonth, viewYear, disabledRules, min, max);\n const showOutOfRangePrompt = mode === 'day' && focusedDateOutOfRange;\n const showPrompt = hasOutOfRangeDates || showRulesPrompt;\n\n const promptText = showOutOfRangePrompt\n ? outOfRangePromptText\n : (disabledRules?.reason ?? outOfRangePromptText);\n const promptSentiment = showOutOfRangePrompt || focusedDateDisabled ? 'negative' : 'neutral';\n // Visible when there's an actionable message; sr-only when only hasOutOfRangeDates is true\n // (prompt exists for aria-describedby but no visual cue needed until an out-of-range date is focused)\n const promptClassName = showOutOfRangePrompt || showRulesPrompt ? 'm-t-1' : 'sr-only';\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div onKeyDown={handleKeyDown}>\n {mode === 'day' && (\n <DayCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewMonth={viewMonth}\n viewYear={viewYear}\n monthFormat={monthFormat}\n disabledRules={disabledRules}\n disabledReasonId={showPrompt ? disabledReasonId : undefined}\n announceReasonOnFocus={!hasInteracted}\n onSelect={handleSelectedDateUpdate}\n onDayFocus={handleDayFocus}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'month' && (\n <MonthCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToDays}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'year' && (\n <YearCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToMonths}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {showPrompt && (\n <InlinePrompt\n sentiment={promptSentiment}\n width=\"full\"\n id={disabledReasonId}\n className={promptClassName}\n >\n {promptText}\n </InlinePrompt>\n )}\n </div>\n );\n};\n\nexport default Calendar;\n"],"names":["Calendar","value","min","minProp","max","maxProp","monthFormat","MonthFormat","LONG","placeholder","disabledRules","onDateFocus","onChange","intl","useIntl","selectedDate","getStartOfDay","disabledReasonId","useId","disabledRulesRef","useRef","useEffect","current","hasInteracted","setHasInteracted","useState","focusedDate","setFocusedDate","getTime","checkIsEnabled","date","isWithinRange","isDateDisabled","focusedDateDisabled","clamped","moveToWithinRange","isEnabled","dateView","returnDateView","viewMonth","setViewMonth","getMonth","viewYear","setViewYear","getFullYear","mode","setMode","view","handleViewDateUpdate","useCallback","month","year","undefined","switchToDays","switchToMonths","switchToYears","handleSelectedDateUpdate","adjustDate","daysToAdd","monthsToAdd","yearsToAdd","base","Date","getDate","clampToDayViewBoundary","monthChanged","handleDayFocus","handleKeyDown","event","key","preventDefault","target","hasAttribute","focusedDateOutOfRange","formatDateForPrompt","formatDate","locale","LONG_DAY_FORMAT","outOfRangePromptText","formatMessage","messages","outOfRangeBetween","outOfRangeAfter","outOfRangeBefore","hasOutOfRangeDates","showRulesPrompt","hasDisabledDatesInMonth","showOutOfRangePrompt","showPrompt","promptText","reason","promptSentiment","promptClassName","_jsxs","onKeyDown","children","_jsx","DayCalendar","announceReasonOnFocus","onSelect","onDayFocus","onLabelClick","onViewDateUpdate","MonthCalendar","YearCalendar","InlinePrompt","sentiment","width","id","className"],"mappings":"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"}
1
+ {"version":3,"file":"Calendar.mjs","sources":["../../src/Calendar/Calendar.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useId, useRef, KeyboardEvent } from 'react';\nimport { useIntl } from 'react-intl';\nimport { formatDate } from '@transferwise/formatting';\n\nimport { MonthFormat } from '../common';\nimport { useDirection } from '../common/hooks';\nimport { isWithinRange, moveToWithinRange, returnDateView } from '../common/DateUtils';\nimport { clampToDayViewBoundary, isDateDisabled, hasDisabledDatesInMonth } from './_helpers';\nimport { LONG_DAY_FORMAT } from './Calendar.constants';\nimport { InlinePrompt } from '../Prompt/InlinePrompt';\nimport type { DateChangeMeta, DisabledRules } from './Calendar.types';\nimport DayCalendar from './DayCalendar';\nimport { getStartOfDay } from './GetStartOfDay';\nimport messages from './Calendar.messages';\nimport MonthCalendar from './MonthCalendar';\nimport YearCalendar from './YearCalendar';\n\nexport interface CalendarProps {\n /** The currently selected date, or `null` for no selection. */\n value: Date | null;\n /** Earliest selectable date (inclusive). Dates before this are interactive but not selectable, and show a boundary prompt. */\n min?: Date | null;\n /** Latest selectable date (inclusive). Dates after this are interactive but not selectable, and show a boundary prompt. */\n max?: Date | null;\n /** Month name format in the header. Defaults to `'long'` (e.g. \"January\"). */\n monthFormat?: `${MonthFormat}`;\n /** Placeholder text shown in the month/year cells when no date is selected. */\n placeholder?: string;\n /** Rules for disabling specific weekdays, individual dates, or date ranges. The required `reason` is shown in an inline prompt and linked to disabled cells via `aria-describedby` for screen reader accessibility. */\n disabledRules?: DisabledRules;\n /** Called whenever the focused date changes — including disabled and out-of-range dates. `meta.isEnabled` is `false` when the date is not selectable. */\n onDateFocus?: (date: Date | null, meta: DateChangeMeta) => void;\n /** Called when a date is confirmed (click or Enter). Only fires for enabled dates. */\n onChange?: (date: Date | null) => void;\n}\n\n/**\n * Temporary toggle — set `true` to restore strict min/max keyboard clamping.\n * @see https://transferwise.atlassian.net/browse/DS-8518\n */\nconst STRICT_KEYBOARD_CLAMPING = false;\n\n/**\n * Inline calendar for selecting a single date. Powers [DateLookup](?path=/docs/forms-datelookup--docs).\n */\nconst Calendar = ({\n value,\n min: minProp = null,\n max: maxProp = null,\n monthFormat = MonthFormat.LONG,\n placeholder,\n disabledRules,\n onDateFocus,\n onChange,\n}: CalendarProps) => {\n const intl = useIntl();\n const { isRTL } = useDirection();\n const selectedDate = getStartOfDay(value);\n const min = getStartOfDay(minProp);\n const max = getStartOfDay(maxProp);\n const disabledReasonId = useId();\n const disabledRulesRef = useRef(disabledRules);\n useEffect(() => {\n disabledRulesRef.current = disabledRules;\n });\n\n const [hasInteracted, setHasInteracted] = useState(false);\n const [focusedDate, setFocusedDate] = useState<Date | null>(selectedDate);\n\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setFocusedDate(selectedDate);\n }, [selectedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const checkIsEnabled = (date: Date | null) => {\n if (!date) return true;\n return isWithinRange(date, min, max) && !isDateDisabled(date, disabledRulesRef.current);\n };\n\n const focusedDateDisabled = focusedDate\n ? !isWithinRange(focusedDate, min, max) || isDateDisabled(focusedDate, disabledRules)\n : false;\n\n useEffect(() => {\n if (selectedDate && !isWithinRange(selectedDate, min, max)) {\n const clamped = moveToWithinRange(selectedDate, min, max);\n setFocusedDate(clamped); // eslint-disable-line react-hooks/set-state-in-effect\n onDateFocus?.(clamped, { isEnabled: checkIsEnabled(clamped) });\n }\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime(), onDateFocus]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const dateView = returnDateView(selectedDate, min, max);\n const [viewMonth, setViewMonth] = useState(dateView.getMonth());\n const [viewYear, setViewYear] = useState(dateView.getFullYear());\n const [mode, setMode] = useState<'day' | 'month' | 'year'>('day');\n\n useEffect(() => {\n const view = returnDateView(selectedDate, min, max);\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(view.getMonth());\n\n setViewYear(view.getFullYear());\n }, [selectedDate?.getTime(), min?.getTime(), max?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n if (focusedDate) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setViewMonth(focusedDate.getMonth());\n setViewYear(focusedDate.getFullYear());\n }\n }, [focusedDate?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleViewDateUpdate = useCallback(\n // eslint-disable-next-line react-hooks/preserve-manual-memoization\n ({ month, year }: { month?: number; year?: number }) => {\n if (month !== undefined) setViewMonth(month);\n if (year !== undefined) setViewYear(year);\n setHasInteracted(false);\n },\n [],\n );\n\n const switchToDays = useCallback(() => setMode('day'), []);\n const switchToMonths = useCallback(() => setMode('month'), []);\n const switchToYears = useCallback(() => setMode('year'), []);\n\n const handleSelectedDateUpdate = useCallback(\n (date: Date) => {\n if (!hasInteracted) setHasInteracted(true);\n const isEnabled = checkIsEnabled(date);\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled });\n if (isEnabled && onChange) {\n onChange(date);\n }\n },\n [onDateFocus, onChange], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const adjustDate = useCallback(\n (daysToAdd: number, monthsToAdd: number, yearsToAdd: number) => {\n const base = focusedDate ?? selectedDate;\n let date: Date | null;\n if (base) {\n date = new Date(\n mode === 'year' ? base.getFullYear() + yearsToAdd : base.getFullYear(),\n mode === 'month' ? base.getMonth() + monthsToAdd : base.getMonth(),\n mode === 'day' ? base.getDate() + daysToAdd : base.getDate(),\n );\n } else {\n date = getStartOfDay(new Date());\n }\n date &&=\n STRICT_KEYBOARD_CLAMPING || mode !== 'day'\n ? moveToWithinRange(date, min, max)\n : clampToDayViewBoundary(date, min, max);\n if (date?.getTime() !== focusedDate?.getTime()) {\n const monthChanged = date\n ? date.getMonth() !== focusedDate?.getMonth() ||\n date.getFullYear() !== focusedDate?.getFullYear()\n : false;\n setFocusedDate(date);\n if (date) {\n setViewMonth(date.getMonth());\n setViewYear(date.getFullYear());\n }\n if (monthChanged) {\n setHasInteracted(false);\n } else if (!hasInteracted) {\n setHasInteracted(true);\n }\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, selectedDate, min, max, mode, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleDayFocus = useCallback(\n (date: Date) => {\n if (date.getTime() !== focusedDate?.getTime()) {\n setFocusedDate(date);\n onDateFocus?.(date, { isEnabled: checkIsEnabled(date) });\n }\n },\n [focusedDate, onDateFocus], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n const orientationSign = isRTL ? -1 : 1;\n switch (event.key) {\n case 'ArrowLeft':\n adjustDate(-1 * orientationSign, -1 * orientationSign, -1 * orientationSign);\n event.preventDefault();\n break;\n case 'ArrowUp':\n adjustDate(-7, -4, -4);\n event.preventDefault();\n break;\n case 'ArrowRight':\n adjustDate(1 * orientationSign, 1 * orientationSign, 1 * orientationSign);\n event.preventDefault();\n break;\n case 'ArrowDown':\n adjustDate(7, 4, 4);\n event.preventDefault();\n break;\n case 'Enter':\n case ' ':\n if (\n mode === 'day' &&\n focusedDate &&\n (event.target as HTMLElement).hasAttribute('data-calendar-cell')\n ) {\n handleSelectedDateUpdate(focusedDate);\n event.preventDefault();\n }\n break;\n default:\n break;\n }\n },\n [adjustDate, focusedDate, mode, handleSelectedDateUpdate, isRTL],\n );\n\n const focusedDateOutOfRange = focusedDate ? !isWithinRange(focusedDate, min, max) : false;\n\n const formatDateForPrompt = (date: Date) => formatDate(date, intl.locale, LONG_DAY_FORMAT);\n\n const outOfRangePromptText =\n min && max\n ? intl.formatMessage(messages.outOfRangeBetween, {\n min: formatDateForPrompt(min),\n max: formatDateForPrompt(max),\n })\n : min\n ? intl.formatMessage(messages.outOfRangeAfter, { min: formatDateForPrompt(min) })\n : max\n ? intl.formatMessage(messages.outOfRangeBefore, { max: formatDateForPrompt(max) })\n : '';\n\n const hasOutOfRangeDates = mode === 'day' && !!(min || max);\n const showRulesPrompt =\n mode === 'day' &&\n !!disabledRules &&\n hasDisabledDatesInMonth(viewMonth, viewYear, disabledRules, min, max);\n const showOutOfRangePrompt = mode === 'day' && focusedDateOutOfRange;\n const showPrompt = hasOutOfRangeDates || showRulesPrompt;\n\n const promptText = showOutOfRangePrompt\n ? outOfRangePromptText\n : (disabledRules?.reason ?? outOfRangePromptText);\n const promptSentiment = showOutOfRangePrompt || focusedDateDisabled ? 'negative' : 'neutral';\n // Visible when there's an actionable message; sr-only when only hasOutOfRangeDates is true\n // (prompt exists for aria-describedby but no visual cue needed until an out-of-range date is focused)\n const promptClassName = showOutOfRangePrompt || showRulesPrompt ? 'm-t-1' : 'sr-only';\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div onKeyDown={handleKeyDown}>\n {mode === 'day' && (\n <DayCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewMonth={viewMonth}\n viewYear={viewYear}\n monthFormat={monthFormat}\n disabledRules={disabledRules}\n disabledReasonId={showPrompt ? disabledReasonId : undefined}\n announceReasonOnFocus={!hasInteracted}\n onSelect={handleSelectedDateUpdate}\n onDayFocus={handleDayFocus}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'month' && (\n <MonthCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToDays}\n onLabelClick={switchToYears}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {mode === 'year' && (\n <YearCalendar\n selectedDate={selectedDate}\n focusedDate={focusedDate}\n min={min}\n max={max}\n viewYear={viewYear}\n {...(placeholder != null && { placeholder })}\n onSelect={switchToMonths}\n onViewDateUpdate={handleViewDateUpdate}\n />\n )}\n {showPrompt && (\n <InlinePrompt\n sentiment={promptSentiment}\n width=\"full\"\n id={disabledReasonId}\n className={promptClassName}\n >\n {promptText}\n </InlinePrompt>\n )}\n </div>\n );\n};\n\nexport default Calendar;\n"],"names":["Calendar","value","min","minProp","max","maxProp","monthFormat","MonthFormat","LONG","placeholder","disabledRules","onDateFocus","onChange","intl","useIntl","isRTL","useDirection","selectedDate","getStartOfDay","disabledReasonId","useId","disabledRulesRef","useRef","useEffect","current","hasInteracted","setHasInteracted","useState","focusedDate","setFocusedDate","getTime","checkIsEnabled","date","isWithinRange","isDateDisabled","focusedDateDisabled","clamped","moveToWithinRange","isEnabled","dateView","returnDateView","viewMonth","setViewMonth","getMonth","viewYear","setViewYear","getFullYear","mode","setMode","view","handleViewDateUpdate","useCallback","month","year","undefined","switchToDays","switchToMonths","switchToYears","handleSelectedDateUpdate","adjustDate","daysToAdd","monthsToAdd","yearsToAdd","base","Date","getDate","clampToDayViewBoundary","monthChanged","handleDayFocus","handleKeyDown","event","orientationSign","key","preventDefault","target","hasAttribute","focusedDateOutOfRange","formatDateForPrompt","formatDate","locale","LONG_DAY_FORMAT","outOfRangePromptText","formatMessage","messages","outOfRangeBetween","outOfRangeAfter","outOfRangeBefore","hasOutOfRangeDates","showRulesPrompt","hasDisabledDatesInMonth","showOutOfRangePrompt","showPrompt","promptText","reason","promptSentiment","promptClassName","_jsxs","onKeyDown","children","_jsx","DayCalendar","announceReasonOnFocus","onSelect","onDayFocus","onLabelClick","onViewDateUpdate","MonthCalendar","YearCalendar","InlinePrompt","sentiment","width","id","className"],"mappings":"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"}
@@ -5,6 +5,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var icons = require('@transferwise/icons');
6
6
  var clsx = require('clsx');
7
7
  var React = require('react');
8
+ require('@transferwise/neptune-validation');
9
+ var useDirection = require('../common/hooks/useDirection/useDirection.js');
10
+ require('@transferwise/neptune-tokens');
8
11
  var IconButton = require('../IconButton/IconButton.js');
9
12
  var Title = require('../Title/Title.js');
10
13
  var PromoCard = require('../PromoCard/PromoCard.js');
@@ -23,8 +26,11 @@ const Carousel = ({
23
26
  const [visibleCardOnMobileView, setVisibleCardOnMobileView] = React.useState('');
24
27
  const carouselElementRef = React.useRef(null);
25
28
  const carouselCardsRef = React.useRef([]);
26
- const isLeftActionButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
27
- const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;
29
+ const {
30
+ isRTL
31
+ } = useDirection.useDirection();
32
+ const isPrevButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
33
+ const areActionButtonsEnabled = isPrevButtonEnabled || !scrollIsAtEnd;
28
34
  const [focusedCard, setFocusedCard] = React.useState(cards?.[0]?.id);
29
35
  const updateScrollButtonsState = () => {
30
36
  if (carouselElementRef.current) {
@@ -51,15 +57,16 @@ const Carousel = ({
51
57
  }
52
58
  setPreviousScrollPosition(scrollPosition);
53
59
  };
54
- const scrollCarousel = (direction = 'right') => {
60
+ const scrollCarousel = direction => {
55
61
  if (carouselElementRef.current) {
56
62
  const {
57
63
  scrollWidth
58
64
  } = carouselElementRef.current;
59
65
  const cardWidth = scrollWidth / carouselCardsRef.current.length;
60
- const res = Math.floor(cardWidth - cardWidth * 0.05);
66
+ const distance = Math.floor(cardWidth - cardWidth * 0.05);
67
+ const sign = direction === 'forward' ? 1 : -1;
61
68
  carouselElementRef.current.scrollBy({
62
- left: direction === 'right' ? res : -res,
69
+ left: isRTL ? -sign * distance : sign * distance,
63
70
  behavior: 'smooth'
64
71
  });
65
72
  }
@@ -126,10 +133,10 @@ const Carousel = ({
126
133
  size: 32,
127
134
  tabIndex: -1,
128
135
  priority: "tertiary",
129
- disabled: !isLeftActionButtonEnabled,
136
+ disabled: !isPrevButtonEnabled,
130
137
  "aria-hidden": "true",
131
138
  "data-testid": "scroll-carousel-left",
132
- onClick: () => scrollCarousel('left'),
139
+ onClick: () => scrollCarousel('backward'),
133
140
  children: /*#__PURE__*/jsxRuntime.jsx(icons.ChevronLeft, {})
134
141
  }), /*#__PURE__*/jsxRuntime.jsx(IconButton.default, {
135
142
  size: 32,
@@ -139,7 +146,7 @@ const Carousel = ({
139
146
  "aria-hidden": "true",
140
147
  "data-testid": "scroll-carousel-right",
141
148
  disabled: scrollIsAtEnd,
142
- onClick: () => scrollCarousel(),
149
+ onClick: () => scrollCarousel('forward'),
143
150
  children: /*#__PURE__*/jsxRuntime.jsx(icons.ChevronRight, {})
144
151
  })]
145
152
  }) : null]
@@ -150,7 +157,7 @@ const Carousel = ({
150
157
  className: "carousel",
151
158
  onScroll: event => {
152
159
  const target = event.target;
153
- setScrollPosition(target.scrollLeft);
160
+ setScrollPosition(Math.abs(target.scrollLeft));
154
161
  },
155
162
  children: cards?.map((card, index) => {
156
163
  const sharedProps = {
@@ -270,7 +277,7 @@ const Carousel = ({
270
277
  };
271
278
  const isVisible = (container, el) => {
272
279
  const cWidth = container.offsetWidth;
273
- const cScrollOffset = container.scrollLeft;
280
+ const cScrollOffset = Math.abs(container.scrollLeft);
274
281
  const elemLeft = el.offsetLeft - container.offsetLeft;
275
282
  const elemRight = elemLeft + el.offsetWidth;
276
283
  return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.js","sources":["../../src/Carousel/Carousel.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { type CSSProperties, type ReactNode, useEffect, useRef, useState } from 'react';\n\nimport IconButton from '../IconButton';\nimport Title from '../Title';\nimport type { PromoCardLinkProps } from '../PromoCard/PromoCard';\nimport PromoCard from '../PromoCard/PromoCard';\n\nexport type CarouselCardCommon = {\n id: string;\n href?: string;\n hrefTarget?: HTMLAnchorElement['target'];\n onClick?: () => void;\n className?: string;\n styles?: CSSProperties;\n};\n\nexport type CarouselDefaultCard = CarouselCardCommon & {\n type: 'anchor' | 'button';\n content: ReactNode;\n};\n\nexport type CarouselPromoCard = CarouselCardCommon & {\n type: 'promo';\n} & Omit<PromoCardLinkProps, 'type'>;\n\nexport type CarouselCard = CarouselDefaultCard | CarouselPromoCard;\nexport interface CarouselProps {\n header: string | ReactNode;\n className?: string;\n cards: CarouselCard[];\n onClick?: (cardId: string) => void;\n}\n\ntype CardsReference = {\n type: 'promo' | 'default';\n cardElement: HTMLDivElement | HTMLAnchorElement;\n anchorElement?: HTMLAnchorElement;\n};\n\nconst LEFT_SCROLL_OFFSET = 8;\n\nconst Carousel: React.FC<CarouselProps> = ({ header, className, cards, onClick }) => {\n const [scrollPosition, setScrollPosition] = useState(0);\n const [previousScrollPosition, setPreviousScrollPosition] = useState(0);\n const [scrollIsAtEnd, setScrollIsAtEnd] = useState(false);\n const [visibleCardOnMobileView, setVisibleCardOnMobileView] = useState<string>('');\n const carouselElementRef = useRef<HTMLDivElement>(null);\n const carouselCardsRef = useRef<CardsReference[]>([]);\n\n const isLeftActionButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;\n\n const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;\n\n const [focusedCard, setFocusedCard] = useState(cards?.[0]?.id);\n\n const updateScrollButtonsState = () => {\n if (carouselElementRef.current) {\n const { scrollWidth, offsetWidth } = carouselElementRef.current;\n\n const scrollAtEnd = scrollWidth - offsetWidth <= scrollPosition + LEFT_SCROLL_OFFSET;\n setScrollIsAtEnd(scrollAtEnd);\n }\n\n const scrollDirecton = scrollPosition > previousScrollPosition ? 'right' : 'left';\n\n const cardsInFullViewIds: string[] = [];\n carouselCardsRef.current.forEach((card) => {\n if (isVisible(carouselElementRef.current as HTMLElement, card.cardElement as HTMLElement)) {\n // eslint-disable-next-line functional/immutable-data\n cardsInFullViewIds.push(card.cardElement.getAttribute('id') ?? '');\n }\n });\n\n if (cardsInFullViewIds.length >= 1) {\n const visibleCardIndex = scrollDirecton === 'right' ? cardsInFullViewIds.length - 1 : 0;\n const visibleCardId = cardsInFullViewIds[visibleCardIndex];\n setVisibleCardOnMobileView(visibleCardId);\n setFocusedCard(visibleCardId);\n }\n\n setPreviousScrollPosition(scrollPosition);\n };\n\n const scrollCarousel = (direction: 'left' | 'right' = 'right') => {\n if (carouselElementRef.current) {\n const { scrollWidth } = carouselElementRef.current;\n\n const cardWidth = scrollWidth / carouselCardsRef.current.length;\n\n const res = Math.floor(cardWidth - cardWidth * 0.05);\n\n carouselElementRef.current.scrollBy({\n left: direction === 'right' ? res : -res,\n behavior: 'smooth',\n });\n }\n };\n\n const handleOnKeyDown = (\n event: React.KeyboardEvent<HTMLAnchorElement | HTMLDivElement>,\n index: number,\n ) => {\n if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {\n const nextIndex = event.key === 'ArrowRight' ? index + 1 : index - 1;\n const nextCard = cards[nextIndex];\n if (nextCard) {\n const ref = carouselCardsRef.current[nextIndex];\n if (ref.type === 'promo') {\n ref.anchorElement?.focus();\n } else {\n ref.cardElement?.focus();\n }\n\n scrollCardIntoView(carouselCardsRef.current[nextIndex].cardElement, nextCard);\n event.preventDefault();\n }\n }\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.currentTarget.click();\n }\n };\n\n const scrollCardIntoView = (element: HTMLElement, card: CarouselCard) => {\n element.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'center',\n });\n\n setFocusedCard(card.id);\n };\n\n useEffect(() => {\n updateScrollButtonsState();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [scrollPosition]);\n\n useEffect(() => {\n window.addEventListener('resize', updateScrollButtonsState);\n\n return () => {\n window.removeEventListener('resize', updateScrollButtonsState);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const addElementToCardsRefArray = (index: number, ref: Partial<CardsReference>) => {\n if (ref) {\n // eslint-disable-next-line functional/immutable-data\n carouselCardsRef.current[index] = {\n type: ref.type ?? carouselCardsRef.current?.[index]?.type,\n cardElement: ref.cardElement ?? carouselCardsRef.current?.[index]?.cardElement,\n anchorElement: ref.anchorElement ?? carouselCardsRef.current?.[index]?.anchorElement,\n };\n }\n };\n\n return (\n <div className={clsx('carousel-wrapper', className)}>\n <div className=\"d-flex justify-content-between carousel__header\">\n {typeof header === 'string' ? (\n <Title as=\"span\" type=\"title-body\">\n {header}\n </Title>\n ) : (\n header\n )}\n {areActionButtonsEnabled ? (\n <div className=\"hidden-xs d-inline-flex\">\n <IconButton\n size={32}\n tabIndex={-1}\n priority=\"tertiary\"\n disabled={!isLeftActionButtonEnabled}\n aria-hidden=\"true\"\n data-testid=\"scroll-carousel-left\"\n onClick={() => scrollCarousel('left')}\n >\n <ChevronLeft />\n </IconButton>\n <IconButton\n size={32}\n tabIndex={-1}\n className=\"m-l-1\"\n priority=\"tertiary\"\n aria-hidden=\"true\"\n data-testid=\"scroll-carousel-right\"\n disabled={scrollIsAtEnd}\n onClick={() => scrollCarousel()}\n >\n <ChevronRight />\n </IconButton>\n </div>\n ) : null}\n </div>\n <div\n ref={carouselElementRef}\n tabIndex={-1}\n role=\"list\"\n className=\"carousel\"\n onScroll={(event) => {\n const target = event.target as HTMLElement;\n setScrollPosition(target.scrollLeft);\n }}\n >\n {cards?.map((card, index) => {\n const sharedProps = {\n id: card.id,\n className: clsx('carousel__card', {\n 'carousel__card--focused': card.id === focusedCard,\n }),\n onClick: () => {\n card.onClick?.();\n onClick?.(card.id);\n },\n onFocus: (event: React.FocusEvent<HTMLAnchorElement | HTMLDivElement>) => {\n scrollCardIntoView(event.currentTarget, card);\n },\n };\n\n const cardContent =\n card.type !== 'promo' ? (\n <div\n id={`${card.id}-content`}\n className={clsx('carousel__card-content', {\n [card.className ?? '']: !!card.className,\n })}\n style={card.styles}\n >\n {card.content}\n </div>\n ) : null;\n\n if (card.type === 'button') {\n return (\n <div key={card.id} aria-labelledby={`${card.id}-content`} role=\"listitem\">\n <div\n {...sharedProps}\n ref={(el) => {\n if (el) {\n // eslint-disable-next-line functional/immutable-data\n carouselCardsRef.current[index] = {\n type: 'default',\n cardElement: el,\n };\n }\n }}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(event) => handleOnKeyDown(event, index)}\n >\n {cardContent}\n </div>\n </div>\n );\n }\n\n if (card.type === 'promo') {\n return (\n <div key={card.id} id={card.id} role=\"listitem\" aria-labelledby={`${card.id}-anchor`}>\n <PromoCard\n {...{ ...card, type: undefined }}\n {...{ ...sharedProps }}\n ref={(el: HTMLDivElement | null) => {\n if (el) {\n addElementToCardsRefArray(index, {\n type: 'promo',\n cardElement: el,\n });\n }\n }}\n anchorRef={(el: HTMLAnchorElement) => {\n if (el) {\n addElementToCardsRefArray(index, {\n type: 'promo',\n anchorElement: el,\n });\n }\n }}\n anchorId={`${card.id}-anchor`}\n onKeyDown={(event) => handleOnKeyDown(event, index)}\n />\n </div>\n );\n }\n\n return (\n <div key={card.id} aria-labelledby={`${card.id}-content`} role=\"listitem\">\n <a\n {...sharedProps}\n ref={(el) => {\n if (el) {\n // eslint-disable-next-line functional/immutable-data\n carouselCardsRef.current[index] = {\n type: 'default',\n cardElement: el,\n };\n }\n }}\n href={card.href}\n target={card.hrefTarget}\n rel=\"noreferrer\"\n onKeyDown={(event) => handleOnKeyDown(event, index)}\n >\n {cardContent}\n </a>\n </div>\n );\n })}\n </div>\n <div className=\"visible-xs\">\n <div className=\"carousel__indicators\">\n {cards?.map((card, index) => (\n <button\n key={`${card.id}-indicator`}\n data-testid={`${card.id}-indicator`}\n tabIndex={-1}\n aria-hidden\n type=\"button\"\n className={clsx('carousel__indicator', {\n 'carousel__indicator--selected': card.id === visibleCardOnMobileView,\n })}\n onClick={() => {\n scrollCardIntoView(carouselCardsRef.current[index].cardElement, card);\n }}\n />\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nconst isVisible = (container: HTMLElement, el: HTMLElement) => {\n const cWidth = container.offsetWidth;\n const cScrollOffset = container.scrollLeft;\n\n const elemLeft = el.offsetLeft - container.offsetLeft;\n const elemRight = elemLeft + el.offsetWidth;\n\n return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;\n};\n\nexport default Carousel;\n"],"names":["LEFT_SCROLL_OFFSET","Carousel","header","className","cards","onClick","scrollPosition","setScrollPosition","useState","previousScrollPosition","setPreviousScrollPosition","scrollIsAtEnd","setScrollIsAtEnd","visibleCardOnMobileView","setVisibleCardOnMobileView","carouselElementRef","useRef","carouselCardsRef","isLeftActionButtonEnabled","areActionButtonsEnabled","focusedCard","setFocusedCard","id","updateScrollButtonsState","current","scrollWidth","offsetWidth","scrollAtEnd","scrollDirecton","cardsInFullViewIds","forEach","card","isVisible","cardElement","push","getAttribute","length","visibleCardIndex","visibleCardId","scrollCarousel","direction","cardWidth","res","Math","floor","scrollBy","left","behavior","handleOnKeyDown","event","index","key","nextIndex","nextCard","ref","type","anchorElement","focus","scrollCardIntoView","preventDefault","currentTarget","click","element","scrollIntoView","block","inline","useEffect","window","addEventListener","removeEventListener","addElementToCardsRefArray","_jsxs","clsx","children","_jsx","Title","as","IconButton","size","tabIndex","priority","disabled","ChevronLeft","ChevronRight","role","onScroll","target","scrollLeft","map","sharedProps","onFocus","cardContent","style","styles","content","el","onKeyDown","PromoCard","undefined","anchorRef","anchorId","href","hrefTarget","rel","container","cWidth","cScrollOffset","elemLeft","offsetLeft","elemRight"],"mappings":"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"}
1
+ {"version":3,"file":"Carousel.js","sources":["../../src/Carousel/Carousel.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { type CSSProperties, type ReactNode, useEffect, useRef, useState } from 'react';\n\nimport { useDirection } from '../common/hooks';\nimport IconButton from '../IconButton';\nimport Title from '../Title';\nimport type { PromoCardLinkProps } from '../PromoCard/PromoCard';\nimport PromoCard from '../PromoCard/PromoCard';\n\nexport type CarouselCardCommon = {\n id: string;\n href?: string;\n hrefTarget?: HTMLAnchorElement['target'];\n onClick?: () => void;\n className?: string;\n styles?: CSSProperties;\n};\n\nexport type CarouselDefaultCard = CarouselCardCommon & {\n type: 'anchor' | 'button';\n content: ReactNode;\n};\n\nexport type CarouselPromoCard = CarouselCardCommon & {\n type: 'promo';\n} & Omit<PromoCardLinkProps, 'type'>;\n\nexport type CarouselCard = CarouselDefaultCard | CarouselPromoCard;\nexport interface CarouselProps {\n header: string | ReactNode;\n className?: string;\n cards: CarouselCard[];\n onClick?: (cardId: string) => void;\n}\n\ntype CardsReference = {\n type: 'promo' | 'default';\n cardElement: HTMLDivElement | HTMLAnchorElement;\n anchorElement?: HTMLAnchorElement;\n};\n\nconst LEFT_SCROLL_OFFSET = 8;\n\nconst Carousel: React.FC<CarouselProps> = ({ header, className, cards, onClick }) => {\n const [scrollPosition, setScrollPosition] = useState(0);\n const [previousScrollPosition, setPreviousScrollPosition] = useState(0);\n const [scrollIsAtEnd, setScrollIsAtEnd] = useState(false);\n const [visibleCardOnMobileView, setVisibleCardOnMobileView] = useState<string>('');\n const carouselElementRef = useRef<HTMLDivElement>(null);\n const carouselCardsRef = useRef<CardsReference[]>([]);\n const { isRTL } = useDirection();\n\n const isPrevButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;\n\n const areActionButtonsEnabled = isPrevButtonEnabled || !scrollIsAtEnd;\n\n const [focusedCard, setFocusedCard] = useState(cards?.[0]?.id);\n\n const updateScrollButtonsState = () => {\n if (carouselElementRef.current) {\n const { scrollWidth, offsetWidth } = carouselElementRef.current;\n\n const scrollAtEnd = scrollWidth - offsetWidth <= scrollPosition + LEFT_SCROLL_OFFSET;\n setScrollIsAtEnd(scrollAtEnd);\n }\n\n const scrollDirecton = scrollPosition > previousScrollPosition ? 'right' : 'left';\n\n const cardsInFullViewIds: string[] = [];\n carouselCardsRef.current.forEach((card) => {\n if (isVisible(carouselElementRef.current as HTMLElement, card.cardElement as HTMLElement)) {\n // eslint-disable-next-line functional/immutable-data\n cardsInFullViewIds.push(card.cardElement.getAttribute('id') ?? '');\n }\n });\n\n if (cardsInFullViewIds.length >= 1) {\n const visibleCardIndex = scrollDirecton === 'right' ? cardsInFullViewIds.length - 1 : 0;\n const visibleCardId = cardsInFullViewIds[visibleCardIndex];\n setVisibleCardOnMobileView(visibleCardId);\n setFocusedCard(visibleCardId);\n }\n\n setPreviousScrollPosition(scrollPosition);\n };\n\n const scrollCarousel = (direction: 'forward' | 'backward') => {\n if (carouselElementRef.current) {\n const { scrollWidth } = carouselElementRef.current;\n\n const cardWidth = scrollWidth / carouselCardsRef.current.length;\n\n const distance = Math.floor(cardWidth - cardWidth * 0.05);\n const sign = direction === 'forward' ? 1 : -1;\n\n carouselElementRef.current.scrollBy({\n left: isRTL ? -sign * distance : sign * distance,\n behavior: 'smooth',\n });\n }\n };\n\n const handleOnKeyDown = (\n event: React.KeyboardEvent<HTMLAnchorElement | HTMLDivElement>,\n index: number,\n ) => {\n if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {\n const nextIndex = event.key === 'ArrowRight' ? index + 1 : index - 1;\n const nextCard = cards[nextIndex];\n if (nextCard) {\n const ref = carouselCardsRef.current[nextIndex];\n if (ref.type === 'promo') {\n ref.anchorElement?.focus();\n } else {\n ref.cardElement?.focus();\n }\n\n scrollCardIntoView(carouselCardsRef.current[nextIndex].cardElement, nextCard);\n event.preventDefault();\n }\n }\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.currentTarget.click();\n }\n };\n\n const scrollCardIntoView = (element: HTMLElement, card: CarouselCard) => {\n element.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'center',\n });\n\n setFocusedCard(card.id);\n };\n\n useEffect(() => {\n updateScrollButtonsState();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [scrollPosition]);\n\n useEffect(() => {\n window.addEventListener('resize', updateScrollButtonsState);\n\n return () => {\n window.removeEventListener('resize', updateScrollButtonsState);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const addElementToCardsRefArray = (index: number, ref: Partial<CardsReference>) => {\n if (ref) {\n // eslint-disable-next-line functional/immutable-data\n carouselCardsRef.current[index] = {\n type: ref.type ?? carouselCardsRef.current?.[index]?.type,\n cardElement: ref.cardElement ?? carouselCardsRef.current?.[index]?.cardElement,\n anchorElement: ref.anchorElement ?? carouselCardsRef.current?.[index]?.anchorElement,\n };\n }\n };\n\n return (\n <div className={clsx('carousel-wrapper', className)}>\n <div className=\"d-flex justify-content-between carousel__header\">\n {typeof header === 'string' ? (\n <Title as=\"span\" type=\"title-body\">\n {header}\n </Title>\n ) : (\n header\n )}\n {areActionButtonsEnabled ? (\n <div className=\"hidden-xs d-inline-flex\">\n <IconButton\n size={32}\n tabIndex={-1}\n priority=\"tertiary\"\n disabled={!isPrevButtonEnabled}\n aria-hidden=\"true\"\n data-testid=\"scroll-carousel-left\"\n onClick={() => scrollCarousel('backward')}\n >\n <ChevronLeft />\n </IconButton>\n <IconButton\n size={32}\n tabIndex={-1}\n className=\"m-l-1\"\n priority=\"tertiary\"\n aria-hidden=\"true\"\n data-testid=\"scroll-carousel-right\"\n disabled={scrollIsAtEnd}\n onClick={() => scrollCarousel('forward')}\n >\n <ChevronRight />\n </IconButton>\n </div>\n ) : null}\n </div>\n <div\n ref={carouselElementRef}\n tabIndex={-1}\n role=\"list\"\n className=\"carousel\"\n onScroll={(event) => {\n const target = event.target as HTMLElement;\n setScrollPosition(Math.abs(target.scrollLeft));\n }}\n >\n {cards?.map((card, index) => {\n const sharedProps = {\n id: card.id,\n className: clsx('carousel__card', {\n 'carousel__card--focused': card.id === focusedCard,\n }),\n onClick: () => {\n card.onClick?.();\n onClick?.(card.id);\n },\n onFocus: (event: React.FocusEvent<HTMLAnchorElement | HTMLDivElement>) => {\n scrollCardIntoView(event.currentTarget, card);\n },\n };\n\n const cardContent =\n card.type !== 'promo' ? (\n <div\n id={`${card.id}-content`}\n className={clsx('carousel__card-content', {\n [card.className ?? '']: !!card.className,\n })}\n style={card.styles}\n >\n {card.content}\n </div>\n ) : null;\n\n if (card.type === 'button') {\n return (\n <div key={card.id} aria-labelledby={`${card.id}-content`} role=\"listitem\">\n <div\n {...sharedProps}\n ref={(el) => {\n if (el) {\n // eslint-disable-next-line functional/immutable-data\n carouselCardsRef.current[index] = {\n type: 'default',\n cardElement: el,\n };\n }\n }}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(event) => handleOnKeyDown(event, index)}\n >\n {cardContent}\n </div>\n </div>\n );\n }\n\n if (card.type === 'promo') {\n return (\n <div key={card.id} id={card.id} role=\"listitem\" aria-labelledby={`${card.id}-anchor`}>\n <PromoCard\n {...{ ...card, type: undefined }}\n {...{ ...sharedProps }}\n ref={(el: HTMLDivElement | null) => {\n if (el) {\n addElementToCardsRefArray(index, {\n type: 'promo',\n cardElement: el,\n });\n }\n }}\n anchorRef={(el: HTMLAnchorElement) => {\n if (el) {\n addElementToCardsRefArray(index, {\n type: 'promo',\n anchorElement: el,\n });\n }\n }}\n anchorId={`${card.id}-anchor`}\n onKeyDown={(event) => handleOnKeyDown(event, index)}\n />\n </div>\n );\n }\n\n return (\n <div key={card.id} aria-labelledby={`${card.id}-content`} role=\"listitem\">\n <a\n {...sharedProps}\n ref={(el) => {\n if (el) {\n // eslint-disable-next-line functional/immutable-data\n carouselCardsRef.current[index] = {\n type: 'default',\n cardElement: el,\n };\n }\n }}\n href={card.href}\n target={card.hrefTarget}\n rel=\"noreferrer\"\n onKeyDown={(event) => handleOnKeyDown(event, index)}\n >\n {cardContent}\n </a>\n </div>\n );\n })}\n </div>\n <div className=\"visible-xs\">\n <div className=\"carousel__indicators\">\n {cards?.map((card, index) => (\n <button\n key={`${card.id}-indicator`}\n data-testid={`${card.id}-indicator`}\n tabIndex={-1}\n aria-hidden\n type=\"button\"\n className={clsx('carousel__indicator', {\n 'carousel__indicator--selected': card.id === visibleCardOnMobileView,\n })}\n onClick={() => {\n scrollCardIntoView(carouselCardsRef.current[index].cardElement, card);\n }}\n />\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nconst isVisible = (container: HTMLElement, el: HTMLElement) => {\n const cWidth = container.offsetWidth;\n const cScrollOffset = Math.abs(container.scrollLeft);\n\n const elemLeft = el.offsetLeft - container.offsetLeft;\n const elemRight = elemLeft + el.offsetWidth;\n\n return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;\n};\n\nexport default Carousel;\n"],"names":["LEFT_SCROLL_OFFSET","Carousel","header","className","cards","onClick","scrollPosition","setScrollPosition","useState","previousScrollPosition","setPreviousScrollPosition","scrollIsAtEnd","setScrollIsAtEnd","visibleCardOnMobileView","setVisibleCardOnMobileView","carouselElementRef","useRef","carouselCardsRef","isRTL","useDirection","isPrevButtonEnabled","areActionButtonsEnabled","focusedCard","setFocusedCard","id","updateScrollButtonsState","current","scrollWidth","offsetWidth","scrollAtEnd","scrollDirecton","cardsInFullViewIds","forEach","card","isVisible","cardElement","push","getAttribute","length","visibleCardIndex","visibleCardId","scrollCarousel","direction","cardWidth","distance","Math","floor","sign","scrollBy","left","behavior","handleOnKeyDown","event","index","key","nextIndex","nextCard","ref","type","anchorElement","focus","scrollCardIntoView","preventDefault","currentTarget","click","element","scrollIntoView","block","inline","useEffect","window","addEventListener","removeEventListener","addElementToCardsRefArray","_jsxs","clsx","children","_jsx","Title","as","IconButton","size","tabIndex","priority","disabled","ChevronLeft","ChevronRight","role","onScroll","target","abs","scrollLeft","map","sharedProps","onFocus","cardContent","style","styles","content","el","onKeyDown","PromoCard","undefined","anchorRef","anchorId","href","hrefTarget","rel","container","cWidth","cScrollOffset","elemLeft","offsetLeft","elemRight"],"mappings":"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"}
@@ -1,6 +1,9 @@
1
1
  import { ChevronLeft, ChevronRight } from '@transferwise/icons';
2
2
  import { clsx } from 'clsx';
3
3
  import { useState, useRef, useEffect } from 'react';
4
+ import '@transferwise/neptune-validation';
5
+ import { useDirection } from '../common/hooks/useDirection/useDirection.mjs';
6
+ import '@transferwise/neptune-tokens';
4
7
  import IconButton from '../IconButton/IconButton.mjs';
5
8
  import Title from '../Title/Title.mjs';
6
9
  import PromoCard from '../PromoCard/PromoCard.mjs';
@@ -19,8 +22,11 @@ const Carousel = ({
19
22
  const [visibleCardOnMobileView, setVisibleCardOnMobileView] = useState('');
20
23
  const carouselElementRef = useRef(null);
21
24
  const carouselCardsRef = useRef([]);
22
- const isLeftActionButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
23
- const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;
25
+ const {
26
+ isRTL
27
+ } = useDirection();
28
+ const isPrevButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
29
+ const areActionButtonsEnabled = isPrevButtonEnabled || !scrollIsAtEnd;
24
30
  const [focusedCard, setFocusedCard] = useState(cards?.[0]?.id);
25
31
  const updateScrollButtonsState = () => {
26
32
  if (carouselElementRef.current) {
@@ -47,15 +53,16 @@ const Carousel = ({
47
53
  }
48
54
  setPreviousScrollPosition(scrollPosition);
49
55
  };
50
- const scrollCarousel = (direction = 'right') => {
56
+ const scrollCarousel = direction => {
51
57
  if (carouselElementRef.current) {
52
58
  const {
53
59
  scrollWidth
54
60
  } = carouselElementRef.current;
55
61
  const cardWidth = scrollWidth / carouselCardsRef.current.length;
56
- const res = Math.floor(cardWidth - cardWidth * 0.05);
62
+ const distance = Math.floor(cardWidth - cardWidth * 0.05);
63
+ const sign = direction === 'forward' ? 1 : -1;
57
64
  carouselElementRef.current.scrollBy({
58
- left: direction === 'right' ? res : -res,
65
+ left: isRTL ? -sign * distance : sign * distance,
59
66
  behavior: 'smooth'
60
67
  });
61
68
  }
@@ -122,10 +129,10 @@ const Carousel = ({
122
129
  size: 32,
123
130
  tabIndex: -1,
124
131
  priority: "tertiary",
125
- disabled: !isLeftActionButtonEnabled,
132
+ disabled: !isPrevButtonEnabled,
126
133
  "aria-hidden": "true",
127
134
  "data-testid": "scroll-carousel-left",
128
- onClick: () => scrollCarousel('left'),
135
+ onClick: () => scrollCarousel('backward'),
129
136
  children: /*#__PURE__*/jsx(ChevronLeft, {})
130
137
  }), /*#__PURE__*/jsx(IconButton, {
131
138
  size: 32,
@@ -135,7 +142,7 @@ const Carousel = ({
135
142
  "aria-hidden": "true",
136
143
  "data-testid": "scroll-carousel-right",
137
144
  disabled: scrollIsAtEnd,
138
- onClick: () => scrollCarousel(),
145
+ onClick: () => scrollCarousel('forward'),
139
146
  children: /*#__PURE__*/jsx(ChevronRight, {})
140
147
  })]
141
148
  }) : null]
@@ -146,7 +153,7 @@ const Carousel = ({
146
153
  className: "carousel",
147
154
  onScroll: event => {
148
155
  const target = event.target;
149
- setScrollPosition(target.scrollLeft);
156
+ setScrollPosition(Math.abs(target.scrollLeft));
150
157
  },
151
158
  children: cards?.map((card, index) => {
152
159
  const sharedProps = {
@@ -266,7 +273,7 @@ const Carousel = ({
266
273
  };
267
274
  const isVisible = (container, el) => {
268
275
  const cWidth = container.offsetWidth;
269
- const cScrollOffset = container.scrollLeft;
276
+ const cScrollOffset = Math.abs(container.scrollLeft);
270
277
  const elemLeft = el.offsetLeft - container.offsetLeft;
271
278
  const elemRight = elemLeft + el.offsetWidth;
272
279
  return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;