@lumx/react 4.3.2-alpha.1 → 4.3.2-alpha.10

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.
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { Kind as Kind$1, Size as Size$1, ColorPalette as ColorPalette$1, Emphasis as Emphasis$1, Theme as Theme$1, AspectRatio, ColorVariant, DIALOG_TRANSITION_DURATION, Orientation as Orientation$1, Alignment, NOTIFICATION_TRANSITION_DURATION, TOOLTIP_LONG_PRESS_DELAY, TOOLTIP_HOVER_DELAY } from '@lumx/core/js/constants';
1
+ import { Kind as Kind$1, Size as Size$1, ColorPalette as ColorPalette$1, Emphasis as Emphasis$1, Theme as Theme$1, AspectRatio as AspectRatio$1, ColorVariant, REAL_SIZE_FOR_LUMX_SIZE, DIALOG_TRANSITION_DURATION, Orientation as Orientation$1, Alignment, NOTIFICATION_TRANSITION_DURATION, TOOLTIP_LONG_PRESS_DELAY, TOOLTIP_HOVER_DELAY } from '@lumx/core/js/constants';
2
2
  export * from '@lumx/core/js/constants';
3
3
  export * from '@lumx/core/js/types';
4
4
  import * as React from 'react';
5
- import React__default, { useState, useEffect, useMemo, useRef, useCallback, Children, useLayoutEffect, cloneElement, createContext, isValidElement, useContext, useReducer } from 'react';
5
+ import React__default, { useState, useEffect, useMemo, useRef, useCallback, useContext, createContext, useReducer, Children, useLayoutEffect, cloneElement, isValidElement } from 'react';
6
6
  import { mdiAlert } from '@lumx/icons/esm/alert';
7
7
  import { mdiAlertCircle } from '@lumx/icons/esm/alert-circle';
8
8
  import { mdiCheckCircle } from '@lumx/icons/esm/check-circle';
@@ -16,7 +16,7 @@ import concat from 'lodash/concat';
16
16
  import dropRight from 'lodash/dropRight';
17
17
  import partition from 'lodash/partition';
18
18
  import reduce from 'lodash/reduce';
19
- import { u as useDisabledStateContext, P as Portal, C as ClickAwayProvider } from './_internal/DpdvhbTO.js';
19
+ import { u as useDisabledStateContext, M as MovingFocusContext, a as useVirtualFocusParent, b as useVirtualFocus, A as A11YLiveMessage, c as MovingFocusProvider, P as Portal, C as ClickAwayProvider } from './_internal/BcRzrT9Y.js';
20
20
  import isEmpty from 'lodash/isEmpty';
21
21
  import { getDisabledState } from '@lumx/core/js/utils/disabledState';
22
22
  import { mdiCloseCircle } from '@lumx/icons/esm/close-circle';
@@ -26,13 +26,17 @@ import isFunction from 'lodash/isFunction';
26
26
  import { mdiImageBroken } from '@lumx/icons/esm/image-broken';
27
27
  import { mdiCheck } from '@lumx/icons/esm/check';
28
28
  import { mdiMinus } from '@lumx/icons/esm/minus';
29
+ import { visuallyHidden, bem as bem$1 } from '@lumx/core/js/utils/classNames';
30
+ import noop from 'lodash/noop';
31
+ import uniqueId from 'lodash/uniqueId';
32
+ import debounce$1 from 'lodash/debounce';
33
+ import { mdiChevronDown } from '@lumx/icons/esm/chevron-down';
34
+ import { mdiChevronUp } from '@lumx/icons/esm/chevron-up';
35
+ import castArray from 'lodash/castArray';
36
+ import { mdiInformationOutline } from '@lumx/icons/esm/information-outline';
29
37
  import { mdiChevronLeft } from '@lumx/icons/esm/chevron-left';
30
38
  import { mdiChevronRight } from '@lumx/icons/esm/chevron-right';
31
- import castArray from 'lodash/castArray';
32
39
  import { mdiDragVertical } from '@lumx/icons/esm/drag-vertical';
33
- import { mdiChevronDown } from '@lumx/icons/esm/chevron-down';
34
- import { mdiChevronUp } from '@lumx/icons/esm/chevron-up';
35
- import noop from 'lodash/noop';
36
40
  import pick from 'lodash/pick';
37
41
  import isInteger from 'lodash/isInteger';
38
42
  import { mdiMagnifyMinusOutline } from '@lumx/icons/esm/magnify-minus-outline';
@@ -101,15 +105,15 @@ const COMPONENT_NAME$1l = 'AlertDialog';
101
105
  /**
102
106
  * Component default class name and class prefix.
103
107
  */
104
- const CLASSNAME$1j = 'lumx-alert-dialog';
108
+ const CLASSNAME$1o = 'lumx-alert-dialog';
105
109
  const {
106
- block: block$14
107
- } = classNames.bem(CLASSNAME$1j);
110
+ block: block$19
111
+ } = classNames.bem(CLASSNAME$1o);
108
112
 
109
113
  /**
110
114
  * Component default props.
111
115
  */
112
- const DEFAULT_PROPS$19 = {
116
+ const DEFAULT_PROPS$1b = {
113
117
  size: Size$1.tiny,
114
118
  kind: Kind$1.info
115
119
  };
@@ -130,8 +134,8 @@ const AlertDialog = forwardRef((props, ref) => {
130
134
  className,
131
135
  cancelProps,
132
136
  confirmProps,
133
- kind = DEFAULT_PROPS$19.kind,
134
- size = DEFAULT_PROPS$19.size,
137
+ kind = DEFAULT_PROPS$1b.kind,
138
+ size = DEFAULT_PROPS$1b.size,
135
139
  dialogProps,
136
140
  children,
137
141
  ...forwardedProps
@@ -172,7 +176,7 @@ const AlertDialog = forwardRef((props, ref) => {
172
176
  'aria-describedby': descriptionId,
173
177
  ...dialogProps
174
178
  },
175
- className: classNames.join(className, block$14({
179
+ className: classNames.join(className, block$19({
176
180
  [`kind-${kind}`]: Boolean(kind)
177
181
  })),
178
182
  ...forwardedProps,
@@ -218,8 +222,8 @@ const AlertDialog = forwardRef((props, ref) => {
218
222
  });
219
223
  });
220
224
  AlertDialog.displayName = COMPONENT_NAME$1l;
221
- AlertDialog.className = CLASSNAME$1j;
222
- AlertDialog.defaultProps = DEFAULT_PROPS$19;
225
+ AlertDialog.className = CLASSNAME$1o;
226
+ AlertDialog.defaultProps = DEFAULT_PROPS$1b;
223
227
 
224
228
  /**
225
229
  * Hook focusing an element when defined and `focus` boolean `true`.
@@ -316,12 +320,12 @@ const COMPONENT_NAME$1k = 'Autocomplete';
316
320
  /**
317
321
  * Component default class name and class prefix.
318
322
  */
319
- const CLASSNAME$1i = 'lumx-autocomplete';
323
+ const CLASSNAME$1n = 'lumx-autocomplete';
320
324
 
321
325
  /**
322
326
  * Component default props.
323
327
  */
324
- const DEFAULT_PROPS$18 = {
328
+ const DEFAULT_PROPS$1a = {
325
329
  anchorToInput: false,
326
330
  closeOnClick: false,
327
331
  closeOnClickAway: true,
@@ -343,13 +347,13 @@ const Autocomplete = forwardRef((props, ref) => {
343
347
  otherProps
344
348
  } = useDisableStateProps(props);
345
349
  const {
346
- anchorToInput = DEFAULT_PROPS$18.anchorToInput,
350
+ anchorToInput = DEFAULT_PROPS$1a.anchorToInput,
347
351
  children,
348
352
  chips,
349
353
  className,
350
- closeOnClick = DEFAULT_PROPS$18.closeOnClick,
351
- closeOnClickAway = DEFAULT_PROPS$18.closeOnClickAway,
352
- closeOnEscape = DEFAULT_PROPS$18.closeOnEscape,
354
+ closeOnClick = DEFAULT_PROPS$1a.closeOnClick,
355
+ closeOnClickAway = DEFAULT_PROPS$1a.closeOnClickAway,
356
+ closeOnEscape = DEFAULT_PROPS$1a.closeOnEscape,
353
357
  error,
354
358
  fitToAnchorWidth,
355
359
  hasError,
@@ -370,7 +374,7 @@ const Autocomplete = forwardRef((props, ref) => {
370
374
  onInfiniteScroll,
371
375
  placeholder,
372
376
  placement,
373
- shouldFocusOnClose = DEFAULT_PROPS$18.shouldFocusOnClose,
377
+ shouldFocusOnClose = DEFAULT_PROPS$1a.shouldFocusOnClose,
374
378
  theme = defaultTheme,
375
379
  value,
376
380
  textFieldProps = {},
@@ -383,7 +387,7 @@ const Autocomplete = forwardRef((props, ref) => {
383
387
  return /*#__PURE__*/jsxs("div", {
384
388
  ref: ref,
385
389
  ...forwardedProps,
386
- className: classNames.join(className, CLASSNAME$1i),
390
+ className: classNames.join(className, CLASSNAME$1n),
387
391
  children: [/*#__PURE__*/jsx(TextField, {
388
392
  ...textFieldProps,
389
393
  chips: chips,
@@ -424,8 +428,8 @@ const Autocomplete = forwardRef((props, ref) => {
424
428
  });
425
429
  });
426
430
  Autocomplete.displayName = COMPONENT_NAME$1k;
427
- Autocomplete.className = CLASSNAME$1i;
428
- Autocomplete.defaultProps = DEFAULT_PROPS$18;
431
+ Autocomplete.className = CLASSNAME$1n;
432
+ Autocomplete.defaultProps = DEFAULT_PROPS$1a;
429
433
 
430
434
  /**
431
435
  * Component display name.
@@ -435,12 +439,12 @@ const COMPONENT_NAME$1j = 'AutocompleteMultiple';
435
439
  /**
436
440
  * Component default class name and class prefix.
437
441
  */
438
- const CLASSNAME$1h = 'lumx-autocomplete-multiple';
442
+ const CLASSNAME$1m = 'lumx-autocomplete-multiple';
439
443
 
440
444
  /**
441
445
  * Component default props.
442
446
  */
443
- const DEFAULT_PROPS$17 = {
447
+ const DEFAULT_PROPS$19 = {
444
448
  closeOnClickAway: true,
445
449
  closeOnEscape: true,
446
450
  selectedChipRender(choice, index, onClear, isDisabled) {
@@ -480,8 +484,8 @@ const AutocompleteMultiple = forwardRef((props, ref) => {
480
484
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
481
485
  chipsAlignment,
482
486
  className,
483
- closeOnClickAway = DEFAULT_PROPS$17.closeOnClickAway,
484
- closeOnEscape = DEFAULT_PROPS$17.closeOnEscape,
487
+ closeOnClickAway = DEFAULT_PROPS$19.closeOnClickAway,
488
+ closeOnEscape = DEFAULT_PROPS$19.closeOnEscape,
485
489
  fitToAnchorWidth,
486
490
  hasError,
487
491
  helper,
@@ -503,19 +507,19 @@ const AutocompleteMultiple = forwardRef((props, ref) => {
503
507
  onKeyDown,
504
508
  placeholder,
505
509
  placement,
506
- selectedChipRender = DEFAULT_PROPS$17.selectedChipRender,
510
+ selectedChipRender = DEFAULT_PROPS$19.selectedChipRender,
507
511
  shouldFocusOnClose,
508
512
  theme = defaultTheme,
509
513
  type,
510
514
  value,
511
- values = DEFAULT_PROPS$17.values,
515
+ values = DEFAULT_PROPS$19.values,
512
516
  ...forwardedProps
513
517
  } = otherProps;
514
518
  return /*#__PURE__*/jsx(Autocomplete, {
515
519
  ref: ref,
516
520
  ...forwardedProps,
517
521
  anchorToInput: anchorToInput,
518
- className: classNames.join(className, CLASSNAME$1h),
522
+ className: classNames.join(className, CLASSNAME$1m),
519
523
  name: name,
520
524
  value: value,
521
525
  onChange: onChange,
@@ -549,8 +553,8 @@ const AutocompleteMultiple = forwardRef((props, ref) => {
549
553
  });
550
554
  });
551
555
  AutocompleteMultiple.displayName = COMPONENT_NAME$1j;
552
- AutocompleteMultiple.className = CLASSNAME$1h;
553
- AutocompleteMultiple.defaultProps = DEFAULT_PROPS$17;
556
+ AutocompleteMultiple.className = CLASSNAME$1m;
557
+ AutocompleteMultiple.defaultProps = DEFAULT_PROPS$19;
554
558
 
555
559
  /**
556
560
  * Component display name.
@@ -560,16 +564,16 @@ const COMPONENT_NAME$1i = 'Avatar';
560
564
  /**
561
565
  * Component default class name and class prefix.
562
566
  */
563
- const CLASSNAME$1g = 'lumx-avatar';
567
+ const CLASSNAME$1l = 'lumx-avatar';
564
568
  const {
565
- block: block$13,
566
- element: element$N
567
- } = classNames.bem(CLASSNAME$1g);
569
+ block: block$18,
570
+ element: element$S
571
+ } = classNames.bem(CLASSNAME$1l);
568
572
 
569
573
  /**
570
574
  * Component default props.
571
575
  */
572
- const DEFAULT_PROPS$16 = {
576
+ const DEFAULT_PROPS$18 = {
573
577
  size: Size$1.m
574
578
  };
575
579
 
@@ -592,7 +596,7 @@ const Avatar = forwardRef((props, ref) => {
592
596
  linkAs,
593
597
  onClick,
594
598
  onKeyPress,
595
- size = DEFAULT_PROPS$16.size,
599
+ size = DEFAULT_PROPS$18.size,
596
600
  theme = defaultTheme,
597
601
  thumbnailProps,
598
602
  ...forwardedProps
@@ -600,34 +604,34 @@ const Avatar = forwardRef((props, ref) => {
600
604
  return /*#__PURE__*/jsxs("div", {
601
605
  ref: ref,
602
606
  ...forwardedProps,
603
- className: classNames.join(className, block$13({
607
+ className: classNames.join(className, block$18({
604
608
  [`size-${size}`]: Boolean(size),
605
609
  [`theme-${theme}`]: Boolean(theme)
606
610
  })),
607
611
  children: [/*#__PURE__*/jsx(Thumbnail, {
608
612
  linkProps: linkProps,
609
613
  linkAs: linkAs,
610
- className: element$N('thumbnail'),
614
+ className: element$S('thumbnail'),
611
615
  onClick: onClick,
612
616
  onKeyPress: onKeyPress,
613
617
  ...thumbnailProps,
614
- aspectRatio: AspectRatio.square,
618
+ aspectRatio: AspectRatio$1.square,
615
619
  size: size,
616
620
  image: image,
617
621
  alt: alt,
618
622
  theme: theme
619
623
  }), actions && /*#__PURE__*/jsx("div", {
620
- className: element$N('actions'),
624
+ className: element$S('actions'),
621
625
  children: actions
622
626
  }), badge && /*#__PURE__*/jsx("div", {
623
- className: element$N('badge'),
627
+ className: element$S('badge'),
624
628
  children: badge
625
629
  })]
626
630
  });
627
631
  });
628
632
  Avatar.displayName = COMPONENT_NAME$1i;
629
- Avatar.className = CLASSNAME$1g;
630
- Avatar.defaultProps = DEFAULT_PROPS$16;
633
+ Avatar.className = CLASSNAME$1l;
634
+ Avatar.defaultProps = DEFAULT_PROPS$18;
631
635
 
632
636
  /**
633
637
  * Alignments.
@@ -668,6 +672,12 @@ const TypographyInterface = {
668
672
  */
669
673
  const Typography = {
670
674
  ...TypographyInterface};
675
+ /**
676
+ * All available aspect ratios.
677
+ */
678
+ const AspectRatio = {
679
+ /** Intrinsic content ratio. */
680
+ original: 'original'};
671
681
  /**
672
682
  * Semantic info about the purpose of the component
673
683
  */
@@ -689,8 +699,6 @@ const ColorPalette = {
689
699
  red: 'red',
690
700
  light: 'light'};
691
701
 
692
- /** ColorPalette with all possible color variant combination */
693
-
694
702
  function getDefaultExportFromCjs (x) {
695
703
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
696
704
  }
@@ -851,7 +859,7 @@ function modifier$1(baseName, modifiers) {
851
859
  * block('button', { active: true, disabled: false }); // 'button button--active'
852
860
  */
853
861
 
854
- function block$12(baseName, modifiersOrAdditionalClasses, additionalClasses) {
862
+ function block$17(baseName, modifiersOrAdditionalClasses, additionalClasses) {
855
863
  let modifiers;
856
864
  let classes;
857
865
  if (Array.isArray(modifiersOrAdditionalClasses)) {
@@ -886,11 +894,11 @@ function block$12(baseName, modifiersOrAdditionalClasses, additionalClasses) {
886
894
  * element('my-button', 'icon', { active: true }); // 'my-button__icon my-button__icon--active'
887
895
  */
888
896
 
889
- function element$M(baseClass, elem, modifiersOrAdditionalClasses, additionalClasses) {
897
+ function element$R(baseClass, elem, modifiersOrAdditionalClasses, additionalClasses) {
890
898
  if (Array.isArray(modifiersOrAdditionalClasses)) {
891
- return block$12(`${baseClass}__${elem}`, modifiersOrAdditionalClasses);
899
+ return block$17(`${baseClass}__${elem}`, modifiersOrAdditionalClasses);
892
900
  }
893
- return block$12(`${baseClass}__${elem}`, modifiersOrAdditionalClasses, additionalClasses);
901
+ return block$17(`${baseClass}__${elem}`, modifiersOrAdditionalClasses, additionalClasses);
894
902
  }
895
903
 
896
904
  /**
@@ -899,15 +907,15 @@ function element$M(baseClass, elem, modifiersOrAdditionalClasses, additionalClas
899
907
  function bem(baseName) {
900
908
  function blockFn(modifiersOrAdditionalClasses, additionalClasses) {
901
909
  if (Array.isArray(modifiersOrAdditionalClasses)) {
902
- return block$12(baseName, modifiersOrAdditionalClasses);
910
+ return block$17(baseName, modifiersOrAdditionalClasses);
903
911
  }
904
- return block$12(baseName, modifiersOrAdditionalClasses, additionalClasses);
912
+ return block$17(baseName, modifiersOrAdditionalClasses, additionalClasses);
905
913
  }
906
914
  function elementFn(elem, modifiersOrAdditionalClasses, additionalClasses) {
907
915
  if (Array.isArray(modifiersOrAdditionalClasses)) {
908
- return element$M(baseName, elem, modifiersOrAdditionalClasses);
916
+ return element$R(baseName, elem, modifiersOrAdditionalClasses);
909
917
  }
910
- return element$M(baseName, elem, modifiersOrAdditionalClasses, additionalClasses);
918
+ return element$R(baseName, elem, modifiersOrAdditionalClasses, additionalClasses);
911
919
  }
912
920
  return {
913
921
  block: blockFn,
@@ -924,15 +932,15 @@ const COMPONENT_NAME$1h = 'Badge';
924
932
  /**
925
933
  * Component default class name and class prefix.
926
934
  */
927
- const CLASSNAME$1f = 'lumx-badge';
935
+ const CLASSNAME$1k = 'lumx-badge';
928
936
  const {
929
- block: block$11
930
- } = bem(CLASSNAME$1f);
937
+ block: block$16
938
+ } = bem(CLASSNAME$1k);
931
939
 
932
940
  /**
933
941
  * Component default props.
934
942
  */
935
- const DEFAULT_PROPS$15 = {
943
+ const DEFAULT_PROPS$17 = {
936
944
  color: ColorPalette.primary
937
945
  };
938
946
 
@@ -946,22 +954,22 @@ const Badge$1 = props => {
946
954
  const {
947
955
  children,
948
956
  className,
949
- color = DEFAULT_PROPS$15.color,
957
+ color = DEFAULT_PROPS$17.color,
950
958
  ref,
951
959
  ...forwardedProps
952
960
  } = props;
953
961
  return /*#__PURE__*/jsx("div", {
954
962
  ref: ref,
955
963
  ...forwardedProps,
956
- className: classnames(className, block$11({
964
+ className: classnames(className, block$16({
957
965
  [`color-${color}`]: Boolean(color)
958
966
  })),
959
967
  children: children
960
968
  });
961
969
  };
962
970
  Badge$1.displayName = COMPONENT_NAME$1h;
963
- Badge$1.className = CLASSNAME$1f;
964
- Badge$1.defaultProps = DEFAULT_PROPS$15;
971
+ Badge$1.className = CLASSNAME$1k;
972
+ Badge$1.defaultProps = DEFAULT_PROPS$17;
965
973
 
966
974
  /**
967
975
  * Defines the props of the component.
@@ -985,11 +993,11 @@ Badge.className = Badge$1.className;
985
993
  Badge.defaultProps = Badge$1.defaultProps;
986
994
 
987
995
  const COMPONENT_NAME$1g = 'BadgeWrapper';
988
- const CLASSNAME$1e = 'lumx-badge-wrapper';
996
+ const CLASSNAME$1j = 'lumx-badge-wrapper';
989
997
  const {
990
- block: block$10,
991
- element: element$L
992
- } = bem(CLASSNAME$1e);
998
+ block: block$15,
999
+ element: element$Q
1000
+ } = bem(CLASSNAME$1j);
993
1001
  const BadgeWrapper$1 = props => {
994
1002
  const {
995
1003
  badge,
@@ -1001,9 +1009,9 @@ const BadgeWrapper$1 = props => {
1001
1009
  return /*#__PURE__*/jsxs("div", {
1002
1010
  ref: ref,
1003
1011
  ...forwardedProps,
1004
- className: classnames(className, block$10()),
1012
+ className: classnames(className, block$15()),
1005
1013
  children: [children, badge && /*#__PURE__*/jsx("div", {
1006
- className: element$L('badge'),
1014
+ className: element$Q('badge'),
1007
1015
  children: badge
1008
1016
  })]
1009
1017
  });
@@ -1016,7 +1024,7 @@ const BadgeWrapper = forwardRef((props, ref) => {
1016
1024
  });
1017
1025
  });
1018
1026
  BadgeWrapper.displayName = COMPONENT_NAME$1g;
1019
- BadgeWrapper.className = CLASSNAME$1e;
1027
+ BadgeWrapper.className = CLASSNAME$1j;
1020
1028
 
1021
1029
  /**
1022
1030
  * Render clickable element (link, button or custom element)
@@ -1177,15 +1185,15 @@ const COMPONENT_NAME$1e = 'Button';
1177
1185
  /**
1178
1186
  * Component default class name and class prefix.
1179
1187
  */
1180
- const CLASSNAME$1d = 'lumx-button';
1188
+ const CLASSNAME$1i = 'lumx-button';
1181
1189
  const {
1182
1190
  modifier
1183
- } = bem(CLASSNAME$1d);
1191
+ } = bem(CLASSNAME$1i);
1184
1192
 
1185
1193
  /**
1186
1194
  * Component default props.
1187
1195
  */
1188
- const DEFAULT_PROPS$14 = {
1196
+ const DEFAULT_PROPS$16 = {
1189
1197
  emphasis: Emphasis.high,
1190
1198
  size: Size.m
1191
1199
  };
@@ -1199,10 +1207,10 @@ const DEFAULT_PROPS$14 = {
1199
1207
  const Button$1 = props => {
1200
1208
  const {
1201
1209
  className,
1202
- emphasis = DEFAULT_PROPS$14.emphasis,
1210
+ emphasis = DEFAULT_PROPS$16.emphasis,
1203
1211
  leftIcon,
1204
1212
  rightIcon,
1205
- size = DEFAULT_PROPS$14.size,
1213
+ size = DEFAULT_PROPS$16.size,
1206
1214
  ...forwardedProps
1207
1215
  } = props;
1208
1216
  const buttonClassName = classnames(className, modifier({
@@ -1218,8 +1226,8 @@ const Button$1 = props => {
1218
1226
  });
1219
1227
  };
1220
1228
  Button$1.displayName = COMPONENT_NAME$1e;
1221
- Button$1.className = CLASSNAME$1d;
1222
- Button$1.defaultProps = DEFAULT_PROPS$14;
1229
+ Button$1.className = CLASSNAME$1i;
1230
+ Button$1.defaultProps = DEFAULT_PROPS$16;
1223
1231
 
1224
1232
  /**
1225
1233
  * Properties of a component to use to determine it's name.
@@ -1286,8 +1294,8 @@ const Button = forwardRef((props, ref) => {
1286
1294
  });
1287
1295
  });
1288
1296
  Button.displayName = COMPONENT_NAME$1e;
1289
- Button.className = CLASSNAME$1d;
1290
- Button.defaultProps = DEFAULT_PROPS$14;
1297
+ Button.className = CLASSNAME$1i;
1298
+ Button.defaultProps = DEFAULT_PROPS$16;
1291
1299
 
1292
1300
  const COMPONENT_NAME$1d = 'Icon';
1293
1301
  const IconClassName = 'lumx-icon';
@@ -1296,15 +1304,15 @@ const IconClassName = 'lumx-icon';
1296
1304
  * Defines the props of the component.
1297
1305
  */
1298
1306
 
1299
- const CLASSNAME$1c = IconClassName;
1307
+ const CLASSNAME$1h = IconClassName;
1300
1308
  const {
1301
- block: block$$
1302
- } = bem(CLASSNAME$1c);
1309
+ block: block$14
1310
+ } = bem(CLASSNAME$1h);
1303
1311
 
1304
1312
  /**
1305
1313
  * Component default props.
1306
1314
  */
1307
- const DEFAULT_PROPS$13 = {};
1315
+ const DEFAULT_PROPS$15 = {};
1308
1316
 
1309
1317
  /**
1310
1318
  * Icon component.
@@ -1353,7 +1361,7 @@ const Icon$1 = props => {
1353
1361
  return /*#__PURE__*/jsx("i", {
1354
1362
  ref: ref,
1355
1363
  ...forwardedProps,
1356
- className: classnames(className, block$$({
1364
+ className: classnames(className, block$14({
1357
1365
  [`color-${iconColor}`]: Boolean(iconColor),
1358
1366
  [`color-variant-${iconColorVariant}`]: Boolean(iconColorVariant),
1359
1367
  'has-shape': hasShape,
@@ -1383,8 +1391,8 @@ const Icon$1 = props => {
1383
1391
  });
1384
1392
  };
1385
1393
  Icon$1.displayName = COMPONENT_NAME$1d;
1386
- Icon$1.className = CLASSNAME$1c;
1387
- Icon$1.defaultProps = DEFAULT_PROPS$13;
1394
+ Icon$1.className = CLASSNAME$1h;
1395
+ Icon$1.defaultProps = DEFAULT_PROPS$15;
1388
1396
 
1389
1397
  /**
1390
1398
  * Component display name.
@@ -1394,12 +1402,12 @@ const COMPONENT_NAME$1c = 'IconButton';
1394
1402
  /**
1395
1403
  * Component default class name and class prefix.
1396
1404
  */
1397
- const CLASSNAME$1b = 'lumx-icon-button';
1405
+ const CLASSNAME$1g = 'lumx-icon-button';
1398
1406
 
1399
1407
  /**
1400
1408
  * Component default props.
1401
1409
  */
1402
- const DEFAULT_PROPS$12 = {
1410
+ const DEFAULT_PROPS$14 = {
1403
1411
  emphasis: Emphasis.high,
1404
1412
  size: Size.m
1405
1413
  };
@@ -1412,11 +1420,11 @@ const DEFAULT_PROPS$12 = {
1412
1420
  */
1413
1421
  const IconButton$1 = props => {
1414
1422
  const {
1415
- emphasis = DEFAULT_PROPS$12.emphasis,
1423
+ emphasis = DEFAULT_PROPS$14.emphasis,
1416
1424
  image,
1417
1425
  icon,
1418
1426
  label,
1419
- size = DEFAULT_PROPS$12.size,
1427
+ size = DEFAULT_PROPS$14.size,
1420
1428
  ...forwardedProps
1421
1429
  } = props;
1422
1430
  const defaultChildren = image ? /*#__PURE__*/jsx("img", {
@@ -1436,8 +1444,8 @@ const IconButton$1 = props => {
1436
1444
  });
1437
1445
  };
1438
1446
  IconButton$1.displayName = COMPONENT_NAME$1c;
1439
- IconButton$1.className = CLASSNAME$1b;
1440
- IconButton$1.defaultProps = DEFAULT_PROPS$12;
1447
+ IconButton$1.className = CLASSNAME$1g;
1448
+ IconButton$1.defaultProps = DEFAULT_PROPS$14;
1441
1449
 
1442
1450
  /**
1443
1451
  * IconButton component.
@@ -1473,8 +1481,8 @@ const IconButton = forwardRef((props, ref) => {
1473
1481
  });
1474
1482
  });
1475
1483
  IconButton.displayName = COMPONENT_NAME$1c;
1476
- IconButton.className = CLASSNAME$1b;
1477
- IconButton.defaultProps = DEFAULT_PROPS$12;
1484
+ IconButton.className = CLASSNAME$1g;
1485
+ IconButton.defaultProps = DEFAULT_PROPS$14;
1478
1486
 
1479
1487
  /**
1480
1488
  * Component display name.
@@ -1484,12 +1492,12 @@ const COMPONENT_NAME$1b = 'ButtonGroup';
1484
1492
  /**
1485
1493
  * Component default class name and class prefix.
1486
1494
  */
1487
- const CLASSNAME$1a = 'lumx-button-group';
1495
+ const CLASSNAME$1f = 'lumx-button-group';
1488
1496
 
1489
1497
  /**
1490
1498
  * Component default props.
1491
1499
  */
1492
- const DEFAULT_PROPS$11 = {};
1500
+ const DEFAULT_PROPS$13 = {};
1493
1501
 
1494
1502
  /**
1495
1503
  * ButtonGroup component.
@@ -1505,13 +1513,13 @@ const ButtonGroup$1 = props => {
1505
1513
  } = props;
1506
1514
  return /*#__PURE__*/jsx("div", {
1507
1515
  ...forwardedProps,
1508
- className: classnames(className, CLASSNAME$1a),
1516
+ className: classnames(className, CLASSNAME$1f),
1509
1517
  children: children
1510
1518
  });
1511
1519
  };
1512
1520
  ButtonGroup$1.displayName = COMPONENT_NAME$1b;
1513
- ButtonGroup$1.className = CLASSNAME$1a;
1514
- ButtonGroup$1.defaultProps = DEFAULT_PROPS$11;
1521
+ ButtonGroup$1.className = CLASSNAME$1f;
1522
+ ButtonGroup$1.defaultProps = DEFAULT_PROPS$13;
1515
1523
 
1516
1524
  /**
1517
1525
  * ButtonGroup component.
@@ -1527,16 +1535,16 @@ const ButtonGroup = forwardRef((props, ref) => {
1527
1535
  });
1528
1536
  });
1529
1537
  ButtonGroup.displayName = COMPONENT_NAME$1b;
1530
- ButtonGroup.className = CLASSNAME$1a;
1531
- ButtonGroup.defaultProps = DEFAULT_PROPS$11;
1538
+ ButtonGroup.className = CLASSNAME$1f;
1539
+ ButtonGroup.defaultProps = DEFAULT_PROPS$13;
1532
1540
 
1533
1541
  const COMPONENT_NAME$1a = 'InputLabel';
1534
1542
  const InputLabelClassName = 'lumx-input-label';
1535
- const CLASSNAME$19 = InputLabelClassName;
1543
+ const CLASSNAME$1e = InputLabelClassName;
1536
1544
  const {
1537
- block: block$_
1538
- } = bem(CLASSNAME$19);
1539
- const DEFAULT_PROPS$10 = {};
1545
+ block: block$13
1546
+ } = bem(CLASSNAME$1e);
1547
+ const DEFAULT_PROPS$12 = {};
1540
1548
 
1541
1549
  /**
1542
1550
  * InputLabel component.
@@ -1556,7 +1564,7 @@ function InputLabel$1(props) {
1556
1564
  ref: ref,
1557
1565
  ...forwardedProps,
1558
1566
  htmlFor: htmlFor,
1559
- className: classnames(className, block$_({
1567
+ className: classnames(className, block$13({
1560
1568
  'is-required': isRequired,
1561
1569
  [`theme-${theme}`]: Boolean(theme),
1562
1570
  'has-custom-typography': Boolean(typography$1)
@@ -1565,8 +1573,8 @@ function InputLabel$1(props) {
1565
1573
  });
1566
1574
  }
1567
1575
  InputLabel$1.displayName = COMPONENT_NAME$1a;
1568
- InputLabel$1.className = CLASSNAME$19;
1569
- InputLabel$1.defaultProps = DEFAULT_PROPS$10;
1576
+ InputLabel$1.className = CLASSNAME$1e;
1577
+ InputLabel$1.defaultProps = DEFAULT_PROPS$12;
1570
1578
 
1571
1579
  const INPUT_HELPER_CONFIGURATION = {
1572
1580
  [Kind.error]: {
@@ -1587,15 +1595,15 @@ const InputHelperClassName = 'lumx-input-helper';
1587
1595
  * Defines the props of the component.
1588
1596
  */
1589
1597
 
1590
- const CLASSNAME$18 = InputHelperClassName;
1598
+ const CLASSNAME$1d = InputHelperClassName;
1591
1599
  const {
1592
- block: block$Z
1593
- } = bem(CLASSNAME$18);
1600
+ block: block$12
1601
+ } = bem(CLASSNAME$1d);
1594
1602
 
1595
1603
  /**
1596
1604
  * Component default props.
1597
1605
  */
1598
- const DEFAULT_PROPS$$ = {
1606
+ const DEFAULT_PROPS$11 = {
1599
1607
  kind: Kind.info
1600
1608
  };
1601
1609
 
@@ -1606,7 +1614,7 @@ function InputHelper$1(props) {
1606
1614
  const {
1607
1615
  children,
1608
1616
  className,
1609
- kind = DEFAULT_PROPS$$.kind,
1617
+ kind = DEFAULT_PROPS$11.kind,
1610
1618
  theme,
1611
1619
  ref,
1612
1620
  ...forwardedProps
@@ -1617,7 +1625,7 @@ function InputHelper$1(props) {
1617
1625
  return /*#__PURE__*/jsx("p", {
1618
1626
  ref: ref,
1619
1627
  ...forwardedProps,
1620
- className: classnames(className, block$Z({
1628
+ className: classnames(className, block$12({
1621
1629
  [`color-${color}`]: Boolean(color),
1622
1630
  [`theme-${theme}`]: Boolean(theme)
1623
1631
  })),
@@ -1625,8 +1633,8 @@ function InputHelper$1(props) {
1625
1633
  });
1626
1634
  }
1627
1635
  InputHelper$1.displayName = COMPONENT_NAME$19;
1628
- InputHelper$1.className = CLASSNAME$18;
1629
- InputHelper$1.defaultProps = DEFAULT_PROPS$$;
1636
+ InputHelper$1.className = CLASSNAME$1d;
1637
+ InputHelper$1.defaultProps = DEFAULT_PROPS$11;
1630
1638
 
1631
1639
  const INTERMEDIATE_STATE = 'intermediate';
1632
1640
 
@@ -1642,11 +1650,11 @@ const COMPONENT_NAME$18 = 'Checkbox';
1642
1650
  /**
1643
1651
  * Component default class name and class prefix.
1644
1652
  */
1645
- const CLASSNAME$17 = 'lumx-checkbox';
1653
+ const CLASSNAME$1c = 'lumx-checkbox';
1646
1654
  const {
1647
- block: block$Y,
1648
- element: element$K
1649
- } = bem(CLASSNAME$17);
1655
+ block: block$11,
1656
+ element: element$P
1657
+ } = bem(CLASSNAME$1c);
1650
1658
 
1651
1659
  /**
1652
1660
  * Checkbox component.
@@ -1682,7 +1690,7 @@ const Checkbox$1 = props => {
1682
1690
  return /*#__PURE__*/jsxs("div", {
1683
1691
  ref: ref,
1684
1692
  ...forwardedProps,
1685
- className: classnames(className, block$Y({
1693
+ className: classnames(className, block$11({
1686
1694
  // Whether state is intermediate class name will "-checked"
1687
1695
  'is-checked': intermediateState ? true : isChecked,
1688
1696
  'is-disabled': isDisabled,
@@ -1690,12 +1698,12 @@ const Checkbox$1 = props => {
1690
1698
  [`theme-${theme}`]: Boolean(theme)
1691
1699
  })),
1692
1700
  children: [/*#__PURE__*/jsxs("div", {
1693
- className: element$K('input-wrapper'),
1701
+ className: element$P('input-wrapper'),
1694
1702
  children: [/*#__PURE__*/jsx("input", {
1695
1703
  ref: inputRef,
1696
1704
  type: "checkbox",
1697
1705
  id: inputId,
1698
- className: element$K('input-native'),
1706
+ className: element$P('input-native'),
1699
1707
  name: name,
1700
1708
  value: value,
1701
1709
  checked: isChecked,
@@ -1707,26 +1715,26 @@ const Checkbox$1 = props => {
1707
1715
  } : {}),
1708
1716
  ...inputProps
1709
1717
  }), /*#__PURE__*/jsxs("div", {
1710
- className: element$K('input-placeholder'),
1718
+ className: element$P('input-placeholder'),
1711
1719
  children: [/*#__PURE__*/jsx("div", {
1712
- className: element$K('input-background')
1720
+ className: element$P('input-background')
1713
1721
  }), /*#__PURE__*/jsx("div", {
1714
- className: element$K('input-indicator'),
1722
+ className: element$P('input-indicator'),
1715
1723
  children: Icon$1({
1716
1724
  icon: intermediateState ? mdiMinus : mdiCheck
1717
1725
  })
1718
1726
  })]
1719
1727
  })]
1720
1728
  }), /*#__PURE__*/jsxs("div", {
1721
- className: element$K('content'),
1729
+ className: element$P('content'),
1722
1730
  children: [label && InputLabel$1({
1723
1731
  htmlFor: inputId,
1724
- className: element$K('label'),
1732
+ className: element$P('label'),
1725
1733
  theme,
1726
1734
  children: label
1727
1735
  }), helper && InputHelper$1({
1728
1736
  id: `${inputId}-helper`,
1729
- className: element$K('helper'),
1737
+ className: element$P('helper'),
1730
1738
  theme,
1731
1739
  children: helper
1732
1740
  })]
@@ -1741,7 +1749,7 @@ const Checkbox$1 = props => {
1741
1749
  /**
1742
1750
  * Component default props.
1743
1751
  */
1744
- const DEFAULT_PROPS$_ = {};
1752
+ const DEFAULT_PROPS$10 = {};
1745
1753
 
1746
1754
  /**
1747
1755
  * Checkbox component.
@@ -1802,8 +1810,8 @@ const Checkbox = forwardRef((props, ref) => {
1802
1810
  });
1803
1811
  });
1804
1812
  Checkbox.displayName = COMPONENT_NAME$18;
1805
- Checkbox.className = CLASSNAME$17;
1806
- Checkbox.defaultProps = DEFAULT_PROPS$_;
1813
+ Checkbox.className = CLASSNAME$1c;
1814
+ Checkbox.defaultProps = DEFAULT_PROPS$10;
1807
1815
 
1808
1816
  /**
1809
1817
  * Wrap mouse event handler to stop event propagation.
@@ -1829,16 +1837,16 @@ const COMPONENT_NAME$17 = 'Chip';
1829
1837
  /**
1830
1838
  * Component default class name and class prefix.
1831
1839
  */
1832
- const CLASSNAME$16 = 'lumx-chip';
1840
+ const CLASSNAME$1b = 'lumx-chip';
1833
1841
  const {
1834
- block: block$X,
1835
- element: element$J
1836
- } = classNames.bem(CLASSNAME$16);
1842
+ block: block$10,
1843
+ element: element$O
1844
+ } = classNames.bem(CLASSNAME$1b);
1837
1845
 
1838
1846
  /**
1839
1847
  * Component default props.
1840
1848
  */
1841
- const DEFAULT_PROPS$Z = {
1849
+ const DEFAULT_PROPS$$ = {
1842
1850
  size: Size$1.m
1843
1851
  };
1844
1852
 
@@ -1868,7 +1876,7 @@ const Chip = forwardRef((props, ref) => {
1868
1876
  onAfterClick,
1869
1877
  onBeforeClick,
1870
1878
  onClick,
1871
- size = DEFAULT_PROPS$Z.size,
1879
+ size = DEFAULT_PROPS$$.size,
1872
1880
  theme = defaultTheme,
1873
1881
  href,
1874
1882
  onKeyDown,
@@ -1899,7 +1907,7 @@ const Chip = forwardRef((props, ref) => {
1899
1907
  ...forwardedProps,
1900
1908
  href: !disabledStateProps.disabled ? href : undefined,
1901
1909
  ref: ref,
1902
- className: classNames.join(className, block$X({
1910
+ className: classNames.join(className, block$10({
1903
1911
  'is-clickable': isClickable,
1904
1912
  [`color-${chipColor}`]: Boolean(chipColor),
1905
1913
  'is-disabled': isAnyDisabled,
@@ -1917,19 +1925,19 @@ const Chip = forwardRef((props, ref) => {
1917
1925
  /*#__PURE__*/
1918
1926
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
1919
1927
  jsx("div", {
1920
- className: element$J('before', {
1928
+ className: element$O('before', {
1921
1929
  'is-clickable': hasBeforeClick
1922
1930
  }),
1923
1931
  onClick: handleOnBeforeClick,
1924
1932
  children: before
1925
1933
  }), /*#__PURE__*/jsx("div", {
1926
- className: element$J('label'),
1934
+ className: element$O('label'),
1927
1935
  children: children
1928
1936
  }), after &&
1929
1937
  /*#__PURE__*/
1930
1938
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
1931
1939
  jsx("div", {
1932
- className: element$J('after', {
1940
+ className: element$O('after', {
1933
1941
  'is-clickable': hasAfterClick
1934
1942
  }),
1935
1943
  onClick: handleOnAfterClick,
@@ -1939,8 +1947,8 @@ const Chip = forwardRef((props, ref) => {
1939
1947
  );
1940
1948
  });
1941
1949
  Chip.displayName = COMPONENT_NAME$17;
1942
- Chip.className = CLASSNAME$16;
1943
- Chip.defaultProps = DEFAULT_PROPS$Z;
1950
+ Chip.className = CLASSNAME$1b;
1951
+ Chip.defaultProps = DEFAULT_PROPS$$;
1944
1952
 
1945
1953
  const INITIAL_STATE_ACTIVE_CHIP = -1;
1946
1954
 
@@ -1996,7 +2004,7 @@ const useChipGroupNavigation = (chips, onChipDeleted, initialActiveChip = INITIA
1996
2004
  /**
1997
2005
  * Component default props.
1998
2006
  */
1999
- const DEFAULT_PROPS$Y = {};
2007
+ const DEFAULT_PROPS$_ = {};
2000
2008
 
2001
2009
  /**
2002
2010
  * Component display name.
@@ -2006,7 +2014,7 @@ const COMPONENT_NAME$16 = 'ChipGroup';
2006
2014
  /**
2007
2015
  * Component default class name and class prefix.
2008
2016
  */
2009
- const CLASSNAME$15 = 'lumx-chip-group';
2017
+ const CLASSNAME$1a = 'lumx-chip-group';
2010
2018
 
2011
2019
  /**
2012
2020
  * ChipGroup component.
@@ -2025,13 +2033,13 @@ const InternalChipGroup = forwardRef((props, ref) => {
2025
2033
  return /*#__PURE__*/jsx("div", {
2026
2034
  ref: ref,
2027
2035
  ...forwardedProps,
2028
- className: classNames.join(className, CLASSNAME$15),
2036
+ className: classNames.join(className, CLASSNAME$1a),
2029
2037
  children: children
2030
2038
  });
2031
2039
  });
2032
2040
  InternalChipGroup.displayName = COMPONENT_NAME$16;
2033
- InternalChipGroup.className = CLASSNAME$15;
2034
- InternalChipGroup.defaultProps = DEFAULT_PROPS$Y;
2041
+ InternalChipGroup.className = CLASSNAME$1a;
2042
+ InternalChipGroup.defaultProps = DEFAULT_PROPS$_;
2035
2043
  const ChipGroup = Object.assign(InternalChipGroup, {
2036
2044
  useChipGroupNavigation
2037
2045
  });
@@ -2121,11 +2129,11 @@ function useFocusLastChipOnBackspace(chipRefs, inputRef) {
2121
2129
  /**
2122
2130
  * Component default class name and class prefix.
2123
2131
  */
2124
- const CLASSNAME$14 = 'lumx-selection-chip-group';
2132
+ const CLASSNAME$19 = 'lumx-selection-chip-group';
2125
2133
  const {
2126
- block: block$W,
2127
- element: element$I
2128
- } = classNames.bem(CLASSNAME$14);
2134
+ block: block$$,
2135
+ element: element$N
2136
+ } = classNames.bem(CLASSNAME$19);
2129
2137
 
2130
2138
  /**
2131
2139
  * SelectionChipGroup component.
@@ -2155,7 +2163,7 @@ const SelectionChipGroup = ({
2155
2163
  return /*#__PURE__*/jsx(ChipGroup, {
2156
2164
  role: "group",
2157
2165
  "aria-label": label,
2158
- className: block$W(),
2166
+ className: block$$(),
2159
2167
  ...forwardedProps,
2160
2168
  children: value?.map((v, index) => {
2161
2169
  const name = getWithSelector(getOptionName, v);
@@ -2199,7 +2207,7 @@ const SelectionChipGroup = ({
2199
2207
  after: /*#__PURE__*/jsx(Icon, {
2200
2208
  icon: mdiClose
2201
2209
  }),
2202
- className: element$I('chip', [props?.className]),
2210
+ className: element$N('chip', [props?.className]),
2203
2211
  size: "s",
2204
2212
  ref: ref,
2205
2213
  onClick: onClick,
@@ -2214,180 +2222,1854 @@ const SelectionChipGroup = ({
2214
2222
  });
2215
2223
  };
2216
2224
 
2217
- /**
2218
- * Comment block variants.
2219
- */
2220
- const CommentBlockVariant = {
2221
- indented: 'indented',
2222
- linear: 'linear'
2225
+ /** Context to store the refs of the combobox elements */
2226
+ const ComboboxRefsContext = /*#__PURE__*/createContext({
2227
+ triggerRef: {
2228
+ current: null
2229
+ },
2230
+ anchorRef: {
2231
+ current: null
2232
+ }
2233
+ });
2234
+ /** Provider to store the required refs for the Combobox */
2235
+ const ComboboxRefsProvider = ({
2236
+ triggerRef,
2237
+ anchorRef,
2238
+ children
2239
+ }) => {
2240
+ const value = useMemo(() => ({
2241
+ triggerRef,
2242
+ anchorRef
2243
+ }), [triggerRef, anchorRef]);
2244
+ return /*#__PURE__*/jsx(ComboboxRefsContext.Provider, {
2245
+ value: value,
2246
+ children: children
2247
+ });
2223
2248
  };
2224
2249
 
2225
- /**
2226
- * Defines the props of the component.
2227
- */
2250
+ /** Retrieves the combobox elements references from context */
2251
+ const useComboboxRefs = () => {
2252
+ const refs = useContext(ComboboxRefsContext);
2253
+ if (!refs) {
2254
+ throw new Error('The useComboboxRefs hook must be called within a ComboboxRefsProvider');
2255
+ }
2256
+ return refs;
2257
+ };
2228
2258
 
2229
- /**
2230
- * Component display name.
2231
- */
2232
- const COMPONENT_NAME$15 = 'CommentBlock';
2259
+ /** Generate the combobox option id from the combobox id and the given id */
2260
+ const generateOptionId = (comboboxId, optionId) => `${comboboxId}-option-${optionId}`;
2233
2261
 
2234
- /**
2235
- * Component default class name and class prefix.
2236
- */
2237
- const CLASSNAME$13 = 'lumx-comment-block';
2238
- const {
2239
- block: block$V,
2240
- element: element$H
2241
- } = classNames.bem(CLASSNAME$13);
2262
+ /** Verifies that the combobox registered option is an action */
2263
+ const isComboboxAction = option => Boolean(option?.isAction);
2242
2264
 
2243
- /**
2244
- * Component default props.
2245
- */
2246
- const DEFAULT_PROPS$X = {
2247
- variant: CommentBlockVariant.indented
2265
+ /** Verifies that the combobox registered option is the option's value */
2266
+ const isComboboxValue = option => {
2267
+ return !isComboboxAction(option);
2248
2268
  };
2249
2269
 
2250
- /**
2251
- * CommentBlock component.
2252
- *
2253
- * @param props Component props.
2254
- * @param ref Component ref.
2255
- * @return React element.
2256
- */
2257
- const CommentBlock = forwardRef((props, ref) => {
2258
- const defaultTheme = useTheme() || Theme$1.light;
2259
- const {
2260
- actions,
2261
- avatarProps,
2262
- children,
2263
- className,
2264
- date,
2265
- fullDate,
2266
- hasActions,
2267
- headerActions,
2268
- isOpen,
2269
- isRelevant,
2270
- name,
2271
- onClick,
2272
- onMouseEnter,
2273
- onMouseLeave,
2274
- text,
2275
- theme = defaultTheme,
2276
- variant = DEFAULT_PROPS$X.variant,
2277
- ...forwardedProps
2278
- } = props;
2279
- const hasChildren = Children.count(children) > 0;
2280
- return /*#__PURE__*/jsxs("div", {
2281
- ref: ref,
2282
- className: classNames.join(className, block$V({
2283
- 'has-children': hasChildren && isOpen,
2284
- 'has-indented-children': hasChildren && variant === CommentBlockVariant.indented,
2285
- 'has-linear-children': hasChildren && variant === CommentBlockVariant.linear,
2286
- 'is-relevant': isRelevant,
2287
- [`theme-${theme}`]: Boolean(theme)
2288
- })),
2289
- ...forwardedProps,
2290
- children: [/*#__PURE__*/jsxs("div", {
2291
- className: element$H('wrapper'),
2292
- children: [/*#__PURE__*/jsx("div", {
2293
- className: element$H('avatar'),
2294
- children: /*#__PURE__*/jsx(Avatar, {
2295
- ...avatarProps,
2296
- size: Size$1.m,
2297
- onClick: onClick
2298
- })
2299
- }), /*#__PURE__*/jsxs("div", {
2300
- className: element$H('container'),
2301
- children: [/*#__PURE__*/jsxs("div", {
2302
- className: element$H('content'),
2303
- children: [/*#__PURE__*/jsxs("div", {
2304
- className: element$H('meta'),
2305
- children: [name &&
2306
- /*#__PURE__*/
2307
- // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
2308
- jsx("span", {
2309
- className: element$H('name'),
2310
- onClick: onClick,
2311
- onMouseEnter: onMouseEnter,
2312
- onMouseLeave: onMouseLeave,
2313
- children: name
2314
- }), headerActions && /*#__PURE__*/jsx("span", {
2315
- className: element$H('header-actions'),
2316
- children: headerActions
2317
- })]
2318
- }), /*#__PURE__*/jsx("div", {
2319
- className: element$H('text'),
2320
- children: text
2321
- }), date && (fullDate ? /*#__PURE__*/jsx(Tooltip, {
2322
- label: fullDate,
2323
- placement: "top",
2324
- children: /*#__PURE__*/jsx("span", {
2325
- className: element$H('date'),
2326
- children: date
2327
- })
2328
- }) : /*#__PURE__*/jsx("span", {
2329
- className: element$H('date'),
2330
- children: date
2331
- }))]
2332
- }), hasActions && /*#__PURE__*/jsx("div", {
2333
- className: element$H('actions'),
2334
- children: actions
2335
- })]
2336
- })]
2337
- }), hasChildren && isOpen && /*#__PURE__*/jsx("div", {
2338
- className: element$H('children'),
2339
- children: children
2340
- })]
2341
- });
2342
- });
2343
- CommentBlock.displayName = COMPONENT_NAME$15;
2344
- CommentBlock.className = CLASSNAME$13;
2345
- CommentBlock.defaultProps = DEFAULT_PROPS$X;
2270
+ const comboboxId = `combobox-${uniqueId()}`;
2271
+ const initialState = {
2272
+ comboboxId,
2273
+ listboxId: `${comboboxId}-popover`,
2274
+ status: 'idle',
2275
+ isOpen: false,
2276
+ inputValue: '',
2277
+ showAll: true,
2278
+ options: {},
2279
+ type: 'listbox',
2280
+ optionsLength: 0
2281
+ };
2346
2282
 
2347
- /**
2348
- * Add a number of months from a date while resetting the day to prevent month length mismatches.
2349
- */
2350
- function addMonthResetDay(date, monthOffset) {
2351
- const newDate = new Date(date.getTime());
2352
- newDate.setDate(1);
2353
- newDate.setMonth(date.getMonth() + monthOffset);
2354
- return newDate;
2355
- }
2283
+ /** Actions when the combobox opens. */
2284
+ const OPEN_COMBOBOX = (state, action) => {
2285
+ const {
2286
+ manual
2287
+ } = action.payload || {};
2288
+ // If the combobox was manually opened, show all suggestions
2289
+ return {
2290
+ ...state,
2291
+ showAll: Boolean(manual),
2292
+ isOpen: true
2293
+ };
2294
+ };
2356
2295
 
2357
- /**
2358
- * Check if given date is valid.
2359
- */
2360
- const isDateValid = date => date instanceof Date && !Number.isNaN(date.getTime());
2296
+ /** Actions when the combobox closes */
2297
+ const CLOSE_COMBOBOX = state => {
2298
+ return {
2299
+ ...state,
2300
+ showAll: true,
2301
+ isOpen: false
2302
+ };
2303
+ };
2361
2304
 
2362
- /**
2363
- * Component display name.
2364
- */
2365
- const COMPONENT_NAME$14 = 'DatePicker';
2305
+ /** Actions on input update. */
2306
+ const SET_INPUT_VALUE = (state, action) => {
2307
+ return {
2308
+ ...state,
2309
+ inputValue: action.payload,
2310
+ // When the user is changing the value, show only values that are related to the input value.
2311
+ showAll: false,
2312
+ isOpen: true
2313
+ };
2314
+ };
2366
2315
 
2367
- /**
2368
- * Component default class name and class prefix.
2369
- */
2370
- const CLASSNAME$12 = 'lumx-date-picker';
2316
+ /** Register an option to the state */
2317
+ const ADD_OPTION = (state, action) => {
2318
+ const {
2319
+ id,
2320
+ option
2321
+ } = action.payload;
2322
+ const {
2323
+ options
2324
+ } = state;
2325
+ if (options[id]) {
2326
+ // Option already exists, return state unchanged
2327
+ return state;
2328
+ }
2329
+ const newOptions = {
2330
+ ...options,
2331
+ [id]: option
2332
+ };
2333
+ let newType = state.type;
2334
+ if (isComboboxAction(option)) {
2335
+ newType = 'grid';
2336
+ }
2337
+ let newOptionsLength = state.optionsLength;
2338
+ if (isComboboxValue(option)) {
2339
+ newOptionsLength += 1;
2340
+ }
2341
+ return {
2342
+ ...state,
2343
+ options: newOptions,
2344
+ type: newType,
2345
+ optionsLength: newOptionsLength
2346
+ };
2347
+ };
2371
2348
 
2372
- /** Get first day of week for locale from the browser API */
2373
- const getFromBrowser = locale => {
2374
- try {
2375
- const localeMetadata = new Intl.Locale(locale.code);
2376
- const {
2377
- firstDay
2378
- } = localeMetadata.getWeekInfo?.() || localeMetadata.weekInfo;
2379
- // Sunday is represented as `0` in Date.getDay()
2380
- if (firstDay === 7) return 0;
2381
- return firstDay;
2382
- } catch (e) {
2383
- return undefined;
2349
+ /** Remove an option from the state */
2350
+ const REMOVE_OPTION = (state, action) => {
2351
+ const {
2352
+ id
2353
+ } = action.payload;
2354
+ const {
2355
+ options
2356
+ } = state;
2357
+ const option = options[id];
2358
+ if (!options[id]) {
2359
+ // Option doesn't exist, return state unchanged
2360
+ return state;
2384
2361
  }
2362
+ const newOptions = {
2363
+ ...options
2364
+ };
2365
+ delete newOptions[id];
2366
+ let newOptionsLength = state.optionsLength;
2367
+ if (isComboboxValue(option)) {
2368
+ newOptionsLength -= 1;
2369
+ }
2370
+ return {
2371
+ ...state,
2372
+ options: newOptions,
2373
+ optionsLength: newOptionsLength
2374
+ };
2385
2375
  };
2386
2376
 
2387
- /** List first day for each locale (could be removed when all browser implement Locale weekInfo) */
2388
- const FIRST_DAY_FOR_LOCALES = [{
2389
- // Locales with Sunday as the first day of the week
2390
- localeRX: /^(af|ar-(dz|eg|sa)|bn|cy|en-(ca|us|za)|fr-ca|gd|he|hi|ja|km|ko|pt-br|te|th|ug|zh-hk)$/i,
2377
+ /** Reducers for each action type: */
2378
+ const REDUCERS = {
2379
+ OPEN_COMBOBOX,
2380
+ CLOSE_COMBOBOX,
2381
+ SET_INPUT_VALUE,
2382
+ ADD_OPTION,
2383
+ REMOVE_OPTION
2384
+ };
2385
+
2386
+ /** Main reducer */
2387
+ const reducer$1 = (state, action) => {
2388
+ return REDUCERS[action.type]?.(state, action) || state;
2389
+ };
2390
+
2391
+ /** Dispatch for the combobox component */
2392
+
2393
+ /** Context for the Combobox component */
2394
+ const ComboboxContext = /*#__PURE__*/React__default.createContext({
2395
+ ...initialState,
2396
+ openOnFocus: false,
2397
+ openOnClick: false,
2398
+ selectionType: 'single',
2399
+ optionsLength: 0,
2400
+ onSelect: noop,
2401
+ onInputChange: noop,
2402
+ onOpen: noop,
2403
+ dispatch: noop,
2404
+ translations: {
2405
+ clearLabel: '',
2406
+ tryReloadLabel: '',
2407
+ showSuggestionsLabel: '',
2408
+ noResultsForInputLabel: input => input || '',
2409
+ loadingLabel: '',
2410
+ serviceUnavailableLabel: '',
2411
+ nbOptionsLabel: options => `${options}`
2412
+ }
2413
+ });
2414
+
2415
+ /** Context for a combobox section to store its unique id */
2416
+ const SectionContext = /*#__PURE__*/React__default.createContext({
2417
+ sectionId: ''
2418
+ });
2419
+
2420
+ /** Retrieve the current combobox state and actions */
2421
+ const useCombobox = () => {
2422
+ const comboboxContext = React__default.useContext(ComboboxContext);
2423
+ const {
2424
+ dispatch: movingFocusDispatch
2425
+ } = React__default.useContext(MovingFocusContext);
2426
+ const {
2427
+ onSelect,
2428
+ onInputChange,
2429
+ onOpen,
2430
+ dispatch,
2431
+ inputValue,
2432
+ ...contextValues
2433
+ } = comboboxContext;
2434
+ const {
2435
+ triggerRef
2436
+ } = useComboboxRefs();
2437
+
2438
+ /** Action triggered when the listBox is closed without selecting any option */
2439
+ const handleClose = React__default.useCallback(() => {
2440
+ dispatch({
2441
+ type: 'CLOSE_COMBOBOX'
2442
+ });
2443
+ // Reset visual focus
2444
+ movingFocusDispatch({
2445
+ type: 'RESET_SELECTED_TAB_STOP'
2446
+ });
2447
+ }, [dispatch, movingFocusDispatch]);
2448
+
2449
+ // Handle callbacks on options mounted
2450
+ const [optionsMountedCallbacks, setOptionsMountedCallback] = React__default.useState();
2451
+ React__default.useEffect(() => {
2452
+ if (comboboxContext.optionsLength > 0 && optionsMountedCallbacks?.length) {
2453
+ const optionsArray = Object.values(comboboxContext.options);
2454
+ // Execute callbacks
2455
+ for (const callback of optionsMountedCallbacks) {
2456
+ callback(optionsArray);
2457
+ }
2458
+ setOptionsMountedCallback(undefined);
2459
+ }
2460
+ }, [comboboxContext.options, comboboxContext.optionsLength, optionsMountedCallbacks]);
2461
+
2462
+ /** Callback for when an option is selected */
2463
+ const handleSelected = React__default.useCallback((option, source) => {
2464
+ if (option?.isDisabled) {
2465
+ return;
2466
+ }
2467
+ if (isComboboxValue(option)) {
2468
+ /**
2469
+ * We only close the list if the selection type is single.
2470
+ * If it is multiple, we want to allow the user to continue
2471
+ * selecting multiple options.
2472
+ */
2473
+ if (comboboxContext.selectionType !== 'multiple') {
2474
+ handleClose();
2475
+ }
2476
+ /** Call parent onSelect callback */
2477
+ if (onSelect) {
2478
+ onSelect(option);
2479
+ }
2480
+ }
2481
+
2482
+ /** If the option itself has a custom action, also call it */
2483
+ if (option?.onSelect) {
2484
+ option.onSelect(option, source);
2485
+ }
2486
+
2487
+ /** Reset focus on input */
2488
+ if (triggerRef?.current) {
2489
+ triggerRef.current?.focus();
2490
+ }
2491
+ }, [comboboxContext.selectionType, handleClose, onSelect, triggerRef]);
2492
+
2493
+ /** Callback for when the input must be updated */
2494
+ const handleInputChange = React__default.useCallback((value, ...args) => {
2495
+ // Update the local state
2496
+ dispatch({
2497
+ type: 'SET_INPUT_VALUE',
2498
+ payload: value
2499
+ });
2500
+ // If a callback if given, call it with the value
2501
+ if (onInputChange) {
2502
+ onInputChange(value, ...args);
2503
+ }
2504
+ // Reset visual focus
2505
+ movingFocusDispatch({
2506
+ type: 'RESET_SELECTED_TAB_STOP'
2507
+ });
2508
+ }, [dispatch, movingFocusDispatch, onInputChange]);
2509
+
2510
+ /**
2511
+ * Open the popover
2512
+ *
2513
+ * @returns a promise with the updated context once all options are mounted
2514
+ */
2515
+ const handleOpen = React__default.useCallback(params => {
2516
+ /** update the local state */
2517
+ dispatch({
2518
+ type: 'OPEN_COMBOBOX',
2519
+ payload: params
2520
+ });
2521
+ /** If a parent callback was given, trigger it with state information */
2522
+ if (onOpen) {
2523
+ onOpen({
2524
+ currentValue: inputValue,
2525
+ manual: Boolean(params?.manual)
2526
+ });
2527
+ }
2528
+
2529
+ // Promise resolving options on mount
2530
+ return new Promise(resolve => {
2531
+ // Append to the list of callback on options mounted
2532
+ setOptionsMountedCallback((callbacks = []) => {
2533
+ callbacks.push(resolve);
2534
+ return callbacks;
2535
+ });
2536
+ });
2537
+ }, [dispatch, inputValue, onOpen]);
2538
+ return React__default.useMemo(() => ({
2539
+ handleClose,
2540
+ handleOpen,
2541
+ handleInputChange,
2542
+ handleSelected,
2543
+ dispatch,
2544
+ inputValue,
2545
+ ...contextValues
2546
+ }), [contextValues, dispatch, handleClose, handleInputChange, handleOpen, handleSelected, inputValue]);
2547
+ };
2548
+
2549
+ /**
2550
+ * Provide props for the semantic and behaviors the combobox trigger.
2551
+ *
2552
+ *
2553
+ */
2554
+ function useComboboxTrigger({
2555
+ context,
2556
+ refs,
2557
+ onBlur,
2558
+ onFocus,
2559
+ onKeyDown
2560
+ }) {
2561
+ const {
2562
+ comboboxId,
2563
+ listboxId,
2564
+ isOpen,
2565
+ options,
2566
+ optionsLength,
2567
+ selectedIds,
2568
+ openOnFocus,
2569
+ handleClose,
2570
+ handleOpen,
2571
+ handleSelected,
2572
+ showEmptyState = false,
2573
+ showErrorState = false,
2574
+ status
2575
+ } = context;
2576
+ const highlightedId = useVirtualFocusParent(refs.triggerRef);
2577
+ const {
2578
+ dispatch: movingFocusDispatch
2579
+ } = React__default.useContext(MovingFocusContext);
2580
+ const isErrorStateDisplayed = showErrorState && isOpen && status === 'error';
2581
+ const isEmptyStateDisplayed = showEmptyState && isOpen && status === 'idle' && optionsLength === 0;
2582
+ const showPopover = isOpen && optionsLength > 0 || isEmptyStateDisplayed || isErrorStateDisplayed;
2583
+
2584
+ /**
2585
+ * A debounce close to use to leave time for the
2586
+ * listbox to process things before closing.
2587
+ * This can be useful when clicking an option to leave time for the
2588
+ * event to be processed before closing the popover.
2589
+ */
2590
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2591
+ const debouncedClose = React__default.useCallback(debounce$1(handleClose, 200), []);
2592
+
2593
+ /** Cleanup any ongoing cleanup */
2594
+ React__default.useEffect(() => {
2595
+ return () => {
2596
+ if (debouncedClose?.cancel) {
2597
+ debouncedClose.cancel();
2598
+ }
2599
+ };
2600
+ }, [debouncedClose]);
2601
+ const handleBlur = React__default.useCallback(event => {
2602
+ debouncedClose();
2603
+ if (onBlur) {
2604
+ onBlur(event);
2605
+ }
2606
+ }, [debouncedClose, onBlur]);
2607
+
2608
+ /** Actions triggered when the input field is focused */
2609
+ const handleFocus = event => {
2610
+ // If the field is refocused in the process of closing, cancel close
2611
+ if (debouncedClose?.cancel) {
2612
+ debouncedClose.cancel();
2613
+ }
2614
+ if (onFocus) {
2615
+ onFocus(event);
2616
+ }
2617
+ /**
2618
+ * Only set the open on focus if the combobox isn't already opened.
2619
+ * This avoids the popover re-opening when an option is selected and the
2620
+ * field is refocused
2621
+ */
2622
+ if (openOnFocus && !showPopover) {
2623
+ handleOpen({
2624
+ manual: true
2625
+ });
2626
+ }
2627
+ };
2628
+ const handleClick = () => {
2629
+ handleOpen({
2630
+ manual: true
2631
+ });
2632
+ };
2633
+
2634
+ /**
2635
+ * Keyboard shortcut management following the WAI APG pattern
2636
+ * https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-autocomplete-list/#kbd_label
2637
+ */
2638
+ const handleKeyDown = React__default.useCallback(async event => {
2639
+ const {
2640
+ key,
2641
+ altKey
2642
+ } = event;
2643
+
2644
+ /**
2645
+ * On Enter key
2646
+ * * Select option that is currently highlighted, if any
2647
+ * * Close suggestions, event if none is highlighted
2648
+ */
2649
+ if (event.key === 'Enter') {
2650
+ if (!showPopover) {
2651
+ return;
2652
+ }
2653
+ if (highlightedId) {
2654
+ // prevent any potential form submission
2655
+ event.preventDefault();
2656
+ const option = options[highlightedId];
2657
+ handleSelected(option, 'keyboard');
2658
+ } else {
2659
+ handleClose();
2660
+ }
2661
+ return;
2662
+ }
2663
+
2664
+ /**
2665
+ * On arrow up/down
2666
+ * * If popover is already opened, do nothing
2667
+ * * If alt key pressed, show the listbox without focusing an option
2668
+ * * If arrow Up is pressed, select last option
2669
+ * * If arrow Down is pressed, select first option
2670
+ * */
2671
+ if (key === 'ArrowDown' || key === 'ArrowUp') {
2672
+ if (showPopover) {
2673
+ return;
2674
+ }
2675
+
2676
+ /** Open the listbox */
2677
+ const listBoxOptions = await handleOpen({
2678
+ manual: true
2679
+ });
2680
+ if (!listBoxOptions) {
2681
+ return;
2682
+ }
2683
+
2684
+ /**
2685
+ * If alt key is pressed, only open without changing visual focus
2686
+ * as per WAI Guidelines
2687
+ */
2688
+ if (!altKey) {
2689
+ /** If a selected id is set, set it as current tabstop */
2690
+ if (selectedIds?.length) {
2691
+ movingFocusDispatch({
2692
+ type: 'SELECT_TAB_STOP',
2693
+ payload: {
2694
+ id: selectedIds?.[0],
2695
+ type: 'keyboard'
2696
+ }
2697
+ });
2698
+ } else {
2699
+ /** Focus either the first or last item depending on the keyboard arrow pressed */
2700
+ movingFocusDispatch({
2701
+ type: 'KEY_NAV',
2702
+ payload: {
2703
+ ctrlKey: false,
2704
+ key: key === 'ArrowUp' ? 'End' : 'Home'
2705
+ }
2706
+ });
2707
+ }
2708
+ }
2709
+ return;
2710
+ }
2711
+
2712
+ // Forward event
2713
+ onKeyDown?.(event);
2714
+ }, [onKeyDown, showPopover, highlightedId, options, handleSelected, handleClose, handleOpen, selectedIds, movingFocusDispatch]);
2715
+ return {
2716
+ id: comboboxId,
2717
+ role: 'combobox',
2718
+ 'aria-activedescendant': showPopover && highlightedId ? highlightedId : '',
2719
+ 'aria-controls': listboxId,
2720
+ 'aria-owns': listboxId,
2721
+ 'aria-expanded': showPopover,
2722
+ onFocus: handleFocus,
2723
+ onBlur: handleBlur,
2724
+ onClick: handleClick,
2725
+ onKeyDown: handleKeyDown
2726
+ };
2727
+ }
2728
+
2729
+ /** Is printable character key press */
2730
+ const isTypeEvent = ({
2731
+ key,
2732
+ altKey,
2733
+ ctrlKey,
2734
+ metaKey
2735
+ }) => key.length === 1 && key !== ' ' && !altKey && !ctrlKey && !metaKey;
2736
+
2737
+ /**
2738
+ * Provide props for the semantic and behaviors the combobox button trigger
2739
+ *
2740
+ * Overrides the useComboboxTrigger() props & behavior to add a jump to option
2741
+ * on printable character key down.
2742
+ */
2743
+ function useComboboxButton(args) {
2744
+ const {
2745
+ context: {
2746
+ handleOpen
2747
+ },
2748
+ onKeyDown: parentOnKeyDown
2749
+ } = args;
2750
+ const {
2751
+ dispatch: movingFocusDispatch,
2752
+ state: {
2753
+ selectedId: highlightedId
2754
+ }
2755
+ } = React__default.useContext(MovingFocusContext);
2756
+ const searchValueRef = React__default.useRef('');
2757
+ const searchTimeoutRef = React__default.useRef();
2758
+ const onKeyDown = React__default.useMemo(() => {
2759
+ function clearSearchTimeout() {
2760
+ const searchTimeout = searchTimeoutRef.current;
2761
+ if (!searchTimeout) {
2762
+ return;
2763
+ }
2764
+ clearTimeout(searchTimeout);
2765
+ searchTimeoutRef.current = undefined;
2766
+ }
2767
+ function clearSearch() {
2768
+ searchValueRef.current = '';
2769
+ clearSearchTimeout();
2770
+ }
2771
+ return async event => {
2772
+ if (!isTypeEvent(event)) {
2773
+ // Forward key down event
2774
+ parentOnKeyDown?.(event);
2775
+ return undefined;
2776
+ }
2777
+ event.stopPropagation();
2778
+
2779
+ // Clear current search timeout
2780
+ clearSearchTimeout();
2781
+
2782
+ // Open combobox and wait for options to mount
2783
+ const options = await handleOpen({
2784
+ manual: false
2785
+ });
2786
+ const optionArray = options && Object.values(options);
2787
+ if (!optionArray?.length) {
2788
+ return undefined;
2789
+ }
2790
+
2791
+ // Append key to current search
2792
+ searchValueRef.current += event.key.toLowerCase();
2793
+ const searchValue = searchValueRef.current;
2794
+
2795
+ // Clear search after 500ms
2796
+ searchTimeoutRef.current = setTimeout(clearSearch, 500);
2797
+
2798
+ // Search is containing all the same letters (ex: aaaa)
2799
+ const allTheSameLetters = searchValue.split('').every(letter => letter === searchValue[0]);
2800
+
2801
+ // start from currently selected option
2802
+ let startIndex = optionArray.findIndex(option => option.generatedId === highlightedId);
2803
+ if (startIndex === -1) {
2804
+ startIndex = 0;
2805
+ }
2806
+ let index = startIndex;
2807
+ do {
2808
+ // Increment index and loop around to 0 if we get over the array length
2809
+ index = (index + 1) % optionArray.length;
2810
+ const option = optionArray[index];
2811
+ // Search by text value or fallback on id.
2812
+ const optionText = isComboboxValue(option) ? option?.textValue || option?.id : null;
2813
+ if (isComboboxValue(option) && optionText) {
2814
+ const optionTextValue = optionText.toLowerCase();
2815
+
2816
+ // Search on first letter if search is all the same letters
2817
+ const searchText = allTheSameLetters ? searchValue[0] : searchValue;
2818
+
2819
+ // Option text value starts with searched text
2820
+ if (optionTextValue.startsWith(searchText)) {
2821
+ movingFocusDispatch({
2822
+ type: 'SELECT_TAB_STOP',
2823
+ payload: {
2824
+ id: option.generatedId,
2825
+ type: 'keyboard'
2826
+ }
2827
+ });
2828
+ break;
2829
+ }
2830
+ }
2831
+ } while (index !== startIndex);
2832
+ return clearSearchTimeout;
2833
+ };
2834
+ }, [handleOpen, parentOnKeyDown, highlightedId, movingFocusDispatch]);
2835
+ return useComboboxTrigger({
2836
+ ...args,
2837
+ onKeyDown
2838
+ });
2839
+ }
2840
+
2841
+ /**
2842
+ * Combobox button trigger.
2843
+ *
2844
+ * @family Combobox
2845
+ */
2846
+ const ComboboxButton = forwardRef((props, ref) => {
2847
+ const {
2848
+ as,
2849
+ label,
2850
+ onFocus,
2851
+ onBlur,
2852
+ labelDisplayMode = 'show-selection',
2853
+ ...forwardedProps
2854
+ } = props;
2855
+ const refs = useComboboxRefs();
2856
+ const context = useCombobox();
2857
+ const buttonProps = useComboboxButton({
2858
+ context,
2859
+ refs,
2860
+ onBlur,
2861
+ onFocus
2862
+ });
2863
+ const Element = as || Button;
2864
+ const showSelection = labelDisplayMode === 'show-selection';
2865
+ const tooltipOnly = labelDisplayMode === 'show-tooltip';
2866
+ const selectionLabel = showSelection && context.selectedIds?.length && context.inputValue;
2867
+ let content = null;
2868
+ if (!tooltipOnly) {
2869
+ // Display selection label or label
2870
+ content = selectionLabel || label;
2871
+ }
2872
+ const hideTooltip =
2873
+ // Hide tooltip if the displayed label and tooltip label are the same
2874
+ label === content ||
2875
+ // Hide tooltip when the combobox is open
2876
+ context.isOpen;
2877
+ const mergedRefs = useMergeRefs(ref, refs.triggerRef, refs.anchorRef);
2878
+ return /*#__PURE__*/jsx(Tooltip, {
2879
+ className: hideTooltip ? visuallyHidden() : undefined,
2880
+ label: label,
2881
+ closeMode: "hide",
2882
+ ariaLinkMode: "aria-labelledby",
2883
+ children: /*#__PURE__*/jsx(Element, {
2884
+ ref: mergedRefs,
2885
+ ...forwardedProps,
2886
+ ...buttonProps,
2887
+ children: content
2888
+ })
2889
+ });
2890
+ });
2891
+
2892
+ const CLASSNAME$18 = 'lumx-combobox-divider';
2893
+
2894
+ /** Combobox option divider */
2895
+ function ComboboxDivider() {
2896
+ return /*#__PURE__*/jsx(ListDivider, {
2897
+ className: CLASSNAME$18,
2898
+ role: "presentation"
2899
+ });
2900
+ }
2901
+
2902
+ /**
2903
+ * Provide props for the semantic and behaviors the combobox input trigger
2904
+ *
2905
+ * Overrides the useComboboxTrigger() props & behavior to prevent open on click
2906
+ * if `openOnFocus` is not enabled.
2907
+ */
2908
+ function useComboboxInput({
2909
+ onKeyDown: propsOnKeyDown,
2910
+ ...args
2911
+ }) {
2912
+ const triggerProps = useComboboxTrigger(args);
2913
+ const {
2914
+ onClick,
2915
+ onKeyDown,
2916
+ 'aria-expanded': showPopover
2917
+ } = triggerProps;
2918
+ const handleClick = () => {
2919
+ if (!args.context.openOnFocus && !args.context.openOnClick) {
2920
+ // Skip if input should not opening on focus nor click
2921
+ return;
2922
+ }
2923
+ onClick();
2924
+ };
2925
+ const handleKeyDown = evt => {
2926
+ if (evt.key === 'Escape') {
2927
+ // Reset field if closed
2928
+ if (!showPopover) {
2929
+ args.context.handleInputChange('');
2930
+ }
2931
+ return;
2932
+ }
2933
+ onKeyDown(evt);
2934
+ if (propsOnKeyDown) {
2935
+ propsOnKeyDown(evt);
2936
+ }
2937
+ };
2938
+ return {
2939
+ ...triggerProps,
2940
+ onClick: handleClick,
2941
+ onKeyDown: handleKeyDown
2942
+ };
2943
+ }
2944
+
2945
+ /**
2946
+ * Combobox input trigger.
2947
+ *
2948
+ * @family Combobox
2949
+ */
2950
+ const ComboboxInput = ({
2951
+ hideToggle,
2952
+ inputRef,
2953
+ textFieldRef,
2954
+ afterElement,
2955
+ onFocus,
2956
+ onBlur,
2957
+ onKeyDown,
2958
+ clearButtonProps,
2959
+ hasClearButton,
2960
+ theme,
2961
+ ...textFieldProps
2962
+ }) => {
2963
+ const refs = useComboboxRefs();
2964
+ const context = useCombobox();
2965
+ const inputProps = useComboboxInput({
2966
+ refs,
2967
+ context,
2968
+ onBlur,
2969
+ onFocus,
2970
+ onKeyDown
2971
+ });
2972
+ const {
2973
+ listboxId,
2974
+ isOpen,
2975
+ handleOpen,
2976
+ handleClose,
2977
+ inputValue,
2978
+ handleInputChange
2979
+ } = context;
2980
+
2981
+ /** Callback for when the toggle button is trigged */
2982
+ const handleManualToggle = () => {
2983
+ if (isOpen) {
2984
+ handleClose();
2985
+ } else {
2986
+ handleOpen({
2987
+ manual: true
2988
+ });
2989
+ }
2990
+ refs.triggerRef?.current?.focus();
2991
+ };
2992
+ return /*#__PURE__*/jsx(TextField
2993
+ // Disable native autocomplete
2994
+ , {
2995
+ autoComplete: "off",
2996
+ ...textFieldProps,
2997
+ inputRef: mergeRefs(refs.triggerRef, inputRef),
2998
+ textFieldRef: mergeRefs(refs.anchorRef, textFieldRef)
2999
+ // Combobox props
3000
+ ,
3001
+ ...inputProps,
3002
+ theme: theme,
3003
+ value: inputValue,
3004
+ onClear: () => handleInputChange(''),
3005
+ onChange: handleInputChange,
3006
+ clearButtonProps: hasClearButton ? {
3007
+ ...clearButtonProps,
3008
+ label: context.translations.clearLabel
3009
+ } : undefined,
3010
+ afterElement: (!hideToggle || afterElement) && /*#__PURE__*/jsxs(Fragment, {
3011
+ children: [afterElement, !hideToggle && /*#__PURE__*/jsx(IconButton, {
3012
+ theme: theme,
3013
+ onClick: handleManualToggle,
3014
+ label: context.translations.showSuggestionsLabel,
3015
+ emphasis: Emphasis$1.low,
3016
+ size: Size$1.s,
3017
+ icon: inputProps['aria-expanded'] ? mdiChevronUp : mdiChevronDown,
3018
+ type: "button",
3019
+ tabIndex: -1,
3020
+ "aria-expanded": inputProps['aria-expanded'],
3021
+ "aria-haspopup": "listbox",
3022
+ "aria-controls": listboxId
3023
+ })]
3024
+ })
3025
+ });
3026
+ };
3027
+
3028
+ const ComboboxOptionContext = /*#__PURE__*/createContext({});
3029
+ /** Context Provider to store the current combobox option id. */
3030
+ const ComboboxOptionContextProvider = ({
3031
+ optionId,
3032
+ isKeyboardHighlighted,
3033
+ children
3034
+ }) => {
3035
+ const value = React__default.useMemo(() => ({
3036
+ optionId,
3037
+ isKeyboardHighlighted
3038
+ }), [optionId, isKeyboardHighlighted]);
3039
+ return /*#__PURE__*/jsx(ComboboxOptionContext.Provider, {
3040
+ value: value,
3041
+ children: children
3042
+ });
3043
+ };
3044
+
3045
+ /**
3046
+ * Retrieve the current combobox option id.
3047
+ * Must be used within a ComboboxOptionIdProvider
3048
+ */
3049
+ const useComboboxOptionContext = () => {
3050
+ const comboboxOption = useContext(ComboboxOptionContext);
3051
+ if (!comboboxOption?.optionId) {
3052
+ throw new Error('This hook must be used within a ComboboxOptionIdProvider');
3053
+ }
3054
+ return comboboxOption;
3055
+ };
3056
+
3057
+ /** Retrieve the current combobox section id */
3058
+ const useComboboxSectionId = () => {
3059
+ return useContext(SectionContext);
3060
+ };
3061
+
3062
+ /**
3063
+ * Register the given option to the context
3064
+ */
3065
+ const useRegisterOption = (registerId, option, shouldRegister) => {
3066
+ const {
3067
+ dispatch
3068
+ } = useCombobox();
3069
+
3070
+ /** Register the given options */
3071
+ React__default.useEffect(() => {
3072
+ if (option && shouldRegister) {
3073
+ dispatch({
3074
+ type: 'ADD_OPTION',
3075
+ payload: {
3076
+ id: registerId,
3077
+ option
3078
+ }
3079
+ });
3080
+ }
3081
+
3082
+ // Unregister ids if/when the component unmounts or if option changes
3083
+ return () => {
3084
+ if (option) {
3085
+ dispatch({
3086
+ type: 'REMOVE_OPTION',
3087
+ payload: {
3088
+ id: registerId
3089
+ }
3090
+ });
3091
+ }
3092
+ };
3093
+ }, [dispatch, option, registerId, shouldRegister]);
3094
+ };
3095
+
3096
+ /* eslint-disable jsx-a11y/click-events-have-key-events */
3097
+ const CLASSNAME$17 = 'lumx-combobox-option';
3098
+ const LUMX_CLASSNAME = 'lumx-list-item';
3099
+ const {
3100
+ block: block$_,
3101
+ element: element$M
3102
+ } = classNames.bem(CLASSNAME$17);
3103
+ const lumxListItem = classNames.bem(LUMX_CLASSNAME);
3104
+
3105
+ /**
3106
+ * Content of the option.
3107
+ * This should only be rendered if the option is shown.
3108
+ */
3109
+ const OptionContent = forwardRef((props, ref) => {
3110
+ const {
3111
+ id,
3112
+ onSelect,
3113
+ isSelected,
3114
+ isDisabled,
3115
+ children,
3116
+ className,
3117
+ before,
3118
+ after,
3119
+ as,
3120
+ size = Size$1.tiny,
3121
+ comboboxType,
3122
+ tooltipProps,
3123
+ description,
3124
+ 'aria-hidden': ariaHidden,
3125
+ autofocus,
3126
+ ...forwardedProps
3127
+ } = props;
3128
+ const itemRef = React__default.useRef(null);
3129
+ const {
3130
+ state
3131
+ } = React__default.useContext(MovingFocusContext);
3132
+ const {
3133
+ selectedIds
3134
+ } = useCombobox();
3135
+ const hasSelection = selectedIds !== undefined;
3136
+ const isHighlighted = useVirtualFocus(id, itemRef, false, comboboxType === 'grid' ? id : undefined, autofocus);
3137
+ const Element = as || 'span';
3138
+ const ariaSelected = isSelected ? 'true' : 'false';
3139
+ const ariaDescriptionId = description ? `${id}-description` : undefined;
3140
+ const isKeyboardHighlighted = state.isUsingKeyboard && isHighlighted;
3141
+
3142
+ /**
3143
+ * The DS `ListItem` component has a lot of behavior / default props we do not want here.
3144
+ * Notably the before/after items are within the interactive element, which we do not want.
3145
+ * So we use a native li tag.
3146
+ */
3147
+ return /*#__PURE__*/jsx("li", {
3148
+ className: block$_(undefined, [className ?? '', lumxListItem.block({
3149
+ [`size-${size}`]: !!size
3150
+ })]),
3151
+ role: "presentation",
3152
+ ref: itemRef,
3153
+ "aria-hidden": ariaHidden,
3154
+ style: {
3155
+ display: ariaHidden ? 'none' : undefined
3156
+ },
3157
+ ...forwardedProps,
3158
+ children: /*#__PURE__*/jsxs(GenericBlock, {
3159
+ as: "div",
3160
+ role: comboboxType === 'grid' ? 'row' : 'presentation',
3161
+ className: element$M('content', {
3162
+ // Not using the lumx list item disabled style as it blocks pointer events
3163
+ 'is-disabled': !!isDisabled
3164
+ },
3165
+ // TODO: migrate away from using lumx-list-item styles https://lumapps.atlassian.net/browse/DSW-288
3166
+ [lumxListItem.element('link', {
3167
+ 'is-selected': Boolean(isSelected),
3168
+ 'is-highlighted': Boolean(isHighlighted)
3169
+ })]),
3170
+ "data-focus-visible-added": isKeyboardHighlighted ? 'true' : undefined,
3171
+ children: [before && /*#__PURE__*/jsx(GenericBlock.Figure, {
3172
+ as: "span",
3173
+ role: "presentation",
3174
+ className: element$M('before', undefined, [lumxListItem.element('before')]),
3175
+ children: before
3176
+ }), /*#__PURE__*/jsxs(GenericBlock.Content, {
3177
+ as: "span",
3178
+ role: "presentation",
3179
+ className: lumxListItem.element('content'),
3180
+ children: [/*#__PURE__*/jsx(Tooltip, {
3181
+ forceOpen: isKeyboardHighlighted,
3182
+ closeMode: "hide",
3183
+ ...tooltipProps,
3184
+ children: /*#__PURE__*/jsx(Element, {
3185
+ id: id,
3186
+ className: element$M('trigger'),
3187
+ role: comboboxType === 'grid' ? 'gridcell' : 'option',
3188
+ "aria-selected": hasSelection ? ariaSelected : undefined,
3189
+ "aria-disabled": isDisabled,
3190
+ "aria-describedby": ariaDescriptionId,
3191
+ onClick: onSelect
3192
+ // Prevent mouse down to avoid blur before the click is activated
3193
+ ,
3194
+ onMouseDown: event => event.preventDefault(),
3195
+ ref: ref,
3196
+ ...forwardedProps,
3197
+ children: children
3198
+ })
3199
+ }), description && /*#__PURE__*/jsx(Text, {
3200
+ as: "span",
3201
+ id: ariaDescriptionId,
3202
+ role: "presentation",
3203
+ className: element$M('description'),
3204
+ typography: "caption",
3205
+ color: "dark",
3206
+ colorVariant: "L2",
3207
+ children: description
3208
+ })]
3209
+ }), after && /*#__PURE__*/jsx(GenericBlock.Actions, {
3210
+ as: "span",
3211
+ role: "presentation",
3212
+ className: element$M('after', undefined, [lumxListItem.element('after')]),
3213
+ children: /*#__PURE__*/jsx(ComboboxOptionContextProvider, {
3214
+ optionId: id,
3215
+ isKeyboardHighlighted: isKeyboardHighlighted,
3216
+ children: after
3217
+ })
3218
+ })]
3219
+ })
3220
+ });
3221
+ });
3222
+
3223
+ /**
3224
+ * Props for ComboboxOption with additional generic properties.
3225
+ */
3226
+
3227
+ /**
3228
+ * Option to set within a combobox list.
3229
+ *
3230
+ * @family Combobox
3231
+ * @param ComboboxOptionProps
3232
+ * @returns ComboboxOption
3233
+ */
3234
+ const ComboboxOption = forwardRef((props, ref) => {
3235
+ const {
3236
+ children,
3237
+ id,
3238
+ textValue,
3239
+ data,
3240
+ filterFromInput = true,
3241
+ onSelect: onOptionSelect,
3242
+ isDisabled,
3243
+ as = 'span',
3244
+ ...optionProps
3245
+ } = props;
3246
+
3247
+ // Get the id of the current group, if any.
3248
+ const section = useComboboxSectionId();
3249
+ const {
3250
+ comboboxId,
3251
+ selectedIds,
3252
+ showAll,
3253
+ inputValue,
3254
+ handleSelected,
3255
+ type
3256
+ } = useCombobox();
3257
+ // Generate a unique id for this option.
3258
+ const generatedId = generateOptionId(comboboxId, id);
3259
+ const isSelected = selectedIds?.includes(generatedId);
3260
+
3261
+ // If no text value is set and the direct child is a simple string, use it as value.
3262
+ const isStringChild = typeof children === 'string' || typeof children === 'number';
3263
+ const value = children && !textValue && isStringChild ? children.toString() : textValue;
3264
+ const showOption = !filterFromInput || showAll || value?.toString()?.toLowerCase().includes(inputValue?.toLowerCase());
3265
+ const registeredOption = React__default.useMemo(() => ({
3266
+ id,
3267
+ generatedId,
3268
+ textValue: value,
3269
+ data,
3270
+ filter: filterFromInput,
3271
+ isDisabled: isDisabled || !showOption,
3272
+ sectionId: section.sectionId,
3273
+ onSelect: onOptionSelect
3274
+ }), [data, filterFromInput, generatedId, section.sectionId, id, isDisabled, onOptionSelect, showOption, value]);
3275
+
3276
+ // Register the option
3277
+ useRegisterOption(generatedId, registeredOption, showOption);
3278
+ const handleSelect = React__default.useCallback(() => handleSelected(registeredOption, 'click'), [handleSelected, registeredOption]);
3279
+ if (!id || !showOption) {
3280
+ return null;
3281
+ }
3282
+ return /*#__PURE__*/jsx(OptionContent, {
3283
+ id: generatedId,
3284
+ onSelect: handleSelect,
3285
+ isSelected: isSelected,
3286
+ isDisabled: isDisabled,
3287
+ as: as,
3288
+ ref: ref,
3289
+ comboboxType: type,
3290
+ "aria-hidden": section.isLoading,
3291
+ ...optionProps,
3292
+ children: children || textValue
3293
+ });
3294
+ });
3295
+
3296
+ // Default widths the skeletons must have
3297
+ const defaultWidths = [REAL_SIZE_FOR_LUMX_SIZE.xxl, REAL_SIZE_FOR_LUMX_SIZE.xl, REAL_SIZE_FOR_LUMX_SIZE.l];
3298
+ const {
3299
+ block: block$Z,
3300
+ element: element$L
3301
+ } = classNames.bem(CLASSNAME$17);
3302
+
3303
+ /**
3304
+ * Skeleton for a combobox option.
3305
+ * A typography skeleton is rendered by default but can be overridden by passing children.
3306
+ */
3307
+ const ComboboxOptionSkeleton = ({
3308
+ className,
3309
+ index,
3310
+ before,
3311
+ after,
3312
+ size = Size$1.tiny,
3313
+ children
3314
+ }) => {
3315
+ const renderedChildren = typeof children === 'function' ? children({
3316
+ index
3317
+ }) : children;
3318
+ const content = renderedChildren || /*#__PURE__*/jsx(SkeletonTypography, {
3319
+ typography: "body1",
3320
+ width: index !== undefined && defaultWidths[index] ? defaultWidths[index] : REAL_SIZE_FOR_LUMX_SIZE.xl
3321
+ });
3322
+ return /*#__PURE__*/jsxs("li", {
3323
+ role: "presentation",
3324
+ className: block$Z({
3325
+ skeleton: true
3326
+ }, ['lumx-list-item', `lumx-list-item--size-${size}`, className]),
3327
+ children: [/*#__PURE__*/jsxs("div", {
3328
+ role: "presentation",
3329
+ className: element$L('content', ['lumx-list-item__wrapper']),
3330
+ children: [before && /*#__PURE__*/jsx(Text, {
3331
+ as: "span",
3332
+ role: "presentation",
3333
+ className: element$L('before', ['lumx-list-item__before']),
3334
+ children: before
3335
+ }), content]
3336
+ }), after && /*#__PURE__*/jsx("div", {
3337
+ role: "presentation",
3338
+ className: element$L('after', ['lumx-list-item__after']),
3339
+ children: after
3340
+ })]
3341
+ });
3342
+ };
3343
+
3344
+ /** Default skeleton for the options list of the combobox */
3345
+ const ComboboxListSkeleton = ({
3346
+ isLoadingMore,
3347
+ children
3348
+ }) => /*#__PURE__*/jsx(Fragment, {
3349
+ children: Array.from({
3350
+ length: isLoadingMore ? 1 : 3
3351
+ }).map((_, index) => {
3352
+ const renderedChildren = typeof children === 'function' ? children({
3353
+ index
3354
+ }) : children || /*#__PURE__*/jsx(ComboboxOptionSkeleton, {
3355
+ index: index
3356
+ });
3357
+ return (
3358
+ /*#__PURE__*/
3359
+ // eslint-disable-next-line react/no-array-index-key
3360
+ jsx(React__default.Fragment, {
3361
+ children: renderedChildren
3362
+ }, index)
3363
+ );
3364
+ })
3365
+ });
3366
+
3367
+ /** The states in which the full loading must be displayed */
3368
+ const FULL_LOADING_STATES = ['loading', 'debouncing', 'filtering'];
3369
+ const CLASSNAME$16 = 'lumx-combobox-listbox';
3370
+ const {
3371
+ block: block$Y,
3372
+ element: element$K
3373
+ } = bem$1(CLASSNAME$16);
3374
+
3375
+ /**
3376
+ * The listbox containing the combobox's options.
3377
+ *
3378
+ * @family Combobox
3379
+ * @param ComboboxListBoxProps
3380
+ * @returns ComboboxListBox
3381
+ */
3382
+ const ComboboxListBox = ({
3383
+ children,
3384
+ renderItemSkeleton,
3385
+ label,
3386
+ popoverProps,
3387
+ footer,
3388
+ listRef,
3389
+ ...forwardedProps
3390
+ }) => {
3391
+ const {
3392
+ status,
3393
+ listboxId,
3394
+ isOpen,
3395
+ optionsLength,
3396
+ handleClose: contextHandleClose,
3397
+ type,
3398
+ inputValue,
3399
+ showEmptyState,
3400
+ showErrorState,
3401
+ translations
3402
+ } = useCombobox();
3403
+ const {
3404
+ anchorRef
3405
+ } = useComboboxRefs();
3406
+ const {
3407
+ onClose,
3408
+ ...otherPopoverProps
3409
+ } = popoverProps || {};
3410
+ const {
3411
+ style,
3412
+ className,
3413
+ ...listProps
3414
+ } = forwardedProps;
3415
+ // The states to show a full skeleton instead of the options
3416
+ const showFullLoading = FULL_LOADING_STATES.includes(status);
3417
+ const isErrorStateDisplayed = showErrorState && isOpen && status === 'error';
3418
+ const isEmptyStateDisplayed = showEmptyState && isOpen && status === 'idle' && optionsLength === 0;
3419
+
3420
+ /**
3421
+ * The conditions in which we want to show the content of the popover
3422
+ * * The parent asked for the popover to be opened
3423
+ * * There is at least one option to displayed OR a skeleton
3424
+ */
3425
+ const showPopover = isOpen && (optionsLength > 0 || showFullLoading) || isEmptyStateDisplayed || isErrorStateDisplayed;
3426
+ const handleClose = () => {
3427
+ if (isOpen) {
3428
+ contextHandleClose?.();
3429
+ onClose?.();
3430
+ }
3431
+ };
3432
+ const emptyMessage = translations.noResultsForInputLabel(inputValue);
3433
+ return /*#__PURE__*/jsxs(Fragment, {
3434
+ children: [/*#__PURE__*/jsxs(Text, {
3435
+ as: "p",
3436
+ className: visuallyHidden(),
3437
+ role: "log",
3438
+ "aria-live": "assertive",
3439
+ children: [isOpen && !showFullLoading && !isEmptyStateDisplayed && !isErrorStateDisplayed && translations.nbOptionsLabel(optionsLength), isErrorStateDisplayed && `${translations.serviceUnavailableLabel} ${translations.tryReloadLabel}`, showFullLoading && translations.loadingLabel, isEmptyStateDisplayed && emptyMessage]
3440
+ }), /*#__PURE__*/jsx(Popover, {
3441
+ role: "none",
3442
+ onClose: handleClose,
3443
+ anchorRef: anchorRef,
3444
+ fitToAnchorWidth: true,
3445
+ fitWithinViewportHeight: true,
3446
+ closeOnEscape: true,
3447
+ closeOnClickAway: true,
3448
+ placement: Placement.BOTTOM,
3449
+ isOpen: isOpen,
3450
+ ...otherPopoverProps,
3451
+ children: /*#__PURE__*/jsxs("div", {
3452
+ style: {
3453
+ ...style,
3454
+ overflowY: 'auto',
3455
+ display: showPopover ? 'flex' : 'none',
3456
+ flexDirection: 'column'
3457
+ },
3458
+ children: [/*#__PURE__*/jsxs("ul", {
3459
+ ref: listRef,
3460
+ id: listboxId,
3461
+ role: type,
3462
+ "aria-label": label,
3463
+ className: block$Y([className, 'lumx-list lumx-list--item-padding-big']),
3464
+ style: {
3465
+ flex: 1,
3466
+ overflowY: 'auto'
3467
+ },
3468
+ ...listProps,
3469
+ children: [!showFullLoading && children, [...FULL_LOADING_STATES, 'loadingMore'].includes(status) && /*#__PURE__*/jsx(ComboboxListSkeleton, {
3470
+ isLoadingMore: status === 'loadingMore',
3471
+ children: renderItemSkeleton
3472
+ })]
3473
+ }), footer, (isEmptyStateDisplayed || isErrorStateDisplayed) && /*#__PURE__*/jsx(GenericBlock, {
3474
+ className: element$K('state'),
3475
+ orientation: "vertical",
3476
+ vAlign: "center",
3477
+ children: /*#__PURE__*/jsxs(GenericBlock.Content, {
3478
+ children: [inputValue && isEmptyStateDisplayed && /*#__PURE__*/jsx(Text, {
3479
+ as: "p",
3480
+ typography: "body1",
3481
+ color: "dark",
3482
+ colorVariant: "L2",
3483
+ dangerouslySetInnerHTML: {
3484
+ __html: translations.noResultsForInputLabel(inputValue)
3485
+ }
3486
+ }), !inputValue && isEmptyStateDisplayed && /*#__PURE__*/jsx(Text, {
3487
+ as: "p",
3488
+ typography: "body1",
3489
+ color: "dark",
3490
+ colorVariant: "L2",
3491
+ children: translations.noResultsForInputLabel()
3492
+ }), isErrorStateDisplayed && /*#__PURE__*/jsxs(Fragment, {
3493
+ children: [/*#__PURE__*/jsx(Heading, {
3494
+ as: "h2",
3495
+ typography: "subtitle2",
3496
+ children: translations.serviceUnavailableLabel
3497
+ }), /*#__PURE__*/jsx(Text, {
3498
+ as: "p",
3499
+ typography: "body1",
3500
+ color: "dark",
3501
+ colorVariant: "L2",
3502
+ children: translations.tryReloadLabel
3503
+ })]
3504
+ })]
3505
+ })
3506
+ })]
3507
+ })
3508
+ })]
3509
+ });
3510
+ };
3511
+
3512
+ /**
3513
+ * Action to set on a Combobox Option.
3514
+ * Allows to add an interactive element that
3515
+ * can be navigated to and triggered using the keyboard.
3516
+ *
3517
+ * Defaults as "button"
3518
+ *
3519
+ * @family Combobox
3520
+ * @param ComboboxOptionActionProps
3521
+ * @returns ComboboxOptionAction
3522
+ */
3523
+ const ComboboxOptionAction = props => {
3524
+ const {
3525
+ as,
3526
+ isDisabled,
3527
+ onClick,
3528
+ id: originalId,
3529
+ ...forwardedProps
3530
+ } = props;
3531
+ const {
3532
+ optionId
3533
+ } = useComboboxOptionContext();
3534
+ const {
3535
+ triggerRef
3536
+ } = useComboboxRefs();
3537
+ const itemRef = React__default.useRef(null);
3538
+ const generatedId = useId();
3539
+ const id = originalId || generatedId;
3540
+ const isHighlighted = useVirtualFocus(id, itemRef, isDisabled, optionId);
3541
+ const {
3542
+ state
3543
+ } = React__default.useContext(MovingFocusContext);
3544
+ const Component = as || 'button';
3545
+ const registeredActionOption = React__default.useMemo(() => ({
3546
+ id,
3547
+ generatedId: id,
3548
+ isAction: true,
3549
+ isDisabled,
3550
+ onSelect: () => {
3551
+ itemRef.current?.click();
3552
+ }
3553
+ }), [id, isDisabled]);
3554
+
3555
+ // Register the option
3556
+ useRegisterOption(id, registeredActionOption, !isDisabled);
3557
+ const handleActionClick = React__default.useCallback(() => {
3558
+ if (onClick) {
3559
+ onClick();
3560
+ }
3561
+ if (triggerRef?.current) {
3562
+ triggerRef.current?.focus();
3563
+ }
3564
+ }, [triggerRef, onClick]);
3565
+ return /*#__PURE__*/jsx(Component, {
3566
+ ...forwardedProps,
3567
+ isDisabled: isDisabled,
3568
+ id: id,
3569
+ role: "gridcell",
3570
+ ref: itemRef,
3571
+ "data-focus-visible-added": state.isUsingKeyboard && isHighlighted ? 'true' : undefined,
3572
+ "aria-disabled": isDisabled,
3573
+ onClick: handleActionClick
3574
+ });
3575
+ };
3576
+
3577
+ const useBooleanState = defaultValue => {
3578
+ const [booleanValue, setBoolean] = useState(defaultValue);
3579
+ const setToFalse = useCallback(() => setBoolean(false), []);
3580
+ const setToTrue = useCallback(() => setBoolean(true), []);
3581
+ const toggleBoolean = useCallback(() => setBoolean(previousValue => !previousValue), []);
3582
+ return [booleanValue, setToFalse, setToTrue, toggleBoolean];
3583
+ };
3584
+
3585
+ const CLASSNAME$15 = 'lumx-combobox-option-more-info';
3586
+ const {
3587
+ block: block$X,
3588
+ element: element$J
3589
+ } = classNames.bem(CLASSNAME$15);
3590
+
3591
+ /**
3592
+ * Display more info on the option as a popover opening on mouse hover or keyboard nav
3593
+ * Please consider using a simpler option description instead for better UX and a11y.
3594
+ *
3595
+ * @family Combobox
3596
+ */
3597
+ const ComboboxOptionMoreInfo = ({
3598
+ buttonProps,
3599
+ popoverProps,
3600
+ onToggle,
3601
+ children
3602
+ }) => {
3603
+ const ref = React__default.useRef(null);
3604
+ const [isHovered,, onMouseLeave, onMouseEnter] = useBooleanState(false);
3605
+ const comboboxOption = useComboboxOptionContext();
3606
+
3607
+ // Open on mouse hover or key nav
3608
+ const isOpen = isHovered || comboboxOption.isKeyboardHighlighted;
3609
+ React__default.useEffect(() => {
3610
+ onToggle?.(isOpen);
3611
+ }, [isOpen, onToggle]);
3612
+ return /*#__PURE__*/jsxs(Fragment, {
3613
+ children: [/*#__PURE__*/jsx(IconButton, {
3614
+ ...buttonProps,
3615
+ ref: ref,
3616
+ className: block$X([buttonProps?.className]),
3617
+ icon: mdiInformationOutline,
3618
+ size: "s",
3619
+ emphasis: "low",
3620
+ onMouseEnter: onMouseEnter,
3621
+ onMouseLeave: onMouseLeave
3622
+ // Button actually plays no role here other than a target for the mouse hover
3623
+ // Keyboard accessibility is handled via combobox keyboard highlighting
3624
+ ,
3625
+ "aria-hidden": true,
3626
+ label: ""
3627
+ }), /*#__PURE__*/jsx(Popover, {
3628
+ ...popoverProps,
3629
+ className: element$J('popover', [popoverProps?.className]),
3630
+ anchorRef: ref,
3631
+ isOpen: isOpen,
3632
+ closeOnEscape: true,
3633
+ closeOnClickAway: true,
3634
+ placement: "bottom-start",
3635
+ children: children
3636
+ }), /*#__PURE__*/jsx(A11YLiveMessage, {
3637
+ hidden: true,
3638
+ children: isOpen ? children : undefined
3639
+ })]
3640
+ });
3641
+ };
3642
+
3643
+ const CLASSNAME$14 = 'lumx-combobox-section';
3644
+ const {
3645
+ block: block$W,
3646
+ element: element$I
3647
+ } = classNames.bem(CLASSNAME$14);
3648
+
3649
+ /**
3650
+ * Content of the ComboboxSection.
3651
+ */
3652
+ const ComboboxSectionContent = ({
3653
+ className,
3654
+ title,
3655
+ children,
3656
+ isLoading,
3657
+ renderItemSkeleton
3658
+ }) => {
3659
+ const {
3660
+ options
3661
+ } = useCombobox();
3662
+ const {
3663
+ sectionId
3664
+ } = useComboboxSectionId();
3665
+ const hasRegisteredChildren = Boolean(Object.values(options).find(option => isComboboxValue(option) && option.sectionId === sectionId));
3666
+ const titleId = title && `${sectionId}-title`;
3667
+ if (!children && !isLoading) {
3668
+ return null;
3669
+ }
3670
+ const isHidden = !hasRegisteredChildren && !isLoading;
3671
+ return /*#__PURE__*/jsxs("li", {
3672
+ className: block$W([className]),
3673
+ role: !isHidden ? 'none' : undefined,
3674
+ "aria-hidden": isHidden,
3675
+ style: {
3676
+ display: isHidden ? 'none' : undefined
3677
+ },
3678
+ children: [title && /*#__PURE__*/jsx(Text, {
3679
+ as: "span",
3680
+ className: element$I('header', [ListSubheader.className]),
3681
+ "aria-hidden": "true",
3682
+ id: titleId,
3683
+ children: title
3684
+ }), /*#__PURE__*/jsxs("ul", {
3685
+ className: element$I('content'),
3686
+ role: "group",
3687
+ "aria-labelledby": titleId,
3688
+ children: [children, isLoading && /*#__PURE__*/jsx(ComboboxListSkeleton, {
3689
+ children: renderItemSkeleton
3690
+ })]
3691
+ })]
3692
+ });
3693
+ };
3694
+
3695
+ /**
3696
+ * Section for options of a Combobox.
3697
+ *
3698
+ * @family Combobox
3699
+ * @param ComboboxSectionProps
3700
+ * @returns ComboboxSection
3701
+ */
3702
+ const ComboboxSection = ({
3703
+ children,
3704
+ ...props
3705
+ }) => {
3706
+ const sectionId = useId();
3707
+ const value = React__default.useMemo(() => ({
3708
+ sectionId,
3709
+ isLoading: props.isLoading
3710
+ }), [sectionId, props.isLoading]);
3711
+ return /*#__PURE__*/jsx(SectionContext.Provider, {
3712
+ value: value,
3713
+ children: /*#__PURE__*/jsx(ComboboxSectionContent, {
3714
+ ...props,
3715
+ children: children
3716
+ })
3717
+ });
3718
+ };
3719
+
3720
+ /** Context provider for the combobox. */
3721
+ const ComboboxProvider = ({
3722
+ children,
3723
+ value
3724
+ }) => {
3725
+ return /*#__PURE__*/jsx(ComboboxContext.Provider, {
3726
+ value: value,
3727
+ children: /*#__PURE__*/jsx(MovingFocusProvider, {
3728
+ options: {
3729
+ direction: value.type === 'grid' ? 'both' : 'vertical',
3730
+ firstFocusDirection: value.type === 'grid' ? 'vertical' : undefined,
3731
+ loopAround: {
3732
+ row: 'next-loop',
3733
+ col: 'inside'
3734
+ },
3735
+ gridJumpToShortcutDirection: 'vertical',
3736
+ defaultSelectedId: value.selectedIds?.[0],
3737
+ listKey: value.inputValue
3738
+ },
3739
+ children: children
3740
+ })
3741
+ });
3742
+ };
3743
+
3744
+ const Combobox$1 = ({
3745
+ id: htmlId,
3746
+ inputValue,
3747
+ defaultInputValue,
3748
+ autoFilter = true,
3749
+ openOnClick,
3750
+ openOnFocus,
3751
+ status,
3752
+ showEmptyState = !autoFilter,
3753
+ showErrorState = !!status,
3754
+ selectedIds,
3755
+ onInputChange,
3756
+ onSelect,
3757
+ onOpen,
3758
+ children,
3759
+ selectionType,
3760
+ translations
3761
+ }) => {
3762
+ const textFieldRef = useRef(null);
3763
+ const triggerRef = useRef(null);
3764
+
3765
+ // Generate a unique id for the combobox that will be used for every child components.
3766
+ const generatedId = useId();
3767
+ const comboboxId = htmlId || generatedId;
3768
+ const listboxId = `${comboboxId}-popover`;
3769
+
3770
+ /** Generate the selected option id from the given selected id. */
3771
+ const currentSelectedIds = selectedIds?.map(selectedId => generateOptionId(comboboxId, selectedId.toString()));
3772
+
3773
+ /** Generate the state */
3774
+ const [state, dispatch] = useReducer(reducer$1, initialState, defaultState => ({
3775
+ ...defaultState,
3776
+ comboboxId,
3777
+ listboxId,
3778
+ // a default input value can be set if needed
3779
+ inputValue: defaultInputValue || defaultState.inputValue
3780
+ }));
3781
+
3782
+ /**
3783
+ * Return the current input value.
3784
+ */
3785
+ const currentInputValue = useMemo(() => {
3786
+ // If the component is controlled and a value is already set by the parent, use this value
3787
+ if (inputValue !== null && inputValue !== undefined) {
3788
+ return inputValue;
3789
+ }
3790
+
3791
+ // Then use the local value
3792
+ if (state.inputValue) {
3793
+ return state.inputValue;
3794
+ }
3795
+
3796
+ // In all other cases, return an empty string.
3797
+ return '';
3798
+ }, [inputValue, state.inputValue]);
3799
+
3800
+ /** Return a memoized state */
3801
+ const synchedState = useMemo(() => {
3802
+ return {
3803
+ ...state,
3804
+ showAll: !autoFilter || state.showAll,
3805
+ inputValue: currentInputValue,
3806
+ status: status || state.status,
3807
+ listboxId
3808
+ };
3809
+ }, [currentInputValue, listboxId, autoFilter, state, status]);
3810
+
3811
+ /** Props to set in the context */
3812
+ const comboboxProviderValue = useMemo(() => ({
3813
+ ...synchedState,
3814
+ openOnFocus,
3815
+ openOnClick,
3816
+ onInputChange,
3817
+ onOpen,
3818
+ onSelect,
3819
+ dispatch,
3820
+ selectionType,
3821
+ selectedIds: currentSelectedIds,
3822
+ showEmptyState,
3823
+ showErrorState,
3824
+ translations
3825
+ }), [synchedState, openOnFocus, openOnClick, onInputChange, onOpen, onSelect, selectionType, currentSelectedIds, showEmptyState, showErrorState, translations]);
3826
+ return /*#__PURE__*/jsx(ComboboxRefsProvider, {
3827
+ triggerRef: triggerRef,
3828
+ anchorRef: textFieldRef,
3829
+ children: /*#__PURE__*/jsx(ComboboxProvider, {
3830
+ value: comboboxProviderValue,
3831
+ children: children
3832
+ })
3833
+ });
3834
+ };
3835
+
3836
+ const SUB_COMPONENTS = {
3837
+ /**
3838
+ * Option to set within a combobox list.
3839
+ *
3840
+ * @family Combobox
3841
+ * @param ComboboxOptionProps
3842
+ * @returns ComboboxOption
3843
+ */
3844
+ Option: ComboboxOption,
3845
+ /**
3846
+ * Skeleton for a combobox option.
3847
+ * A typography skeleton is rendered by default but can be overridden by passing children.
3848
+ */
3849
+ OptionSkeleton: ComboboxOptionSkeleton,
3850
+ /**
3851
+ * Section for options of a Combobox.
3852
+ *
3853
+ * @family Combobox
3854
+ * @param ComboboxSectionProps
3855
+ * @returns ComboboxSection
3856
+ */
3857
+ Section: ComboboxSection,
3858
+ /**
3859
+ * Combobox input trigger.
3860
+ *
3861
+ * @family Combobox
3862
+ */
3863
+ Input: ComboboxInput,
3864
+ /**
3865
+ * The listbox containing the combobox's options.
3866
+ *
3867
+ * @family Combobox
3868
+ * @param ComboboxListBoxProps
3869
+ * @returns ComboboxListBox
3870
+ */
3871
+ List: ComboboxListBox,
3872
+ /**
3873
+ * Combobox button trigger.
3874
+ *
3875
+ * @family Combobox
3876
+ */
3877
+ Button: ComboboxButton
3878
+ };
3879
+
3880
+ /**
3881
+ *
3882
+ * A Combobox is a combination of two components:
3883
+ * * An input to enter the user's value
3884
+ * * A popover with a list of suggestions to fill the value.
3885
+ *
3886
+ * These two components are included via the Combobox.Input and Combobox.ListBox components.
3887
+ *
3888
+ * In its simplest implementation the component will automatically filter the given options
3889
+ * from the value of the input and fill the input with the textValue of the selected option.
3890
+ *
3891
+ * Props are available for more complex implementations.
3892
+ *
3893
+ * @family Combobox
3894
+ * @param ComboboxProps
3895
+ * @returns Combobox
3896
+ */
3897
+ const Combobox = Object.assign(Combobox$1, SUB_COMPONENTS);
3898
+
3899
+ /**
3900
+ * Comment block variants.
3901
+ */
3902
+ const CommentBlockVariant = {
3903
+ indented: 'indented',
3904
+ linear: 'linear'
3905
+ };
3906
+
3907
+ /**
3908
+ * Defines the props of the component.
3909
+ */
3910
+
3911
+ /**
3912
+ * Component display name.
3913
+ */
3914
+ const COMPONENT_NAME$15 = 'CommentBlock';
3915
+
3916
+ /**
3917
+ * Component default class name and class prefix.
3918
+ */
3919
+ const CLASSNAME$13 = 'lumx-comment-block';
3920
+ const {
3921
+ block: block$V,
3922
+ element: element$H
3923
+ } = classNames.bem(CLASSNAME$13);
3924
+
3925
+ /**
3926
+ * Component default props.
3927
+ */
3928
+ const DEFAULT_PROPS$Z = {
3929
+ variant: CommentBlockVariant.indented
3930
+ };
3931
+
3932
+ /**
3933
+ * CommentBlock component.
3934
+ *
3935
+ * @param props Component props.
3936
+ * @param ref Component ref.
3937
+ * @return React element.
3938
+ */
3939
+ const CommentBlock = forwardRef((props, ref) => {
3940
+ const defaultTheme = useTheme() || Theme$1.light;
3941
+ const {
3942
+ actions,
3943
+ avatarProps,
3944
+ children,
3945
+ className,
3946
+ date,
3947
+ fullDate,
3948
+ hasActions,
3949
+ headerActions,
3950
+ isOpen,
3951
+ isRelevant,
3952
+ name,
3953
+ onClick,
3954
+ onMouseEnter,
3955
+ onMouseLeave,
3956
+ text,
3957
+ theme = defaultTheme,
3958
+ variant = DEFAULT_PROPS$Z.variant,
3959
+ ...forwardedProps
3960
+ } = props;
3961
+ const hasChildren = Children.count(children) > 0;
3962
+ return /*#__PURE__*/jsxs("div", {
3963
+ ref: ref,
3964
+ className: classNames.join(className, block$V({
3965
+ 'has-children': hasChildren && isOpen,
3966
+ 'has-indented-children': hasChildren && variant === CommentBlockVariant.indented,
3967
+ 'has-linear-children': hasChildren && variant === CommentBlockVariant.linear,
3968
+ 'is-relevant': isRelevant,
3969
+ [`theme-${theme}`]: Boolean(theme)
3970
+ })),
3971
+ ...forwardedProps,
3972
+ children: [/*#__PURE__*/jsxs("div", {
3973
+ className: element$H('wrapper'),
3974
+ children: [/*#__PURE__*/jsx("div", {
3975
+ className: element$H('avatar'),
3976
+ children: /*#__PURE__*/jsx(Avatar, {
3977
+ ...avatarProps,
3978
+ size: Size$1.m,
3979
+ onClick: onClick
3980
+ })
3981
+ }), /*#__PURE__*/jsxs("div", {
3982
+ className: element$H('container'),
3983
+ children: [/*#__PURE__*/jsxs("div", {
3984
+ className: element$H('content'),
3985
+ children: [/*#__PURE__*/jsxs("div", {
3986
+ className: element$H('meta'),
3987
+ children: [name &&
3988
+ /*#__PURE__*/
3989
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
3990
+ jsx("span", {
3991
+ className: element$H('name'),
3992
+ onClick: onClick,
3993
+ onMouseEnter: onMouseEnter,
3994
+ onMouseLeave: onMouseLeave,
3995
+ children: name
3996
+ }), headerActions && /*#__PURE__*/jsx("span", {
3997
+ className: element$H('header-actions'),
3998
+ children: headerActions
3999
+ })]
4000
+ }), /*#__PURE__*/jsx("div", {
4001
+ className: element$H('text'),
4002
+ children: text
4003
+ }), date && (fullDate ? /*#__PURE__*/jsx(Tooltip, {
4004
+ label: fullDate,
4005
+ placement: "top",
4006
+ children: /*#__PURE__*/jsx("span", {
4007
+ className: element$H('date'),
4008
+ children: date
4009
+ })
4010
+ }) : /*#__PURE__*/jsx("span", {
4011
+ className: element$H('date'),
4012
+ children: date
4013
+ }))]
4014
+ }), hasActions && /*#__PURE__*/jsx("div", {
4015
+ className: element$H('actions'),
4016
+ children: actions
4017
+ })]
4018
+ })]
4019
+ }), hasChildren && isOpen && /*#__PURE__*/jsx("div", {
4020
+ className: element$H('children'),
4021
+ children: children
4022
+ })]
4023
+ });
4024
+ });
4025
+ CommentBlock.displayName = COMPONENT_NAME$15;
4026
+ CommentBlock.className = CLASSNAME$13;
4027
+ CommentBlock.defaultProps = DEFAULT_PROPS$Z;
4028
+
4029
+ /**
4030
+ * Add a number of months from a date while resetting the day to prevent month length mismatches.
4031
+ */
4032
+ function addMonthResetDay(date, monthOffset) {
4033
+ const newDate = new Date(date.getTime());
4034
+ newDate.setDate(1);
4035
+ newDate.setMonth(date.getMonth() + monthOffset);
4036
+ return newDate;
4037
+ }
4038
+
4039
+ /**
4040
+ * Check if given date is valid.
4041
+ */
4042
+ const isDateValid = date => date instanceof Date && !Number.isNaN(date.getTime());
4043
+
4044
+ /**
4045
+ * Component display name.
4046
+ */
4047
+ const COMPONENT_NAME$14 = 'DatePicker';
4048
+
4049
+ /**
4050
+ * Component default class name and class prefix.
4051
+ */
4052
+ const CLASSNAME$12 = 'lumx-date-picker';
4053
+
4054
+ /** Get first day of week for locale from the browser API */
4055
+ const getFromBrowser = locale => {
4056
+ try {
4057
+ const localeMetadata = new Intl.Locale(locale.code);
4058
+ const {
4059
+ firstDay
4060
+ } = localeMetadata.getWeekInfo?.() || localeMetadata.weekInfo;
4061
+ // Sunday is represented as `0` in Date.getDay()
4062
+ if (firstDay === 7) return 0;
4063
+ return firstDay;
4064
+ } catch (e) {
4065
+ return undefined;
4066
+ }
4067
+ };
4068
+
4069
+ /** List first day for each locale (could be removed when all browser implement Locale weekInfo) */
4070
+ const FIRST_DAY_FOR_LOCALES = [{
4071
+ // Locales with Sunday as the first day of the week
4072
+ localeRX: /^(af|ar-(dz|eg|sa)|bn|cy|en-(ca|us|za)|fr-ca|gd|he|hi|ja|km|ko|pt-br|te|th|ug|zh-hk)$/i,
2391
4073
  firstDay: 0
2392
4074
  }, {
2393
4075
  // Locales with Monday as the first day of the week
@@ -2832,14 +4514,6 @@ const DatePicker = forwardRef((props, ref) => {
2832
4514
  DatePicker.displayName = COMPONENT_NAME$14;
2833
4515
  DatePicker.className = CLASSNAME$12;
2834
4516
 
2835
- const useBooleanState = defaultValue => {
2836
- const [booleanValue, setBoolean] = useState(defaultValue);
2837
- const setToFalse = useCallback(() => setBoolean(false), []);
2838
- const setToTrue = useCallback(() => setBoolean(true), []);
2839
- const toggleBoolean = useCallback(() => setBoolean(previousValue => !previousValue), []);
2840
- return [booleanValue, setToFalse, setToTrue, toggleBoolean];
2841
- };
2842
-
2843
4517
  /**
2844
4518
  * Component display name.
2845
4519
  */
@@ -3447,7 +5121,7 @@ const {
3447
5121
  /**
3448
5122
  * Component default props.
3449
5123
  */
3450
- const DEFAULT_PROPS$W = {
5124
+ const DEFAULT_PROPS$Y = {
3451
5125
  size: Size$1.big,
3452
5126
  disableBodyScroll: true
3453
5127
  };
@@ -3478,11 +5152,11 @@ const Dialog = forwardRef((props, ref) => {
3478
5152
  parentElement,
3479
5153
  contentRef,
3480
5154
  preventAutoClose,
3481
- size = DEFAULT_PROPS$W.size,
5155
+ size = DEFAULT_PROPS$Y.size,
3482
5156
  zIndex,
3483
5157
  dialogProps,
3484
5158
  onVisibilityChange,
3485
- disableBodyScroll = DEFAULT_PROPS$W.disableBodyScroll,
5159
+ disableBodyScroll = DEFAULT_PROPS$Y.disableBodyScroll,
3486
5160
  preventCloseOnClick,
3487
5161
  preventCloseOnEscape,
3488
5162
  ...forwardedProps
@@ -3622,7 +5296,7 @@ const Dialog = forwardRef((props, ref) => {
3622
5296
  });
3623
5297
  Dialog.displayName = COMPONENT_NAME$11;
3624
5298
  Dialog.className = CLASSNAME$11;
3625
- Dialog.defaultProps = DEFAULT_PROPS$W;
5299
+ Dialog.defaultProps = DEFAULT_PROPS$Y;
3626
5300
 
3627
5301
  /**
3628
5302
  * Component display name.
@@ -3666,7 +5340,7 @@ const Divider$1 = props => {
3666
5340
  /**
3667
5341
  * Component default props.
3668
5342
  */
3669
- const DEFAULT_PROPS$V = {};
5343
+ const DEFAULT_PROPS$X = {};
3670
5344
 
3671
5345
  /**
3672
5346
  * Divider component.
@@ -3689,7 +5363,7 @@ const Divider = forwardRef((props, ref) => {
3689
5363
  });
3690
5364
  Divider.displayName = COMPONENT_NAME$10;
3691
5365
  Divider.className = CLASSNAME$10;
3692
- Divider.defaultProps = DEFAULT_PROPS$V;
5366
+ Divider.defaultProps = DEFAULT_PROPS$X;
3693
5367
 
3694
5368
  /**
3695
5369
  * Component display name.
@@ -3914,7 +5588,7 @@ const {
3914
5588
  /**
3915
5589
  * Component default props.
3916
5590
  */
3917
- const DEFAULT_PROPS$U = {
5591
+ const DEFAULT_PROPS$W = {
3918
5592
  tabIndex: -1
3919
5593
  };
3920
5594
 
@@ -3933,7 +5607,7 @@ const InternalList = forwardRef((props, ref) => {
3933
5607
  isClickable,
3934
5608
  itemPadding,
3935
5609
  onListItemSelected,
3936
- tabIndex = DEFAULT_PROPS$U.tabIndex,
5610
+ tabIndex = DEFAULT_PROPS$W.tabIndex,
3937
5611
  ...forwardedProps
3938
5612
  } = props;
3939
5613
  const adjustedItemPadding = itemPadding ?? (isClickable ? Size$1.big : undefined);
@@ -3949,7 +5623,7 @@ const InternalList = forwardRef((props, ref) => {
3949
5623
  });
3950
5624
  InternalList.displayName = COMPONENT_NAME$_;
3951
5625
  InternalList.className = CLASSNAME$_;
3952
- InternalList.defaultProps = DEFAULT_PROPS$U;
5626
+ InternalList.defaultProps = DEFAULT_PROPS$W;
3953
5627
  const List = Object.assign(InternalList, {
3954
5628
  useKeyboardListNavigation
3955
5629
  });
@@ -6394,7 +8068,7 @@ const {
6394
8068
  /**
6395
8069
  * Component default props.
6396
8070
  */
6397
- const DEFAULT_PROPS$T = {
8071
+ const DEFAULT_PROPS$V = {
6398
8072
  elevation: 3,
6399
8073
  placement: Placement.AUTO,
6400
8074
  focusAnchorOnClose: true,
@@ -6411,24 +8085,24 @@ const _InnerPopover = forwardRef((props, ref) => {
6411
8085
  className,
6412
8086
  closeOnClickAway,
6413
8087
  closeOnEscape,
6414
- elevation = DEFAULT_PROPS$T.elevation,
8088
+ elevation = DEFAULT_PROPS$V.elevation,
6415
8089
  focusElement,
6416
8090
  hasArrow,
6417
8091
  isOpen,
6418
8092
  onClose,
6419
8093
  parentElement,
6420
- usePortal = DEFAULT_PROPS$T.usePortal,
6421
- focusAnchorOnClose = DEFAULT_PROPS$T.focusAnchorOnClose,
8094
+ usePortal = DEFAULT_PROPS$V.usePortal,
8095
+ focusAnchorOnClose = DEFAULT_PROPS$V.focusAnchorOnClose,
6422
8096
  withFocusTrap,
6423
8097
  boundaryRef,
6424
8098
  fitToAnchorWidth,
6425
8099
  fitWithinViewportHeight,
6426
8100
  focusTrapZoneElement,
6427
8101
  offset,
6428
- placement = DEFAULT_PROPS$T.placement,
8102
+ placement = DEFAULT_PROPS$V.placement,
6429
8103
  style,
6430
8104
  theme,
6431
- zIndex = DEFAULT_PROPS$T.zIndex,
8105
+ zIndex = DEFAULT_PROPS$V.zIndex,
6432
8106
  ...forwardedProps
6433
8107
  } = props;
6434
8108
  const popoverRef = useRef(null);
@@ -6514,7 +8188,7 @@ const Popover = skipRender(
6514
8188
  () => Boolean(DOCUMENT), _InnerPopover);
6515
8189
  Popover.displayName = COMPONENT_NAME$Z;
6516
8190
  Popover.className = CLASSNAME$Z;
6517
- Popover.defaultProps = DEFAULT_PROPS$T;
8191
+ Popover.defaultProps = DEFAULT_PROPS$V;
6518
8192
 
6519
8193
  // The error margin in px we want to have for triggering infinite scroll
6520
8194
  const SCROLL_TRIGGER_MARGIN = 5;
@@ -6574,7 +8248,7 @@ const {
6574
8248
  /**
6575
8249
  * Component default props.
6576
8250
  */
6577
- const DEFAULT_PROPS$S = {
8251
+ const DEFAULT_PROPS$U = {
6578
8252
  closeOnClick: true,
6579
8253
  closeOnClickAway: true,
6580
8254
  closeOnEscape: true,
@@ -6597,18 +8271,18 @@ const Dropdown = forwardRef((props, ref) => {
6597
8271
  anchorRef,
6598
8272
  children,
6599
8273
  className,
6600
- closeOnClick = DEFAULT_PROPS$S.closeOnClick,
6601
- closeOnClickAway = DEFAULT_PROPS$S.closeOnClickAway,
6602
- closeOnEscape = DEFAULT_PROPS$S.closeOnEscape,
6603
- fitToAnchorWidth = DEFAULT_PROPS$S.fitToAnchorWidth,
6604
- fitWithinViewportHeight = DEFAULT_PROPS$S.fitWithinViewportHeight,
8274
+ closeOnClick = DEFAULT_PROPS$U.closeOnClick,
8275
+ closeOnClickAway = DEFAULT_PROPS$U.closeOnClickAway,
8276
+ closeOnEscape = DEFAULT_PROPS$U.closeOnEscape,
8277
+ fitToAnchorWidth = DEFAULT_PROPS$U.fitToAnchorWidth,
8278
+ fitWithinViewportHeight = DEFAULT_PROPS$U.fitWithinViewportHeight,
6605
8279
  isOpen,
6606
8280
  offset,
6607
- focusAnchorOnClose = DEFAULT_PROPS$S.focusAnchorOnClose,
8281
+ focusAnchorOnClose = DEFAULT_PROPS$U.focusAnchorOnClose,
6608
8282
  onClose,
6609
8283
  onInfiniteScroll,
6610
- placement = DEFAULT_PROPS$S.placement,
6611
- shouldFocusOnOpen = DEFAULT_PROPS$S.shouldFocusOnOpen,
8284
+ placement = DEFAULT_PROPS$U.placement,
8285
+ shouldFocusOnOpen = DEFAULT_PROPS$U.shouldFocusOnOpen,
6612
8286
  zIndex,
6613
8287
  ...forwardedProps
6614
8288
  } = props;
@@ -6654,7 +8328,7 @@ const Dropdown = forwardRef((props, ref) => {
6654
8328
  });
6655
8329
  Dropdown.displayName = COMPONENT_NAME$Y;
6656
8330
  Dropdown.className = CLASSNAME$Y;
6657
- Dropdown.defaultProps = DEFAULT_PROPS$S;
8331
+ Dropdown.defaultProps = DEFAULT_PROPS$U;
6658
8332
 
6659
8333
  /**
6660
8334
  * Component display name.
@@ -6673,7 +8347,7 @@ const {
6673
8347
  /**
6674
8348
  * Component default props.
6675
8349
  */
6676
- const DEFAULT_PROPS$R = {
8350
+ const DEFAULT_PROPS$T = {
6677
8351
  closeMode: 'unmount'
6678
8352
  };
6679
8353
  const isDragHandle = isComponent(DragHandle);
@@ -6691,7 +8365,7 @@ const ExpansionPanel = forwardRef((props, ref) => {
6691
8365
  const defaultTheme = useTheme() || Theme$1.light;
6692
8366
  const {
6693
8367
  className,
6694
- closeMode = DEFAULT_PROPS$R.closeMode,
8368
+ closeMode = DEFAULT_PROPS$T.closeMode,
6695
8369
  children: anyChildren,
6696
8370
  hasBackground,
6697
8371
  hasHeaderDivider,
@@ -6808,11 +8482,11 @@ const ExpansionPanel = forwardRef((props, ref) => {
6808
8482
  });
6809
8483
  ExpansionPanel.displayName = COMPONENT_NAME$X;
6810
8484
  ExpansionPanel.className = CLASSNAME$X;
6811
- ExpansionPanel.defaultProps = DEFAULT_PROPS$R;
8485
+ ExpansionPanel.defaultProps = DEFAULT_PROPS$T;
6812
8486
 
6813
8487
  const COMPONENT_NAME$W = 'Flag';
6814
8488
  const CLASSNAME$W = 'lumx-flag';
6815
- const DEFAULT_PROPS$Q = {};
8489
+ const DEFAULT_PROPS$S = {};
6816
8490
  const {
6817
8491
  block: block$N,
6818
8492
  element: element$B
@@ -6876,7 +8550,7 @@ const Flag = forwardRef((props, ref) => {
6876
8550
  });
6877
8551
  Flag.displayName = COMPONENT_NAME$W;
6878
8552
  Flag.className = CLASSNAME$W;
6879
- Flag.defaultProps = DEFAULT_PROPS$Q;
8553
+ Flag.defaultProps = DEFAULT_PROPS$S;
6880
8554
 
6881
8555
  /**
6882
8556
  * Defines the props of the component.
@@ -6969,7 +8643,7 @@ const {
6969
8643
  /**
6970
8644
  * Component default props.
6971
8645
  */
6972
- const DEFAULT_PROPS$P = {
8646
+ const DEFAULT_PROPS$R = {
6973
8647
  gap: Size$1.big,
6974
8648
  orientation: Orientation$1.horizontal
6975
8649
  };
@@ -6999,8 +8673,8 @@ const BaseGenericBlock = forwardRef((props, ref) => {
6999
8673
  children,
7000
8674
  actions,
7001
8675
  actionsProps,
7002
- gap = DEFAULT_PROPS$P.gap,
7003
- orientation = DEFAULT_PROPS$P.orientation,
8676
+ gap = DEFAULT_PROPS$R.gap,
8677
+ orientation = DEFAULT_PROPS$R.orientation,
7004
8678
  contentProps,
7005
8679
  ...forwardedProps
7006
8680
  } = props;
@@ -7054,7 +8728,7 @@ const BaseGenericBlock = forwardRef((props, ref) => {
7054
8728
  });
7055
8729
  BaseGenericBlock.displayName = COMPONENT_NAME$U;
7056
8730
  BaseGenericBlock.className = CLASSNAME$U;
7057
- BaseGenericBlock.defaultProps = DEFAULT_PROPS$P;
8731
+ BaseGenericBlock.defaultProps = DEFAULT_PROPS$R;
7058
8732
  const GenericBlock = Object.assign(BaseGenericBlock, {
7059
8733
  Figure,
7060
8734
  Content,
@@ -7102,7 +8776,7 @@ const CLASSNAME$T = 'lumx-heading';
7102
8776
  /**
7103
8777
  * Component default props.
7104
8778
  */
7105
- const DEFAULT_PROPS$O = {};
8779
+ const DEFAULT_PROPS$Q = {};
7106
8780
 
7107
8781
  /**
7108
8782
  * Get Heading component common props
@@ -7203,7 +8877,7 @@ const {
7203
8877
  /**
7204
8878
  * Component default props.
7205
8879
  */
7206
- const DEFAULT_PROPS$N = {};
8880
+ const DEFAULT_PROPS$P = {};
7207
8881
 
7208
8882
  /**
7209
8883
  * Text component common props
@@ -7290,7 +8964,7 @@ const Text = forwardRef((props, ref) => {
7290
8964
  });
7291
8965
  Text.displayName = COMPONENT_NAME$S;
7292
8966
  Text.className = CLASSNAME$S;
7293
- Text.defaultProps = DEFAULT_PROPS$N;
8967
+ Text.defaultProps = DEFAULT_PROPS$P;
7294
8968
 
7295
8969
  const HeadingLevelContext = /*#__PURE__*/createContext(defaultContext);
7296
8970
 
@@ -7327,7 +9001,7 @@ const Heading = forwardRef((props, ref) => {
7327
9001
  });
7328
9002
  Heading.displayName = COMPONENT_NAME$T;
7329
9003
  Heading.className = CLASSNAME$T;
7330
- Heading.defaultProps = DEFAULT_PROPS$O;
9004
+ Heading.defaultProps = DEFAULT_PROPS$Q;
7331
9005
 
7332
9006
  /**
7333
9007
  * Computes the next heading level based on the optional prop level or the parent context level.
@@ -7378,7 +9052,7 @@ const {
7378
9052
  /**
7379
9053
  * Component default props.
7380
9054
  */
7381
- const DEFAULT_PROPS$M = {
9055
+ const DEFAULT_PROPS$O = {
7382
9056
  orientation: Orientation$1.horizontal,
7383
9057
  wrap: 'nowrap'
7384
9058
  };
@@ -7396,9 +9070,9 @@ const Grid = forwardRef((props, ref) => {
7396
9070
  className,
7397
9071
  gutter,
7398
9072
  hAlign,
7399
- orientation = DEFAULT_PROPS$M.orientation,
9073
+ orientation = DEFAULT_PROPS$O.orientation,
7400
9074
  vAlign,
7401
- wrap = DEFAULT_PROPS$M.wrap,
9075
+ wrap = DEFAULT_PROPS$O.wrap,
7402
9076
  ...forwardedProps
7403
9077
  } = props;
7404
9078
  return /*#__PURE__*/jsx("div", {
@@ -7416,7 +9090,7 @@ const Grid = forwardRef((props, ref) => {
7416
9090
  });
7417
9091
  Grid.displayName = COMPONENT_NAME$R;
7418
9092
  Grid.className = CLASSNAME$R;
7419
- Grid.defaultProps = DEFAULT_PROPS$M;
9093
+ Grid.defaultProps = DEFAULT_PROPS$O;
7420
9094
 
7421
9095
  /**
7422
9096
  * Component display name.
@@ -7474,7 +9148,7 @@ const CLASSNAME$P = 'lumx-grid-column';
7474
9148
  /**
7475
9149
  * Component default props.
7476
9150
  */
7477
- const DEFAULT_PROPS$L = {};
9151
+ const DEFAULT_PROPS$N = {};
7478
9152
 
7479
9153
  /**
7480
9154
  * The GridColumn is a layout component that can display children in a grid
@@ -7482,10 +9156,9 @@ const DEFAULT_PROPS$L = {};
7482
9156
  * with a number of column that reduce when there is not enough space for each item.
7483
9157
  *
7484
9158
  * @param props Component props.
7485
- * @param ref Component ref.
7486
- * @return React element.
9159
+ * @return JSX element.
7487
9160
  */
7488
- const GridColumn = forwardRef((props, ref) => {
9161
+ const GridColumn$1 = props => {
7489
9162
  const {
7490
9163
  as: Component = 'div',
7491
9164
  gap,
@@ -7494,12 +9167,13 @@ const GridColumn = forwardRef((props, ref) => {
7494
9167
  children,
7495
9168
  className,
7496
9169
  style = {},
9170
+ ref,
7497
9171
  ...forwardedProps
7498
9172
  } = props;
7499
9173
  return /*#__PURE__*/jsx(Component, {
7500
9174
  ...forwardedProps,
7501
9175
  ref: ref,
7502
- className: classNames.join(className, CLASSNAME$P),
9176
+ className: classnames(className, CLASSNAME$P),
7503
9177
  style: {
7504
9178
  ...style,
7505
9179
  ['--lumx-grid-column-item-min-width']: isInteger(itemMinWidth) && `${itemMinWidth}px`,
@@ -7508,10 +9182,40 @@ const GridColumn = forwardRef((props, ref) => {
7508
9182
  },
7509
9183
  children: children
7510
9184
  });
9185
+ };
9186
+ GridColumn$1.displayName = COMPONENT_NAME$P;
9187
+ GridColumn$1.className = CLASSNAME$P;
9188
+ GridColumn$1.defaultProps = DEFAULT_PROPS$N;
9189
+
9190
+ /**
9191
+ * Defines the props of the component.
9192
+ */
9193
+
9194
+ // Re-export types for backward compatibility
9195
+
9196
+ /**
9197
+ * Component default props.
9198
+ */
9199
+ const DEFAULT_PROPS$M = {};
9200
+
9201
+ /**
9202
+ * The GridColumn is a layout component that can display children in a grid
9203
+ * with custom display properties. It also comes with a responsive design,
9204
+ * with a number of column that reduce when there is not enough space for each item.
9205
+ *
9206
+ * @param props Component props.
9207
+ * @param ref Component ref.
9208
+ * @return React element.
9209
+ */
9210
+ const GridColumn = forwardRef((props, ref) => {
9211
+ return GridColumn$1({
9212
+ ref,
9213
+ ...props
9214
+ });
7511
9215
  });
7512
9216
  GridColumn.displayName = COMPONENT_NAME$P;
7513
9217
  GridColumn.className = CLASSNAME$P;
7514
- GridColumn.defaultProps = DEFAULT_PROPS$L;
9218
+ GridColumn.defaultProps = DEFAULT_PROPS$M;
7515
9219
 
7516
9220
  /**
7517
9221
  * Icon component.
@@ -7629,7 +9333,7 @@ const {
7629
9333
  /**
7630
9334
  * Component default props.
7631
9335
  */
7632
- const DEFAULT_PROPS$K = {
9336
+ const DEFAULT_PROPS$L = {
7633
9337
  captionPosition: ImageBlockCaptionPosition.below,
7634
9338
  align: Alignment.left
7635
9339
  };
@@ -7645,9 +9349,9 @@ const ImageBlock = forwardRef((props, ref) => {
7645
9349
  const defaultTheme = useTheme() || Theme$1.light;
7646
9350
  const {
7647
9351
  actions,
7648
- align = DEFAULT_PROPS$K.align,
9352
+ align = DEFAULT_PROPS$L.align,
7649
9353
  alt,
7650
- captionPosition = DEFAULT_PROPS$K.captionPosition,
9354
+ captionPosition = DEFAULT_PROPS$L.captionPosition,
7651
9355
  captionStyle,
7652
9356
  className,
7653
9357
  description,
@@ -7701,7 +9405,7 @@ const ImageBlock = forwardRef((props, ref) => {
7701
9405
  });
7702
9406
  ImageBlock.displayName = COMPONENT_NAME$O;
7703
9407
  ImageBlock.className = CLASSNAME$O;
7704
- ImageBlock.defaultProps = DEFAULT_PROPS$K;
9408
+ ImageBlock.defaultProps = DEFAULT_PROPS$L;
7705
9409
 
7706
9410
  /**
7707
9411
  * Component display name.
@@ -8461,7 +10165,7 @@ const {
8461
10165
  /**
8462
10166
  * Component default props.
8463
10167
  */
8464
- const DEFAULT_PROPS$J = {};
10168
+ const DEFAULT_PROPS$K = {};
8465
10169
 
8466
10170
  /**
8467
10171
  * InlineList component.
@@ -8514,7 +10218,7 @@ const InlineList = forwardRef((props, ref) => {
8514
10218
  });
8515
10219
  InlineList.displayName = COMPONENT_NAME$M;
8516
10220
  InlineList.className = CLASSNAME$M;
8517
- InlineList.defaultProps = DEFAULT_PROPS$J;
10221
+ InlineList.defaultProps = DEFAULT_PROPS$K;
8518
10222
 
8519
10223
  /**
8520
10224
  * InputHelper component.
@@ -8685,26 +10389,12 @@ const Lightbox = forwardRef((props, ref) => {
8685
10389
  })
8686
10390
  })
8687
10391
  })
8688
- })]
8689
- })
8690
- });
8691
- });
8692
- Lightbox.displayName = COMPONENT_NAME$L;
8693
- Lightbox.className = CLASSNAME$L;
8694
-
8695
- /** Same as `React.forwardRef` but inferring Ref type from the `as` prop. */
8696
- const forwardRefPolymorphic = React__default.forwardRef;
8697
-
8698
- /**
8699
- * Render clickable element (link, button or custom element)
8700
- * (also does some basic disabled state handling)
8701
- */
8702
- const RawClickable = forwardRefPolymorphic((props, ref) => {
8703
- return RawClickable$1({
8704
- ref,
8705
- ...props
10392
+ })]
10393
+ })
8706
10394
  });
8707
10395
  });
10396
+ Lightbox.displayName = COMPONENT_NAME$L;
10397
+ Lightbox.className = CLASSNAME$L;
8708
10398
 
8709
10399
  /**
8710
10400
  * Component display name.
@@ -8718,7 +10408,101 @@ const CLASSNAME$K = 'lumx-link';
8718
10408
  const {
8719
10409
  block: block$E,
8720
10410
  element: element$u
8721
- } = classNames.bem(CLASSNAME$K);
10411
+ } = bem(CLASSNAME$K);
10412
+
10413
+ /**
10414
+ * Link component (Core UI).
10415
+ *
10416
+ * @param props Component props.
10417
+ * @return JSX element.
10418
+ */
10419
+ const Link$1 = props => {
10420
+ const {
10421
+ label,
10422
+ className,
10423
+ color: propColor,
10424
+ colorVariant: propColorVariant,
10425
+ leftIcon,
10426
+ rightIcon,
10427
+ typography: typography$1,
10428
+ as,
10429
+ ref,
10430
+ isDisabled,
10431
+ theme,
10432
+ href,
10433
+ target,
10434
+ onClick,
10435
+ ...forwardedProps
10436
+ } = props;
10437
+ const [color, colorVariant] = resolveColorWithVariants(propColor, propColorVariant);
10438
+
10439
+ // Determine element type
10440
+ const ElementType = as || (href ? 'a' : 'button');
10441
+
10442
+ // Build disabled props
10443
+ const disabledProps = {};
10444
+ if (isDisabled) {
10445
+ if (ElementType === 'button' || !href && !as) {
10446
+ disabledProps.disabled = true;
10447
+ } else {
10448
+ disabledProps['aria-disabled'] = true;
10449
+ disabledProps.tabIndex = -1;
10450
+ }
10451
+ }
10452
+
10453
+ // Build class name
10454
+ const combinedClassName = classnames(className, block$E({
10455
+ [`color-${color}`]: Boolean(color),
10456
+ [`color-variant-${colorVariant}`]: Boolean(colorVariant),
10457
+ 'has-typography': !!typography$1
10458
+ }), typography$1 && typography(typography$1));
10459
+
10460
+ // Build content with proper spacing for icons
10461
+ const content = /*#__PURE__*/jsxs(Fragment, {
10462
+ children: [leftIcon && /*#__PURE__*/jsxs(Fragment, {
10463
+ children: [" ", Icon$1({
10464
+ icon: leftIcon,
10465
+ className: element$u('left-icon')
10466
+ }), " "]
10467
+ }), label && /*#__PURE__*/jsx("span", {
10468
+ className: element$u('content'),
10469
+ children: label
10470
+ }), rightIcon && /*#__PURE__*/jsxs(Fragment, {
10471
+ children: [" ", Icon$1({
10472
+ icon: rightIcon,
10473
+ className: element$u('right-icon')
10474
+ }), " "]
10475
+ })]
10476
+ });
10477
+
10478
+ // Build element props
10479
+ const elementProps = {
10480
+ ref,
10481
+ className: combinedClassName,
10482
+ onClick: isDisabled ? undefined : onClick,
10483
+ ...forwardedProps,
10484
+ ...disabledProps
10485
+ };
10486
+ if (href) {
10487
+ elementProps.href = href;
10488
+ }
10489
+ if (target) {
10490
+ elementProps.target = target;
10491
+ }
10492
+ return /*#__PURE__*/jsx(ElementType, {
10493
+ ...elementProps,
10494
+ children: content
10495
+ });
10496
+ };
10497
+
10498
+ /**
10499
+ * Defines the props of the component.
10500
+ */
10501
+
10502
+ /**
10503
+ * Component default props.
10504
+ */
10505
+ const DEFAULT_PROPS$J = {};
8722
10506
 
8723
10507
  /**
8724
10508
  * Link component.
@@ -8729,47 +10513,42 @@ const {
8729
10513
  */
8730
10514
  const Link = forwardRef((props, ref) => {
8731
10515
  const {
10516
+ isAnyDisabled,
8732
10517
  disabledStateProps,
8733
10518
  otherProps
8734
10519
  } = useDisableStateProps(props);
8735
10520
  const {
8736
10521
  children,
8737
10522
  className,
8738
- color: propColor,
8739
- colorVariant: propColorVariant,
10523
+ color,
10524
+ colorVariant,
8740
10525
  leftIcon,
8741
10526
  rightIcon,
8742
10527
  typography,
8743
10528
  linkAs,
8744
10529
  ...forwardedProps
8745
10530
  } = otherProps;
8746
- const [color, colorVariant] = resolveColorWithVariants(propColor, propColorVariant);
8747
- return /*#__PURE__*/jsx(RawClickable, {
8748
- ref: ref,
8749
- as: linkAs || (forwardedProps.href ? 'a' : 'button'),
10531
+
10532
+ // Wrap children with spaces if they contain icons
10533
+ const label = wrapChildrenIconWithSpaces(children);
10534
+ return Link$1({
10535
+ ref,
10536
+ label,
10537
+ className,
10538
+ color,
10539
+ colorVariant,
10540
+ leftIcon,
10541
+ rightIcon,
10542
+ typography,
10543
+ as: linkAs,
8750
10544
  ...forwardedProps,
8751
10545
  ...disabledStateProps,
8752
- className: classNames.join(className, block$E({
8753
- [`color-${color}`]: Boolean(color),
8754
- [`color-variant-${colorVariant}`]: Boolean(colorVariant),
8755
- 'has-typography': !!typography
8756
- }), typography && classNames.typography(typography)),
8757
- children: wrapChildrenIconWithSpaces(/*#__PURE__*/jsxs(Fragment, {
8758
- children: [leftIcon && /*#__PURE__*/jsx(Icon, {
8759
- icon: leftIcon,
8760
- className: element$u('left-icon')
8761
- }), children && /*#__PURE__*/jsx("span", {
8762
- className: element$u('content'),
8763
- children: children
8764
- }), rightIcon && /*#__PURE__*/jsx(Icon, {
8765
- icon: rightIcon,
8766
- className: element$u('right-icon')
8767
- })]
8768
- }))
10546
+ isDisabled: isAnyDisabled
8769
10547
  });
8770
10548
  });
8771
10549
  Link.displayName = COMPONENT_NAME$K;
8772
10550
  Link.className = CLASSNAME$K;
10551
+ Link.defaultProps = DEFAULT_PROPS$J;
8773
10552
 
8774
10553
  /**
8775
10554
  * Component display name.
@@ -8839,7 +10618,7 @@ const LinkPreview = forwardRef((props, ref) => {
8839
10618
  // Avoid redundant links in focus order
8840
10619
  tabIndex: -1
8841
10620
  },
8842
- aspectRatio: AspectRatio.free,
10621
+ aspectRatio: AspectRatio$1.free,
8843
10622
  fillHeight: true
8844
10623
  })
8845
10624
  }), /*#__PURE__*/jsxs("div", {
@@ -9248,7 +11027,7 @@ const Mosaic = forwardRef((props, ref) => {
9248
11027
  align: align || Alignment.left,
9249
11028
  image: image,
9250
11029
  theme: theme,
9251
- aspectRatio: AspectRatio.free,
11030
+ aspectRatio: AspectRatio$1.free,
9252
11031
  fillHeight: true,
9253
11032
  onClick: handleImageClick?.(index, onClick) || onClick
9254
11033
  }), thumbnails.length > 4 && index === 3 && /*#__PURE__*/jsx("div", {
@@ -9266,6 +11045,20 @@ Mosaic.displayName = COMPONENT_NAME$E;
9266
11045
  Mosaic.className = CLASSNAME$E;
9267
11046
  Mosaic.defaultProps = DEFAULT_PROPS$G;
9268
11047
 
11048
+ /** Same as `React.forwardRef` but inferring Ref type from the `as` prop. */
11049
+ const forwardRefPolymorphic = React__default.forwardRef;
11050
+
11051
+ /**
11052
+ * Render clickable element (link, button or custom element)
11053
+ * (also does some basic disabled state handling)
11054
+ */
11055
+ const RawClickable = forwardRefPolymorphic((props, ref) => {
11056
+ return RawClickable$1({
11057
+ ref,
11058
+ ...props
11059
+ });
11060
+ });
11061
+
9269
11062
  const NavigationContext = /*#__PURE__*/createContext({
9270
11063
  orientation: Orientation$1.vertical
9271
11064
  });
@@ -11013,6 +12806,8 @@ const SelectMultipleField = props => {
11013
12806
  const defaultTheme = useTheme();
11014
12807
  const {
11015
12808
  anchorRef,
12809
+ // We don't have a clear button in select multiple but it must be removed from the forwardedProps
12810
+ clearButtonProps,
11016
12811
  handleKeyboardNav,
11017
12812
  hasError,
11018
12813
  icon,
@@ -13009,7 +14804,7 @@ const CLASSNAME$c = 'lumx-table';
13009
14804
 
13010
14805
  const {
13011
14806
  block: block$d
13012
- } = classNames.bem(CLASSNAME$c);
14807
+ } = bem(CLASSNAME$c);
13013
14808
 
13014
14809
  /**
13015
14810
  * Defines the props of the component.
@@ -13024,29 +14819,54 @@ const DEFAULT_PROPS$f = {};
13024
14819
  * Table component.
13025
14820
  *
13026
14821
  * @param props Component props.
13027
- * @param ref Component ref.
13028
14822
  * @return React element.
13029
14823
  */
13030
- const Table = forwardRef((props, ref) => {
13031
- const defaultTheme = useTheme() || Theme$1.light;
14824
+ const Table$1 = props => {
13032
14825
  const {
13033
14826
  children,
13034
14827
  className,
13035
14828
  hasBefore,
13036
14829
  hasDividers,
13037
- theme = defaultTheme,
14830
+ ref,
14831
+ theme,
13038
14832
  ...forwardedProps
13039
14833
  } = props;
13040
14834
  return /*#__PURE__*/jsx("table", {
13041
14835
  ref: ref,
13042
14836
  ...forwardedProps,
13043
- className: classNames.join(className, block$d({
14837
+ className: classnames(className, block$d({
13044
14838
  'has-before': hasBefore,
13045
14839
  'has-dividers': hasDividers,
13046
14840
  [`theme-${theme}`]: Boolean(theme)
13047
14841
  })),
13048
14842
  children: children
13049
14843
  });
14844
+ };
14845
+
14846
+ /**
14847
+ * Defines the props of the component.
14848
+ */
14849
+
14850
+ /**
14851
+ * Table component.
14852
+ *
14853
+ * @param props Component props.
14854
+ * @param ref Component ref.
14855
+ * @return React element.
14856
+ */
14857
+ const Table = forwardRef((props, ref) => {
14858
+ const defaultTheme = useTheme() || Theme$1.light;
14859
+ const {
14860
+ children,
14861
+ theme = defaultTheme,
14862
+ ...otherProps
14863
+ } = props;
14864
+ return Table$1({
14865
+ ref,
14866
+ theme,
14867
+ children,
14868
+ ...otherProps
14869
+ });
13050
14870
  });
13051
14871
  Table.displayName = COMPONENT_NAME$d;
13052
14872
  Table.className = CLASSNAME$c;
@@ -13066,21 +14886,44 @@ const CLASSNAME$b = `${CLASSNAME$c}__body`;
13066
14886
  * TableBody component.
13067
14887
  *
13068
14888
  * @param props Component props.
13069
- * @param ref Component ref.
13070
14889
  * @return React element.
13071
14890
  */
13072
- const TableBody = forwardRef((props, ref) => {
14891
+ const TableBody$1 = props => {
13073
14892
  const {
13074
14893
  children,
13075
14894
  className,
14895
+ ref,
13076
14896
  ...forwardedProps
13077
14897
  } = props;
13078
14898
  return /*#__PURE__*/jsx("tbody", {
13079
14899
  ref: ref,
13080
14900
  ...forwardedProps,
13081
- className: classNames.join(className, CLASSNAME$b),
14901
+ className: classnames(className, CLASSNAME$b),
13082
14902
  children: children
13083
14903
  });
14904
+ };
14905
+
14906
+ /**
14907
+ * Defines the props of the component.
14908
+ */
14909
+
14910
+ /**
14911
+ * TableBody component.
14912
+ *
14913
+ * @param props Component props.
14914
+ * @param ref Component ref.
14915
+ * @return React element.
14916
+ */
14917
+ const TableBody = forwardRef((props, ref) => {
14918
+ const {
14919
+ children,
14920
+ ...otherProps
14921
+ } = props;
14922
+ return TableBody$1({
14923
+ ref,
14924
+ children,
14925
+ ...otherProps
14926
+ });
13084
14927
  });
13085
14928
  TableBody.displayName = COMPONENT_NAME$c;
13086
14929
  TableBody.className = CLASSNAME$b;
@@ -13112,7 +14955,7 @@ const COMPONENT_NAME$b = 'TableCell';
13112
14955
  const CLASSNAME$a = `${CLASSNAME$c}__cell`;
13113
14956
  const {
13114
14957
  block: block$c
13115
- } = classNames.bem(CLASSNAME$a);
14958
+ } = bem(CLASSNAME$a);
13116
14959
 
13117
14960
  /**
13118
14961
  * Component default props.
@@ -13125,16 +14968,16 @@ const DEFAULT_PROPS$e = {
13125
14968
  * TableCell component.
13126
14969
  *
13127
14970
  * @param props Component props.
13128
- * @param ref Component ref.
13129
14971
  * @return React element.
13130
14972
  */
13131
- const TableCell = forwardRef((props, ref) => {
14973
+ const TableCell$1 = props => {
13132
14974
  const {
13133
14975
  children,
13134
14976
  className,
13135
14977
  icon,
13136
14978
  isSortable,
13137
14979
  onHeaderClick,
14980
+ ref,
13138
14981
  sortOrder,
13139
14982
  variant = DEFAULT_PROPS$e.variant,
13140
14983
  ...forwardedProps
@@ -13158,7 +15001,7 @@ const TableCell = forwardRef((props, ref) => {
13158
15001
  children: [variant === TableCellVariant.head && /*#__PURE__*/jsx("th", {
13159
15002
  ref: ref,
13160
15003
  ...forwardedProps,
13161
- className: classNames.join(className, block$c({
15004
+ className: classnames(className, block$c({
13162
15005
  'is-sortable': isSortable,
13163
15006
  'is-sorted': isSortable && !!sortOrder,
13164
15007
  head: true
@@ -13167,26 +15010,27 @@ const TableCell = forwardRef((props, ref) => {
13167
15010
  children: /*#__PURE__*/jsxs(Wrapper, {
13168
15011
  className: `${CLASSNAME$a}-wrapper`,
13169
15012
  ...wrapperProps,
13170
- children: [icon && !isSortable && /*#__PURE__*/jsx(Icon, {
15013
+ children: [icon && !isSortable && Icon$1({
13171
15014
  className: `${CLASSNAME$a}-icon`,
13172
- icon: icon,
13173
- size: Size$1.xxs
13174
- }), isSortable && sortOrder === ThOrder.asc && /*#__PURE__*/jsx(Icon, {
15015
+ icon,
15016
+ size: Size.xxs
15017
+ }), isSortable && sortOrder === ThOrder.asc && Icon$1({
13175
15018
  className: `${CLASSNAME$a}-icon`,
13176
15019
  icon: mdiArrowUp,
13177
- size: Size$1.xxs
13178
- }), isSortable && sortOrder === ThOrder.desc && /*#__PURE__*/jsx(Icon, {
15020
+ size: Size.xxs
15021
+ }), isSortable && sortOrder === ThOrder.desc && Icon$1({
13179
15022
  className: `${CLASSNAME$a}-icon`,
13180
15023
  icon: mdiArrowDown,
13181
- size: Size$1.xxs
15024
+ size: Size.xxs
13182
15025
  }), /*#__PURE__*/jsx("div", {
13183
15026
  className: `${CLASSNAME$a}-content`,
13184
15027
  children: children
13185
15028
  })]
13186
15029
  })
13187
15030
  }), variant === TableCellVariant.body && /*#__PURE__*/jsx("td", {
15031
+ ref: ref,
13188
15032
  ...forwardedProps,
13189
- className: classNames.join(className, block$c({
15033
+ className: classnames(className, block$c({
13190
15034
  body: true
13191
15035
  })),
13192
15036
  children: /*#__PURE__*/jsx("div", {
@@ -13195,6 +15039,29 @@ const TableCell = forwardRef((props, ref) => {
13195
15039
  })
13196
15040
  })]
13197
15041
  });
15042
+ };
15043
+
15044
+ /**
15045
+ * Defines the props of the component.
15046
+ */
15047
+
15048
+ /**
15049
+ * TableCell component.
15050
+ *
15051
+ * @param props Component props.
15052
+ * @param ref Component ref.
15053
+ * @return React element.
15054
+ */
15055
+ const TableCell = forwardRef((props, ref) => {
15056
+ const {
15057
+ children,
15058
+ ...otherProps
15059
+ } = props;
15060
+ return TableCell$1({
15061
+ ref,
15062
+ children,
15063
+ ...otherProps
15064
+ });
13198
15065
  });
13199
15066
  TableCell.displayName = COMPONENT_NAME$b;
13200
15067
  TableCell.className = CLASSNAME$a;
@@ -13219,21 +15086,44 @@ const DEFAULT_PROPS$d = {};
13219
15086
  * TableHeader component.
13220
15087
  *
13221
15088
  * @param props Component props.
13222
- * @param ref Component ref.
13223
15089
  * @return React element.
13224
15090
  */
13225
- const TableHeader = forwardRef((props, ref) => {
15091
+ const TableHeader$1 = props => {
13226
15092
  const {
13227
15093
  children,
13228
15094
  className,
15095
+ ref,
13229
15096
  ...forwardedProps
13230
15097
  } = props;
13231
15098
  return /*#__PURE__*/jsx("thead", {
13232
15099
  ref: ref,
13233
15100
  ...forwardedProps,
13234
- className: classNames.join(className, CLASSNAME$9),
15101
+ className: classnames(className, CLASSNAME$9),
13235
15102
  children: children
13236
15103
  });
15104
+ };
15105
+
15106
+ /**
15107
+ * Defines the props of the component.
15108
+ */
15109
+
15110
+ /**
15111
+ * TableHeader component.
15112
+ *
15113
+ * @param props Component props.
15114
+ * @param ref Component ref.
15115
+ * @return React element.
15116
+ */
15117
+ const TableHeader = forwardRef((props, ref) => {
15118
+ const {
15119
+ children,
15120
+ ...otherProps
15121
+ } = props;
15122
+ return TableHeader$1({
15123
+ ref,
15124
+ children,
15125
+ ...otherProps
15126
+ });
13237
15127
  });
13238
15128
  TableHeader.displayName = COMPONENT_NAME$a;
13239
15129
  TableHeader.className = CLASSNAME$9;
@@ -13250,7 +15140,7 @@ const COMPONENT_NAME$9 = 'TableRow';
13250
15140
  const CLASSNAME$8 = `${CLASSNAME$c}__row`;
13251
15141
  const {
13252
15142
  block: block$b
13253
- } = classNames.bem(CLASSNAME$8);
15143
+ } = bem(CLASSNAME$8);
13254
15144
 
13255
15145
  /**
13256
15146
  * Component default props.
@@ -13261,34 +15151,69 @@ const DEFAULT_PROPS$c = {};
13261
15151
  * TableRow component.
13262
15152
  *
13263
15153
  * @param props Component props.
13264
- * @param ref Component ref.
13265
15154
  * @return React element.
13266
15155
  */
13267
- const TableRow = forwardRef((props, ref) => {
13268
- const {
13269
- isAnyDisabled,
13270
- disabledStateProps,
13271
- otherProps
13272
- } = useDisableStateProps(props);
15156
+ const TableRow$1 = props => {
13273
15157
  const {
13274
15158
  children,
13275
15159
  className,
13276
15160
  isClickable,
13277
15161
  isSelected,
15162
+ ref,
15163
+ tabIndex,
15164
+ 'aria-disabled': ariaDisabled,
13278
15165
  ...forwardedProps
13279
- } = otherProps;
15166
+ } = props;
15167
+ const isDisabled = Boolean(ariaDisabled);
15168
+
15169
+ // Use object spread for tabIndex to ensure cross-framework compatibility (Vue JSX expects lowercase 'tabindex')
15170
+ const tabIndexProps = tabIndex !== undefined ? {
15171
+ tabIndex
15172
+ } : {};
13280
15173
  return /*#__PURE__*/jsx("tr", {
13281
15174
  ref: ref,
13282
- tabIndex: isClickable && !disabledStateProps.disabled ? 0 : -1,
15175
+ "aria-disabled": ariaDisabled,
15176
+ ...tabIndexProps,
13283
15177
  ...forwardedProps,
13284
- className: classNames.join(className, block$b({
13285
- 'is-clickable': isClickable && !isAnyDisabled,
13286
- 'is-disabled': isAnyDisabled,
13287
- 'is-selected': isSelected && !isAnyDisabled
15178
+ className: classnames(className, block$b({
15179
+ 'is-clickable': isClickable && !isDisabled,
15180
+ 'is-disabled': isDisabled,
15181
+ 'is-selected': isSelected && !isDisabled
13288
15182
  })),
13289
- "aria-disabled": isAnyDisabled,
13290
15183
  children: children
13291
15184
  });
15185
+ };
15186
+
15187
+ /**
15188
+ * Defines the props of the component.
15189
+ */
15190
+
15191
+ /**
15192
+ * TableRow component.
15193
+ *
15194
+ * @param props Component props.
15195
+ * @param ref Component ref.
15196
+ * @return React element.
15197
+ */
15198
+ const TableRow = forwardRef((props, ref) => {
15199
+ const {
15200
+ isAnyDisabled,
15201
+ otherProps
15202
+ } = useDisableStateProps(props);
15203
+ const {
15204
+ children,
15205
+ isClickable,
15206
+ 'aria-disabled': _ariaDisabled,
15207
+ ...forwardedProps
15208
+ } = otherProps;
15209
+ return TableRow$1({
15210
+ ref,
15211
+ children,
15212
+ isClickable,
15213
+ tabIndex: isClickable && !isAnyDisabled ? 0 : -1,
15214
+ 'aria-disabled': isAnyDisabled,
15215
+ ...forwardedProps
15216
+ });
13292
15217
  });
13293
15218
  TableRow.displayName = COMPONENT_NAME$9;
13294
15219
  TableRow.className = CLASSNAME$8;
@@ -13953,7 +15878,14 @@ TextField.displayName = COMPONENT_NAME$5;
13953
15878
  TextField.className = CLASSNAME$5;
13954
15879
  TextField.defaultProps = DEFAULT_PROPS$5;
13955
15880
 
13956
- function getState(img, event) {
15881
+ /**
15882
+ * Determines the loading state of an HTML image element.
15883
+ *
15884
+ * @param img - The HTML image element to check
15885
+ * @param event - Optional event (load or error) that triggered the state check
15886
+ * @returns The current loading state: 'hasError', 'isLoading', or 'isLoaded'
15887
+ */
15888
+ function getImageLoadingState(img, event) {
13957
15889
  // Error event occurred or image has no source.
13958
15890
  if (event?.type === 'error' || img?.complete && !img.getAttribute('src')) {
13959
15891
  return 'hasError';
@@ -13965,30 +15897,58 @@ function getState(img, event) {
13965
15897
  // Else loaded.
13966
15898
  return 'isLoaded';
13967
15899
  }
13968
- function useImageLoad(imageURL, imgRef) {
13969
- const [state, setState] = useState(getState(imgRef));
13970
15900
 
13971
- // Update state when changing image URL or DOM reference.
13972
- useEffect(() => {
13973
- setState(getState(imgRef));
13974
- }, [imageURL, imgRef]);
15901
+ /**
15902
+ * Parameters for getting image size.
15903
+ */
13975
15904
 
13976
- // Listen to `load` and `error` event on image
13977
- useEffect(() => {
13978
- const img = imgRef;
13979
- if (!img) return undefined;
13980
- const update = event => setState(getState(img, event));
13981
- img.addEventListener('load', update);
13982
- img.addEventListener('error', update);
13983
- return () => {
13984
- img.removeEventListener('load', update);
13985
- img.removeEventListener('error', update);
15905
+ /**
15906
+ * Gets the natural image size from props or element.
15907
+ * Returns undefined if focus point is not applicable or size cannot be determined.
15908
+ *
15909
+ * @param params - Image size parameters
15910
+ * @returns Image size or undefined
15911
+ */
15912
+ function getImageSize({
15913
+ image,
15914
+ aspectRatio,
15915
+ focusPoint,
15916
+ width,
15917
+ height,
15918
+ element,
15919
+ isLoaded
15920
+ }) {
15921
+ // Focus point is not applicable => exit early
15922
+ if (!image || aspectRatio === AspectRatio.original || !focusPoint?.x && !focusPoint?.y) {
15923
+ return undefined;
15924
+ }
15925
+ // Size provided via props
15926
+ if (typeof width === 'number' && typeof height === 'number') {
15927
+ return {
15928
+ width,
15929
+ height
13986
15930
  };
13987
- }, [imgRef, imgRef?.src]);
13988
- return state;
15931
+ }
15932
+ // Size from loaded element
15933
+ if (element && isLoaded) {
15934
+ return {
15935
+ width: element.naturalWidth,
15936
+ height: element.naturalHeight
15937
+ };
15938
+ }
15939
+ return undefined;
13989
15940
  }
13990
15941
 
13991
- // Calculate shift to center the focus point in the container.
15942
+ /**
15943
+ * Calculate shift position to center the focus point in the container.
15944
+ *
15945
+ * This function computes the percentage offset needed to position an image
15946
+ * such that a specific focus point on the image aligns with the center of
15947
+ * the container, taking into account the image's scale.
15948
+ *
15949
+ * @param params - Focus point shift calculation parameters
15950
+ * @returns Percentage shift (0-100) for CSS positioning
15951
+ */
13992
15952
  function shiftPosition({
13993
15953
  scale,
13994
15954
  focusPoint,
@@ -14003,92 +15963,64 @@ function shiftPosition({
14003
15963
  return Math.floor(Math.max(Math.min(shift, 1), 0) * 100);
14004
15964
  }
14005
15965
 
14006
- // Compute CSS properties to apply the focus point.
14007
- const useFocusPointStyle = ({
15966
+ /**
15967
+ * Parameters for calculating focus point style.
15968
+ */
15969
+
15970
+ /**
15971
+ * Calculates CSS style for applying focus point positioning.
15972
+ *
15973
+ * @param params - Focus point style parameters
15974
+ * @returns CSS properties to apply to the image
15975
+ */
15976
+ function calculateFocusPointStyle({
14008
15977
  image,
14009
15978
  aspectRatio,
14010
15979
  focusPoint,
14011
- imgProps: {
14012
- width,
14013
- height
14014
- } = {}
14015
- }, element, isLoaded) => {
14016
- // Get natural image size from imgProps or img element.
14017
- const imageSize = useMemo(() => {
14018
- // Focus point is not applicable => exit early
14019
- if (!image || aspectRatio === AspectRatio.original || !focusPoint?.x && !focusPoint?.y) return undefined;
14020
- if (typeof width === 'number' && typeof height === 'number') return {
14021
- width,
14022
- height
14023
- };
14024
- if (element && isLoaded) return {
14025
- width: element.naturalWidth,
14026
- height: element.naturalHeight
15980
+ element,
15981
+ imageSize,
15982
+ containerSize
15983
+ }) {
15984
+ // Focus point is not applicable => exit early
15985
+ if (!image || aspectRatio === AspectRatio.original || !focusPoint?.x && !focusPoint?.y) {
15986
+ return {};
15987
+ }
15988
+ if (!element || !imageSize) {
15989
+ // Focus point can be computed but not right now (image size unknown).
15990
+ return {
15991
+ visibility: 'hidden'
14027
15992
  };
14028
- return undefined;
14029
- }, [aspectRatio, element, focusPoint?.x, focusPoint?.y, height, image, isLoaded, width]);
14030
-
14031
- // Get container size (dependant on imageSize).
14032
- const [containerSize, setContainerSize] = useState(undefined);
14033
- useEffect(function updateContainerSize() {
14034
- const cWidth = element?.offsetWidth;
14035
- const cHeight = element?.offsetHeight;
14036
- if (cWidth && cHeight) {
14037
- // Update only if needed.
14038
- setContainerSize(oldContainerSize => oldContainerSize?.width === cWidth && oldContainerSize.height === cHeight ? oldContainerSize : {
14039
- width: cWidth,
14040
- height: cHeight
14041
- });
14042
- } else if (imageSize) {
14043
- // Wait for a render (in case the container size is dependent on the image size).
14044
- requestAnimationFrame(updateContainerSize);
14045
- }
14046
- }, [element?.offsetHeight, element?.offsetWidth, imageSize]);
15993
+ }
15994
+ if (!containerSize || !imageSize.height || !imageSize.width) {
15995
+ // Missing container or image size, abort focus point compute.
15996
+ return {};
15997
+ }
15998
+ const heightScale = imageSize.height / containerSize.height;
15999
+ const widthScale = imageSize.width / containerSize.width;
16000
+ const scale = Math.min(widthScale, heightScale);
14047
16001
 
14048
- // Compute style.
14049
- const style = useMemo(() => {
14050
- // Focus point is not applicable => exit early
14051
- if (!image || aspectRatio === AspectRatio.original || !focusPoint?.x && !focusPoint?.y) {
14052
- return {};
14053
- }
14054
- if (!element || !imageSize) {
14055
- // Focus point can be computed but now right now (image size unknown).
14056
- return {
14057
- visibility: 'hidden'
14058
- };
14059
- }
14060
- if (!containerSize || !imageSize.height || !imageSize.width) {
14061
- // Missing container or image size abort focus point compute.
14062
- return {};
14063
- }
14064
- const heightScale = imageSize.height / containerSize.height;
14065
- const widthScale = imageSize.width / containerSize.width;
14066
- const scale = Math.min(widthScale, heightScale);
14067
-
14068
- // Focus Y relative to the top (instead of the center)
14069
- const focusPointFromTop = Math.abs((focusPoint?.y || 0) - 1) / 2;
14070
- const y = shiftPosition({
14071
- scale,
14072
- focusPoint: focusPointFromTop,
14073
- imageSize: imageSize.height,
14074
- containerSize: containerSize.height
14075
- });
16002
+ // Focus Y relative to the top (instead of the center)
16003
+ const focusPointFromTop = Math.abs((focusPoint?.y || 0) - 1) / 2;
16004
+ const y = shiftPosition({
16005
+ scale,
16006
+ focusPoint: focusPointFromTop,
16007
+ imageSize: imageSize.height,
16008
+ containerSize: containerSize.height
16009
+ });
14076
16010
 
14077
- // Focus X relative to the left (instead of the center)
14078
- const focusPointFromLeft = Math.abs((focusPoint?.x || 0) + 1) / 2;
14079
- const x = shiftPosition({
14080
- scale,
14081
- focusPoint: focusPointFromLeft,
14082
- imageSize: imageSize.width,
14083
- containerSize: containerSize.width
14084
- });
14085
- const objectPosition = `${x}% ${y}%`;
14086
- return {
14087
- objectPosition
14088
- };
14089
- }, [aspectRatio, containerSize, element, focusPoint?.x, focusPoint?.y, image, imageSize]);
14090
- return style;
14091
- };
16011
+ // Focus X relative to the left (instead of the center)
16012
+ const focusPointFromLeft = Math.abs((focusPoint?.x || 0) + 1) / 2;
16013
+ const x = shiftPosition({
16014
+ scale,
16015
+ focusPoint: focusPointFromLeft,
16016
+ imageSize: imageSize.width,
16017
+ containerSize: containerSize.width
16018
+ });
16019
+ const objectPosition = `${x}% ${y}%`;
16020
+ return {
16021
+ objectPosition
16022
+ };
16023
+ }
14092
16024
 
14093
16025
  /**
14094
16026
  * Component display name.
@@ -14119,25 +16051,18 @@ const DEFAULT_PROPS$4 = {
14119
16051
  * @param ref Component ref.
14120
16052
  * @return React element.
14121
16053
  */
14122
- const Thumbnail = forwardRef((props, ref) => {
14123
- const {
14124
- isAnyDisabled,
14125
- otherProps,
14126
- disabledStateProps
14127
- } = useDisableStateProps(props);
14128
- const defaultTheme = useTheme() || Theme$1.light;
16054
+ const Thumbnail$1 = props => {
14129
16055
  const {
14130
16056
  align,
14131
16057
  alt,
14132
- aspectRatio = AspectRatio.original,
16058
+ aspectRatio = AspectRatio$1.original,
14133
16059
  badge,
14134
16060
  className,
14135
16061
  crossOrigin,
16062
+ ref,
14136
16063
  fallback = DEFAULT_PROPS$4.fallback,
16064
+ focusPointStyle,
14137
16065
  fillHeight,
14138
- // `focusPoint` needs to be here to remove it from `forwardedProps`.
14139
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
14140
- focusPoint,
14141
16066
  image,
14142
16067
  imgProps,
14143
16068
  imgRef: propImgRef,
@@ -14145,23 +16070,18 @@ const Thumbnail = forwardRef((props, ref) => {
14145
16070
  objectFit,
14146
16071
  loading = DEFAULT_PROPS$4.loading,
14147
16072
  loadingPlaceholderImageRef,
16073
+ isAnyDisabled,
16074
+ disabledStateProps,
14148
16075
  size,
14149
- theme = defaultTheme,
16076
+ theme,
16077
+ loadingState,
14150
16078
  variant,
14151
16079
  linkProps,
14152
16080
  linkAs,
14153
16081
  ...forwardedProps
14154
- } = otherProps;
14155
- const [imgElement, setImgElement] = useState();
14156
-
14157
- // Image loading state.
14158
- const loadingState = useImageLoad(image, imgElement);
14159
- const isLoaded = loadingState === 'isLoaded';
16082
+ } = props;
14160
16083
  const isLoading = isLoadingProp || loadingState === 'isLoading';
14161
16084
  const hasError = loadingState === 'hasError';
14162
-
14163
- // Focus point.
14164
- const focusPointStyle = useFocusPointStyle(props, imgElement, isLoaded);
14165
16085
  const hasIconErrorFallback = hasError && typeof fallback === 'string';
14166
16086
  const hasCustomErrorFallback = hasError && !hasIconErrorFallback;
14167
16087
  const imageErrorStyle = {};
@@ -14174,7 +16094,6 @@ const Thumbnail = forwardRef((props, ref) => {
14174
16094
  }
14175
16095
  const isLink = Boolean(linkProps?.href || linkAs);
14176
16096
  const isClickable = !isAnyDisabled && Boolean(isLink || !!forwardedProps.onClick);
14177
- const Wrapper = isClickable ? RawClickable : 'div';
14178
16097
  const wrapperProps = {
14179
16098
  ...forwardedProps
14180
16099
  };
@@ -14188,6 +16107,21 @@ const Thumbnail = forwardRef((props, ref) => {
14188
16107
  wrapperProps['aria-label'] = forwardedProps['aria-label'] || alt;
14189
16108
  }
14190
16109
  }
16110
+ const wrapperClassName = classNames.join(linkProps?.className, className, block$4({
16111
+ [`align-${align}`]: Boolean(align),
16112
+ [`aspect-ratio-${aspectRatio}`]: Boolean(aspectRatio),
16113
+ [`size-${size}`]: Boolean(size),
16114
+ [`theme-${theme}`]: Boolean(theme),
16115
+ [`variant-${variant}`]: Boolean(variant),
16116
+ 'is-clickable': isClickable,
16117
+ 'has-error': hasError,
16118
+ 'has-icon-error-fallback': hasIconErrorFallback,
16119
+ 'has-custom-error-fallback': hasCustomErrorFallback,
16120
+ 'is-loading': isLoading,
16121
+ [`object-fit-${objectFit}`]: Boolean(objectFit),
16122
+ 'has-badge': !!badge,
16123
+ 'fill-height': fillHeight
16124
+ }));
14191
16125
 
14192
16126
  // If we have a loading placeholder image that is really loaded (complete)
14193
16127
  const loadingPlaceholderImage = isLoading && loadingPlaceholderImageRef?.current?.complete && loadingPlaceholderImageRef?.current || undefined;
@@ -14196,24 +16130,7 @@ const Thumbnail = forwardRef((props, ref) => {
14196
16130
  const loadingStyle = loadingPlaceholderImage ? {
14197
16131
  backgroundImage: `url(${loadingPlaceholderImage.src})`
14198
16132
  } : undefined;
14199
- return /*#__PURE__*/jsxs(Wrapper, {
14200
- ...wrapperProps,
14201
- ref: ref,
14202
- className: classNames.join(linkProps?.className, className, block$4({
14203
- [`align-${align}`]: Boolean(align),
14204
- [`aspect-ratio-${aspectRatio}`]: Boolean(aspectRatio),
14205
- [`size-${size}`]: Boolean(size),
14206
- [`theme-${theme}`]: Boolean(theme),
14207
- [`variant-${variant}`]: Boolean(variant),
14208
- 'is-clickable': isClickable,
14209
- 'has-error': hasError,
14210
- 'has-icon-error-fallback': hasIconErrorFallback,
14211
- 'has-custom-error-fallback': hasCustomErrorFallback,
14212
- 'is-loading': isLoading,
14213
- [`object-fit-${objectFit}`]: Boolean(objectFit),
14214
- 'has-badge': !!badge,
14215
- 'fill-height': fillHeight
14216
- })),
16133
+ const innerImage = /*#__PURE__*/jsxs(Fragment, {
14217
16134
  children: [/*#__PURE__*/jsxs("span", {
14218
16135
  className: element$4('background'),
14219
16136
  children: [/*#__PURE__*/jsx("img", {
@@ -14229,26 +16146,165 @@ const Thumbnail = forwardRef((props, ref) => {
14229
16146
  ...focusPointStyle,
14230
16147
  ...loadingStyle
14231
16148
  },
14232
- ref: useMergeRefs(setImgElement, propImgRef),
16149
+ ref: propImgRef,
14233
16150
  className: classNames.join(element$4('image', {
14234
16151
  'is-loading': isLoading,
14235
16152
  'has-defined-size': Boolean(imgProps?.height && imgProps.width)
14236
- }), imgProps?.className),
16153
+ }), imgProps?.className)
16154
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
16155
+ // @ts-ignore - crossOrigin prop compatibility between React and Vue JSX
16156
+ ,
14237
16157
  crossOrigin: crossOrigin,
14238
16158
  src: image,
14239
16159
  alt: alt,
14240
16160
  loading: loading
14241
16161
  }), !isLoading && hasError && /*#__PURE__*/jsx("span", {
14242
16162
  className: element$4('fallback'),
14243
- children: hasIconErrorFallback ? /*#__PURE__*/jsx(Icon, {
16163
+ children: hasIconErrorFallback ? Icon$1({
14244
16164
  icon: fallback,
14245
16165
  size: Size$1.xxs,
14246
- theme: theme
16166
+ theme
14247
16167
  }) : fallback
14248
16168
  })]
14249
- }), badge && /*#__PURE__*/React__default.cloneElement(badge, {
16169
+ }), badge]
16170
+ });
16171
+
16172
+ /** Render `RawClickable` as a function since it is a core component which needs to be treated as such */
16173
+ if (isClickable) {
16174
+ return RawClickable$1({
16175
+ ref,
16176
+ ...wrapperProps,
16177
+ className: wrapperClassName,
16178
+ children: innerImage
16179
+ });
16180
+ }
16181
+ return /*#__PURE__*/jsx("div", {
16182
+ ref: ref,
16183
+ ...wrapperProps,
16184
+ className: wrapperClassName,
16185
+ children: innerImage
16186
+ });
16187
+ };
16188
+
16189
+ function useImageLoad(imageURL, imgRef) {
16190
+ const [state, setState] = useState(getImageLoadingState(imgRef));
16191
+
16192
+ // Update state when changing image URL or DOM reference.
16193
+ useEffect(() => {
16194
+ setState(getImageLoadingState(imgRef));
16195
+ }, [imageURL, imgRef]);
16196
+
16197
+ // Listen to `load` and `error` event on image
16198
+ useEffect(() => {
16199
+ const img = imgRef;
16200
+ if (!img) return undefined;
16201
+ const update = event => setState(getImageLoadingState(img, event));
16202
+ img.addEventListener('load', update);
16203
+ img.addEventListener('error', update);
16204
+ return () => {
16205
+ img.removeEventListener('load', update);
16206
+ img.removeEventListener('error', update);
16207
+ };
16208
+ }, [imgRef, imgRef?.src]);
16209
+ return state;
16210
+ }
16211
+
16212
+ // Compute CSS properties to apply the focus point.
16213
+ const useFocusPointStyle = ({
16214
+ image,
16215
+ aspectRatio,
16216
+ focusPoint,
16217
+ imgProps: {
16218
+ width,
16219
+ height
16220
+ } = {}
16221
+ }, element, isLoaded) => {
16222
+ // Get natural image size from imgProps or img element.
16223
+ const imageSize = useMemo(() => getImageSize({
16224
+ image,
16225
+ aspectRatio,
16226
+ focusPoint,
16227
+ width: typeof width === 'number' ? width : undefined,
16228
+ height: typeof height === 'number' ? height : undefined,
16229
+ element,
16230
+ isLoaded
16231
+ }), [aspectRatio, element, focusPoint, height, image, isLoaded, width]);
16232
+
16233
+ // Get container size (dependant on imageSize).
16234
+ const [containerSize, setContainerSize] = useState(undefined);
16235
+ useEffect(function updateContainerSize() {
16236
+ const cWidth = element?.offsetWidth;
16237
+ const cHeight = element?.offsetHeight;
16238
+ if (cWidth && cHeight) {
16239
+ // Update only if needed.
16240
+ setContainerSize(oldContainerSize => oldContainerSize?.width === cWidth && oldContainerSize.height === cHeight ? oldContainerSize : {
16241
+ width: cWidth,
16242
+ height: cHeight
16243
+ });
16244
+ } else if (imageSize) {
16245
+ // Wait for a render (in case the container size is dependent on the image size).
16246
+ requestAnimationFrame(updateContainerSize);
16247
+ }
16248
+ }, [element?.offsetHeight, element?.offsetWidth, imageSize]);
16249
+
16250
+ // Compute style.
16251
+ const style = useMemo(() => calculateFocusPointStyle({
16252
+ image,
16253
+ aspectRatio,
16254
+ focusPoint,
16255
+ element,
16256
+ imageSize,
16257
+ containerSize
16258
+ }), [aspectRatio, containerSize, element, focusPoint, image, imageSize]);
16259
+ return style;
16260
+ };
16261
+
16262
+ /**
16263
+ * Defines the props of the component.
16264
+ */
16265
+
16266
+ /**
16267
+ * Thumbnail component.
16268
+ *
16269
+ * @param props Component props.
16270
+ * @param ref Component ref.
16271
+ * @return React element.
16272
+ */
16273
+ const Thumbnail = forwardRef((props, ref) => {
16274
+ const {
16275
+ isAnyDisabled,
16276
+ otherProps,
16277
+ disabledStateProps
16278
+ } = useDisableStateProps(props);
16279
+ const defaultTheme = useTheme() || Theme$1.light;
16280
+ const {
16281
+ badge,
16282
+ focusPoint,
16283
+ image,
16284
+ imgRef: propImgRef,
16285
+ ...forwardedProps
16286
+ } = otherProps;
16287
+ const [imgElement, setImgElement] = useState();
16288
+
16289
+ // Image loading state.
16290
+ const loadingState = useImageLoad(image, imgElement);
16291
+ const isLoaded = loadingState === 'isLoaded';
16292
+
16293
+ // Focus point.
16294
+ const focusPointStyle = useFocusPointStyle(props, imgElement, isLoaded);
16295
+ return Thumbnail$1({
16296
+ ref,
16297
+ ...forwardedProps,
16298
+ theme: forwardedProps.theme || defaultTheme,
16299
+ isAnyDisabled,
16300
+ disabledStateProps,
16301
+ focusPointStyle,
16302
+ loadingState,
16303
+ imgRef: useMergeRefs(setImgElement, propImgRef),
16304
+ image,
16305
+ badge: badge && /*#__PURE__*/React__default.cloneElement(badge, {
14250
16306
  className: classNames.join(element$4('badge'), badge.props.className)
14251
- })]
16307
+ })
14252
16308
  });
14253
16309
  });
14254
16310
  Thumbnail.displayName = COMPONENT_NAME$4;
@@ -14270,7 +16326,7 @@ Thumbnail.defaultProps = DEFAULT_PROPS$4;
14270
16326
  * @deprecated
14271
16327
  */
14272
16328
  const ThumbnailAspectRatio = {
14273
- ...AspectRatio
16329
+ ...AspectRatio$1
14274
16330
  };
14275
16331
 
14276
16332
  /**
@@ -14701,7 +16757,7 @@ const {
14701
16757
  * Component default props.
14702
16758
  */
14703
16759
  const DEFAULT_PROPS$1 = {
14704
- aspectRatio: AspectRatio.horizontal,
16760
+ aspectRatio: AspectRatio$1.horizontal,
14705
16761
  size: Size$1.xl,
14706
16762
  variant: UploaderVariant.square
14707
16763
  };
@@ -14733,7 +16789,7 @@ const Uploader = forwardRef((props, ref) => {
14733
16789
  ...forwardedProps
14734
16790
  } = otherProps;
14735
16791
  // Adjust to square aspect ratio when using circle variants.
14736
- const adjustedAspectRatio = variant === UploaderVariant.circle ? AspectRatio.square : aspectRatio;
16792
+ const adjustedAspectRatio = variant === UploaderVariant.circle ? AspectRatio$1.square : aspectRatio;
14737
16793
  const handleClick = React__default.useCallback(evt => {
14738
16794
  if (isAnyDisabled) {
14739
16795
  evt.preventDefault();
@@ -14946,5 +17002,5 @@ UserBlock.displayName = COMPONENT_NAME;
14946
17002
  UserBlock.className = CLASSNAME;
14947
17003
  UserBlock.defaultProps = DEFAULT_PROPS;
14948
17004
 
14949
- export { AlertDialog, Autocomplete, AutocompleteMultiple, Avatar, Badge, BadgeWrapper, Button, ButtonGroup, CLASSNAME$1d as CLASSNAME, COMPONENT_NAME$1e as COMPONENT_NAME, Checkbox, Chip, ChipGroup, CommentBlock, CommentBlockVariant, DEFAULT_PROPS$14 as DEFAULT_PROPS, DatePicker, DatePickerControlled, DatePickerField, Dialog, Divider, DragHandle, Dropdown, ExpansionPanel, Flag, FlexBox, GenericBlock, GenericBlockGapSize, Grid, GridColumn, GridItem, Heading, HeadingLevelProvider, Icon, IconButton, ImageBlock, ImageBlockCaptionPosition, ImageLightbox, InlineList, InputHelper, InputLabel, Lightbox, Link, LinkPreview, List, ListDivider, ListItem, ListSubheader, Message, Mosaic, Navigation, Notification, Placement, Popover, PopoverDialog, PostBlock, Progress, ProgressCircular, ProgressLinear, ProgressTracker, ProgressTrackerProvider, ProgressTrackerStep, ProgressTrackerStepPanel, ProgressVariant, RadioButton, RadioGroup, RawInputText, RawInputTextarea, Select, SelectMultiple, SelectMultipleField, SelectVariant, SelectionChipGroup, SideNavigation, SideNavigationItem, SkeletonCircle, SkeletonRectangle, SkeletonRectangleVariant, SkeletonTypography, Slider, Slides, Slideshow, SlideshowControls, SlideshowItem, Switch, Tab, TabList, TabListLayout, TabPanel, TabProvider, Table, TableBody, TableCell, TableCellVariant, TableHeader, TableRow, Text, TextField, ThOrder, ThemeProvider, Thumbnail, ThumbnailAspectRatio, ThumbnailObjectFit, ThumbnailVariant, Toolbar, Tooltip, Uploader, UploaderVariant, UserBlock, clamp, isClickable, useFocusPointStyle, useHeadingLevel, useTheme };
17005
+ export { AlertDialog, Autocomplete, AutocompleteMultiple, Avatar, Badge, BadgeWrapper, Button, ButtonGroup, COMPONENT_NAME$1e as COMPONENT_NAME, Checkbox, Chip, ChipGroup, Combobox, ComboboxButton, ComboboxDivider, ComboboxInput, ComboboxListBox, ComboboxOption, ComboboxOptionAction, ComboboxOptionMoreInfo, ComboboxOptionSkeleton, ComboboxSection, CommentBlock, CommentBlockVariant, DEFAULT_PROPS$16 as DEFAULT_PROPS, DatePicker, DatePickerControlled, DatePickerField, Dialog, Divider, DragHandle, Dropdown, ExpansionPanel, Flag, FlexBox, GenericBlock, GenericBlockGapSize, Grid, GridColumn, GridItem, Heading, HeadingLevelProvider, Icon, IconButton, ImageBlock, ImageBlockCaptionPosition, ImageLightbox, InlineList, InputHelper, InputLabel, LUMX_CLASSNAME, Lightbox, Link, LinkPreview, List, ListDivider, ListItem, ListSubheader, Message, Mosaic, Navigation, Notification, Placement, Popover, PopoverDialog, PostBlock, Progress, ProgressCircular, ProgressLinear, ProgressTracker, ProgressTrackerProvider, ProgressTrackerStep, ProgressTrackerStepPanel, ProgressVariant, RadioButton, RadioGroup, RawInputText, RawInputTextarea, SUB_COMPONENTS, Select, SelectMultiple, SelectMultipleField, SelectVariant, SelectionChipGroup, SideNavigation, SideNavigationItem, SkeletonCircle, SkeletonRectangle, SkeletonRectangleVariant, SkeletonTypography, Slider, Slides, Slideshow, SlideshowControls, SlideshowItem, Switch, Tab, TabList, TabListLayout, TabPanel, TabProvider, Table, TableBody, TableCell, TableCellVariant, TableHeader, TableRow, Text, TextField, ThOrder, ThemeProvider, Thumbnail, ThumbnailAspectRatio, ThumbnailObjectFit, ThumbnailVariant, Toolbar, Tooltip, Uploader, UploaderVariant, UserBlock, clamp, isClickable, useFocusPointStyle, useHeadingLevel, useTheme };
14950
17006
  //# sourceMappingURL=index.js.map