@transferwise/components 0.0.0-experimental-bb7ed4a → 0.0.0-experimental-f34234e

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 (40) hide show
  1. package/build/i18n/hu.json +1 -1
  2. package/build/index.js +213 -13
  3. package/build/index.js.map +1 -1
  4. package/build/index.mjs +214 -15
  5. package/build/index.mjs.map +1 -1
  6. package/build/main.css +126 -0
  7. package/build/styles/carousel/Carousel.css +126 -0
  8. package/build/styles/main.css +126 -0
  9. package/build/types/carousel/Carousel.d.ts +19 -0
  10. package/build/types/carousel/Carousel.d.ts.map +1 -0
  11. package/build/types/carousel/Carousel.test.d.ts +2 -0
  12. package/build/types/carousel/Carousel.test.d.ts.map +1 -0
  13. package/build/types/carousel/index.d.ts +3 -0
  14. package/build/types/carousel/index.d.ts.map +1 -0
  15. package/build/types/common/dateUtils/index.d.ts +0 -1
  16. package/build/types/common/dateUtils/index.d.ts.map +1 -1
  17. package/build/types/dateLookup/DateLookup.d.ts +2 -2
  18. package/build/types/dateLookup/DateLookup.d.ts.map +1 -1
  19. package/build/types/dateLookup/dayCalendar/table/DayCalendarTable.d.ts +1 -1
  20. package/build/types/dateLookup/dayCalendar/table/DayCalendarTable.d.ts.map +1 -1
  21. package/build/types/index.d.ts +2 -0
  22. package/build/types/index.d.ts.map +1 -1
  23. package/package.json +5 -5
  24. package/src/carousel/Carousel.css +126 -0
  25. package/src/carousel/Carousel.less +125 -0
  26. package/src/carousel/Carousel.story.tsx +62 -0
  27. package/src/carousel/Carousel.test.tsx +221 -0
  28. package/src/carousel/Carousel.tsx +269 -0
  29. package/src/carousel/index.ts +3 -0
  30. package/src/common/dateUtils/index.ts +0 -1
  31. package/src/dateLookup/DateLookup.tests.story.tsx +10 -44
  32. package/src/dateLookup/DateLookup.tsx +12 -9
  33. package/src/dateLookup/dayCalendar/table/DayCalendarTable.tsx +2 -5
  34. package/src/i18n/hu.json +1 -1
  35. package/src/index.ts +2 -0
  36. package/src/main.css +126 -0
  37. package/src/main.less +1 -0
  38. package/build/types/common/dateUtils/getDateView/getDateView.d.ts +0 -2
  39. package/build/types/common/dateUtils/getDateView/getDateView.d.ts.map +0 -1
  40. package/src/common/dateUtils/getDateView/getDateView.ts +0 -5
package/build/index.mjs CHANGED
@@ -3,7 +3,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import * as React from 'react';
4
4
  import React__default, { forwardRef, cloneElement, useState, useEffect, useRef, useMemo, useCallback, useLayoutEffect, createContext, useContext, useImperativeHandle, createElement, Component, PureComponent, createRef, isValidElement, Children, Fragment as Fragment$1 } from 'react';
5
5
  import { useId } from '@radix-ui/react-id';
6
- import { ChevronUp, CrossCircleFill, Cross, NavigateAway, Check, Info as Info$1, Alert as Alert$1, ClockBorderless, Briefcase, Person, ArrowLeft, QuestionMarkCircle, AlertCircle, Search, CrossCircle, ChevronDown, CheckCircleFill, ArrowRight, Download, ClockFill, Upload as Upload$2, Document, Plus, PlusCircle, AlertCircleFill } from '@transferwise/icons';
6
+ import { ChevronUp, CrossCircleFill, Cross, NavigateAway, Check, Info as Info$1, Alert as Alert$1, ClockBorderless, Briefcase, Person, ChevronLeft, ChevronRight, ArrowLeft, QuestionMarkCircle, AlertCircle, Search, CrossCircle, ChevronDown, CheckCircleFill, ArrowRight, Download, ClockFill, Upload as Upload$2, Document, Plus, PlusCircle, AlertCircleFill } from '@transferwise/icons';
7
7
  import { defineMessages, useIntl, injectIntl, IntlProvider } from 'react-intl';
8
8
  import PropTypes from 'prop-types';
9
9
  import commonmark from 'commonmark';
@@ -2153,6 +2153,210 @@ const Button = /*#__PURE__*/forwardRef(({
2153
2153
  });
2154
2154
  });
2155
2155
 
2156
+ const Carousel = ({
2157
+ header,
2158
+ className,
2159
+ cards,
2160
+ onClick
2161
+ }) => {
2162
+ const [scrollPosition, setScrollPosition] = useState(0);
2163
+ const [previousScrollPosition, setPreviousScrollPosition] = useState(0);
2164
+ const [scrollIsAtEnd, setScrollIsAtEnd] = useState(false);
2165
+ const [visibleCardOnMobileView, setVisibleCardOnMobileView] = useState('');
2166
+ const carouselElementRef = useRef(null);
2167
+ const caraouselCardsRef = useRef([]);
2168
+ const isLeftActionButtonEnabled = scrollPosition > 8;
2169
+ const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;
2170
+ const [focusedCard, setFocusedCard] = useState(cards?.[0]?.id);
2171
+ const updateScrollButtonsState = () => {
2172
+ if (carouselElementRef.current) {
2173
+ const {
2174
+ scrollWidth,
2175
+ offsetWidth
2176
+ } = carouselElementRef.current;
2177
+ const scrollAtEnd = scrollWidth - offsetWidth <= scrollPosition + 8;
2178
+ setScrollIsAtEnd(scrollAtEnd);
2179
+ }
2180
+ const scrollDirecton = scrollPosition > previousScrollPosition ? 'right' : 'left';
2181
+ const cardsInFullViewIds = [];
2182
+ caraouselCardsRef.current.forEach(card => {
2183
+ if (isVisible(carouselElementRef.current, card)) {
2184
+ // eslint-disable-next-line functional/immutable-data
2185
+ cardsInFullViewIds.push(card.getAttribute('id') ?? '');
2186
+ }
2187
+ });
2188
+ if (cardsInFullViewIds.length >= 1) {
2189
+ const visibleCardIndex = scrollDirecton === 'right' ? cardsInFullViewIds.length - 1 : 0;
2190
+ const visibleCardId = cardsInFullViewIds[visibleCardIndex];
2191
+ setVisibleCardOnMobileView(visibleCardId);
2192
+ setFocusedCard(visibleCardId);
2193
+ }
2194
+ setPreviousScrollPosition(scrollPosition);
2195
+ };
2196
+ const scrollCarousel = (direction = 'right') => {
2197
+ if (carouselElementRef.current) {
2198
+ const {
2199
+ scrollWidth
2200
+ } = carouselElementRef.current;
2201
+ const cardWidth = scrollWidth / caraouselCardsRef.current.length;
2202
+ const res = Math.floor(cardWidth - cardWidth * 0.05);
2203
+ carouselElementRef.current.scrollBy({
2204
+ left: direction === 'right' ? res : -res,
2205
+ behavior: 'smooth'
2206
+ });
2207
+ }
2208
+ };
2209
+ const handleOnKeyDown = (event, index) => {
2210
+ if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
2211
+ const nextIndex = event.key === 'ArrowRight' ? index + 1 : index - 1;
2212
+ const nextCard = cards[nextIndex];
2213
+ if (nextCard) {
2214
+ caraouselCardsRef.current[nextIndex].focus();
2215
+ scrollCardIntoView(caraouselCardsRef.current[nextIndex], nextCard);
2216
+ event.preventDefault();
2217
+ }
2218
+ }
2219
+ };
2220
+ const scrollCardIntoView = (element, card) => {
2221
+ element.scrollIntoView({
2222
+ behavior: 'smooth',
2223
+ block: 'nearest',
2224
+ inline: 'center'
2225
+ });
2226
+ setFocusedCard(card.id);
2227
+ };
2228
+ useEffect(() => {
2229
+ updateScrollButtonsState();
2230
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2231
+ }, [scrollPosition]);
2232
+ useEffect(() => {
2233
+ window.addEventListener('resize', updateScrollButtonsState);
2234
+ return () => {
2235
+ window.removeEventListener('resize', updateScrollButtonsState);
2236
+ };
2237
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2238
+ }, []);
2239
+ return /*#__PURE__*/jsxs("div", {
2240
+ className: className,
2241
+ children: [/*#__PURE__*/jsxs("div", {
2242
+ className: "d-flex justify-content-between carousel__header",
2243
+ children: [typeof header === 'string' ? /*#__PURE__*/jsx(Title, {
2244
+ as: "span",
2245
+ type: "title-body",
2246
+ children: header
2247
+ }) : header, areActionButtonsEnabled ? /*#__PURE__*/jsxs("div", {
2248
+ className: "hidden-xs",
2249
+ children: [/*#__PURE__*/jsx(ActionButton, {
2250
+ className: "carousel__scroll-button",
2251
+ tabIndex: -1,
2252
+ priority: "secondary",
2253
+ disabled: !isLeftActionButtonEnabled,
2254
+ "aria-hidden": "true",
2255
+ "data-testid": "scroll-carousel-left",
2256
+ onClick: () => scrollCarousel('left'),
2257
+ children: /*#__PURE__*/jsx(ChevronLeft, {})
2258
+ }), /*#__PURE__*/jsx(ActionButton, {
2259
+ tabIndex: -1,
2260
+ className: "carousel__scroll-button m-l-1",
2261
+ priority: "secondary",
2262
+ "aria-hidden": "true",
2263
+ "data-testid": "scroll-carousel-right",
2264
+ disabled: scrollIsAtEnd,
2265
+ onClick: () => scrollCarousel(),
2266
+ children: /*#__PURE__*/jsx(ChevronRight, {})
2267
+ })]
2268
+ }) : null]
2269
+ }), /*#__PURE__*/jsx("div", {
2270
+ ref: carouselElementRef,
2271
+ tabIndex: -1,
2272
+ role: "list",
2273
+ className: "carousel",
2274
+ onScroll: event => {
2275
+ const target = event.target;
2276
+ setScrollPosition(target.scrollLeft);
2277
+ },
2278
+ children: cards?.map((card, index) => {
2279
+ const sharedProps = {
2280
+ id: card.id,
2281
+ className: classNames('carousel__card', {
2282
+ 'carousel__card--focused': card.id === focusedCard
2283
+ }),
2284
+ role: 'listitem',
2285
+ 'aria-labelledby': `${card.id}-content`,
2286
+ onClick: () => {
2287
+ card.onClick?.();
2288
+ onClick?.(card.id);
2289
+ },
2290
+ onFocus: event => {
2291
+ scrollCardIntoView(event.currentTarget, card);
2292
+ }
2293
+ };
2294
+ const cardContent = /*#__PURE__*/jsx("div", {
2295
+ id: `${card.id}-content`,
2296
+ className: classNames('carousel__card-content', 'p-a-1', {
2297
+ [card.className ?? '']: !!card.className
2298
+ })
2299
+ // eslint-disable-next-line react/forbid-dom-props
2300
+ ,
2301
+ style: card.styles,
2302
+ children: card.content
2303
+ });
2304
+ if (card.type === 'button') {
2305
+ return /*#__PURE__*/createElement("button", {
2306
+ ...sharedProps,
2307
+ ref: el => {
2308
+ if (el) {
2309
+ // eslint-disable-next-line functional/immutable-data
2310
+ caraouselCardsRef.current[index] = el;
2311
+ }
2312
+ },
2313
+ key: card.id,
2314
+ type: "button",
2315
+ onKeyDown: event => handleOnKeyDown(event, index)
2316
+ }, cardContent);
2317
+ }
2318
+ return /*#__PURE__*/createElement("a", {
2319
+ ...sharedProps,
2320
+ ref: el => {
2321
+ if (el) {
2322
+ // eslint-disable-next-line functional/immutable-data
2323
+ caraouselCardsRef.current[index] = el;
2324
+ }
2325
+ },
2326
+ key: card.id,
2327
+ target: "_blank",
2328
+ rel: "noreferrer",
2329
+ href: card.href,
2330
+ onKeyDown: event => handleOnKeyDown(event, index)
2331
+ }, cardContent);
2332
+ })
2333
+ }), /*#__PURE__*/jsx("div", {
2334
+ className: "visible-xs",
2335
+ children: /*#__PURE__*/jsx("div", {
2336
+ className: "carousel__indicators",
2337
+ children: cards?.map((card, index) => /*#__PURE__*/jsx("button", {
2338
+ "data-testid": `${card.id}-indicator`,
2339
+ tabIndex: -1,
2340
+ type: "button",
2341
+ className: classNames('carousel__indicator', {
2342
+ 'carousel__indicator--selected': card.id === visibleCardOnMobileView
2343
+ }),
2344
+ onClick: () => {
2345
+ scrollCardIntoView(caraouselCardsRef.current[index], card);
2346
+ }
2347
+ }, `${card.id}-indicator`))
2348
+ })
2349
+ })]
2350
+ });
2351
+ };
2352
+ const isVisible = (container, el) => {
2353
+ const cWidth = container.offsetWidth;
2354
+ const cScrollOffset = container.scrollLeft;
2355
+ const elemLeft = el.offsetLeft - container.offsetLeft;
2356
+ const elemRight = elemLeft + el.offsetWidth;
2357
+ return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;
2358
+ };
2359
+
2156
2360
  const Card$1 = /*#__PURE__*/forwardRef((props, reference) => {
2157
2361
  const {
2158
2362
  'aria-label': ariaLabel,
@@ -2579,10 +2783,6 @@ const isMonthAndYearFormat = dateString => validDateString(dateString) && dateSt
2579
2783
  const MDY = new Set(['en-US']);
2580
2784
  const YMD = new Set(['hu', 'hu-HU', 'zh-HK', 'zh-CN', 'ja', 'ja-JP']);
2581
2785
 
2582
- const returnDateView = (selectedDate, min, max) => {
2583
- return selectedDate || (min || max) && moveToWithinRange(new Date(), min, max) || new Date();
2584
- };
2585
-
2586
2786
  var messages$9 = defineMessages({
2587
2787
  monthLabel: {
2588
2788
  id: "neptune.DateInput.month.label"
@@ -3327,9 +3527,6 @@ class DayCalendarTable extends PureComponent {
3327
3527
  onSelect(new Date(viewYear, viewMonth, day));
3328
3528
  };
3329
3529
  isDisabled = day => {
3330
- if (day === -1) {
3331
- return true;
3332
- }
3333
3530
  const {
3334
3531
  min,
3335
3532
  max,
@@ -3345,7 +3542,7 @@ class DayCalendarTable extends PureComponent {
3345
3542
  viewMonth,
3346
3543
  viewYear
3347
3544
  } = this.props;
3348
- return !!(selectedDate && Number(new Date(viewYear, viewMonth, day)) === Number(selectedDate));
3545
+ return !!(selectedDate && +new Date(viewYear, viewMonth, day) === +selectedDate);
3349
3546
  };
3350
3547
  isToday = day => {
3351
3548
  const {
@@ -3739,8 +3936,8 @@ class DateLookup extends PureComponent {
3739
3936
  originalDate: null,
3740
3937
  min: getStartOfDay(props.min),
3741
3938
  max: getStartOfDay(props.max),
3742
- viewMonth: returnDateView(props.value, props.min, props.max).getMonth(),
3743
- viewYear: returnDateView(props.value, props.min, props.max).getFullYear(),
3939
+ viewMonth: (props.value || new Date()).getMonth(),
3940
+ viewYear: (props.value || new Date()).getFullYear(),
3744
3941
  open: false,
3745
3942
  mode: 'day',
3746
3943
  isMobile: false
@@ -3761,7 +3958,7 @@ class DateLookup extends PureComponent {
3761
3958
  props.onChange(moveToWithinRange(selectedDate, min, max));
3762
3959
  return null;
3763
3960
  }
3764
- const viewDateThatIsWithinRange = returnDateView(selectedDate, min, max);
3961
+ const viewDateThatIsWithinRange = selectedDate || (min || max) && moveToWithinRange(new Date(), min, max) || new Date();
3765
3962
  const viewMonth = viewDateThatIsWithinRange.getMonth();
3766
3963
  const viewYear = viewDateThatIsWithinRange.getFullYear();
3767
3964
  return {
@@ -3886,7 +4083,9 @@ class DateLookup extends PureComponent {
3886
4083
  } else {
3887
4084
  date = getStartOfDay(new Date());
3888
4085
  }
3889
- date &&= moveToWithinRange(date, min, max);
4086
+ if (date) {
4087
+ date = moveToWithinRange(date, min, max);
4088
+ }
3890
4089
  if (date?.getTime() !== selectedDate?.getTime()) {
3891
4090
  this.props.onChange(date);
3892
4091
  }
@@ -13605,7 +13804,7 @@ var hu = {
13605
13804
  "neptune.Upload.psProcessingText": "Feltöltés...",
13606
13805
  "neptune.Upload.usButtonText": "Vagy válaszd ki a fájlt",
13607
13806
  "neptune.Upload.usDropMessage": "Húzd ide a fájlokat a feltöltéshez",
13608
- "neptune.Upload.usPlaceholder": "Húzz ide egy legfeljebb {maxSize} MB méretű fájlt",
13807
+ "neptune.Upload.usPlaceholder": "Húzz ide egy legfeljebb {maxSize}MB méretű fájlt",
13609
13808
  "neptune.UploadButton.allFileTypes": "Összes fájltípus",
13610
13809
  "neptune.UploadButton.dropFiles": "Húzd a fájlokat ide a feltöltéshez",
13611
13810
  "neptune.UploadButton.instructions": "{fileTypes}, legfeljebb {size}MB",
@@ -14343,5 +14542,5 @@ const translations = {
14343
14542
  'zh-HK': zhHK
14344
14543
  };
14345
14544
 
14346
- export { Accordion, ActionButton, ActionOption, Alert, Avatar, AvatarType, AvatarWrapper, Badge, Card as BaseCard, Body, BottomSheet$2 as BottomSheet, Breakpoint, Button, Card$2 as Card, Checkbox$1 as Checkbox, CheckboxButton$1 as CheckboxButton, CheckboxOption, Chevron, Chip, Chips, CircularButton, ControlType, CriticalCommsBanner, DEFAULT_LANG, DEFAULT_LOCALE, DateInput, DateLookup, DateMode, Decision, DecisionPresentation, DecisionType, DefinitionList$1 as DefinitionList, Dimmer$1 as Dimmer, Direction, DirectionProvider, Display, Drawer$1 as Drawer, DropFade, Emphasis, FileType, FlowNavigation, Header, Image, Info, InfoPresentation, InlineAlert, Input, InputGroup, InputWithDisplayFormat, InstructionsList, LanguageProvider, Layout, Link, ListItem$1 as ListItem, Loader, Logo$1 as Logo, LogoType, Markdown, MarkdownNodeType, Modal, Money, MoneyInput$1 as MoneyInput, MonthFormat, NavigationOption, NavigationOptionList as NavigationOptionsList, Nudge, Option$2 as Option, OverlayHeader$1 as OverlayHeader, PhoneNumberInput, Popover$1 as Popover, Position, Priority, ProcessIndicator$1 as ProcessIndicator, ProfileType, Progress, ProgressBar, PromoCard$1 as PromoCard, PromoCard$1 as PromoCardGroup, Provider, RTL_LANGUAGES, Radio, RadioGroup, RadioOption, SUPPORTED_LANGUAGES, Scroll, SearchInput, Section, SegmentedControl, Select, SelectInput, SelectInputOptionContent, SelectInputTriggerButton, Sentiment, Size, SlidingPanel, SnackbarConsumer, SnackbarContext, SnackbarPortal, SnackbarProvider, Status, StatusIcon, Stepper, Sticky, Summary, Switch, SwitchOption, Tabs$1 as Tabs, TextArea, TextareaWithDisplayFormat, Theme, Title, Tooltip, Type, Typeahead, Typography, Upload$1 as Upload, UploadInput, UploadStep, Variant, Width, adjustLocale, getCountryFromLocale, getDirectionFromLocale, getLangFromLocale, isBrowser, isServerSide, translations, useDirection, useLayout, useScreenSize, useSnackbar };
14545
+ export { Accordion, ActionButton, ActionOption, Alert, Avatar, AvatarType, AvatarWrapper, Badge, Card as BaseCard, Body, BottomSheet$2 as BottomSheet, Breakpoint, Button, Card$2 as Card, Carousel, Checkbox$1 as Checkbox, CheckboxButton$1 as CheckboxButton, CheckboxOption, Chevron, Chip, Chips, CircularButton, ControlType, CriticalCommsBanner, DEFAULT_LANG, DEFAULT_LOCALE, DateInput, DateLookup, DateMode, Decision, DecisionPresentation, DecisionType, DefinitionList$1 as DefinitionList, Dimmer$1 as Dimmer, Direction, DirectionProvider, Display, Drawer$1 as Drawer, DropFade, Emphasis, FileType, FlowNavigation, Header, Image, Info, InfoPresentation, InlineAlert, Input, InputGroup, InputWithDisplayFormat, InstructionsList, LanguageProvider, Layout, Link, ListItem$1 as ListItem, Loader, Logo$1 as Logo, LogoType, Markdown, MarkdownNodeType, Modal, Money, MoneyInput$1 as MoneyInput, MonthFormat, NavigationOption, NavigationOptionList as NavigationOptionsList, Nudge, Option$2 as Option, OverlayHeader$1 as OverlayHeader, PhoneNumberInput, Popover$1 as Popover, Position, Priority, ProcessIndicator$1 as ProcessIndicator, ProfileType, Progress, ProgressBar, PromoCard$1 as PromoCard, PromoCard$1 as PromoCardGroup, Provider, RTL_LANGUAGES, Radio, RadioGroup, RadioOption, SUPPORTED_LANGUAGES, Scroll, SearchInput, Section, SegmentedControl, Select, SelectInput, SelectInputOptionContent, SelectInputTriggerButton, Sentiment, Size, SlidingPanel, SnackbarConsumer, SnackbarContext, SnackbarPortal, SnackbarProvider, Status, StatusIcon, Stepper, Sticky, Summary, Switch, SwitchOption, Tabs$1 as Tabs, TextArea, TextareaWithDisplayFormat, Theme, Title, Tooltip, Type, Typeahead, Typography, Upload$1 as Upload, UploadInput, UploadStep, Variant, Width, adjustLocale, getCountryFromLocale, getDirectionFromLocale, getLangFromLocale, isBrowser, isServerSide, translations, useDirection, useLayout, useScreenSize, useSnackbar };
14347
14546
  //# sourceMappingURL=index.mjs.map