@porsche-design-system/components-react 3.15.1 → 3.16.0-rc.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.
Files changed (30) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/cjs/lib/components/flyout.wrapper.cjs +3 -3
  3. package/esm/lib/components/carousel.wrapper.d.ts +2 -2
  4. package/esm/lib/components/flyout.wrapper.d.ts +8 -0
  5. package/esm/lib/components/flyout.wrapper.mjs +3 -3
  6. package/esm/lib/components/modal.wrapper.d.ts +2 -2
  7. package/esm/lib/components/pagination.wrapper.d.ts +1 -1
  8. package/esm/lib/types.d.ts +4 -4
  9. package/package.json +2 -2
  10. package/ssr/cjs/components/dist/styles/esm/styles-entry.cjs +347 -320
  11. package/ssr/cjs/components/dist/utils/esm/utils-entry.cjs +13 -9
  12. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/components/flyout.wrapper.cjs +4 -4
  13. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout-navigation-item.cjs +5 -1
  14. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout-navigation.cjs +5 -1
  15. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout.cjs +11 -5
  16. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/modal.cjs +13 -7
  17. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/multi-select.cjs +1 -1
  18. package/ssr/esm/components/dist/styles/esm/styles-entry.mjs +347 -320
  19. package/ssr/esm/components/dist/utils/esm/utils-entry.mjs +13 -9
  20. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/components/flyout.wrapper.mjs +4 -4
  21. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout-navigation-item.mjs +5 -1
  22. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout-navigation.mjs +5 -1
  23. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout.mjs +11 -5
  24. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/modal.mjs +13 -7
  25. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/multi-select.mjs +1 -1
  26. package/ssr/esm/lib/components/flyout.wrapper.d.ts +8 -0
  27. package/ssr/esm/lib/components/modal.wrapper.d.ts +2 -2
  28. package/ssr/esm/lib/dsr-components/banner.d.ts +8 -0
  29. package/ssr/esm/lib/dsr-components/flyout.d.ts +1 -3
  30. package/ssr/esm/lib/types.d.ts +4 -4
@@ -3476,6 +3476,7 @@ const themeLight = {
3476
3476
  backgroundSurfaceColor: '#EEEFF2',
3477
3477
  backgroundSurfaceColorDarken: '#CBCED7',
3478
3478
  backgroundSurfaceColorLighten: '#FFFFFF',
3479
+ backgroundShadingColor: 'rgba(1, 2, 5, 0.67)',
3479
3480
  contrastLowColor: '#D8D8DB',
3480
3481
  contrastMediumColor: '#6B6D70',
3481
3482
  contrastHighColor: '#535457',
@@ -3514,6 +3515,7 @@ const themeDark = {
3514
3515
  backgroundSurfaceColor: '#212225',
3515
3516
  backgroundSurfaceColorDarken: '#040405',
3516
3517
  backgroundSurfaceColorLighten: '#3E4045',
3518
+ backgroundShadingColor: 'rgba(38, 38, 41, 0.67)',
3517
3519
  contrastLowColor: '#404044',
3518
3520
  contrastMediumColor: '#88898C',
3519
3521
  contrastHighColor: '#AFB0B3',
@@ -3666,8 +3668,7 @@ const getHiddenTextJssStyle = (isHidden = true, isShownJssStyle) => {
3666
3668
  ...isShownJssStyle,
3667
3669
  };
3668
3670
  };
3669
- // TODO: there should be a shared style util for modal, flyout and flyout-navigation instead of having this code in the
3670
- // main bundle. Or don't share it at all, in case same transition concept isn't ideal to be shared from an UI point of view.
3671
+ // TODO: migrate flyout-navigation to use shared backdrop of dialog-styles.ts
3671
3672
  /**
3672
3673
  * Generates JSS styles for a frosted glass background.
3673
3674
  * @param {boolean} isVisible - Determines if the frosted glass effect is visible.
@@ -3677,7 +3678,7 @@ const getHiddenTextJssStyle = (isHidden = true, isShownJssStyle) => {
3677
3678
  * @param {'blur' | 'shading'} backdrop - The backdrop variant.
3678
3679
  * @returns {JssStyle} - The JSS styles for the frosted glass backdrop.
3679
3680
  */
3680
- const getBackdropJssStyle = (isVisible, zIndex, theme, duration = 'long', backdrop = 'blur') => {
3681
+ const getBackdropJssStyle = (isVisible, zIndex, theme, duration = 'long') => {
3681
3682
  return {
3682
3683
  position: 'fixed',
3683
3684
  inset: 0,
@@ -3691,17 +3692,14 @@ const getBackdropJssStyle = (isVisible, zIndex, theme, duration = 'long', backdr
3691
3692
  ? {
3692
3693
  visibility: 'inherit',
3693
3694
  pointerEvents: 'auto',
3694
- ...(backdrop === 'blur' && frostedGlassStyle),
3695
+ ...frostedGlassStyle,
3695
3696
  opacity: 1,
3696
3697
  }
3697
3698
  : {
3698
3699
  visibility: 'hidden', // element shall not be tabbable after fade out transition has finished
3699
3700
  pointerEvents: 'none',
3700
- ...(backdrop === 'blur' && {
3701
- // TODO: is `blur(0px)` necessary at all?
3702
- WebkitBackdropFilter: 'blur(0px)',
3703
- backdropFilter: 'blur(0px)',
3704
- }),
3701
+ WebkitBackdropFilter: 'blur(0px)',
3702
+ backdropFilter: 'blur(0px)',
3705
3703
  opacity: 0,
3706
3704
  }),
3707
3705
  transition: `${getTransition('opacity', duration)}, ${getTransition('backdrop-filter', duration)}, ${getTransition('-webkit-backdrop-filter', duration)}, visibility 0s linear var(${cssVariableTransitionDuration}, ${isVisible ? '0s' : motionDurationMap[duration]})`,
@@ -4028,9 +4026,6 @@ const getCDNBaseURL = () => global.PORSCHE_DESIGN_SYSTEM_CDN_URL + "/porsche-des
4028
4026
 
4029
4027
  const MODEL_SIGNATURES_MANIFEST = { "718": { "src": "718.min.493a9e3509d6e263fa2207150082def5.svg", "width": 79, "height": 26 }, "911": { "src": "911.min.b68f913216168583298ccf83f1a6b8d5.svg", "width": 94, "height": 25 }, "boxster": { "src": "boxster.min.c321738789b37fda4bba3f7c587542aa.svg", "width": 239, "height": 26 }, "cayenne": { "src": "cayenne.min.25562011631a831516f91ec31d144104.svg", "width": 245, "height": 35 }, "cayman": { "src": "cayman.min.cc8919694c002873e1bb6a3c1dae5d41.svg", "width": 229, "height": 35 }, "macan": { "src": "macan.min.a1844f4c8d23b75e371745e9b8eb49b9.svg", "width": 196, "height": 26 }, "panamera": { "src": "panamera.min.6dae8095186567168f85c145845f090c.svg", "width": 260, "height": 25 }, "taycan": { "src": "taycan.min.df444c6f4cc1f627ceaf1b02584d6bea.svg", "width": 167, "height": 36 }, "turbo-s": { "src": "turbo-s.min.73f1e10731caffe93c07d96fa08546c1.svg", "width": 199, "height": 25 }, "turbo": { "src": "turbo.min.6a4084a8704a6c47a099b2de56b22aef.svg", "width": 143, "height": 25 } };
4030
4028
 
4031
- const scrollShadowColor = 'rgba(204, 204, 204, 0.35)';
4032
- const scrollShadowColorDark = 'rgba(0, 0, 0, 0.6)';
4033
-
4034
4029
  const OPTION_HEIGHT = 40; // optgroups are higher and ignored
4035
4030
  const MULTI_SELECT_OPTION_HEIGHT = 44;
4036
4031
  const getNoResultsOptionJssStyle = () => ({
@@ -4237,7 +4232,6 @@ const getComponentCss$15 = (size, compact, open, theme, sticky) => {
4237
4232
  };
4238
4233
 
4239
4234
  const TOAST_Z_INDEX = 999999;
4240
- const MODAL_Z_INDEX = 99999;
4241
4235
  const FLYOUT_Z_INDEX = 99998;
4242
4236
  const POPOVER_Z_INDEX = 9999;
4243
4237
  const BANNER_Z_INDEX = 99;
@@ -4673,14 +4667,14 @@ const getComponentCss$11 = (isDisabledOrLoading, ...args) => {
4673
4667
  });
4674
4668
  };
4675
4669
 
4676
- const { primaryColor: darkThemePrimaryColor$1 } = getThemedColors('dark');
4670
+ const { primaryColor: darkThemePrimaryColor } = getThemedColors('dark');
4677
4671
  const { primaryColor: lightThemePrimaryColor } = getThemedColors('light');
4678
4672
  const getVariantColors = (variant, theme) => {
4679
4673
  const { primaryColor, contrastHighColor, contrastMediumColor, hoverColor } = getThemedColors(theme);
4680
4674
  const { canvasColor } = getHighContrastColors();
4681
4675
  const colors = {
4682
4676
  primary: {
4683
- textColor: theme === 'dark' ? lightThemePrimaryColor : darkThemePrimaryColor$1,
4677
+ textColor: theme === 'dark' ? lightThemePrimaryColor : darkThemePrimaryColor,
4684
4678
  borderColor: primaryColor,
4685
4679
  borderColorHover: contrastHighColor,
4686
4680
  backgroundColor: primaryColor,
@@ -6024,150 +6018,260 @@ const getComponentCss$Q = (isSecondaryScrollerVisible, theme) => {
6024
6018
  });
6025
6019
  };
6026
6020
 
6027
- const headerShadowClass = 'header--shadow';
6028
- const footerShadowClass$1 = 'footer--shadow';
6029
- const getComponentCss$P = (isOpen, position, hasFooter, hasSubFooter, theme) => {
6021
+ const headingTags = 'h1,h2,h3,h4,h5,h6';
6022
+ const dialogHostJssStyle = {
6023
+ '--pds-internal-grid-outer-column': `calc(${spacingFluidLarge} - ${gridGap})`,
6024
+ '--pds-internal-grid-margin': `calc(${spacingFluidLarge} * -1)`,
6025
+ '--pds-internal-grid-width-min': 'auto',
6026
+ '--pds-internal-grid-width-max': 'none',
6027
+ };
6028
+ const getDialogJssStyle = (isVisible, theme, backdrop = 'blur') => {
6029
+ return {
6030
+ ...dialogBackdropResetJssStyle,
6031
+ ...getDialogBackdropTransitionJssStyle(isVisible, theme, backdrop),
6032
+ };
6033
+ };
6034
+ const dialogBackdropResetJssStyle = {
6035
+ position: 'fixed', // ua-style
6036
+ inset: 0, // ua-style
6037
+ margin: 0, // ua-style
6038
+ padding: 0, // ua-style
6039
+ border: 0, // ua-style
6040
+ width: '100dvw', // ua-style
6041
+ height: '100dvh', // ua-style
6042
+ maxWidth: '100dvw', // ua-style
6043
+ maxHeight: '100dvh', // ua-style
6044
+ overflow: 'hidden', // ua-style
6045
+ display: 'block', // ua-style
6046
+ outline: 0, // ua-style (we always expect a focusable element to be within the dialog)
6047
+ '&::backdrop': {
6048
+ display: 'none', // ua-style (we can't use it atm because it's not animatable in all browsers)
6049
+ },
6050
+ };
6051
+ const getDialogBackdropTransitionJssStyle = (isVisible, theme, backdrop = 'blur') => {
6052
+ const isBackdropBlur = backdrop === 'blur';
6053
+ const { backgroundShadingColor } = getThemedColors(theme);
6054
+ const { backgroundShadingColor: backgroundShadingColorDark } = getThemedColors('dark');
6055
+ const duration = isVisible ? 'long' : 'moderate';
6056
+ const easing = isVisible ? 'in' : 'out';
6057
+ // as soon as all browsers are supporting `allow-discrete`, visibility transition shouldn't be necessary anymore
6058
+ const transition = `visibility 0s linear var(${cssVariableTransitionDuration}, ${isVisible ? '0s' : motionDurationMap[duration]}), ${getTransition('background-color', duration, easing)}, ${getTransition('-webkit-backdrop-filter', duration, easing)}, ${getTransition('backdrop-filter', duration, easing)}`;
6059
+ return {
6060
+ zIndex: 9999999, // fallback for fade out stacking until `overlay` + `allow-discrete` is supported in all browsers. It tries to mimic #top-layer positioning hierarchy.
6061
+ ...(isVisible
6062
+ ? {
6063
+ visibility: 'inherit',
6064
+ pointerEvents: 'auto',
6065
+ background: backgroundShadingColor,
6066
+ ...(isBackdropBlur && frostedGlassStyle),
6067
+ ...prefersColorSchemeDarkMediaQuery(theme, {
6068
+ background: backgroundShadingColorDark,
6069
+ }),
6070
+ }
6071
+ : {
6072
+ visibility: 'hidden', // element shall not be tabbable with keyboard after fade out transition has finished
6073
+ pointerEvents: 'none', // element can't be interacted with mouse
6074
+ background: 'transparent',
6075
+ }),
6076
+ transition,
6077
+ // `allow-discrete` transition for ua-style `overlay` (supported browsers only) ensures dialog is rendered on
6078
+ // #top-layer as long as fade-in or fade-out transition/animation is running
6079
+ '@supports (transition-behavior: allow-discrete)': {
6080
+ transition: `${transition}, ${getTransition('overlay', duration, easing)} allow-discrete`,
6081
+ },
6082
+ };
6083
+ };
6084
+ const getScrollerJssStyle = (position, theme) => {
6085
+ // ensures scrollbar color is set correctly (e.g. when scrollbar is shown on backdrop, on flyout/modal surface or with Auto Dark Mode)
6086
+ const backgroundLight = 'rgba(255,255,255,.01)';
6087
+ const backgroundDark = 'rgba(0,0,0,.01)';
6088
+ const background = {
6089
+ light: backgroundLight,
6090
+ dark: backgroundDark,
6091
+ auto: backgroundLight,
6092
+ };
6093
+ return {
6094
+ position: 'absolute',
6095
+ display: 'grid',
6096
+ ...(position === 'fullscreen'
6097
+ ? {
6098
+ inset: 0,
6099
+ }
6100
+ : {
6101
+ insetBlock: 0,
6102
+ [position === 'start' ? 'insetInlineStart' : 'insetInlineEnd']: 0,
6103
+ }),
6104
+ overflow: 'hidden auto',
6105
+ overscrollBehaviorY: 'none',
6106
+ // TODO: check if smooth scrolling on iOS is given?
6107
+ background: background[theme],
6108
+ ...prefersColorSchemeDarkMediaQuery(theme, {
6109
+ background: background.dark,
6110
+ }),
6111
+ };
6112
+ };
6113
+ const dialogGridJssStyle = {
6114
+ display: 'grid',
6115
+ gridTemplate: `auto/${spacingFluidSmall} auto ${spacingFluidSmall}`,
6116
+ paddingBlock: `calc(${spacingFluidSmall} + ${spacingFluidMedium})`,
6117
+ rowGap: spacingFluidMedium,
6118
+ columnGap: `calc(${spacingFluidLarge} - ${spacingFluidSmall})`,
6119
+ alignContent: 'flex-start',
6120
+ };
6121
+ const getDialogColorJssStyle = (theme) => {
6030
6122
  const { primaryColor, backgroundColor } = getThemedColors(theme);
6031
6123
  const { primaryColor: primaryColorDark, backgroundColor: backgroundColorDark } = getThemedColors('dark');
6032
- const isPositionStart = position === 'start';
6033
- const contentPadding = `${spacingStaticMedium} ${spacingFluidLarge}`;
6034
- const isDark = isThemeDark(theme);
6035
- const shadowColor = isDark ? scrollShadowColorDark : scrollShadowColor;
6036
- const transparentColorDark = 'rgba(14, 14, 18, 0)';
6037
- const transparentColor = isDark ? transparentColorDark : 'rgba(255, 255, 255, 0)';
6124
+ return {
6125
+ color: primaryColor, // enables color inheritance for slots
6126
+ background: backgroundColor,
6127
+ ...prefersColorSchemeDarkMediaQuery(theme, {
6128
+ color: primaryColorDark,
6129
+ background: backgroundColorDark,
6130
+ }),
6131
+ };
6132
+ };
6133
+ const getDialogTransitionJssStyle = (isVisible, slideIn) => {
6134
+ const duration = isVisible ? 'moderate' : 'short';
6135
+ const easing = isVisible ? 'in' : 'out';
6136
+ return {
6137
+ // transition offset relies vertically on viewport (vh) because the dialog height can be infinite, while horizontally
6138
+ // it relies on the dialog width (%) which has a max-width
6139
+ ...(isVisible
6140
+ ? {
6141
+ opacity: 1,
6142
+ transform: 'initial',
6143
+ }
6144
+ : {
6145
+ opacity: 0,
6146
+ transform: slideIn === '^' ? 'translateY(25vh)' : `translateX(${slideIn === '>' ? '-' : ''}100%)`,
6147
+ '&:dir(rtl)': {
6148
+ transform: slideIn === '^' ? 'translateY(25vh)' : `translateX(${slideIn === '>' ? '' : '-'}100%)`,
6149
+ },
6150
+ }),
6151
+ transition: `${getTransition('opacity', duration, easing)}, ${getTransition('transform', duration, easing)}`,
6152
+ };
6153
+ };
6154
+ const getDismissButtonJssStyle = (theme, isOpen, applyAutoFocusHack = false) => {
6155
+ const { backgroundSurfaceColor } = getThemedColors(theme);
6156
+ const { backgroundSurfaceColor: backgroundSurfaceColorDark } = getThemedColors('dark');
6157
+ return {
6158
+ width: 'fit-content',
6159
+ height: 'fit-content',
6160
+ border: `2px solid ${backgroundSurfaceColor}`, // needed to enlarge button slightly without affecting the hover area (are equal now).
6161
+ borderRadius: borderRadiusSmall,
6162
+ background: backgroundSurfaceColor,
6163
+ ...prefersColorSchemeDarkMediaQuery(theme, {
6164
+ background: backgroundSurfaceColorDark,
6165
+ borderColor: backgroundSurfaceColorDark,
6166
+ }),
6167
+ // we need to ensure that the dismiss button, which gets auto focused by `.showModal()`, to always be in the
6168
+ // viewport (or off the view on the start-hand side) before the dialog transition starts otherwise the transition
6169
+ // won't work in all cases, e.g. `dir="rtl"` and `<p-flyout position="end" />`. Because auto focus would force the
6170
+ // dismiss button to be rendered in the viewport immediately and ignore the transition.
6171
+ ...(applyAutoFocusHack && {
6172
+ marginInlineEnd: isOpen ? 0 : '200vw',
6173
+ transition: `margin-inline-end 0s linear var(${cssVariableTransitionDuration}, ${isOpen ? '1ms' : '0s'})`,
6174
+ }),
6175
+ };
6176
+ };
6177
+ const getDialogStickyAreaJssStyle = (area, theme) => {
6178
+ const { backgroundColor } = getThemedColors(theme);
6179
+ const { backgroundColor: backgroundColorDark } = getThemedColors('dark');
6180
+ const scrollShadowColor = 'rgba(204, 204, 204, 0.35)';
6181
+ const scrollShadowColorDark = 'rgba(0, 0, 0, 0.6)';
6182
+ const isAreaHeader = area === 'header';
6183
+ const boxShadowDimension = `0 ${isAreaHeader ? 5 : -5}px 10px`;
6184
+ return {
6185
+ position: 'sticky',
6186
+ [isAreaHeader ? 'top' : 'bottom']: '-.1px', // necessary for `IntersectionObserver` to detect if sticky element is stuck or not. Float value is used, so that sticky area isn't moved out visually by e.g. 1px when container gets scrolled.
6187
+ transform: 'translateZ(0)', // prevents slightly squeezed elements within sticky area for some browsers (e.g. Firefox) caused by float value of sticky top position
6188
+ padding: `${spacingStaticMedium} ${spacingFluidLarge}`,
6189
+ marginBlock: `${isAreaHeader ? `calc((${spacingFluidSmall} + ${spacingFluidMedium}) * -1)` : `-${spacingStaticMedium}`} -${spacingStaticMedium}`,
6190
+ background: backgroundColor,
6191
+ ...prefersColorSchemeDarkMediaQuery(theme, {
6192
+ background: backgroundColorDark,
6193
+ }),
6194
+ clipPath: `inset(${isAreaHeader ? '0 0 -20px 0' : '-20px 0 0 0'})`, // crop leaking box-shadow on left and right side
6195
+ transition: `${getTransition('box-shadow')}`,
6196
+ '&[data-stuck]': {
6197
+ boxShadow: `${isThemeDark(theme) ? scrollShadowColorDark : scrollShadowColor} ${boxShadowDimension}`,
6198
+ ...prefersColorSchemeDarkMediaQuery(theme, {
6199
+ boxShadow: `${scrollShadowColorDark} ${boxShadowDimension}`,
6200
+ }),
6201
+ },
6202
+ };
6203
+ };
6204
+
6205
+ const cssVariableWidth$2 = '--p-flyout-width';
6206
+ // TODO: we shouldn't expose --p-flyout-max-width
6207
+ const cssVariableMaxWidth = '--p-flyout-max-width';
6208
+ const getComponentCss$P = (isOpen, position, hasHeader, hasFooter, hasSubFooter, theme) => {
6209
+ const isPositionStart = position === 'start' || position === 'left';
6038
6210
  return getCss({
6039
6211
  '@global': {
6040
6212
  ':host': {
6041
6213
  display: 'block',
6042
6214
  ...addImportantToEachRule({
6043
- // needed for correct alignment of the Porsche Grid within the Flyout
6044
- '--pds-internal-grid-outer-column': `calc(${spacingFluidLarge} - ${gridGap})`,
6045
- '--pds-internal-grid-margin': `calc(${spacingFluidLarge} * -1)`,
6046
- ...getBackdropJssStyle(isOpen, FLYOUT_Z_INDEX, theme),
6215
+ ...dialogHostJssStyle,
6047
6216
  ...colorSchemeStyles,
6048
6217
  ...hostHiddenStyles,
6049
6218
  }),
6050
6219
  },
6051
- dialog: {
6052
- ...getFlyoutDialogResetJssStyle(),
6053
- insetInline: isPositionStart ? '0 0' : 'auto 0',
6054
- insetBlock: '0 0',
6055
- display: 'flex',
6056
- flexDirection: 'column',
6057
- boxSizing: 'border-box',
6058
- width: 'var(--p-flyout-width, fit-content)',
6059
- minWidth: '320px',
6060
- maxWidth: 'var(--p-flyout-max-width, 1180px)',
6061
- color: primaryColor, // enables color inheritance for slotted content
6062
- background: backgroundColor,
6063
- ...(isOpen
6064
- ? {
6065
- opacity: 1,
6066
- transform: 'initial',
6067
- transition: `${getTransition('opacity', 'long', 'in')}, ${getTransition('transform', 'long', 'in')}`,
6068
- }
6069
- : {
6070
- opacity: 0,
6071
- transform: `translate3d(${isPositionStart ? '-100%' : '100%'}, 0, 0)`,
6072
- transition: `${getTransition('opacity', 'short', 'out', 'long')}, ${getTransition('transform', 'long', 'out')}`,
6073
- }),
6074
- boxShadow: `${isPositionStart ? '3px' : '-3px'} 0px 30px rgba(0, 0, 0, 0.25)`,
6075
- ...prefersColorSchemeDarkMediaQuery(theme, {
6076
- color: primaryColorDark,
6077
- background: backgroundColorDark,
6078
- }),
6079
- '&:focus-visible': {
6080
- outline: 'none', // ua-style reset
6220
+ slot: {
6221
+ display: 'block',
6222
+ '&:first-of-type': {
6223
+ gridRowStart: 1,
6081
6224
  },
6082
- '&::backdrop': {
6083
- // to improve browser backwards compatibility we visually style the backdrop on the :host,
6084
- // although it's not on the #top-layer like it would be for modern browsers supporting ::backdrop
6085
- opacity: 0, // to support backdrop click for modern browsers supporting ::backdrop
6225
+ '&:not([name])': {
6226
+ gridColumn: '2/3',
6227
+ zIndex: 0, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
6086
6228
  },
6229
+ ...(hasHeader && {
6230
+ '&[name=header]': {
6231
+ ...getDialogStickyAreaJssStyle('header', theme),
6232
+ gridColumn: '1/-1',
6233
+ zIndex: 3, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
6234
+ },
6235
+ }),
6236
+ ...(hasFooter && {
6237
+ '&[name=footer]': {
6238
+ ...getDialogStickyAreaJssStyle('footer', theme),
6239
+ gridColumn: '1/-1',
6240
+ zIndex: 2, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
6241
+ },
6242
+ }),
6243
+ ...(hasSubFooter && {
6244
+ '&[name=sub-footer]': {
6245
+ gridColumn: '2/3',
6246
+ zIndex: 1, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
6247
+ },
6248
+ }),
6087
6249
  },
6250
+ dialog: getDialogJssStyle(isOpen, theme),
6088
6251
  },
6089
- wrapper: {
6090
- display: 'flex', // ua-style reset
6091
- flexGrow: 1,
6092
- height: 0,
6093
- flexDirection: 'column',
6094
- ...(hasSubFooter && {
6095
- overflowY: 'auto',
6096
- overscrollBehaviorY: 'none',
6097
- }),
6098
- },
6099
- header: {
6100
- position: 'sticky',
6101
- top: 0,
6102
- zIndex: 2,
6103
- display: 'grid',
6104
- gridTemplateColumns: `minmax(0, 1fr) ${spacingFluidLarge}`,
6105
- alignItems: 'flex-start',
6106
- padding: `${spacingStaticMedium} 0`,
6107
- paddingInlineStart: spacingFluidLarge,
6108
- background: backgroundColor,
6109
- ...prefersColorSchemeDarkMediaQuery(theme, {
6110
- background: backgroundColorDark,
6111
- }),
6112
- },
6113
- [headerShadowClass]: {
6114
- boxShadow: `${isDark ? scrollShadowColorDark : scrollShadowColor} 0px 5px 10px`,
6115
- ...prefersColorSchemeDarkMediaQuery(theme, {
6116
- boxShadow: `${scrollShadowColorDark} 0px 5px 10px`,
6117
- }),
6252
+ scroller: {
6253
+ ...getScrollerJssStyle(isPositionStart ? 'start' : 'end', theme),
6254
+ // compared to Modal, the transition is handled on the scroller to have correct stucked behaviour (visibility of drop shadow)
6255
+ // for sticky header area while transitioned
6256
+ ...getDialogTransitionJssStyle(isOpen, isPositionStart ? '>' : '<'),
6257
+ },
6258
+ flyout: {
6259
+ ...dialogGridJssStyle,
6260
+ ...getDialogColorJssStyle(theme),
6261
+ width: `var(${cssVariableWidth$2},auto)`,
6262
+ minWidth: '320px',
6263
+ maxWidth: `var(${cssVariableMaxWidth},1180px)`,
6118
6264
  },
6119
6265
  dismiss: {
6120
- gridArea: '1 / 2',
6121
- justifySelf: 'center',
6122
- },
6123
- content: {
6124
- padding: contentPadding,
6125
- maxWidth: `calc(100vw - calc(${spacingFluidLarge} * 2))`,
6126
- position: 'relative',
6127
- zIndex: 0,
6128
- backgroundColor, // to ensure scrollbar coloring is optimal for light theme
6129
- ...prefersColorSchemeDarkMediaQuery(theme, {
6130
- backgroundColor: backgroundColorDark, // to ensure scrollbar coloring is optimal for dark theme
6131
- }),
6132
- // If sub-footer is used scroll shadows have to be done via JS
6133
- ...(!hasSubFooter && {
6134
- overflowY: 'auto',
6135
- WebkitOverflowScrolling: 'touch',
6136
- backgroundImage: `linear-gradient(to top, ${backgroundColor}, ${backgroundColor}), linear-gradient(to top, ${backgroundColor}, ${backgroundColor}), linear-gradient(to top, ${shadowColor}, ${transparentColor}), linear-gradient(to bottom, ${shadowColor}, ${transparentColor})`,
6137
- backgroundPosition: 'bottom center, top center, bottom center, top center',
6138
- backgroundRepeat: 'no-repeat',
6139
- backgroundSize: '100% 20px, 100% 20px, 100% 10px, 100% 10px',
6140
- backgroundAttachment: 'local, local, scroll, scroll',
6141
- overscrollBehaviorY: 'none',
6142
- ...prefersColorSchemeDarkMediaQuery(theme, {
6143
- backgroundImage: `linear-gradient(to top, ${backgroundColorDark}, ${backgroundColorDark}), linear-gradient(to top, ${backgroundColorDark}, ${backgroundColorDark}), linear-gradient(to top, ${scrollShadowColorDark}, ${transparentColorDark}), linear-gradient(to bottom, ${scrollShadowColorDark}, ${transparentColorDark})`,
6144
- backgroundColor: backgroundColorDark, // to ensure scrollbar coloring is optimal for dark theme
6145
- }),
6146
- }),
6266
+ ...getDismissButtonJssStyle(theme, isOpen, !isPositionStart),
6267
+ gridArea: '1/3',
6268
+ zIndex: 4, // ensures dismiss button is above everything
6269
+ position: 'sticky',
6270
+ insetBlockStart: spacingFluidSmall,
6271
+ insetInlineEnd: spacingFluidSmall,
6272
+ marginBlockStart: `calc(${spacingFluidMedium} * -1)`,
6273
+ justifySelf: 'flex-end',
6147
6274
  },
6148
- ...(hasFooter && {
6149
- footer: {
6150
- position: 'sticky',
6151
- bottom: 0,
6152
- zIndex: 1,
6153
- padding: contentPadding,
6154
- background: backgroundColor,
6155
- ...prefersColorSchemeDarkMediaQuery(theme, {
6156
- background: backgroundColorDark,
6157
- }),
6158
- },
6159
- [footerShadowClass$1]: {
6160
- boxShadow: `${isDark ? scrollShadowColorDark : scrollShadowColor} 0px -5px 10px`,
6161
- ...prefersColorSchemeDarkMediaQuery(theme, {
6162
- boxShadow: `${scrollShadowColorDark} 0px -5px 10px`,
6163
- }),
6164
- },
6165
- }),
6166
- ...(hasSubFooter && {
6167
- 'sub-footer': {
6168
- padding: contentPadding,
6169
- },
6170
- }),
6171
6275
  });
6172
6276
  };
6173
6277
 
@@ -6880,203 +6984,126 @@ const getComponentCss$D = (size) => {
6880
6984
  });
6881
6985
  };
6882
6986
 
6883
- const cssVariableSpacingTop = '--p-modal-spacing-top';
6884
- const cssVariableSpacingBottom = '--p-modal-spacing-bottom';
6885
- const mediaQueryXl = getMediaQueryMin('xl');
6886
- const { primaryColor: darkThemePrimaryColor, contrastHighColor: darkThemeContrastHighColor } = getThemedColors('dark');
6887
- const stretchToFullModalWidthClassName = 'stretch-to-full-modal-width';
6888
- const marginTopBottomFallback = 'clamp(16px, 7vh, 192px)';
6889
- const marginTopBottomXlandXxlFallback = 'min(192px, 10vh)';
6890
- const footerShadowClass = 'footer--shadow';
6891
- const getFullscreenJssStyles = (fullscreen) => {
6892
- return fullscreen
6893
- ? {
6894
- minWidth: '100%',
6895
- maxWidth: 'none',
6896
- minHeight: '100%',
6897
- margin: 0,
6898
- borderRadius: 0,
6899
- }
6900
- : {
6901
- minWidth: '276px', // on viewport 320px: calc(${gridColumnWidthBase} * 6 + ${gridGap} * 5)
6902
- maxWidth: '1535.5px', // on viewport 1920px: `calc(${gridColumnWidthXXL} * 14 + ${gridGap} * 13)`
6903
- minHeight: 'auto',
6904
- margin: `var(${cssVariableSpacingTop},${marginTopBottomFallback}) ${gridExtendedOffsetBase} var(${cssVariableSpacingBottom},${marginTopBottomFallback})`,
6905
- borderRadius: borderRadiusMedium,
6906
- };
6907
- };
6908
- const isFullscreenForXl = (fullscreen) => {
6909
- const fullscreenParsed = parseJSON(fullscreen);
6910
- if (typeof fullscreenParsed === 'boolean') {
6911
- return fullscreenParsed;
6912
- }
6913
- else {
6914
- const entries = Object.entries(fullscreenParsed);
6915
- const [lastTrueBreakpoint] = entries.filter(([, val]) => val).pop() || [];
6916
- const [lastFalseBreakpoint] = entries.filter(([, val]) => !val).pop() || [];
6917
- return breakpoints.indexOf(lastTrueBreakpoint) > breakpoints.indexOf(lastFalseBreakpoint);
6918
- }
6919
- };
6920
- const getSlottedJssStyle = (marginValue, hasHeader, hasDismissButton) => {
6921
- const marginPx = `${-marginValue}px`;
6922
- return {
6923
- [`&(.${stretchToFullModalWidthClassName})`]: {
6924
- width: `calc(100% + ${marginValue * 2}px)`,
6925
- margin: `0 ${marginPx}`,
6926
- },
6927
- ...(!hasHeader && {
6928
- [`&(.${stretchToFullModalWidthClassName}:first-child)`]: {
6929
- marginTop: hasDismissButton ? `${-marginValue / 16}rem` : marginPx,
6930
- },
6931
- }),
6932
- [`&(.${stretchToFullModalWidthClassName}:last-child)`]: {
6933
- marginBottom: marginPx,
6934
- },
6935
- };
6936
- };
6937
- const getComponentCss$C = (isOpen, backdrop, isFullscreen, hasDismissButton, hasHeader, hasFooter, theme) => {
6938
- const { primaryColor, backgroundColor } = getThemedColors(theme);
6939
- const { primaryColor: primaryColorDark, backgroundColor: backgroundColorDark } = getThemedColors('dark');
6940
- const isFullscreenForXlAndXxl = isFullscreenForXl(isFullscreen);
6941
- const duration = isOpen ? 'moderate' : 'short';
6942
- const easing = isOpen ? 'in' : 'out';
6943
- const contentPadding = '32px';
6987
+ const cssVariableWidth$1 = '--p-modal-width';
6988
+ const cssVariableSpacingTop = '--p-modal-spacing-top'; // TODO: maybe --p-modal-spacing-block-start would be more precise?
6989
+ const cssVariableSpacingBottom = '--p-modal-spacing-bottom'; // TODO: maybe --p-modal-spacing-block-end would be more precise?
6990
+ const safeZoneVertical = `calc(${spacingFluidSmall} + ${spacingFluidMedium})`;
6991
+ const safeZoneHorizontal = `${spacingFluidLarge}`;
6992
+ const cssClassNameStretchToFullModalWidth = 'stretch-to-full-modal-width';
6993
+ const getComponentCss$C = (isOpen, backdrop, fullscreen, hasDismissButton, hasHeader, hasFooter, theme) => {
6944
6994
  return getCss({
6945
6995
  '@global': {
6946
6996
  ':host': {
6947
- overflowY: 'auto', // overrideable
6997
+ display: 'block',
6948
6998
  ...addImportantToEachRule({
6999
+ ...dialogHostJssStyle,
6949
7000
  ...colorSchemeStyles,
6950
7001
  ...hostHiddenStyles,
6951
- ...getBackdropJssStyle(isOpen, MODAL_Z_INDEX, theme, duration, backdrop),
6952
7002
  }),
6953
7003
  },
6954
- '::slotted': addImportantToEachRule(mergeDeep(getSlottedJssStyle(32, hasHeader, hasDismissButton), buildResponsiveStyles(isFullscreen, (fullscreenValue) => ({
6955
- [`&(.${stretchToFullModalWidthClassName}`]: {
6956
- '&:first-child)': {
6957
- borderRadius: fullscreenValue ? 0 : '8px 8px 0 0',
7004
+ // TODO: why not available to Flyout too?
7005
+ // TODO: discussable if so many styles are a good thing, since we could also expose one or two CSS variables with which a stretch to full width is possible too
7006
+ '::slotted': addImportantToEachRule(mergeDeep({
7007
+ [`&(.${cssClassNameStretchToFullModalWidth})`]: {
7008
+ display: 'block',
7009
+ margin: `0 calc(${safeZoneHorizontal} * -1)`,
7010
+ width: `calc(100% + calc(${safeZoneHorizontal} * 2))`,
7011
+ },
7012
+ ...(!hasHeader && {
7013
+ [`&(.${cssClassNameStretchToFullModalWidth}:first-child)`]: {
7014
+ marginBlockStart: `calc(${safeZoneVertical} * -1)`,
6958
7015
  },
6959
- '&:last-child)': {
6960
- borderRadius: fullscreenValue ? 0 : '0 0 8px 8px',
7016
+ }),
7017
+ ...(!hasFooter && {
7018
+ [`&(.${cssClassNameStretchToFullModalWidth}:last-child)`]: {
7019
+ marginBlockEnd: `calc(${safeZoneVertical} * -1)`,
6961
7020
  },
7021
+ }),
7022
+ }, buildResponsiveStyles(fullscreen, (fullscreenValue) => ({
7023
+ [`&(.${cssClassNameStretchToFullModalWidth}:first-child)`]: {
7024
+ borderTopLeftRadius: fullscreenValue ? 0 : borderRadiusMedium,
7025
+ borderTopRightRadius: fullscreenValue ? 0 : borderRadiusMedium,
7026
+ },
7027
+ [`&(.${cssClassNameStretchToFullModalWidth}:last-child)`]: {
7028
+ borderBottomLeftRadius: fullscreenValue ? 0 : borderRadiusMedium,
7029
+ borderBottomRightRadius: fullscreenValue ? 0 : borderRadiusMedium,
6962
7030
  },
6963
7031
  })))),
6964
- h2: {
6965
- ...headingLargeStyle,
6966
- margin: 0,
6967
- color: primaryColor,
6968
- ...prefersColorSchemeDarkMediaQuery(theme, {
6969
- color: primaryColorDark,
7032
+ slot: {
7033
+ display: 'block',
7034
+ '&:first-of-type': {
7035
+ gridRowStart: 1,
7036
+ },
7037
+ '&:not([name])': {
7038
+ gridColumn: '2/3',
7039
+ zIndex: 0, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
7040
+ },
7041
+ ...(hasHeader && {
7042
+ '&[name=header]': {
7043
+ gridColumn: '2/3',
7044
+ zIndex: 0, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
7045
+ },
6970
7046
  }),
6971
- },
6972
- },
6973
- 'scroll-container': {
6974
- display: 'flex',
6975
- inset: 0, // TODO: is this still needed?
6976
- height: '100%',
6977
- overflowY: 'inherit',
6978
- alignItems: 'center',
6979
- justifyContent: 'center',
6980
- flexWrap: 'wrap',
6981
- },
6982
- root: mergeDeep({
6983
- color: primaryColor, // enables color inheritance for slotted content
6984
- position: 'relative',
6985
- boxSizing: 'border-box',
6986
- transform: isOpen ? 'translateY(0%)' : 'translateY(25%)',
6987
- opacity: isOpen ? 1 : 0,
6988
- transition: `${getTransition('opacity', duration, easing)}, ${getTransition('transform', duration, easing)}`,
6989
- paddingTop: hasDismissButton ? '2rem' : contentPadding, // rem value needed to prevent overlapping of close button and contents in scaling mode
6990
- ...(!hasFooter && { paddingBottom: contentPadding }),
6991
- background: backgroundColor,
6992
- outline: isHighContrastMode ? '1px solid transparent' : 0,
6993
- // TODO: getFocusJssStyle() can't be re-used atm, but as soon as component is refactored to `<dialog />` then no
6994
- // focus should be necessary at all because focus is auto forwarded to dismiss button.
6995
- // ::after to be above sticky footer without z-index games
6996
- '&:focus::after': {
6997
- content: '""',
6998
- position: 'fixed',
6999
- border: `${borderWidthBase} solid`,
7000
- pointerEvents: 'none', // fix text selection in focus state
7001
- ...buildResponsiveStyles(isFullscreen, (fullscreenValue) => ({
7002
- borderRadius: fullscreenValue ? 0 : '12px',
7003
- borderColor: fullscreenValue ? primaryColor : darkThemePrimaryColor,
7004
- inset: fullscreenValue ? 0 : '-4px',
7005
- ...prefersColorSchemeDarkMediaQuery(theme, {
7006
- borderColor: darkThemePrimaryColor,
7007
- }),
7008
- })),
7009
- },
7010
- '&:not(:focus-visible)::before': {
7011
- border: 0,
7012
- },
7013
- [mediaQueryXl]: {
7014
- margin: isFullscreenForXlAndXxl
7015
- ? 0
7016
- : `var(${cssVariableSpacingTop},${marginTopBottomXlandXxlFallback}) ${gridExtendedOffsetBase} var(${cssVariableSpacingBottom},${marginTopBottomXlandXxlFallback})`,
7017
- },
7018
- ...prefersColorSchemeDarkMediaQuery(theme, {
7019
- color: primaryColorDark,
7020
- background: backgroundColorDark,
7021
- }),
7022
- }, buildResponsiveStyles(isFullscreen, getFullscreenJssStyles) // potentially needs to be merged with mediaQueryXl
7023
- ),
7024
- ...(hasHeader && {
7025
- header: {
7026
- padding: `0 ${contentPadding} 8px`,
7027
- },
7028
- }),
7029
- content: {
7030
- ...(hasFooter && {
7031
- position: 'relative', // to make sure content isn't above sticky footer, but might affect consumer's absolute positioning
7032
- zIndex: 0,
7033
- }),
7034
- padding: `0 ${contentPadding}`,
7035
- },
7036
- ...(hasFooter && {
7037
- footer: {
7038
- position: 'sticky',
7039
- background: backgroundColor,
7040
- padding: contentPadding,
7041
- bottom: 0,
7042
- borderBottomLeftRadius: borderRadiusMedium,
7043
- borderBottomRightRadius: borderRadiusMedium,
7044
- ...prefersColorSchemeDarkMediaQuery(theme, {
7045
- background: backgroundColorDark,
7047
+ ...(hasFooter && {
7048
+ '&[name=footer]': {
7049
+ ...getDialogStickyAreaJssStyle('footer', theme),
7050
+ gridColumn: '1/-1',
7051
+ zIndex: 1, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
7052
+ },
7046
7053
  }),
7047
7054
  },
7048
- [footerShadowClass]: {
7049
- boxShadow: `${isThemeDark(theme) ? scrollShadowColorDark : scrollShadowColor} 0 -5px 10px`,
7050
- clipPath: 'inset(-20px 0 0 0)', // crop leaking box-shadow on left and right side
7051
- ...prefersColorSchemeDarkMediaQuery(theme, {
7052
- boxShadow: `${scrollShadowColorDark} 0 -5px 10px`,
7055
+ ...(hasHeader && {
7056
+ // TODO: we should either deprecate heading slot + pre-styled headings or implement it in flyout too
7057
+ [`slot[name=heading],${headingTags}`]: {
7058
+ gridRowStart: 1,
7059
+ gridColumn: '2/3',
7060
+ zIndex: 0, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
7061
+ ...headingLargeStyle,
7062
+ margin: 0, // relevant for shadowed h1,h2,h3,…
7063
+ },
7064
+ [`:is(${headingTags}) ~ slot:first-of-type`]: {
7065
+ gridRowStart: 'auto',
7066
+ },
7067
+ [`::slotted([slot="heading"]:is(${headingTags}))`]: {
7068
+ margin: 0, // ua-style (relevant for e.g. <h3 slot="heading"/>)
7069
+ },
7070
+ }),
7071
+ dialog: getDialogJssStyle(isOpen, theme, backdrop),
7072
+ },
7073
+ scroller: getScrollerJssStyle('fullscreen', theme),
7074
+ modal: {
7075
+ ...dialogGridJssStyle,
7076
+ ...getDialogColorJssStyle(theme),
7077
+ ...getDialogTransitionJssStyle(isOpen, '^'),
7078
+ // TODO: maybe we should deprecate the fullscreen property and force the modal to be fullscreen on mobile only
7079
+ ...buildResponsiveStyles(fullscreen, (fullscreenValue) => fullscreenValue
7080
+ ? {
7081
+ width: 'auto',
7082
+ minWidth: 'auto',
7083
+ maxWidth: 'none',
7084
+ placeSelf: 'stretch',
7085
+ margin: 0,
7086
+ borderRadius: 0,
7087
+ }
7088
+ : {
7089
+ width: `var(${cssVariableWidth$1},auto)`,
7090
+ minWidth: '276px', // to be in sync with "Porsche Grid" on viewport = 320px: calc(${gridColumnWidthBase} * 6 + ${gridGap} * 5)
7091
+ maxWidth: '1535.5px', // to be in sync with "Porsche Grid" on viewport >= 1920px: `calc(${gridColumnWidthXXL} * 14 + ${gridGap} * 13)`
7092
+ placeSelf: 'center',
7093
+ margin: `var(${cssVariableSpacingTop},clamp(16px, 10vh, 192px)) ${gridExtendedOffsetBase} var(${cssVariableSpacingBottom},clamp(16px, 10vh, 192px))`, // horizontal margin is needed to ensure modal is placed on "Porsche Grid" when slotted content is wider than the viewport width
7094
+ borderRadius: borderRadiusMedium,
7053
7095
  }),
7054
- },
7055
- }),
7096
+ },
7056
7097
  ...(hasDismissButton && {
7057
- controls: {
7058
- position: 'absolute',
7059
- top: '8px',
7060
- right: '8px',
7061
- left: '8px',
7062
- display: 'flex',
7063
- justifyContent: 'flex-end',
7064
- zIndex: 1, // To assure controls are on top when using stretchToFullModalWidthClassName and transformed slotted content
7065
- },
7066
7098
  dismiss: {
7067
- border: `2px solid ${backgroundColor}`, // needed to enlarge button slightly without affecting the hover area (are equal now).
7068
- borderRadius: '4px',
7069
- background: backgroundColor,
7070
- ...hoverMediaQuery({
7071
- '&:hover': {
7072
- background: darkThemeContrastHighColor,
7073
- borderColor: darkThemeContrastHighColor,
7074
- },
7075
- }),
7076
- ...prefersColorSchemeDarkMediaQuery(theme, {
7077
- background: backgroundColorDark,
7078
- borderColor: backgroundColorDark,
7079
- }),
7099
+ ...getDismissButtonJssStyle(theme, isOpen),
7100
+ gridArea: '1/3',
7101
+ zIndex: 2, // ensures dismiss button is above sticky footer, header and content
7102
+ position: 'sticky',
7103
+ insetBlockStart: spacingFluidSmall,
7104
+ marginBlockStart: `calc(${spacingFluidMedium} * -1)`,
7105
+ marginInlineEnd: spacingFluidSmall,
7106
+ justifySelf: 'flex-end',
7080
7107
  },
7081
7108
  }),
7082
7109
  });