@equinor/eds-core-react 0.41.1 → 0.41.3

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.
@@ -6320,19 +6320,25 @@ const PopoverPaper = styled__default.default(Paper).withConfig({
6320
6320
  paper
6321
6321
  }
6322
6322
  } = theme;
6323
- return styled.css(["", " background:", ";", " z-index:1400;&:focus-visible{", "}"], edsUtils.typographyTemplate(theme.typography), theme.background, edsUtils.bordersTemplate(theme.border), edsUtils.outlineTemplate(paper.states.focus.outline));
6323
+ return styled.css(["position:relative;", " background:", ";", " &:focus-visible{", "}"], edsUtils.typographyTemplate(theme.typography), theme.background, edsUtils.bordersTemplate(theme.border), edsUtils.outlineTemplate(paper.states.focus.outline));
6324
6324
  });
6325
+ const StyledPopover$2 = styled__default.default('div').withConfig({
6326
+ shouldForwardProp: () => true //workaround to avoid warning until popover gets added to react types
6327
+ }).withConfig({
6328
+ displayName: "Popover__StyledPopover",
6329
+ componentId: "sc-b7p1is-1"
6330
+ })(["inset:unset;border:0;padding:0;margin:0;overflow:visible;background-color:transparent;&::backdrop{background-color:transparent;}"]);
6325
6331
  const ArrowWrapper = styled__default.default.div.withConfig({
6326
6332
  displayName: "Popover__ArrowWrapper",
6327
- componentId: "sc-b7p1is-1"
6333
+ componentId: "sc-b7p1is-2"
6328
6334
  })(({
6329
6335
  theme
6330
6336
  }) => {
6331
- return styled.css(["position:absolute;width:", ";height:", ";z-index:-1;"], theme.entities.arrow.width, theme.entities.arrow.height);
6337
+ return styled.css(["position:absolute;width:", ";height:", ";"], theme.entities.arrow.width, theme.entities.arrow.height);
6332
6338
  });
6333
6339
  const InnerWrapper = styled__default.default.div.withConfig({
6334
6340
  displayName: "Popover__InnerWrapper",
6335
- componentId: "sc-b7p1is-2"
6341
+ componentId: "sc-b7p1is-3"
6336
6342
  })(({
6337
6343
  theme
6338
6344
  }) => {
@@ -6340,7 +6346,7 @@ const InnerWrapper = styled__default.default.div.withConfig({
6340
6346
  });
6341
6347
  const PopoverArrow = styled__default.default.svg.withConfig({
6342
6348
  displayName: "Popover__PopoverArrow",
6343
- componentId: "sc-b7p1is-3"
6349
+ componentId: "sc-b7p1is-4"
6344
6350
  })(({
6345
6351
  theme
6346
6352
  }) => {
@@ -6357,6 +6363,9 @@ const Popover$1 = /*#__PURE__*/react.forwardRef(function Popover({
6357
6363
  trapFocus,
6358
6364
  ...rest
6359
6365
  }, ref) {
6366
+ if (withinPortal) {
6367
+ console.warn('Popover "withinPortal" prop has been deprecated. Popover now uses the native popover api');
6368
+ }
6360
6369
  const arrowRef = react.useRef(null);
6361
6370
  const {
6362
6371
  x,
@@ -6389,6 +6398,13 @@ const Popover$1 = /*#__PURE__*/react.forwardRef(function Popover({
6389
6398
  const {
6390
6399
  getFloatingProps
6391
6400
  } = react$1.useInteractions([react$1.useDismiss(context)]);
6401
+ edsUtils.useIsomorphicLayoutEffect(() => {
6402
+ if (open) {
6403
+ refs.floating.current?.showPopover();
6404
+ } else {
6405
+ refs.floating.current?.hidePopover();
6406
+ }
6407
+ }, [open, refs.floating]);
6392
6408
  react.useEffect(() => {
6393
6409
  if (arrowRef.current) {
6394
6410
  const staticSide = {
@@ -6424,7 +6440,6 @@ const Popover$1 = /*#__PURE__*/react.forwardRef(function Popover({
6424
6440
  // eslint-disable-next-line react-hooks/exhaustive-deps
6425
6441
  }, [arrowRef.current, arrowX, arrowY, finalPlacement]);
6426
6442
  const props = {
6427
- open,
6428
6443
  ...rest
6429
6444
  };
6430
6445
  const {
@@ -6433,14 +6448,10 @@ const Popover$1 = /*#__PURE__*/react.forwardRef(function Popover({
6433
6448
  const token = edsUtils.useToken({
6434
6449
  density
6435
6450
  }, popover);
6436
-
6437
- //temporary fix when inside dialog. Should be replaced by popover api when it is ready
6438
- const inDialog = edsUtils.useIsInDialog(anchorEl);
6439
6451
  const popover$1 = /*#__PURE__*/jsxRuntime.jsx(styled.ThemeProvider, {
6440
6452
  theme: token,
6441
- children: /*#__PURE__*/jsxRuntime.jsxs(PopoverPaper, {
6442
- elevation: "overlay",
6443
- ...props,
6453
+ children: /*#__PURE__*/jsxRuntime.jsx(StyledPopover$2, {
6454
+ popover: "manual",
6444
6455
  ...getFloatingProps({
6445
6456
  ref: popoverRef,
6446
6457
  style: {
@@ -6450,35 +6461,30 @@ const Popover$1 = /*#__PURE__*/react.forwardRef(function Popover({
6450
6461
  left: x || 0
6451
6462
  }
6452
6463
  }),
6453
- children: [/*#__PURE__*/jsxRuntime.jsx(ArrowWrapper, {
6454
- ref: arrowRef,
6455
- className: "arrow",
6456
- children: /*#__PURE__*/jsxRuntime.jsx(PopoverArrow, {
6457
- className: "arrowSvg",
6458
- children: /*#__PURE__*/jsxRuntime.jsx("path", {
6459
- d: "M0.504838 4.86885C-0.168399 4.48524 -0.168399 3.51476 0.504838 3.13115L6 8.59227e-08L6 8L0.504838 4.86885Z"
6464
+ children: /*#__PURE__*/jsxRuntime.jsxs(PopoverPaper, {
6465
+ elevation: "overlay",
6466
+ ...props,
6467
+ children: [/*#__PURE__*/jsxRuntime.jsx(ArrowWrapper, {
6468
+ ref: arrowRef,
6469
+ className: "arrow",
6470
+ children: /*#__PURE__*/jsxRuntime.jsx(PopoverArrow, {
6471
+ className: "arrowSvg",
6472
+ children: /*#__PURE__*/jsxRuntime.jsx("path", {
6473
+ d: "M0.504838 4.86885C-0.168399 4.48524 -0.168399 3.51476 0.504838 3.13115L6 8.59227e-08L6 8L0.504838 4.86885Z"
6474
+ })
6460
6475
  })
6461
- })
6462
- }), /*#__PURE__*/jsxRuntime.jsx(InnerWrapper, {
6463
- children: children
6464
- })]
6476
+ }), /*#__PURE__*/jsxRuntime.jsx(InnerWrapper, {
6477
+ children: children
6478
+ })]
6479
+ })
6465
6480
  })
6466
6481
  });
6467
6482
  return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
6468
- children: withinPortal && !inDialog ? /*#__PURE__*/jsxRuntime.jsx(react$1.FloatingPortal, {
6469
- id: "eds-popover-container",
6470
- children: open && trapFocus ? open && /*#__PURE__*/jsxRuntime.jsx(react$1.FloatingFocusManager, {
6471
- context: context,
6472
- modal: true,
6473
- children: popover$1
6474
- }) : open && popover$1
6475
- }) : /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
6476
- children: trapFocus ? open && /*#__PURE__*/jsxRuntime.jsx(react$1.FloatingFocusManager, {
6477
- context: context,
6478
- modal: true,
6479
- children: popover$1
6480
- }) : open && popover$1
6481
- })
6483
+ children: trapFocus ? open && /*#__PURE__*/jsxRuntime.jsx(react$1.FloatingFocusManager, {
6484
+ context: context,
6485
+ modal: true,
6486
+ children: popover$1
6487
+ }) : open && popover$1
6482
6488
  });
6483
6489
  });
6484
6490
 
@@ -9562,7 +9568,6 @@ function AutocompleteInner(props, ref) {
9562
9568
  itemCompare,
9563
9569
  allowSelectAll,
9564
9570
  initialSelectedOptions: _initialSelectedOptions = [],
9565
- disablePortal,
9566
9571
  optionDisabled = defaultOptionDisabled,
9567
9572
  optionsFilter,
9568
9573
  autoWidth,
@@ -9582,9 +9587,6 @@ function AutocompleteInner(props, ref) {
9582
9587
  // MARK: initializing data/setup
9583
9588
  const selectedOptions = _selectedOptions ? itemCompare ? options.filter(item => _selectedOptions.some(compare => itemCompare(item, compare))) : _selectedOptions : undefined;
9584
9589
  const initialSelectedOptions = _initialSelectedOptions ? itemCompare ? options.filter(item => _initialSelectedOptions.some(compare => itemCompare(item, compare))) : _initialSelectedOptions : undefined;
9585
- if (disablePortal) {
9586
- console.warn('Autocomplete "disablePortal" prop has been deprecated. Autocomplete now uses the native popover api');
9587
- }
9588
9590
  const isControlled = Boolean(selectedOptions);
9589
9591
  const [inputOptions, setInputOptions] = react.useState(options);
9590
9592
  const [_availableItems, setAvailableItems] = react.useState(inputOptions);
@@ -9774,7 +9776,12 @@ function AutocompleteInner(props, ref) {
9774
9776
  if (selectedItem === AllSymbol) {
9775
9777
  toggleAllSelected();
9776
9778
  } else if (multiple) {
9777
- selectedItems.includes(selectedItem) ? removeSelectedItem(selectedItem) : addSelectedItem(selectedItem);
9779
+ const shouldRemove = itemCompare ? selectedItems.some(i => itemCompare(selectedItem, i)) : selectedItems.includes(selectedItem);
9780
+ if (shouldRemove) {
9781
+ removeSelectedItem(selectedItem);
9782
+ } else {
9783
+ addSelectedItem(selectedItem);
9784
+ }
9778
9785
  } else {
9779
9786
  setSelectedItems([selectedItem]);
9780
9787
  }
@@ -11193,23 +11200,58 @@ const GridColumn = styled__default.default.button.withConfig({
11193
11200
  })(["background-color:transparent;outline:none;border:none;display:flex;justify-content:center;cursor:pointer;padding:8px;font-size:", ";font-family:", ";font-weight:", ";line-height:", ";color:", ";border-radius:999px;", ";&:hover{background-color:#f0f0f0;}&:focus{outline:2px dashed ", ";}"], edsTokens.tokens.typography.navigation.button.fontSize, edsTokens.tokens.typography.navigation.button.fontFamily, edsTokens.tokens.typography.navigation.button.fontWeight, edsTokens.tokens.typography.navigation.button.lineHeight, edsTokens.tokens.colors.text.static_icons__default.rgba, ({
11194
11201
  $active
11195
11202
  }) => $active ? `background-color: ${edsTokens.tokens.colors.interactive.primary__selected_highlight.rgba}` : '', edsTokens.tokens.colors.interactive.primary__resting.rgba);
11203
+ const TOTAL_VISIBLE_YEARS = 36;
11204
+ const RANGE_OFFSET = 30 / 2;
11196
11205
  const GridFocusManager = ({
11197
11206
  year: selectedYear,
11198
- setFocusedYear
11207
+ setFocusedYear,
11208
+ yearPickerPage,
11209
+ setYearPickerPage
11199
11210
  }) => {
11200
11211
  const focusManager = reactAria.useFocusManager();
11201
- const onKeyDown = e => {
11212
+ const prevYear = react.useRef();
11213
+ const navByKeyboard = react.useRef(false);
11214
+ const page = yearPickerPage * TOTAL_VISIBLE_YEARS;
11215
+ const years = Array.from({
11216
+ length: TOTAL_VISIBLE_YEARS
11217
+ }, (_, i) => i + (selectedYear + page - RANGE_OFFSET));
11218
+ react.useEffect(() => {
11219
+ if (prevYear.current === undefined) {
11220
+ prevYear.current = yearPickerPage;
11221
+ return;
11222
+ }
11223
+ if (!navByKeyboard.current) {
11224
+ focusManager.focusFirst();
11225
+ return;
11226
+ }
11227
+ navByKeyboard.current = false;
11228
+ yearPickerPage > prevYear.current ? focusManager.focusFirst() : focusManager.focusLast();
11229
+ prevYear.current = yearPickerPage;
11230
+ }, [yearPickerPage, focusManager]);
11231
+ const onKeyDown = year => e => {
11202
11232
  const target = e.currentTarget;
11203
11233
  const parent = target.parentElement;
11234
+ const isFirstYear = years.at(0) === year;
11235
+ const isLastYear = years.at(-1) === year;
11204
11236
  switch (e.key) {
11205
11237
  case 'ArrowRight':
11206
11238
  e.preventDefault();
11239
+ if (isLastYear) {
11240
+ navByKeyboard.current = true;
11241
+ setYearPickerPage(page => page + 1);
11242
+ break;
11243
+ }
11207
11244
  focusManager.focusNext({
11208
11245
  wrap: true
11209
11246
  });
11210
11247
  break;
11211
11248
  case 'ArrowLeft':
11212
11249
  e.preventDefault();
11250
+ if (isFirstYear) {
11251
+ navByKeyboard.current = true;
11252
+ setYearPickerPage(page => page - 1);
11253
+ break;
11254
+ }
11213
11255
  focusManager.focusPrevious({
11214
11256
  wrap: true
11215
11257
  });
@@ -11217,6 +11259,11 @@ const GridFocusManager = ({
11217
11259
  case 'ArrowDown':
11218
11260
  {
11219
11261
  e.preventDefault();
11262
+ if (isLastYear) {
11263
+ navByKeyboard.current = true;
11264
+ setYearPickerPage(page => page + 1);
11265
+ break;
11266
+ }
11220
11267
  const selfIndex = Array.from(parent.children).indexOf(target);
11221
11268
  const focusElement = Array.from(parent.children).at(selfIndex + 5);
11222
11269
  focusManager.focusNext({
@@ -11227,6 +11274,11 @@ const GridFocusManager = ({
11227
11274
  case 'ArrowUp':
11228
11275
  {
11229
11276
  e.preventDefault();
11277
+ if (isFirstYear) {
11278
+ navByKeyboard.current = true;
11279
+ setYearPickerPage(page => page - 1);
11280
+ break;
11281
+ }
11230
11282
  const selfIndex = Array.from(parent.children).indexOf(target);
11231
11283
  const focusElement = Array.from(parent.children).at(selfIndex - 5);
11232
11284
  focusManager.focusPrevious({
@@ -11236,12 +11288,9 @@ const GridFocusManager = ({
11236
11288
  }
11237
11289
  }
11238
11290
  };
11239
- const years = Array.from({
11240
- length: 36
11241
- }, (_, i) => i + (selectedYear - 30 / 2));
11242
11291
  return years.map(year => /*#__PURE__*/jsxRuntime.jsx(GridColumn, {
11243
11292
  $active: selectedYear === year,
11244
- onKeyDown: onKeyDown,
11293
+ onKeyDown: onKeyDown(year),
11245
11294
  onClick: () => setFocusedYear(year),
11246
11295
  "aria-label": `Set year to ${year}`,
11247
11296
  tabIndex: 0,
@@ -11250,7 +11299,9 @@ const GridFocusManager = ({
11250
11299
  };
11251
11300
  const YearGrid = ({
11252
11301
  setFocusedYear,
11253
- year: selectedYear
11302
+ year: selectedYear,
11303
+ yearPickerPage,
11304
+ setYearPickerPage
11254
11305
  }) => {
11255
11306
  return /*#__PURE__*/jsxRuntime.jsx(Grid, {
11256
11307
  children: /*#__PURE__*/jsxRuntime.jsx(reactAria.FocusScope, {
@@ -11259,7 +11310,9 @@ const YearGrid = ({
11259
11310
  autoFocus: true,
11260
11311
  children: /*#__PURE__*/jsxRuntime.jsx(GridFocusManager, {
11261
11312
  year: selectedYear,
11262
- setFocusedYear: setFocusedYear
11313
+ setFocusedYear: setFocusedYear,
11314
+ yearPickerPage: yearPickerPage,
11315
+ setYearPickerPage: setYearPickerPage
11263
11316
  })
11264
11317
  })
11265
11318
  });
@@ -11267,10 +11320,15 @@ const YearGrid = ({
11267
11320
 
11268
11321
  /* eslint-disable react/no-array-index-key */
11269
11322
 
11323
+ /**
11324
+ * The grid laying out the cells for the calendars in {link Calendar} and {link RangeCalendar}
11325
+ */
11270
11326
  function CalendarGrid({
11271
11327
  state,
11272
11328
  showYearPicker,
11273
11329
  setShowYearPicker,
11330
+ yearPickerPage,
11331
+ setYearPickerPage,
11274
11332
  ...props
11275
11333
  }) {
11276
11334
  const {
@@ -11295,7 +11353,9 @@ function CalendarGrid({
11295
11353
  year
11296
11354
  }));
11297
11355
  setShowYearPicker(false);
11298
- }
11356
+ },
11357
+ yearPickerPage: yearPickerPage,
11358
+ setYearPickerPage: setYearPickerPage
11299
11359
  }) : /*#__PURE__*/jsxRuntime.jsxs("table", {
11300
11360
  ...gridProps,
11301
11361
  style: {
@@ -11356,15 +11416,16 @@ function CalendarHeader({
11356
11416
  previousMonthDisabled,
11357
11417
  nextMonthDisabled,
11358
11418
  showYearPicker,
11359
- setShowYearPicker
11419
+ setShowYearPicker,
11420
+ setYearPickerPage
11360
11421
  }) {
11361
11422
  return /*#__PURE__*/jsxRuntime.jsx(HeaderWrapper, {
11362
11423
  children: /*#__PURE__*/jsxRuntime.jsxs(HeaderActions, {
11363
11424
  children: [/*#__PURE__*/jsxRuntime.jsx(Button$1, {
11364
11425
  variant: 'ghost_icon',
11365
11426
  "aria-label": 'Previous month',
11366
- disabled: previousMonthDisabled || showYearPicker,
11367
- onClick: () => state.focusPreviousPage(),
11427
+ disabled: previousMonthDisabled,
11428
+ onClick: () => showYearPicker ? setYearPickerPage(page => page - 1) : state.focusPreviousPage(),
11368
11429
  children: /*#__PURE__*/jsxRuntime.jsx(Icon$1, {
11369
11430
  data: edsIcons.chevron_left
11370
11431
  })
@@ -11393,8 +11454,8 @@ function CalendarHeader({
11393
11454
  }
11394
11455
  }), /*#__PURE__*/jsxRuntime.jsx(Button$1, {
11395
11456
  variant: 'ghost_icon',
11396
- onClick: () => state.focusNextPage(),
11397
- disabled: nextMonthDisabled || showYearPicker,
11457
+ onClick: () => showYearPicker ? setYearPickerPage(page => page + 1) : state.focusNextPage(),
11458
+ disabled: nextMonthDisabled,
11398
11459
  "aria-label": 'Next month',
11399
11460
  children: /*#__PURE__*/jsxRuntime.jsx(Icon$1, {
11400
11461
  data: edsIcons.chevron_right
@@ -11415,6 +11476,7 @@ const Calendar = /*#__PURE__*/react.forwardRef(({
11415
11476
  ...props
11416
11477
  }, ref) => {
11417
11478
  const [showYearPicker, setShowYearPicker] = react.useState(false);
11479
+ const [yearPickerPage, setYearPickerPage] = react.useState(0);
11418
11480
  const {
11419
11481
  locale
11420
11482
  } = reactAria.useLocale();
@@ -11452,7 +11514,8 @@ const Calendar = /*#__PURE__*/react.forwardRef(({
11452
11514
  previousMonthDisabled: prevButtonProps.isDisabled,
11453
11515
  nextMonthDisabled: nextButtonProps.isDisabled,
11454
11516
  setShowYearPicker: setShowYearPicker,
11455
- showYearPicker: showYearPicker
11517
+ showYearPicker: showYearPicker,
11518
+ setYearPickerPage: setYearPickerPage
11456
11519
  })
11457
11520
  }), /*#__PURE__*/jsxRuntime.jsx(Popover.Content, {
11458
11521
  className: "calendar",
@@ -11462,7 +11525,9 @@ const Calendar = /*#__PURE__*/react.forwardRef(({
11462
11525
  children: /*#__PURE__*/jsxRuntime.jsx(CalendarGrid, {
11463
11526
  state: calendarState,
11464
11527
  setShowYearPicker: setShowYearPicker,
11465
- showYearPicker: showYearPicker
11528
+ showYearPicker: showYearPicker,
11529
+ yearPickerPage: yearPickerPage,
11530
+ setYearPickerPage: setYearPickerPage
11466
11531
  })
11467
11532
  }), Footer && /*#__PURE__*/jsxRuntime.jsx(Popover.Actions, {
11468
11533
  children: /*#__PURE__*/jsxRuntime.jsx(Footer, {
@@ -11998,6 +12063,7 @@ const RangeCalendar = /*#__PURE__*/react.forwardRef(({
11998
12063
  ...props
11999
12064
  }, ref) => {
12000
12065
  const [showYearPicker, setShowYearPicker] = react.useState(false);
12066
+ const [yearPickerPage, setYearPickerPage] = react.useState(0);
12001
12067
  const {
12002
12068
  locale
12003
12069
  } = reactAria.useLocale();
@@ -12028,13 +12094,16 @@ const RangeCalendar = /*#__PURE__*/react.forwardRef(({
12028
12094
  state: state,
12029
12095
  title: title,
12030
12096
  setShowYearPicker: setShowYearPicker,
12031
- showYearPicker: showYearPicker
12097
+ showYearPicker: showYearPicker,
12098
+ setYearPickerPage: setYearPickerPage
12032
12099
  })
12033
12100
  }), /*#__PURE__*/jsxRuntime.jsx(Popover.Content, {
12034
12101
  children: /*#__PURE__*/jsxRuntime.jsx(CalendarGrid, {
12035
12102
  state: state,
12036
12103
  setShowYearPicker: setShowYearPicker,
12037
- showYearPicker: showYearPicker
12104
+ showYearPicker: showYearPicker,
12105
+ yearPickerPage: yearPickerPage,
12106
+ setYearPickerPage: setYearPickerPage
12038
12107
  })
12039
12108
  }), Footer && /*#__PURE__*/jsxRuntime.jsx(Popover.Actions, {
12040
12109
  children: /*#__PURE__*/jsxRuntime.jsx(Footer, {
@@ -172,7 +172,6 @@ function AutocompleteInner(props, ref) {
172
172
  itemCompare,
173
173
  allowSelectAll,
174
174
  initialSelectedOptions: _initialSelectedOptions = [],
175
- disablePortal,
176
175
  optionDisabled = defaultOptionDisabled,
177
176
  optionsFilter,
178
177
  autoWidth,
@@ -192,9 +191,6 @@ function AutocompleteInner(props, ref) {
192
191
  // MARK: initializing data/setup
193
192
  const selectedOptions = _selectedOptions ? itemCompare ? options.filter(item => _selectedOptions.some(compare => itemCompare(item, compare))) : _selectedOptions : undefined;
194
193
  const initialSelectedOptions = _initialSelectedOptions ? itemCompare ? options.filter(item => _initialSelectedOptions.some(compare => itemCompare(item, compare))) : _initialSelectedOptions : undefined;
195
- if (disablePortal) {
196
- console.warn('Autocomplete "disablePortal" prop has been deprecated. Autocomplete now uses the native popover api');
197
- }
198
194
  const isControlled = Boolean(selectedOptions);
199
195
  const [inputOptions, setInputOptions] = useState(options);
200
196
  const [_availableItems, setAvailableItems] = useState(inputOptions);
@@ -384,7 +380,12 @@ function AutocompleteInner(props, ref) {
384
380
  if (selectedItem === AllSymbol) {
385
381
  toggleAllSelected();
386
382
  } else if (multiple) {
387
- selectedItems.includes(selectedItem) ? removeSelectedItem(selectedItem) : addSelectedItem(selectedItem);
383
+ const shouldRemove = itemCompare ? selectedItems.some(i => itemCompare(selectedItem, i)) : selectedItems.includes(selectedItem);
384
+ if (shouldRemove) {
385
+ removeSelectedItem(selectedItem);
386
+ } else {
387
+ addSelectedItem(selectedItem);
388
+ }
388
389
  } else {
389
390
  setSelectedItems([selectedItem]);
390
391
  }
@@ -14,6 +14,7 @@ const Calendar = /*#__PURE__*/forwardRef(({
14
14
  ...props
15
15
  }, ref) => {
16
16
  const [showYearPicker, setShowYearPicker] = useState(false);
17
+ const [yearPickerPage, setYearPickerPage] = useState(0);
17
18
  const {
18
19
  locale
19
20
  } = useLocale();
@@ -51,7 +52,8 @@ const Calendar = /*#__PURE__*/forwardRef(({
51
52
  previousMonthDisabled: prevButtonProps.isDisabled,
52
53
  nextMonthDisabled: nextButtonProps.isDisabled,
53
54
  setShowYearPicker: setShowYearPicker,
54
- showYearPicker: showYearPicker
55
+ showYearPicker: showYearPicker,
56
+ setYearPickerPage: setYearPickerPage
55
57
  })
56
58
  }), /*#__PURE__*/jsx(Popover.Content, {
57
59
  className: "calendar",
@@ -61,7 +63,9 @@ const Calendar = /*#__PURE__*/forwardRef(({
61
63
  children: /*#__PURE__*/jsx(CalendarGrid, {
62
64
  state: calendarState,
63
65
  setShowYearPicker: setShowYearPicker,
64
- showYearPicker: showYearPicker
66
+ showYearPicker: showYearPicker,
67
+ yearPickerPage: yearPickerPage,
68
+ setYearPickerPage: setYearPickerPage
65
69
  })
66
70
  }), Footer && /*#__PURE__*/jsx(Popover.Actions, {
67
71
  children: /*#__PURE__*/jsx(Footer, {
@@ -6,10 +6,15 @@ import { jsx, jsxs } from 'react/jsx-runtime';
6
6
 
7
7
  /* eslint-disable react/no-array-index-key */
8
8
 
9
+ /**
10
+ * The grid laying out the cells for the calendars in {link Calendar} and {link RangeCalendar}
11
+ */
9
12
  function CalendarGrid({
10
13
  state,
11
14
  showYearPicker,
12
15
  setShowYearPicker,
16
+ yearPickerPage,
17
+ setYearPickerPage,
13
18
  ...props
14
19
  }) {
15
20
  const {
@@ -34,7 +39,9 @@ function CalendarGrid({
34
39
  year
35
40
  }));
36
41
  setShowYearPicker(false);
37
- }
42
+ },
43
+ yearPickerPage: yearPickerPage,
44
+ setYearPickerPage: setYearPickerPage
38
45
  }) : /*#__PURE__*/jsxs("table", {
39
46
  ...gridProps,
40
47
  style: {
@@ -39,15 +39,16 @@ function CalendarHeader({
39
39
  previousMonthDisabled,
40
40
  nextMonthDisabled,
41
41
  showYearPicker,
42
- setShowYearPicker
42
+ setShowYearPicker,
43
+ setYearPickerPage
43
44
  }) {
44
45
  return /*#__PURE__*/jsx(HeaderWrapper, {
45
46
  children: /*#__PURE__*/jsxs(HeaderActions, {
46
47
  children: [/*#__PURE__*/jsx(Button, {
47
48
  variant: 'ghost_icon',
48
49
  "aria-label": 'Previous month',
49
- disabled: previousMonthDisabled || showYearPicker,
50
- onClick: () => state.focusPreviousPage(),
50
+ disabled: previousMonthDisabled,
51
+ onClick: () => showYearPicker ? setYearPickerPage(page => page - 1) : state.focusPreviousPage(),
51
52
  children: /*#__PURE__*/jsx(Icon, {
52
53
  data: chevron_left
53
54
  })
@@ -76,8 +77,8 @@ function CalendarHeader({
76
77
  }
77
78
  }), /*#__PURE__*/jsx(Button, {
78
79
  variant: 'ghost_icon',
79
- onClick: () => state.focusNextPage(),
80
- disabled: nextMonthDisabled || showYearPicker,
80
+ onClick: () => showYearPicker ? setYearPickerPage(page => page + 1) : state.focusNextPage(),
81
+ disabled: nextMonthDisabled,
81
82
  "aria-label": 'Next month',
82
83
  children: /*#__PURE__*/jsx(Icon, {
83
84
  data: chevron_right
@@ -14,6 +14,7 @@ const RangeCalendar = /*#__PURE__*/forwardRef(({
14
14
  ...props
15
15
  }, ref) => {
16
16
  const [showYearPicker, setShowYearPicker] = useState(false);
17
+ const [yearPickerPage, setYearPickerPage] = useState(0);
17
18
  const {
18
19
  locale
19
20
  } = useLocale();
@@ -44,13 +45,16 @@ const RangeCalendar = /*#__PURE__*/forwardRef(({
44
45
  state: state,
45
46
  title: title,
46
47
  setShowYearPicker: setShowYearPicker,
47
- showYearPicker: showYearPicker
48
+ showYearPicker: showYearPicker,
49
+ setYearPickerPage: setYearPickerPage
48
50
  })
49
51
  }), /*#__PURE__*/jsx(Popover.Content, {
50
52
  children: /*#__PURE__*/jsx(CalendarGrid, {
51
53
  state: state,
52
54
  setShowYearPicker: setShowYearPicker,
53
- showYearPicker: showYearPicker
55
+ showYearPicker: showYearPicker,
56
+ yearPickerPage: yearPickerPage,
57
+ setYearPickerPage: setYearPickerPage
54
58
  })
55
59
  }), Footer && /*#__PURE__*/jsx(Popover.Actions, {
56
60
  children: /*#__PURE__*/jsx(Footer, {
@@ -1,6 +1,7 @@
1
1
  import styled from 'styled-components';
2
2
  import { tokens } from '@equinor/eds-tokens';
3
3
  import { FocusScope, useFocusManager } from 'react-aria';
4
+ import { useRef, useEffect } from 'react';
4
5
  import { jsx } from 'react/jsx-runtime';
5
6
 
6
7
  // Disable no-autofocus - it's not the native autofocus attribute, but react-aria's autoFocus prop
@@ -15,23 +16,58 @@ const GridColumn = styled.button.withConfig({
15
16
  })(["background-color:transparent;outline:none;border:none;display:flex;justify-content:center;cursor:pointer;padding:8px;font-size:", ";font-family:", ";font-weight:", ";line-height:", ";color:", ";border-radius:999px;", ";&:hover{background-color:#f0f0f0;}&:focus{outline:2px dashed ", ";}"], tokens.typography.navigation.button.fontSize, tokens.typography.navigation.button.fontFamily, tokens.typography.navigation.button.fontWeight, tokens.typography.navigation.button.lineHeight, tokens.colors.text.static_icons__default.rgba, ({
16
17
  $active
17
18
  }) => $active ? `background-color: ${tokens.colors.interactive.primary__selected_highlight.rgba}` : '', tokens.colors.interactive.primary__resting.rgba);
19
+ const TOTAL_VISIBLE_YEARS = 36;
20
+ const RANGE_OFFSET = 30 / 2;
18
21
  const GridFocusManager = ({
19
22
  year: selectedYear,
20
- setFocusedYear
23
+ setFocusedYear,
24
+ yearPickerPage,
25
+ setYearPickerPage
21
26
  }) => {
22
27
  const focusManager = useFocusManager();
23
- const onKeyDown = e => {
28
+ const prevYear = useRef();
29
+ const navByKeyboard = useRef(false);
30
+ const page = yearPickerPage * TOTAL_VISIBLE_YEARS;
31
+ const years = Array.from({
32
+ length: TOTAL_VISIBLE_YEARS
33
+ }, (_, i) => i + (selectedYear + page - RANGE_OFFSET));
34
+ useEffect(() => {
35
+ if (prevYear.current === undefined) {
36
+ prevYear.current = yearPickerPage;
37
+ return;
38
+ }
39
+ if (!navByKeyboard.current) {
40
+ focusManager.focusFirst();
41
+ return;
42
+ }
43
+ navByKeyboard.current = false;
44
+ yearPickerPage > prevYear.current ? focusManager.focusFirst() : focusManager.focusLast();
45
+ prevYear.current = yearPickerPage;
46
+ }, [yearPickerPage, focusManager]);
47
+ const onKeyDown = year => e => {
24
48
  const target = e.currentTarget;
25
49
  const parent = target.parentElement;
50
+ const isFirstYear = years.at(0) === year;
51
+ const isLastYear = years.at(-1) === year;
26
52
  switch (e.key) {
27
53
  case 'ArrowRight':
28
54
  e.preventDefault();
55
+ if (isLastYear) {
56
+ navByKeyboard.current = true;
57
+ setYearPickerPage(page => page + 1);
58
+ break;
59
+ }
29
60
  focusManager.focusNext({
30
61
  wrap: true
31
62
  });
32
63
  break;
33
64
  case 'ArrowLeft':
34
65
  e.preventDefault();
66
+ if (isFirstYear) {
67
+ navByKeyboard.current = true;
68
+ setYearPickerPage(page => page - 1);
69
+ break;
70
+ }
35
71
  focusManager.focusPrevious({
36
72
  wrap: true
37
73
  });
@@ -39,6 +75,11 @@ const GridFocusManager = ({
39
75
  case 'ArrowDown':
40
76
  {
41
77
  e.preventDefault();
78
+ if (isLastYear) {
79
+ navByKeyboard.current = true;
80
+ setYearPickerPage(page => page + 1);
81
+ break;
82
+ }
42
83
  const selfIndex = Array.from(parent.children).indexOf(target);
43
84
  const focusElement = Array.from(parent.children).at(selfIndex + 5);
44
85
  focusManager.focusNext({
@@ -49,6 +90,11 @@ const GridFocusManager = ({
49
90
  case 'ArrowUp':
50
91
  {
51
92
  e.preventDefault();
93
+ if (isFirstYear) {
94
+ navByKeyboard.current = true;
95
+ setYearPickerPage(page => page - 1);
96
+ break;
97
+ }
52
98
  const selfIndex = Array.from(parent.children).indexOf(target);
53
99
  const focusElement = Array.from(parent.children).at(selfIndex - 5);
54
100
  focusManager.focusPrevious({
@@ -58,12 +104,9 @@ const GridFocusManager = ({
58
104
  }
59
105
  }
60
106
  };
61
- const years = Array.from({
62
- length: 36
63
- }, (_, i) => i + (selectedYear - 30 / 2));
64
107
  return years.map(year => /*#__PURE__*/jsx(GridColumn, {
65
108
  $active: selectedYear === year,
66
- onKeyDown: onKeyDown,
109
+ onKeyDown: onKeyDown(year),
67
110
  onClick: () => setFocusedYear(year),
68
111
  "aria-label": `Set year to ${year}`,
69
112
  tabIndex: 0,
@@ -72,7 +115,9 @@ const GridFocusManager = ({
72
115
  };
73
116
  const YearGrid = ({
74
117
  setFocusedYear,
75
- year: selectedYear
118
+ year: selectedYear,
119
+ yearPickerPage,
120
+ setYearPickerPage
76
121
  }) => {
77
122
  return /*#__PURE__*/jsx(Grid, {
78
123
  children: /*#__PURE__*/jsx(FocusScope, {
@@ -81,7 +126,9 @@ const YearGrid = ({
81
126
  autoFocus: true,
82
127
  children: /*#__PURE__*/jsx(GridFocusManager, {
83
128
  year: selectedYear,
84
- setFocusedYear: setFocusedYear
129
+ setFocusedYear: setFocusedYear,
130
+ yearPickerPage: yearPickerPage,
131
+ setYearPickerPage: setYearPickerPage
85
132
  })
86
133
  })
87
134
  });
@@ -1,8 +1,8 @@
1
1
  import { forwardRef, useRef, useMemo, useEffect } from 'react';
2
2
  import styled, { css, ThemeProvider } from 'styled-components';
3
- import { typographyTemplate, bordersTemplate, outlineTemplate, mergeRefs, useToken, useIsInDialog } from '@equinor/eds-utils';
3
+ import { typographyTemplate, bordersTemplate, outlineTemplate, mergeRefs, useIsomorphicLayoutEffect, useToken } from '@equinor/eds-utils';
4
4
  import { popover } from './Popover.tokens.js';
5
- import { useFloating, offset, flip, shift, arrow, autoUpdate, useInteractions, useDismiss, FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
5
+ import { useFloating, offset, flip, shift, arrow, autoUpdate, useInteractions, useDismiss, FloatingFocusManager } from '@floating-ui/react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { Paper } from '../Paper/Paper.js';
8
8
  import { useEds } from '../EdsProvider/eds.context.js';
@@ -18,19 +18,25 @@ const PopoverPaper = styled(Paper).withConfig({
18
18
  paper
19
19
  }
20
20
  } = theme;
21
- return css(["", " background:", ";", " z-index:1400;&:focus-visible{", "}"], typographyTemplate(theme.typography), theme.background, bordersTemplate(theme.border), outlineTemplate(paper.states.focus.outline));
21
+ return css(["position:relative;", " background:", ";", " &:focus-visible{", "}"], typographyTemplate(theme.typography), theme.background, bordersTemplate(theme.border), outlineTemplate(paper.states.focus.outline));
22
22
  });
23
+ const StyledPopover = styled('div').withConfig({
24
+ shouldForwardProp: () => true //workaround to avoid warning until popover gets added to react types
25
+ }).withConfig({
26
+ displayName: "Popover__StyledPopover",
27
+ componentId: "sc-b7p1is-1"
28
+ })(["inset:unset;border:0;padding:0;margin:0;overflow:visible;background-color:transparent;&::backdrop{background-color:transparent;}"]);
23
29
  const ArrowWrapper = styled.div.withConfig({
24
30
  displayName: "Popover__ArrowWrapper",
25
- componentId: "sc-b7p1is-1"
31
+ componentId: "sc-b7p1is-2"
26
32
  })(({
27
33
  theme
28
34
  }) => {
29
- return css(["position:absolute;width:", ";height:", ";z-index:-1;"], theme.entities.arrow.width, theme.entities.arrow.height);
35
+ return css(["position:absolute;width:", ";height:", ";"], theme.entities.arrow.width, theme.entities.arrow.height);
30
36
  });
31
37
  const InnerWrapper = styled.div.withConfig({
32
38
  displayName: "Popover__InnerWrapper",
33
- componentId: "sc-b7p1is-2"
39
+ componentId: "sc-b7p1is-3"
34
40
  })(({
35
41
  theme
36
42
  }) => {
@@ -38,7 +44,7 @@ const InnerWrapper = styled.div.withConfig({
38
44
  });
39
45
  const PopoverArrow = styled.svg.withConfig({
40
46
  displayName: "Popover__PopoverArrow",
41
- componentId: "sc-b7p1is-3"
47
+ componentId: "sc-b7p1is-4"
42
48
  })(({
43
49
  theme
44
50
  }) => {
@@ -55,6 +61,9 @@ const Popover = /*#__PURE__*/forwardRef(function Popover({
55
61
  trapFocus,
56
62
  ...rest
57
63
  }, ref) {
64
+ if (withinPortal) {
65
+ console.warn('Popover "withinPortal" prop has been deprecated. Popover now uses the native popover api');
66
+ }
58
67
  const arrowRef = useRef(null);
59
68
  const {
60
69
  x,
@@ -87,6 +96,13 @@ const Popover = /*#__PURE__*/forwardRef(function Popover({
87
96
  const {
88
97
  getFloatingProps
89
98
  } = useInteractions([useDismiss(context)]);
99
+ useIsomorphicLayoutEffect(() => {
100
+ if (open) {
101
+ refs.floating.current?.showPopover();
102
+ } else {
103
+ refs.floating.current?.hidePopover();
104
+ }
105
+ }, [open, refs.floating]);
90
106
  useEffect(() => {
91
107
  if (arrowRef.current) {
92
108
  const staticSide = {
@@ -122,7 +138,6 @@ const Popover = /*#__PURE__*/forwardRef(function Popover({
122
138
  // eslint-disable-next-line react-hooks/exhaustive-deps
123
139
  }, [arrowRef.current, arrowX, arrowY, finalPlacement]);
124
140
  const props = {
125
- open,
126
141
  ...rest
127
142
  };
128
143
  const {
@@ -131,14 +146,10 @@ const Popover = /*#__PURE__*/forwardRef(function Popover({
131
146
  const token = useToken({
132
147
  density
133
148
  }, popover);
134
-
135
- //temporary fix when inside dialog. Should be replaced by popover api when it is ready
136
- const inDialog = useIsInDialog(anchorEl);
137
149
  const popover$1 = /*#__PURE__*/jsx(ThemeProvider, {
138
150
  theme: token,
139
- children: /*#__PURE__*/jsxs(PopoverPaper, {
140
- elevation: "overlay",
141
- ...props,
151
+ children: /*#__PURE__*/jsx(StyledPopover, {
152
+ popover: "manual",
142
153
  ...getFloatingProps({
143
154
  ref: popoverRef,
144
155
  style: {
@@ -148,35 +159,30 @@ const Popover = /*#__PURE__*/forwardRef(function Popover({
148
159
  left: x || 0
149
160
  }
150
161
  }),
151
- children: [/*#__PURE__*/jsx(ArrowWrapper, {
152
- ref: arrowRef,
153
- className: "arrow",
154
- children: /*#__PURE__*/jsx(PopoverArrow, {
155
- className: "arrowSvg",
156
- children: /*#__PURE__*/jsx("path", {
157
- d: "M0.504838 4.86885C-0.168399 4.48524 -0.168399 3.51476 0.504838 3.13115L6 8.59227e-08L6 8L0.504838 4.86885Z"
162
+ children: /*#__PURE__*/jsxs(PopoverPaper, {
163
+ elevation: "overlay",
164
+ ...props,
165
+ children: [/*#__PURE__*/jsx(ArrowWrapper, {
166
+ ref: arrowRef,
167
+ className: "arrow",
168
+ children: /*#__PURE__*/jsx(PopoverArrow, {
169
+ className: "arrowSvg",
170
+ children: /*#__PURE__*/jsx("path", {
171
+ d: "M0.504838 4.86885C-0.168399 4.48524 -0.168399 3.51476 0.504838 3.13115L6 8.59227e-08L6 8L0.504838 4.86885Z"
172
+ })
158
173
  })
159
- })
160
- }), /*#__PURE__*/jsx(InnerWrapper, {
161
- children: children
162
- })]
174
+ }), /*#__PURE__*/jsx(InnerWrapper, {
175
+ children: children
176
+ })]
177
+ })
163
178
  })
164
179
  });
165
180
  return /*#__PURE__*/jsx(Fragment, {
166
- children: withinPortal && !inDialog ? /*#__PURE__*/jsx(FloatingPortal, {
167
- id: "eds-popover-container",
168
- children: open && trapFocus ? open && /*#__PURE__*/jsx(FloatingFocusManager, {
169
- context: context,
170
- modal: true,
171
- children: popover$1
172
- }) : open && popover$1
173
- }) : /*#__PURE__*/jsx(Fragment, {
174
- children: trapFocus ? open && /*#__PURE__*/jsx(FloatingFocusManager, {
175
- context: context,
176
- modal: true,
177
- children: popover$1
178
- }) : open && popover$1
179
- })
181
+ children: trapFocus ? open && /*#__PURE__*/jsx(FloatingFocusManager, {
182
+ context: context,
183
+ modal: true,
184
+ children: popover$1
185
+ }) : open && popover$1
180
186
  });
181
187
  });
182
188
 
@@ -61,10 +61,6 @@ export type AutocompleteProps<T> = {
61
61
  optionLabel?: (option: T) => string;
62
62
  /** Custom option template */
63
63
  optionComponent?: (option: T, isSelected: boolean) => ReactNode;
64
- /** Disable use of react portal for dropdown
65
- * @deprecated Autocomplete now uses the native popover api to render the dropdown. This prop will be removed in a future version
66
- */
67
- disablePortal?: boolean;
68
64
  /** Disable option
69
65
  * @default () => false
70
66
  */
@@ -1,10 +1,13 @@
1
1
  import { CalendarState, RangeCalendarState } from '@react-stately/calendar';
2
2
  import { AriaCalendarGridProps } from 'react-aria';
3
+ import { Dispatch, SetStateAction } from 'react';
3
4
  /**
4
5
  * The grid laying out the cells for the calendars in {link Calendar} and {link RangeCalendar}
5
6
  */
6
- export declare function CalendarGrid({ state, showYearPicker, setShowYearPicker, ...props }: {
7
+ export declare function CalendarGrid({ state, showYearPicker, setShowYearPicker, yearPickerPage, setYearPickerPage, ...props }: {
7
8
  state: CalendarState | RangeCalendarState;
8
9
  showYearPicker: boolean;
9
10
  setShowYearPicker: (showYearPicker: boolean) => void;
11
+ yearPickerPage: number;
12
+ setYearPickerPage: Dispatch<SetStateAction<number>>;
10
13
  } & AriaCalendarGridProps): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,14 @@
1
1
  import { CalendarState, RangeCalendarState } from '@react-stately/calendar';
2
+ import { Dispatch, SetStateAction } from 'react';
2
3
  /**
3
4
  * The default header for the calendar components if no custom header is provided
4
5
  */
5
- export declare function CalendarHeader({ state, title, previousMonthDisabled, nextMonthDisabled, showYearPicker, setShowYearPicker, }: {
6
+ export declare function CalendarHeader({ state, title, previousMonthDisabled, nextMonthDisabled, showYearPicker, setShowYearPicker, setYearPickerPage, }: {
6
7
  state: CalendarState | RangeCalendarState;
7
8
  title: string;
8
9
  previousMonthDisabled?: boolean;
9
10
  nextMonthDisabled?: boolean;
10
11
  showYearPicker: boolean;
11
12
  setShowYearPicker: (showYearPicker: boolean) => void;
13
+ setYearPickerPage?: Dispatch<SetStateAction<number>>;
12
14
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,7 @@
1
- export declare const YearGrid: ({ setFocusedYear, year: selectedYear, }: {
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ export declare const YearGrid: ({ setFocusedYear, year: selectedYear, yearPickerPage, setYearPickerPage, }: {
2
3
  setFocusedYear: (year: number) => void;
3
4
  year: number;
5
+ yearPickerPage: number;
6
+ setYearPickerPage?: Dispatch<SetStateAction<number>>;
4
7
  }) => import("react/jsx-runtime").JSX.Element;
@@ -9,7 +9,9 @@ export type PopoverProps = {
9
9
  anchorEl?: HTMLElement | null;
10
10
  /** Is Popover open */
11
11
  open: boolean;
12
- /** initializes react portal for dropdown, default to false. */
12
+ /**
13
+ * @deprecated Popover now uses the native popover api instead of react portal. This prop will be removed in a future version
14
+ */
13
15
  withinPortal?: boolean;
14
16
  /** Determines whether focus should be trapped within dropdown,
15
17
  * default to false. */
@@ -24,7 +26,9 @@ export declare const Popover: import("react").ForwardRefExoticComponent<{
24
26
  anchorEl?: HTMLElement | null;
25
27
  /** Is Popover open */
26
28
  open: boolean;
27
- /** initializes react portal for dropdown, default to false. */
29
+ /**
30
+ * @deprecated Popover now uses the native popover api instead of react portal. This prop will be removed in a future version
31
+ */
28
32
  withinPortal?: boolean;
29
33
  /** Determines whether focus should be trapped within dropdown,
30
34
  * default to false. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/eds-core-react",
3
- "version": "0.41.1",
3
+ "version": "0.41.3",
4
4
  "description": "The React implementation of the Equinor Design System",
5
5
  "sideEffects": [
6
6
  "**/*.css"