@digital-ai/dot-components 4.5.0 → 4.6.0

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.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { useState, useRef, useEffect, createContext, useMemo, useContext, forwardRef, useCallback, createElement, Fragment as Fragment$1, useLayoutEffect } from 'react';
4
- import { Tooltip, InputAdornment, InputLabel, TextField, Icon, Typography, Accordion, AccordionSummary, AccordionDetails, AccordionActions, Toolbar, Fade, StyledEngineProvider, Alert, Avatar, Button, Link, List, ListSubheader, Divider, CircularProgress, Popper, MenuList, MenuItem, Paper, ClickAwayListener, Drawer, IconButton, ListItem, ListItemButton, Collapse, ListItemIcon, ListItemText, Badge, useMediaQuery, Autocomplete, Chip, AvatarGroup, Breadcrumbs, ToggleButtonGroup, ToggleButton, Card, CardContent, CardHeader, FormControlLabel, Checkbox, FormControl, FormGroup, FormLabel, FormHelperText, Dialog, DialogContent, DialogActions, useTheme as useTheme$1, Snackbar, RadioGroup, Radio, Switch, Skeleton, ButtonGroup, Stepper, Step, StepLabel, StepContent, TablePagination, TableContainer, TableBody, TableCell, TableRow, TableSortLabel, TableHead, Table, Tabs, Tab, LinearProgress, Slide } from '@mui/material';
4
+ import { Tooltip, InputAdornment, InputLabel, TextField, Icon, Typography, Accordion, AccordionSummary, AccordionDetails, AccordionActions, Toolbar, Fade, StyledEngineProvider, Alert, Avatar, Button, Link, List, ListSubheader, Divider, CircularProgress, Popper, MenuList, MenuItem, Paper, ClickAwayListener, Drawer, IconButton, ListItem, ListItemButton, Collapse, ListItemIcon, ListItemText, Badge, useMediaQuery, Chip, Autocomplete, AvatarGroup, Breadcrumbs, ToggleButtonGroup, ToggleButton, Card, CardContent, CardHeader, FormControlLabel, Checkbox, FormControl, FormGroup, FormLabel, FormHelperText, Dialog, DialogContent, DialogActions, useTheme as useTheme$1, Snackbar, RadioGroup, Radio, Switch, Skeleton, ButtonGroup, Stepper, Step, StepLabel, TablePagination, TableContainer, TableBody, TableCell, TableRow, TableSortLabel, TableHead, Table, Tabs, Tab, LinearProgress, Slide } from '@mui/material';
5
5
  import '@digital-ai/dot-icons';
6
6
  import styled, { css, createGlobalStyle, ThemeProvider as ThemeProvider$1, keyframes } from 'styled-components';
7
7
  import { createTheme, ThemeProvider, useTheme } from '@mui/material/styles';
@@ -231,12 +231,22 @@ const StyledTextField = styled(TextField)`
231
231
  &.${rootClassName$1l} {
232
232
  .MuiInputBase-root {
233
233
  margin-bottom: 0;
234
+
235
+ &:not(.MuiAutocomplete-inputRoot) {
236
+ &.MuiInputBase-adornedStart {
237
+ padding-left: ${theme.spacing(1.5)};
238
+ }
239
+ &.MuiInputBase-adornedEnd {
240
+ padding-right: ${theme.spacing(1)};
241
+ }
242
+ }
234
243
  }
235
244
  .MuiInputBase-input {
236
245
  box-sizing: content-box;
237
246
  }
238
247
  .MuiOutlinedInput-input {
239
- padding: ${InputProps.startAdornment ? `18px 12px 18px 0px` : `18px 12px`};
248
+ padding: 18px ${InputProps.endAdornment ? '0px' : '12px'} 18px
249
+ ${InputProps.startAdornment ? '0px' : '12px'};
240
250
  &::placeholder {
241
251
  opacity: 1;
242
252
  color: ${theme.palette.figma.typography.gray};
@@ -280,6 +290,14 @@ const StyledTextField = styled(TextField)`
280
290
  .MuiInputBase-adornedEnd .clear-icon-button.hidden {
281
291
  visibility: hidden;
282
292
  }
293
+
294
+ .${adornmentIconClassName}.MuiInputAdornment-positionStart {
295
+ margin-right: ${theme.spacing(0.5)};
296
+ }
297
+
298
+ .${adornmentIconClassName}.MuiInputAdornment-positionEnd {
299
+ margin: ${theme.spacing(0)};
300
+ }
283
301
  }
284
302
 
285
303
  .dot-select,
@@ -377,12 +395,6 @@ const StyledTextField = styled(TextField)`
377
395
  }
378
396
  }
379
397
 
380
- .MuiInputBase-inputAdornedStart {
381
- padding-left: 12px;
382
- }
383
- .MuiInputBase-inputAdornedEnd {
384
- padding-right: 12px;
385
- }
386
398
  .MuiFormHelperText-root {
387
399
  ${formHelperTextRootStyles(theme)};
388
400
  }
@@ -6297,6 +6309,15 @@ const DotAppToolbar = ({
6297
6309
  }, index)
6298
6310
  }, index);
6299
6311
  });
6312
+ const getLogoLinkComponent = (accessibilityLabel, customClass, dataTestid, linkHref, component) => {
6313
+ return linkHref ? jsx(DotLink, {
6314
+ ariaLabel: accessibilityLabel,
6315
+ className: customClass,
6316
+ "data-testid": dataTestid,
6317
+ href: linkHref,
6318
+ children: component
6319
+ }) : component;
6320
+ };
6300
6321
  const appToolbar = jsxs(StyledAppToolbar, {
6301
6322
  "aria-label": ariaLabel,
6302
6323
  className: rootClasses,
@@ -6339,27 +6360,34 @@ const DotAppToolbar = ({
6339
6360
  })]
6340
6361
  }), jsxs("div", {
6341
6362
  className: "dot-branding",
6342
- children: [jsx(DotLink, {
6343
- ariaLabel: "Digital.ai Logo",
6344
- className: "primary-logo",
6345
- "data-testid": "primary-logo",
6346
- href: primaryLogoHref,
6347
- children: customLogo ? customLogo : jsx(DotTooltip, {
6348
- "data-testid": "logo-tooltip",
6349
- title: "digital.ai",
6350
- children: jsx(ForwardRef, {})
6351
- })
6352
- }), displayAppLogo && jsx(DotLink, {
6353
- ariaLabel: "Application Logo",
6354
- href: appLogoHref,
6355
- "data-testid": "app-logo",
6356
- children: jsx(DotAppLogo, {
6357
- appLogo: appLogo,
6358
- appLogoSmall: appLogoSmall,
6359
- className: "dot-app-logo",
6360
- smallOnly: !targetBreakpoint
6363
+ children: [getLogoLinkComponent('Digital.ai Logo',
6364
+ // aria-label
6365
+ 'primary-logo',
6366
+ // class name
6367
+ 'primary-logo',
6368
+ // data-testid
6369
+ primaryLogoHref,
6370
+ // href
6371
+ customLogo ? customLogo : jsx(DotTooltip, {
6372
+ "data-testid": "logo-tooltip",
6373
+ title: primaryLogoHref ? 'digital.ai' : '',
6374
+ children: jsx(ForwardRef, {
6375
+ className: !primaryLogoHref ? 'primary-logo' : ''
6361
6376
  })
6362
- })]
6377
+ })), displayAppLogo && getLogoLinkComponent('Application Logo',
6378
+ // aria-label
6379
+ '',
6380
+ // class name
6381
+ 'app-logo',
6382
+ // data-testid
6383
+ appLogoHref,
6384
+ // href
6385
+ jsx(DotAppLogo, {
6386
+ appLogo: appLogo,
6387
+ appLogoSmall: appLogoSmall,
6388
+ className: "dot-app-logo",
6389
+ smallOnly: !targetBreakpoint
6390
+ }))]
6363
6391
  }), children, jsxs("div", {
6364
6392
  className: "dot-right-side",
6365
6393
  children: [navItems.length > 0 && jsx("nav", {
@@ -6386,56 +6414,12 @@ const DotAppToolbar = ({
6386
6414
  }) : appToolbar;
6387
6415
  };
6388
6416
 
6389
- const rootClassName$Y = 'dot-autocomplete';
6390
- const inputRootClassName = 'dot-input-root';
6391
- const inputMediumClassName = 'dot-input-medium';
6392
- const StyledAutocomplete = styled(Autocomplete)`
6393
- ${({
6394
- theme
6395
- }) => css`
6396
- &.${rootClassName$Y} {
6397
- &.${inputMediumClassName} .dot-text-field .${inputRootClassName} {
6398
- height: 56px;
6399
- padding-left: ${theme.spacing(2)};
6400
- }
6401
-
6402
- .MuiInputBase-root.Mui-disabled,
6403
- .${readOnlyClassName$1} .MuiInputBase-root {
6404
- ${readOnlyStyles(theme)};
6405
- }
6406
-
6407
- .${inputRootClassName} {
6408
- /* Override only top/bottom, but preserve left/right padding */
6409
- padding-top: ${theme.spacing(1)};
6410
- padding-bottom: ${theme.spacing(1)};
6411
- }
6412
-
6413
- .dot-chip:first-child {
6414
- margin-left: ${theme.spacing(0)};
6415
- }
6416
-
6417
- .dot-text-field {
6418
- .${inputRootClassName} {
6419
- min-height: ${theme.spacing(5)};
6420
- }
6421
-
6422
- .warning-icon {
6423
- color: ${theme.palette.warning.main};
6424
- }
6425
- .error-icon {
6426
- color: ${theme.palette.error.main};
6427
- }
6428
- }
6429
- }
6430
- `}
6431
- `;
6432
-
6433
- const rootClassName$X = 'dot-chip';
6417
+ const rootClassName$Y = 'dot-chip';
6434
6418
  const StyledChip = styled(Chip)`
6435
6419
  ${({
6436
6420
  theme
6437
6421
  }) => css`
6438
- &.${rootClassName$X} {
6422
+ &.${rootClassName$Y} {
6439
6423
  background: ${theme.palette.figma.neutral.normal};
6440
6424
  border-color: ${theme.palette.figma.border.darker};
6441
6425
  color: ${theme.palette.figma.typography.black};
@@ -6541,7 +6525,7 @@ const DotChip = ({
6541
6525
  charactersLimit = DEFAULT_CHARACTERS_LIMIT,
6542
6526
  children,
6543
6527
  className,
6544
- 'data-pendoid': dataPendoId = rootClassName$X,
6528
+ 'data-pendoid': dataPendoId = rootClassName$Y,
6545
6529
  'data-testid': dataTestId,
6546
6530
  disabled = false,
6547
6531
  error = false,
@@ -6554,7 +6538,7 @@ const DotChip = ({
6554
6538
  tabIndex
6555
6539
  }) => {
6556
6540
  const errorClass = error ? 'Mui-error' : '';
6557
- const rootClasses = useStylesWithRootClass(rootClassName$X, className, errorClass);
6541
+ const rootClasses = useStylesWithRootClass(rootClassName$Y, className, errorClass);
6558
6542
  const getChipLabel = () => {
6559
6543
  if (charactersLimit <= 0 || children.length < charactersLimit) return children;
6560
6544
  const label = `${children.substring(0, charactersLimit)}...`;
@@ -6586,6 +6570,50 @@ const DotChip = ({
6586
6570
  });
6587
6571
  };
6588
6572
 
6573
+ const rootClassName$X = 'dot-autocomplete';
6574
+ const inputRootClassName = 'dot-input-root';
6575
+ const inputMediumClassName = 'dot-input-medium';
6576
+ const StyledAutocomplete = styled(Autocomplete)`
6577
+ ${({
6578
+ theme
6579
+ }) => css`
6580
+ &.${rootClassName$X} {
6581
+ &.${inputMediumClassName} .dot-text-field .${inputRootClassName} {
6582
+ height: 56px;
6583
+ padding-left: ${theme.spacing(2)};
6584
+ }
6585
+
6586
+ .MuiInputBase-root.Mui-disabled,
6587
+ .${readOnlyClassName$1} .MuiInputBase-root {
6588
+ ${readOnlyStyles(theme)};
6589
+ }
6590
+
6591
+ .${inputRootClassName} {
6592
+ /* Override only top/bottom, but preserve left/right padding */
6593
+ padding-top: ${theme.spacing(1)};
6594
+ padding-bottom: ${theme.spacing(1)};
6595
+ }
6596
+
6597
+ .dot-chip:first-child {
6598
+ margin-left: ${theme.spacing(0)};
6599
+ }
6600
+
6601
+ .dot-text-field {
6602
+ .${inputRootClassName} {
6603
+ min-height: ${theme.spacing(5)};
6604
+ }
6605
+
6606
+ .warning-icon {
6607
+ color: ${theme.palette.warning.main};
6608
+ }
6609
+ .error-icon {
6610
+ color: ${theme.palette.error.main};
6611
+ }
6612
+ }
6613
+ }
6614
+ `}
6615
+ `;
6616
+
6589
6617
  // takes multiple types of data from autocomplete selection
6590
6618
  // parses value and returns a string which is saved to state
6591
6619
  const parseAutoCompleteValue = value => {
@@ -6642,6 +6670,11 @@ const isEmptyValue = value => {
6642
6670
  return !value;
6643
6671
  }
6644
6672
  };
6673
+ const getRootClassNames = (className, size) => useStylesWithRootClass(rootClassName$X, size === 'medium' && inputMediumClassName, className);
6674
+ const getTextFieldRootClassNames = (textFieldWarningClassName, isReadOnly) => useStylesWithRootClass(rootClassName$1l, isReadOnly && readOnlyClassName$1, textFieldWarningClassName);
6675
+ const getInputRootClassNames = isDense => useStylesWithRootClass(inputRootClassName, !isDense && inputMediumClassName);
6676
+ const getDefaultAutoCompleteValue = (hasMultiple, defaultValue) => hasMultiple && isString$2(defaultValue) ? [defaultValue] : defaultValue;
6677
+ const getAutoCompleteGroupBy = group => group ? option => option.group : undefined;
6645
6678
 
6646
6679
  function ariaLabelOrAlternates(ariaLabel, label, placeholder) {
6647
6680
  return ariaLabel || label || placeholder;
@@ -6654,7 +6687,7 @@ const DotAutoComplete = ({
6654
6687
  autoFocus,
6655
6688
  autoHighlight,
6656
6689
  className,
6657
- 'data-pendoid': dataPendoId = rootClassName$Y,
6690
+ 'data-pendoid': dataPendoId = rootClassName$X,
6658
6691
  'data-testid': dataTestId,
6659
6692
  defaultValue,
6660
6693
  dense = true,
@@ -6696,12 +6729,18 @@ const DotAutoComplete = ({
6696
6729
  renderTags,
6697
6730
  required = false,
6698
6731
  size = 'small',
6732
+ trimLongOptions = false,
6699
6733
  value,
6700
6734
  warning = false
6701
6735
  }) => {
6702
6736
  const [showPlaceholder, setShowPlaceholder] = useState(isEmptyValue(value) && isEmptyValue(defaultValue));
6703
6737
  const [isOpened, setIsOpened] = useState(false);
6704
6738
  const [inputText, setInputText] = useState('');
6739
+ useEffect(() => {
6740
+ if (trimLongOptions && renderOption) {
6741
+ console.warn('Please use `trimLongOptions` or `renderOption`. If both are used, `trimLongOptions` is ignored.');
6742
+ }
6743
+ }, []);
6705
6744
  // Used for focus management while popper is opened
6706
6745
  const actionItemRef = useRef();
6707
6746
  const onActionItemClick = actionItem === null || actionItem === void 0 ? void 0 : actionItem.onClick;
@@ -6710,9 +6749,9 @@ const DotAutoComplete = ({
6710
6749
  const popperOpen = !readOnly && (open || isOpened);
6711
6750
  const preventDuplicateInsertion = actionItem === null || actionItem === void 0 ? void 0 : actionItem.preventDuplicateInsertion;
6712
6751
  const textFieldWarningClassName = !error && warning && warningClassName;
6713
- const rootClasses = useStylesWithRootClass(rootClassName$Y, size === 'medium' && inputMediumClassName, className);
6714
- const textFieldRootClasses = useStylesWithRootClass(rootClassName$1l, readOnly && readOnlyClassName$1, textFieldWarningClassName);
6715
- const inputRootClasses = useStylesWithRootClass(inputRootClassName, !dense && inputMediumClassName);
6752
+ const rootClasses = getRootClassNames(className, size);
6753
+ const textFieldRootClasses = getTextFieldRootClassNames(textFieldWarningClassName, readOnly);
6754
+ const inputRootClasses = getInputRootClassNames(dense);
6716
6755
  const popperClasses = useStylesWithRootClass(rootClassName$1b, popperClassName);
6717
6756
  let highlightedOption = null;
6718
6757
  let textFieldInput;
@@ -6881,6 +6920,24 @@ const DotAutoComplete = ({
6881
6920
  }), getInputAdornment(), nativeEndAdornment]
6882
6921
  });
6883
6922
  };
6923
+ const renderTrimmedLongOptions = (props, option) => {
6924
+ const key = 'id' in option ? option.id : option.title;
6925
+ return jsx(DotTooltip, {
6926
+ "data-testid": dataTestId && `${dataTestId}-option-tooltip-${key}`,
6927
+ hoverVisibility: "overflow",
6928
+ title: option.title,
6929
+ children: jsx("li", Object.assign({}, props, {
6930
+ children: jsx(DotTypography, {
6931
+ noWrap: true,
6932
+ variant: "body1",
6933
+ children: option.title
6934
+ })
6935
+ }))
6936
+ }, key);
6937
+ };
6938
+ const handleRenderOption = (props, option, state) => {
6939
+ return renderOption ? renderOption(props, option, state) : renderTrimmedLongOptions(props, option);
6940
+ };
6884
6941
  return jsx(StyledAutocomplete, {
6885
6942
  PopperComponent: DotPopper,
6886
6943
  "aria-label": ariaLabel,
@@ -6891,14 +6948,14 @@ const DotAutoComplete = ({
6891
6948
  },
6892
6949
  "data-pendoid": dataPendoId,
6893
6950
  "data-testid": dataTestId,
6894
- defaultValue: multiple && isString$2(defaultValue) ? [defaultValue] : defaultValue,
6951
+ defaultValue: getDefaultAutoCompleteValue(multiple, defaultValue),
6895
6952
  disabled: disabled,
6896
6953
  filterOptions: filterOptions,
6897
6954
  filterSelectedOptions: filterSelectedOptions,
6898
6955
  freeSolo: freesolo,
6899
6956
  getOptionLabel: option => parseAutoCompleteValue(option),
6900
6957
  getOptionDisabled: checkIfOptionDisabled,
6901
- groupBy: group ? option => option.group : undefined,
6958
+ groupBy: getAutoCompleteGroupBy(group),
6902
6959
  id: inputId,
6903
6960
  inputValue: inputValue,
6904
6961
  isOptionEqualToValue: isOptionEqualToValue,
@@ -6989,7 +7046,7 @@ const DotAutoComplete = ({
6989
7046
  );
6990
7047
  },
6991
7048
  renderGroup: group ? renderGroup : undefined,
6992
- renderOption: renderOption,
7049
+ renderOption: renderOption || trimLongOptions ? handleRenderOption : undefined,
6993
7050
  renderTags: handleTagsRender(),
6994
7051
  size: size,
6995
7052
  value: value
@@ -14804,7 +14861,8 @@ const stepListClassName = 'dot-stepper-list';
14804
14861
  const contentClassName = 'dot-stepper-content';
14805
14862
  const StyledStepper = styled.div`
14806
14863
  ${({
14807
- theme
14864
+ theme,
14865
+ offset
14808
14866
  }) => css`
14809
14867
  &.${rootClassName$p} {
14810
14868
  display: flex;
@@ -14820,22 +14878,25 @@ const StyledStepper = styled.div`
14820
14878
  flex-direction: row-reverse;
14821
14879
  }
14822
14880
 
14823
- .MuiStepConnector-root .MuiStepConnector-line {
14824
- border-left: 1px solid ${theme.palette.figma.border.default};
14881
+ &.bottom {
14882
+ flex-direction: column;
14825
14883
  }
14826
14884
 
14827
- .${stepListClassName} {
14828
- padding: ${theme.spacing(3)};
14885
+ &.top {
14886
+ flex-direction: column-reverse;
14887
+ }
14829
14888
 
14830
- &.MuiStepper-horizontal {
14831
- padding: 0;
14832
- display: flex;
14833
- flex-direction: column;
14889
+ .MuiStepConnector-root {
14890
+ .MuiStepConnector-line {
14891
+ border-left: 1px solid ${theme.palette.figma.border.default};
14892
+ }
14893
+ &.MuiStepConnector-vertical {
14894
+ display: none;
14834
14895
  }
14896
+ }
14835
14897
 
14898
+ .${stepListClassName} {
14836
14899
  .MuiStep-root {
14837
- width: 315px;
14838
-
14839
14900
  .dot-icon {
14840
14901
  display: flex;
14841
14902
  background: ${theme.palette.figma.primary.rippleLight};
@@ -14845,101 +14906,113 @@ const StyledStepper = styled.div`
14845
14906
  width: 28px;
14846
14907
  }
14847
14908
 
14848
- .MuiStepContent-root {
14849
- border-left: 1px solid ${theme.palette.figma.border.default};
14909
+ .MuiStepLabel-root {
14910
+ padding: 0px;
14911
+ gap: 8px;
14850
14912
  }
14851
14913
 
14852
- &.MuiStep-horizontal {
14853
- padding: ${theme.spacing(1)};
14914
+ &:hover {
14915
+ cursor: pointer;
14916
+ }
14917
+
14918
+ .MuiStepLabel-labelContainer {
14919
+ overflow: hidden;
14920
+ min-width: 0;
14854
14921
 
14855
- .dot-avatar i:before {
14856
- color: ${theme.palette.figma.icon.disabled};
14857
- }
14858
- .dot-avatar,
14859
- .dot-icon {
14860
- background: ${theme.palette.figma.neutral.active};
14861
- }
14862
14922
  .dot-typography {
14863
- color: ${theme.palette.figma.typography.disabled};
14864
- }
14865
- .horizontal-step-description {
14866
- color: ${theme.palette.figma.typography.gray};
14923
+ white-space: nowrap;
14867
14924
  }
14925
+ }
14868
14926
 
14869
- &:hover {
14870
- cursor: pointer;
14871
- }
14927
+ .MuiStepContent-root {
14928
+ border-left-color: transparent;
14929
+ }
14872
14930
 
14873
- &.completed {
14931
+ &.MuiStep-horizontal {
14932
+ padding: ${theme.spacing(3)};
14933
+
14934
+ &.active:not(&.completed):not(&.in-progress) {
14874
14935
  .dot-avatar i:before {
14875
- color: ${theme.palette.figma.overlay.alerts.success.icon};
14936
+ color: ${theme.palette.figma.icon.black};
14876
14937
  }
14877
- .dot-avatar,
14878
- .dot-icon {
14879
- background: ${theme.palette.figma.overlay.alerts.success.background};
14938
+ }
14939
+
14940
+ &.active {
14941
+ .dot-typography {
14942
+ color: ${theme.palette.figma.primary.normal};
14880
14943
  }
14881
14944
  }
14945
+ }
14946
+
14947
+ &.MuiStep-vertical {
14948
+ width: 315px;
14949
+ padding: 8px 4px 8px 16px;
14882
14950
 
14883
14951
  &.active {
14884
14952
  background: ${theme.palette.figma.border.darker};
14885
14953
  }
14886
14954
 
14887
- &.error {
14888
- .dot-avatar i:before {
14889
- color: ${theme.palette.figma.overlay.alerts.error.icon};
14890
- }
14891
- .dot-avatar,
14892
- .dot-icon {
14893
- background: ${theme.palette.figma.overlay.alerts.error.background};
14894
- }
14955
+ .MuiStepConnector-root {
14956
+ display: none;
14895
14957
  }
14896
14958
 
14897
- &.in-progress {
14898
- .dot-avatar i:before {
14899
- color: ${theme.palette.figma.primary.active};
14900
- }
14959
+ .MuiStepLabel-root {
14960
+ width: 90%;
14961
+ }
14962
+
14963
+ .dot-typography {
14964
+ white-space: nowrap;
14965
+ overflow: hidden;
14966
+ text-overflow: ellipsis;
14901
14967
  }
14902
14968
  }
14903
14969
 
14904
- &.MuiStep-vertical {
14905
- &.completed {
14906
- .dot-typography,
14907
- .dot-icon {
14908
- color: ${theme.palette.figma.typography.black};
14909
- }
14970
+ &.inactive {
14971
+ .step-label.dot-typography {
14972
+ color: ${theme.palette.figma.typography.gray};
14910
14973
  }
14974
+ }
14911
14975
 
14912
- &.active {
14913
- .dot-icon {
14914
- background: ${theme.palette.figma.primary.active};
14915
- color: ${theme.palette.figma.typography.white};
14916
- }
14917
- .step-label.dot-typography {
14918
- color: ${theme.palette.figma.primary.normal};
14919
- }
14920
- .dot-typography {
14921
- color: ${theme.palette.figma.typography.black};
14922
- }
14976
+ &.active {
14977
+ .dot-typography {
14978
+ color: ${theme.palette.figma.typography.black};
14923
14979
  }
14980
+ }
14924
14981
 
14925
- &.inactive .step-label.dot-typography {
14926
- color: ${theme.palette.figma.typography.gray};
14982
+ .dot-avatar i:before {
14983
+ color: ${theme.palette.figma.icon.disabled};
14984
+ }
14985
+
14986
+ .dot-avatar,
14987
+ .dot-icon {
14988
+ background: ${theme.palette.figma.neutral.active};
14989
+ }
14990
+
14991
+ &.completed {
14992
+ .dot-avatar i:before {
14993
+ color: ${theme.palette.figma.overlay.alerts.success.icon};
14927
14994
  }
14995
+ }
14928
14996
 
14929
- &.error {
14930
- .dot-typography {
14931
- color: ${theme.palette.figma.destructive.normal};
14932
- }
14997
+ &.error {
14998
+ .dot-avatar i:before {
14999
+ color: ${theme.palette.figma.overlay.alerts.error.icon};
15000
+ }
15001
+ .dot-typography {
15002
+ color: ${theme.palette.figma.destructive.normal} !important;
15003
+ }
15004
+ }
14933
15005
 
14934
- .dot-icon {
14935
- background: ${theme.palette.figma.background.level0.bckgWhite};
14936
- border: 1px solid ${theme.palette.figma.destructive.normal};
14937
- color: ${theme.palette.figma.destructive.normal};
14938
- }
15006
+ &.in-progress {
15007
+ .dot-avatar i:before {
15008
+ color: ${theme.palette.figma.primary.active};
14939
15009
  }
14940
15010
  }
14941
15011
 
14942
15012
  &.disabled {
15013
+ &:hover {
15014
+ cursor: default;
15015
+ }
14943
15016
  .dot-icon {
14944
15017
  color: ${theme.palette.figma.primary.light};
14945
15018
  }
@@ -14947,16 +15020,28 @@ const StyledStepper = styled.div`
14947
15020
  color: ${theme.palette.figma.typography.disabled};
14948
15021
  }
14949
15022
  }
14950
-
14951
- &:last-of-type .MuiStepContent-root {
14952
- border-left-color: transparent;
14953
- }
14954
15023
  }
14955
15024
  }
14956
15025
 
14957
15026
  .${contentClassName} {
14958
15027
  width: 100%;
14959
15028
 
15029
+ .left {
15030
+ border: 0;
15031
+ }
15032
+ .right {
15033
+ border: 0;
15034
+ }
15035
+
15036
+ .bottom {
15037
+ height: ${`calc(100vh - ${offset}px)`};
15038
+ border: 0;
15039
+ }
15040
+ .top {
15041
+ height: ${`calc(100vh - ${offset}px)`};
15042
+ border: 0;
15043
+ }
15044
+
14960
15045
  .step-content-container {
14961
15046
  padding: ${theme.spacing(3, 3, 2, 3)};
14962
15047
  }
@@ -14969,15 +15054,24 @@ const ScrollbarContainer = styled.div`
14969
15054
  theme,
14970
15055
  offset
14971
15056
  }) => css`
14972
- height: ${`calc(100vh - ${offset}px)`};
14973
15057
  overflow-y: auto;
14974
15058
 
14975
15059
  &.left {
15060
+ height: ${`calc(100vh - ${offset}px)`};
14976
15061
  border-right: 1px solid ${theme.palette.figma.border.default};
14977
15062
  }
14978
15063
  &.right {
15064
+ height: ${`calc(100vh - ${offset}px)`};
14979
15065
  border-left: 1px solid ${theme.palette.figma.border.default};
14980
15066
  }
15067
+ &.bottom {
15068
+ width: 100%;
15069
+ border-bottom: 1px solid ${theme.palette.figma.border.default};
15070
+ }
15071
+ &.top {
15072
+ width: 100%;
15073
+ border-top: 1px solid ${theme.palette.figma.border.default};
15074
+ }
14981
15075
  &.center-content {
14982
15076
  display: flex;
14983
15077
  flex-direction: column;
@@ -14991,13 +15085,8 @@ const StepContentWrapper = styled.div`
14991
15085
  flex: 1;
14992
15086
  display: flex;
14993
15087
  justify-content: center;
14994
- `;
14995
- const StepDescription = styled(DotTypography)`
14996
- ${({
14997
- theme
14998
- }) => css`
14999
- margin-bottom: ${theme.spacing(6)};
15000
- `}
15088
+ width: 100%;
15089
+ height: 100%;
15001
15090
  `;
15002
15091
  const StepActionsContainer = styled.div`
15003
15092
  ${({
@@ -15071,32 +15160,47 @@ const DotStepper = ({
15071
15160
  submitButtonText = 'Complete'
15072
15161
  }) => {
15073
15162
  const [currentStep, setActiveStep] = useState(activeStep);
15163
+ const [stepperOffset, setStepperOffset] = useState(activeStep);
15074
15164
  const [isStickyBottom, setIsStickyBottom] = useState(false);
15075
15165
  const actionsRef = useRef(null);
15076
15166
  const stepperContentRef = useRef(null);
15077
- const isHorizontal = orientation === 'horizontal';
15167
+ const stepperRef = useRef(null);
15078
15168
  const displayInitialContent = initialContent && currentStep === 0;
15079
15169
  const displayFinalContent = finalContent && currentStep > steps.length;
15080
15170
  const displayCancelButton = !!(!displayInitialContent && !displayFinalContent && onCancel);
15081
15171
  const isLastStep = currentStep === steps.length && !finalContent || currentStep > steps.length && finalContent;
15082
- const rootClasses = useStylesWithRootClass(rootClassName$p, stepsPosition, className);
15172
+ const getStepsPosition = () => {
15173
+ if (orientation === 'horizontal') {
15174
+ return ['top', 'bottom'].includes(stepsPosition) ? stepsPosition : 'bottom';
15175
+ } else {
15176
+ return ['left', 'right'].includes(stepsPosition) ? stepsPosition : 'left';
15177
+ }
15178
+ };
15179
+ const rootClasses = useStylesWithRootClass(rootClassName$p, getStepsPosition(), className);
15083
15180
  const stepContentClasses = displayInitialContent || displayFinalContent ? 'center-content' : '';
15084
15181
  const stickyBottomClasses = useStylesWithRootClass('actions-container', isStickyBottom ? 'with-top-border' : '');
15085
15182
  const actionsClasses = useStylesWithRootClass('actions', displayInitialContent || displayFinalContent ? 'center-actions' : '');
15086
15183
  useEffect(() => {
15087
15184
  const actionsElement = actionsRef.current;
15088
15185
  const stepperContentElement = stepperContentRef.current;
15089
- let observer;
15186
+ let intersectionObserver;
15090
15187
  if (actionsElement && stepperContentElement) {
15091
- observer = new IntersectionObserver(([e]) => setIsStickyBottom(e.intersectionRatio < 1), {
15188
+ intersectionObserver = new IntersectionObserver(([e]) => setIsStickyBottom(e.intersectionRatio < 1), {
15092
15189
  root: stepperContentElement,
15093
15190
  rootMargin: '0px 0px -1px 0px',
15094
15191
  threshold: [1]
15095
15192
  });
15096
- observer.observe(actionsElement);
15193
+ intersectionObserver.observe(actionsElement);
15194
+ }
15195
+ const stepperContent = stepperRef.current;
15196
+ let resizeObserver;
15197
+ if (stepperContent) {
15198
+ resizeObserver = new ResizeObserver(([e]) => setStepperOffset(e.contentRect.height));
15199
+ resizeObserver.observe(stepperContent);
15097
15200
  }
15098
15201
  return () => {
15099
- actionsElement && observer.unobserve(actionsElement);
15202
+ actionsElement && intersectionObserver.unobserve(actionsElement);
15203
+ stepperContent && resizeObserver.unobserve(stepperContent);
15100
15204
  };
15101
15205
  }, []);
15102
15206
  useEffect(() => {
@@ -15121,23 +15225,21 @@ const DotStepper = ({
15121
15225
  if (displayFinalContent) return finalContent;
15122
15226
  return (_a = steps.find(step => step.id === id)) === null || _a === void 0 ? void 0 : _a.content;
15123
15227
  };
15124
- const getStepIcon = (iconId, completed, error) => {
15228
+ const getStepIcon = (iconId, completed, error, isActive) => {
15125
15229
  let stepIcon;
15126
15230
  if (completed) {
15127
- stepIcon = isHorizontal ? 'check-solid' : 'check-line';
15231
+ stepIcon = 'check-solid';
15128
15232
  } else if (error) {
15129
15233
  stepIcon = 'error-solid';
15130
- } else if (iconId) {
15234
+ } else if (isActive) {
15131
15235
  stepIcon = iconId;
15132
15236
  } else {
15133
- stepIcon = isHorizontal ? 'circle' : 'edit';
15237
+ stepIcon = 'circle';
15134
15238
  }
15135
- return isHorizontal ? jsx(DotAvatar, {
15239
+ return jsx(DotAvatar, {
15136
15240
  alt: iconId || stepIcon,
15137
15241
  iconId: stepIcon,
15138
15242
  type: "icon"
15139
- }) : jsx(DotIcon, {
15140
- iconId: stepIcon
15141
15243
  });
15142
15244
  };
15143
15245
  const navigateToStep = id => {
@@ -15173,7 +15275,7 @@ const DotStepper = ({
15173
15275
  ref: stepperContentRef,
15174
15276
  children: jsxs(ScrollbarContainer, {
15175
15277
  offset: offset,
15176
- className: stepContentClasses,
15278
+ className: `${stepContentClasses} ${getStepsPosition()}`,
15177
15279
  children: [jsx(CssGrid, {
15178
15280
  className: "step-content-container",
15179
15281
  children: jsx(CssCell, Object.assign({}, defaultCellProps, {
@@ -15219,58 +15321,69 @@ const DotStepper = ({
15219
15321
  })
15220
15322
  });
15221
15323
  };
15324
+ const memoizedSteps = useMemo(() => {
15325
+ return steps.map((step, index) => {
15326
+ const isActive = currentStep === step.id;
15327
+ // Memoize step classes
15328
+ const stepClasses = [step.className, isActive ? 'active' : 'inactive', step.completed ? 'completed' : '', step.disabled ? 'disabled' : '', step.error ? 'error' : '', step.inProgress ? 'in-progress' : ''].join(' ').trim();
15329
+ // Memoize step description
15330
+ const getContent = isString$2(step.description) ? step.description : null;
15331
+ // Memoize step icon
15332
+ const icon = getStepIcon(step.iconId, step.completed, step.error, isActive);
15333
+ return {
15334
+ step,
15335
+ index,
15336
+ isActive,
15337
+ stepClasses,
15338
+ getContent,
15339
+ icon
15340
+ };
15341
+ });
15342
+ }, [steps, currentStep]);
15222
15343
  return jsxs(StyledStepper, {
15223
15344
  className: rootClasses,
15345
+ offset: stepperOffset + offset,
15224
15346
  children: [jsx(ScrollbarContainer, {
15225
- className: stepsPosition,
15347
+ className: getStepsPosition(),
15226
15348
  offset: offset,
15227
15349
  tabIndex: 0,
15350
+ ref: stepperRef,
15228
15351
  children: jsx(Stepper, {
15229
15352
  activeStep: currentStep,
15230
15353
  "aria-label": ariaLabel,
15231
15354
  className: stepListClassName,
15232
15355
  "data-testid": dataTestId,
15233
15356
  orientation: orientation,
15234
- children: steps.map((step, index) => {
15235
- const isActive = currentStep === step.id;
15236
- // TODO: use useStylesWithRootClass here
15237
- const stepClasses = () => {
15238
- return [step.className, isActive ? 'active' : 'inactive', step.completed ? 'completed' : '', step.disabled ? 'disabled' : '', step.error ? 'error' : '', step.inProgress ? 'in-progress' : ''].concat().join(' ').trim();
15239
- };
15240
- const getContent = () => {
15241
- return isString$2(step.description) ? jsx(StepDescription, {
15242
- variant: "body2",
15243
- children: step.description
15244
- }) : step.description;
15245
- };
15246
- const getHorizontalDescription = () => {
15247
- return isString$2(step.description) ? jsx(DotTypography, {
15248
- variant: "body2",
15249
- className: "horizontal-step-description",
15250
- children: step.description
15251
- }) : null;
15252
- };
15253
- return jsxs(Step, {
15254
- active: isActive,
15255
- classes: {
15256
- root: stepClasses()
15257
- },
15258
- completed: step.completed,
15259
- disabled: step.disabled,
15260
- expanded: true,
15261
- children: [jsxs(StepLabel, {
15262
- icon: getStepIcon(step.iconId, step.completed, step.error),
15357
+ children: memoizedSteps.map(({
15358
+ step,
15359
+ index,
15360
+ isActive,
15361
+ stepClasses,
15362
+ getContent,
15363
+ icon
15364
+ }) => jsx(Step, {
15365
+ active: isActive,
15366
+ classes: {
15367
+ root: stepClasses
15368
+ },
15369
+ completed: step.completed,
15370
+ disabled: step.disabled,
15371
+ children: jsx(DotTooltip, {
15372
+ title: getContent,
15373
+ children: jsxs(StepLabel, {
15374
+ icon: icon,
15263
15375
  onClick: () => navigateToStep(step.id),
15264
15376
  children: [jsx(DotTypography, {
15265
15377
  className: "step-label",
15266
- variant: isHorizontal ? 'body1' : 'subtitle1',
15378
+ variant: orientation === 'horizontal' ? 'subtitle1' : 'body1',
15267
15379
  children: step.label
15268
- }), orientation === 'horizontal' && getHorizontalDescription()]
15269
- }), orientation === 'vertical' && jsx(StepContent, {
15270
- children: getContent()
15271
- })]
15272
- }, index);
15273
- })
15380
+ }), orientation === 'vertical' && jsx(DotTypography, {
15381
+ variant: "body2",
15382
+ children: getContent
15383
+ })]
15384
+ })
15385
+ })
15386
+ }, index))
15274
15387
  })
15275
15388
  }), jsx(StepContentWrapper, {
15276
15389
  children: renderContent()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digital-ai/dot-components",
3
- "version": "4.5.0",
3
+ "version": "4.6.0",
4
4
  "private": false,
5
5
  "license": "SEE LICENSE IN <LICENSE.md>",
6
6
  "contributors": [
@@ -2,5 +2,5 @@ export declare const dashboardCategoriesContainerClassName = "dashboard-categori
2
2
  export declare const InlineMessage: import("styled-components").StyledComponent<({ ariaLabel, ariaLevel, ariaRole, className, "data-testid": dataTestId, children, component, noMarginBottom, noWrap, variant, }: import("../../typography/Typography").TypographyProps) => import("react/jsx-runtime").JSX.Element, any, {}, never>;
3
3
  export declare const StyledPublishConfirmDiv: import("styled-components").StyledComponent<"div", any, {}, never>;
4
4
  export declare const StyledAppSelectDiv: import("styled-components").StyledComponent<"div", any, {}, never>;
5
- export declare const StyledAppSelectDotAutoComplete: import("styled-components").StyledComponent<(<T extends import("../..").AutoCompleteOption>({ ListboxComponent, actionItem, ariaLabel, autoFocus, autoHighlight, className, "data-pendoid": dataPendoId, "data-testid": dataTestId, defaultValue, dense, disabled, disablePortal, endAdornmentTooltip, error, filterOptions, filterSelectedOptions, freesolo, checkIfOptionDisabled, group, helperText, informationToolTip, inputId, inputRef, inputValue, isOptionEqualToValue, label, loading, maxHeight, multiple, onBlur, onChange, onClose, onInputChange, onOpen, open, options, persistentLabel, placeholder, popperClassName, popperPlacement, popperZIndex, preserveGroupOrder, readOnly, renderGroup, renderOption, renderTags, required, size, value, warning, }: import("../../auto-complete/AutoComplete").AutoCompleteProps<T>) => import("react/jsx-runtime").JSX.Element), any, {}, never>;
5
+ export declare const StyledAppSelectDotAutoComplete: import("styled-components").StyledComponent<(<T extends import("../..").AutoCompleteOption>({ ListboxComponent, actionItem, ariaLabel, autoFocus, autoHighlight, className, "data-pendoid": dataPendoId, "data-testid": dataTestId, defaultValue, dense, disabled, disablePortal, endAdornmentTooltip, error, filterOptions, filterSelectedOptions, freesolo, checkIfOptionDisabled, group, helperText, informationToolTip, inputId, inputRef, inputValue, isOptionEqualToValue, label, loading, maxHeight, multiple, onBlur, onChange, onClose, onInputChange, onOpen, open, options, persistentLabel, placeholder, popperClassName, popperPlacement, popperZIndex, preserveGroupOrder, readOnly, renderGroup, renderOption, renderTags, required, size, trimLongOptions, value, warning, }: import("../../auto-complete/AutoComplete").AutoCompleteProps<T>) => import("react/jsx-runtime").JSX.Element), any, {}, never>;
6
6
  export declare const StyledAppSelectAutoCompleteOption: import("styled-components").StyledComponent<"li", any, {}, never>;
@@ -95,9 +95,11 @@ export interface AutoCompleteProps<T extends AutoCompleteOption = AutoCompleteOp
95
95
  required?: boolean;
96
96
  /** Determines the padding within the input field 'medium' or 'small' */
97
97
  size?: inputSizeOptions;
98
+ /** If true, longs options won't be wrapped into multiple lines but trimmed with ellipsis and a tooltip */
99
+ trimLongOptions?: boolean;
98
100
  /** value if this is a controlled component */
99
101
  value?: AutoCompleteValue;
100
102
  /** If true, the label will be displayed in a warning state. */
101
103
  warning?: boolean;
102
104
  }
103
- export declare const DotAutoComplete: <T extends AutoCompleteOption>({ ListboxComponent, actionItem, ariaLabel, autoFocus, autoHighlight, className, "data-pendoid": dataPendoId, "data-testid": dataTestId, defaultValue, dense, disabled, disablePortal, endAdornmentTooltip, error, filterOptions, filterSelectedOptions, freesolo, checkIfOptionDisabled, group, helperText, informationToolTip, inputId, inputRef, inputValue, isOptionEqualToValue, label, loading, maxHeight, multiple, onBlur, onChange, onClose, onInputChange, onOpen, open, options, persistentLabel, placeholder, popperClassName, popperPlacement, popperZIndex, preserveGroupOrder, readOnly, renderGroup, renderOption, renderTags, required, size, value, warning, }: AutoCompleteProps<T>) => import("react/jsx-runtime").JSX.Element;
105
+ export declare const DotAutoComplete: <T extends AutoCompleteOption>({ ListboxComponent, actionItem, ariaLabel, autoFocus, autoHighlight, className, "data-pendoid": dataPendoId, "data-testid": dataTestId, defaultValue, dense, disabled, disablePortal, endAdornmentTooltip, error, filterOptions, filterSelectedOptions, freesolo, checkIfOptionDisabled, group, helperText, informationToolTip, inputId, inputRef, inputValue, isOptionEqualToValue, label, loading, maxHeight, multiple, onBlur, onChange, onClose, onInputChange, onOpen, open, options, persistentLabel, placeholder, popperClassName, popperPlacement, popperZIndex, preserveGroupOrder, readOnly, renderGroup, renderOption, renderTags, required, size, trimLongOptions, value, warning, }: AutoCompleteProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,7 @@
1
1
  import { AutocompleteGetTagProps } from '@mui/material';
2
2
  import { ChipSize } from '../../chip/Chip';
3
3
  import { AutoCompleteOption, AutoCompleteValue } from './interface';
4
+ import { inputSizeOptions } from '../../input-form-fields/InputFormFields.propTypes';
4
5
  export declare const parseAutoCompleteValue: (value: AutoCompleteValue) => string;
5
6
  export interface GetChipsFromAutocompleteProps {
6
7
  chipSize?: ChipSize;
@@ -11,3 +12,8 @@ export interface GetChipsFromAutocompleteProps {
11
12
  export declare const getChipsFromAutocomplete: ({ chipSize, getTagProps, isReadOnly, values, }: GetChipsFromAutocompleteProps) => import("react/jsx-runtime").JSX.Element[];
12
13
  export declare const checkIfDuplicateItem: (itemText: string, autocompleteOptions: AutoCompleteOption[]) => boolean;
13
14
  export declare const isEmptyValue: (value: AutoCompleteValue) => boolean;
15
+ export declare const getRootClassNames: (className: string, size: inputSizeOptions) => string;
16
+ export declare const getTextFieldRootClassNames: (textFieldWarningClassName: string, isReadOnly: boolean) => string;
17
+ export declare const getInputRootClassNames: (isDense: boolean) => string;
18
+ export declare const getDefaultAutoCompleteValue: (hasMultiple: boolean, defaultValue: AutoCompleteValue) => string | AutoCompleteOption | AutoCompleteValue[];
19
+ export declare const getAutoCompleteGroupBy: (group: boolean) => (option: AutoCompleteOption) => string;
@@ -3,7 +3,7 @@ import { CommonProps } from '../CommonProps';
3
3
  import { CssCellProps } from '../css-grid/CssCell';
4
4
  export declare const defaultCellProps: CssCellProps;
5
5
  export type StepperOrientation = 'horizontal' | 'vertical';
6
- export type StepsPosition = 'left' | 'right';
6
+ export type StepsPosition = 'top' | 'bottom' | 'left' | 'right';
7
7
  export interface StepProps extends CommonProps {
8
8
  /** if set to `true` the step will display a checkmark icon */
9
9
  completed?: boolean;
@@ -57,6 +57,7 @@ export interface StepperProps extends CommonProps {
57
57
  /** array of steps to be displayed */
58
58
  steps: StepProps[];
59
59
  /** determines where to display the array of steps */
60
+ /** top/bottom are for horizontal orientation (bottom by default) & left/right for vertical orientation (left by default) */
60
61
  stepsPosition?: StepsPosition;
61
62
  /** if passed, will overwrite the default "submit" button text */
62
63
  submitButtonText?: string;
@@ -4,12 +4,11 @@ export declare const contentClassName = "dot-stepper-content";
4
4
  interface StyledStepActionsContainerProps {
5
5
  displayCancelButton?: boolean;
6
6
  }
7
- export declare const StyledStepper: import("styled-components").StyledComponent<"div", any, {}, never>;
8
7
  interface StyledScrollbarContainerProps {
9
8
  offset?: number;
10
9
  }
10
+ export declare const StyledStepper: import("styled-components").StyledComponent<"div", any, StyledScrollbarContainerProps, never>;
11
11
  export declare const ScrollbarContainer: import("styled-components").StyledComponent<"div", any, StyledScrollbarContainerProps, never>;
12
12
  export declare const StepContentWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
13
- export declare const StepDescription: import("styled-components").StyledComponent<({ ariaLabel, ariaLevel, ariaRole, className, "data-testid": dataTestId, children, component, noMarginBottom, noWrap, variant, }: import("../typography/Typography").TypographyProps) => import("react/jsx-runtime").JSX.Element, any, {}, never>;
14
13
  export declare const StepActionsContainer: import("styled-components").StyledComponent<"div", any, StyledStepActionsContainerProps, never>;
15
14
  export {};