@porsche-design-system/components-react 4.4.0-rc.0 → 4.4.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 (32) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +2 -2
  3. package/ssr/cjs/components/dist/styles/esm/styles-entry.cjs +164 -68
  4. package/ssr/cjs/components/dist/utils/esm/utils-entry.cjs +1 -1
  5. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/banner.cjs +15 -5
  6. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/dialog-base.cjs +3 -7
  7. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/drilldown.cjs +3 -0
  8. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/fc-dismiss-button.cjs +16 -0
  9. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout.cjs +14 -1
  10. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/inline-notification.cjs +2 -2
  11. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/modal.cjs +14 -1
  12. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/popover.cjs +5 -1
  13. package/ssr/cjs/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/sheet.cjs +14 -1
  14. package/ssr/esm/components/dist/styles/esm/styles-entry.mjs +164 -69
  15. package/ssr/esm/components/dist/utils/esm/utils-entry.mjs +1 -1
  16. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/banner.mjs +15 -5
  17. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/dialog-base.mjs +3 -7
  18. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/drilldown.mjs +3 -0
  19. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/fc-dismiss-button.mjs +14 -0
  20. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/flyout.mjs +14 -1
  21. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/inline-notification.mjs +2 -2
  22. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/modal.mjs +14 -1
  23. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/popover.mjs +5 -1
  24. package/ssr/esm/components-react/projects/react-ssr-wrapper/src/lib/dsr-components/sheet.mjs +14 -1
  25. package/ssr/esm/lib/dsr-components/banner.d.ts +2 -0
  26. package/ssr/esm/lib/dsr-components/dialog-base.d.ts +2 -2
  27. package/ssr/esm/lib/dsr-components/drilldown.d.ts +1 -0
  28. package/ssr/esm/lib/dsr-components/fc-dismiss-button.d.ts +16 -0
  29. package/ssr/esm/lib/dsr-components/flyout.d.ts +1 -0
  30. package/ssr/esm/lib/dsr-components/modal.d.ts +1 -0
  31. package/ssr/esm/lib/dsr-components/popover.d.ts +1 -0
  32. package/ssr/esm/lib/dsr-components/sheet.d.ts +1 -0
@@ -7,8 +7,8 @@ var splitChildren = require('../../splitChildren.cjs');
7
7
  var minifyCss = require('../../minifyCss.cjs');
8
8
  var stylesEntry = require('../../../../../../components/dist/styles/esm/styles-entry.cjs');
9
9
  var utilsEntry = require('../../../../../../components/dist/utils/esm/utils-entry.cjs');
10
+ var fcDismissButton = require('./fc-dismiss-button.cjs');
10
11
  var notificationBase = require('./notification-base.cjs');
11
- var button_wrapper = require('../components/button.wrapper.cjs');
12
12
  var buttonPure_wrapper = require('../components/button-pure.wrapper.cjs');
13
13
 
14
14
  /**
@@ -26,7 +26,7 @@ class DSRInlineNotification extends react.Component {
26
26
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: style } }), jsxRuntime.jsx(notificationBase.NotificationBase, { ...utilsEntry.getInlineNotificationAriaAttributes(this.props.state, headingText), heading: this.props.heading, headingTag: this.props.headingTag, hasHeadingSlot: hasHeadingSlot, description: this.props.description, ...(this.props.actionLabel && {
27
27
  actionLabel: (jsxRuntime.jsx(buttonPure_wrapper.PButtonPure, { className: "action", icon: this.props.actionIcon, loading: this.props.actionLoading, children: this.props.actionLabel })),
28
28
  }), ...(this.props.dismissButton && {
29
- dismissButton: (jsxRuntime.jsx(button_wrapper.PButton, { className: "dismiss", type: "button", variant: "secondary", icon: "close", hideLabel: true, compact: true, ...(headingText ? { aria: { 'aria-description': headingText } } : {}), children: "Close notification" })),
29
+ dismissButton: (jsxRuntime.jsx(fcDismissButton.FCDismissButton, { label: "Close notification", ariaDescription: headingText || undefined })),
30
30
  }) })] }), this.props.children] }));
31
31
  }
32
32
  }
@@ -22,6 +22,9 @@ class DSRModal extends react.Component {
22
22
  footer;
23
23
  hasHeader;
24
24
  hasFooter;
25
+ // Tracks whether the current pointer gesture started inside the panel (not on the backdrop). Lets `onClickDialog`
26
+ // skip dismissal when a selection is dragged out of the panel and released on the backdrop.
27
+ isPointerDownInside = false;
25
28
  topLayer = utilsEntry.createTopLayerController({
26
29
  getElement: () => this.props.dialog,
27
30
  isShown: () => !!this.props.dialog?.open,
@@ -35,7 +38,17 @@ class DSRModal extends react.Component {
35
38
  this.props.disableCloseButton ? false : this.props.dismissButton;
36
39
  // TODO: why do we validate only when opened?
37
40
  const style = minifyCss.minifyCss(stylesEntry.getModalCss(this.props.open, this.props.background, this.props.backdrop, this.props.fullscreen, this.props.dismissButton, hasHeader, hasFooter));
38
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: style } }), jsxRuntime.jsx(dialogBase.DialogBase, { host: null, inert: !this.props.open, dismissable: this.props.dismissButton ?? undefined, containerClass: "modal", header: hasHeader ? jsxRuntime.jsx("slot", { name: "header" }) : undefined, footer: hasFooter ? jsxRuntime.jsx("slot", { name: "footer" }) : undefined, ariaAttributes: utilsEntry.parseAndGetAriaAttributes({
41
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: style } }), jsxRuntime.jsx(dialogBase.DialogBase
42
+ // `inert` (not `aria-hidden`) removes the panel from the a11y tree AND prevents focus while closed / during the
43
+ // fade-out. Using `aria-hidden` here triggers a browser warning when a focusable descendant still holds focus
44
+ // during the closing transition ("Blocked aria-hidden on an element because its descendant retained focus").
45
+ // `inert` avoids that and mirrors the pattern used by `p-flyout` / `p-popover` / `p-drilldown`.
46
+ , {
47
+ // `inert` (not `aria-hidden`) removes the panel from the a11y tree AND prevents focus while closed / during the
48
+ // fade-out. Using `aria-hidden` here triggers a browser warning when a focusable descendant still holds focus
49
+ // during the closing transition ("Blocked aria-hidden on an element because its descendant retained focus").
50
+ // `inert` avoids that and mirrors the pattern used by `p-flyout` / `p-popover` / `p-drilldown`.
51
+ inert: !this.props.open, dismissable: this.props.dismissButton ?? undefined, containerClass: "modal", header: hasHeader ? jsxRuntime.jsx("slot", { name: "header" }) : undefined, footer: hasFooter ? jsxRuntime.jsx("slot", { name: "footer" }) : undefined, ariaAttributes: utilsEntry.parseAndGetAriaAttributes({
39
52
  'aria-modal': true,
40
53
  ...(hasHeader && { 'aria-label': this.props.ariaLabel }),
41
54
  ...utilsEntry.parseAndGetAriaAttributes(this.props.aria),
@@ -22,6 +22,10 @@ var utilsEntry = require('../../../../../../components/dist/utils/esm/utils-entr
22
22
  class DSRPopover extends react.Component {
23
23
  host;
24
24
  isOpen = false;
25
+ // Tracks the component's first render. While `true`, the entry transition (`@starting-style`) is suppressed so an
26
+ // initially-open popover (`open=true` on page load) appears instantly instead of fading in; flipped to `false` in
27
+ // `componentDidLoad`, so every later (user-triggered) open keeps the fade-in.
28
+ isInitialRender = true;
25
29
  // The `[popover]` panel element on the #top-layer that holds the content and the arrow.
26
30
  refPopover;
27
31
  // The default info button rendered in the Shadow DOM (only present when no `button` slot is used).
@@ -75,7 +79,7 @@ class DSRPopover extends react.Component {
75
79
  const { namedSlotChildren} = splitChildren.splitChildren(this.props.children);
76
80
  const hasSlottedButton = namedSlotChildren.filter(({ props: { slot } }) => slot === 'button').length > 0;
77
81
  const id = 'popover';
78
- const style = minifyCss.minifyCss(stylesEntry.getPopoverCss(this.props.effectiveOpen, this.props.compact).replace(/(:host {[\S\s]+?})[\S\s]+(button {[\S\s]+?})[\S\s]+(.icon {[\S\s]+?})[\S\s]+(.label {[\S\s]+?})[\S\s]+/, '$1\n$2\n$3\n$4'));
82
+ const style = minifyCss.minifyCss(stylesEntry.getPopoverCss(this.props.effectiveOpen, this.props.compact, this.props.isInitialRender).replace(/(:host {[\S\s]+?})[\S\s]+(button {[\S\s]+?})[\S\s]+(.icon {[\S\s]+?})[\S\s]+(.label {[\S\s]+?})[\S\s]+/, '$1\n$2\n$3\n$4'));
79
83
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: style } }), jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasSlottedButton ? (jsxRuntime.jsx("slot", { name: "button" })) : (jsxRuntime.jsx("button", { type: "button", "aria-label": "More information", "aria-details": id, ...utilsEntry.parseAndGetAriaAttributes(this.props.aria), "aria-expanded": this.props.effectiveOpen ? 'true' : 'false' })), jsxRuntime.jsxs("div", { id: id, popover: "manual", inert: !this.props.effectiveOpen, children: [jsxRuntime.jsx("div", { className: "arrow" }), this.props.description ? jsxRuntime.jsx("p", { children: this.props.description }) : jsxRuntime.jsx("slot", {})] })] })] }), this.props.children] }));
80
84
  }
81
85
  }
@@ -19,6 +19,9 @@ class DSRSheet extends react.Component {
19
19
  dialog;
20
20
  scroller;
21
21
  hasHeader;
22
+ // Tracks whether the current pointer gesture started inside the panel (not on the backdrop). Lets `onClickDialog`
23
+ // skip dismissal when a selection is dragged out of the panel and released on the backdrop.
24
+ isPointerDownInside = false;
22
25
  topLayer = utilsEntry.createTopLayerController({
23
26
  getElement: () => this.props.dialog,
24
27
  isShown: () => !!this.props.dialog?.open,
@@ -30,7 +33,17 @@ class DSRSheet extends react.Component {
30
33
  const hasHeader = namedSlotChildren.filter(({ props: { slot } }) => slot === 'header').length > 0;
31
34
  if (this.props.open) ;
32
35
  const style = minifyCss.minifyCss(stylesEntry.getSheetCss(this.props.open, this.props.background, this.props.dismissButton));
33
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: style } }), jsxRuntime.jsx(dialogBase.DialogBase, { host: null, inert: !this.props.open, dismissable: this.props.dismissButton ?? undefined, containerClass: "sheet", header: hasHeader ? jsxRuntime.jsx("slot", { name: "header" }) : undefined, ariaAttributes: utilsEntry.parseAndGetAriaAttributes({
36
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: style } }), jsxRuntime.jsx(dialogBase.DialogBase
37
+ // `inert` (not `aria-hidden`) removes the panel from the a11y tree AND prevents focus while closed / during the
38
+ // fade-out. Using `aria-hidden` here triggers a browser warning when a focusable descendant still holds focus
39
+ // during the closing transition ("Blocked aria-hidden on an element because its descendant retained focus").
40
+ // `inert` avoids that and mirrors the pattern used by `p-modal` / `p-popover` / `p-drilldown`.
41
+ , {
42
+ // `inert` (not `aria-hidden`) removes the panel from the a11y tree AND prevents focus while closed / during the
43
+ // fade-out. Using `aria-hidden` here triggers a browser warning when a focusable descendant still holds focus
44
+ // during the closing transition ("Blocked aria-hidden on an element because its descendant retained focus").
45
+ // `inert` avoids that and mirrors the pattern used by `p-modal` / `p-popover` / `p-drilldown`.
46
+ inert: !this.props.open, dismissable: this.props.dismissButton ?? undefined, containerClass: "sheet", header: hasHeader ? jsxRuntime.jsx("slot", { name: "header" }) : undefined, ariaAttributes: utilsEntry.parseAndGetAriaAttributes({
34
47
  'aria-modal': true,
35
48
  ...(hasHeader && {
36
49
  'aria-label': namedSlotChildren.filter(({ props: { slot } }) => slot === 'header').length > 0 && namedSlotChildren.find(({ props: { slot } }) => slot === 'header')?.props.children,
@@ -3847,7 +3847,7 @@ const OPTION_LIST_SAFE_ZONE = 6;
3847
3847
 
3848
3848
  const getCDNBaseURL = () => global.PORSCHE_DESIGN_SYSTEM_CDN_URL + "/porsche-design-system";
3849
3849
 
3850
- const prefix = `[Porsche Design System v${"4.4.0-rc.0"}]` // this part isn't covered by unit tests
3850
+ const prefix = `[Porsche Design System v${"4.4.0"}]` // this part isn't covered by unit tests
3851
3851
  ;
3852
3852
  const consoleError = (...messages) => {
3853
3853
  console.error(prefix, ...messages);
@@ -4220,9 +4220,6 @@ const getComponentCss$19 = () => {
4220
4220
  });
4221
4221
  };
4222
4222
 
4223
- const TOAST_Z_INDEX = 999999;
4224
- const BANNER_Z_INDEX = 99;
4225
-
4226
4223
  const colorMap$3 = {
4227
4224
  primary: ref(colorPrimary),
4228
4225
  'contrast-higher': ref(colorContrastHigher),
@@ -4287,6 +4284,86 @@ const weightMap = {
4287
4284
  bold: ref(fontWeightBold),
4288
4285
  };
4289
4286
 
4287
+ // Inlined `close` icon (mirrors packages/assets/projects/icons/src/close.svg) rendered as a CSS mask, so the dismiss
4288
+ // button needs neither a nested `p-button` nor a `p-icon` (which would fetch the SVG from the CDN asynchronously).
4289
+ const iconClose = getInlineSVGBackgroundImage('<path d="m18 6.706-5.294 5.294 5.294 5.294-.706.706-5.294-5.294-5.294 5.294-.706-.706 5.294-5.294-5.294-5.294.706-.706 5.294 5.294 5.294-5.294z"/>');
4290
+ // NOTE: Values copied (and reduced to the fixed `compact` + `hideLabel` case the dismiss button always uses) from
4291
+ // `getVariantColors` in `packages/components/src/styles/link-button-styles.ts` to keep the visual identical to the
4292
+ // previously nested `p-button`. If the shared button styling changes, mirror it here (or extract a shared helper).
4293
+ const getVariantColors$1 = (variant) => {
4294
+ const colors = {
4295
+ primary: {
4296
+ textColor: ref(colorCanvas),
4297
+ backgroundColor: ref(colorPrimary),
4298
+ backgroundColorHover: ref(colorContrastHigh),
4299
+ },
4300
+ secondary: {
4301
+ textColor: ref(colorPrimary),
4302
+ backgroundColor: ref(colorFrostedStrong),
4303
+ backgroundColorHover: ref(colorFrosted),
4304
+ },
4305
+ };
4306
+ return colors[variant];
4307
+ };
4308
+ /**
4309
+ * Visual styles for the shared native `<button class="dismiss">` dismiss button. Returns the button rule (reset,
4310
+ * variant colors, focus ring, High Contrast Mode, hover, inlined close-icon mask and the visually-hidden label). Each
4311
+ * consumer merges this with its own positioning styles for the `dismiss` key (e.g. grid placement in
4312
+ * `notification-base-styles` / `dialog-base-styles`).
4313
+ *
4314
+ * Reduced to the dismiss button's fixed configuration (always `compact` + `hideLabel`): padding `6px`, full border
4315
+ * radius and no gap — the responsive `compact`/`hideLabel` branches from `getLinkButtonStyles` are therefore collapsed.
4316
+ */
4317
+ const getFCDismissButtonStyles = (variant) => {
4318
+ const { textColor, backgroundColor, backgroundColorHover } = getVariantColors$1(variant);
4319
+ return {
4320
+ all: 'unset',
4321
+ boxSizing: 'border-box',
4322
+ display: 'grid',
4323
+ placeItems: 'center',
4324
+ padding: '6px',
4325
+ borderRadius: ref(radiusFull),
4326
+ font: `${ref(fontWeightNormal$1)} ${ref(typescaleSm$1)} / ${ref(leadingNormal$1)} ${ref(fontPorscheNext$1)}`,
4327
+ backgroundColor,
4328
+ color: textColor,
4329
+ cursor: 'pointer',
4330
+ // The frosted backdrop-filter is only meaningful for the translucent `secondary` (frosted) background. For the
4331
+ // opaque `primary` background it is invisible AND — because the dialog consumer additionally applies
4332
+ // `filter: invert(1)` on the same element (see `getDialogDismissButtonJssStyle`) — the blurred backdrop bleeds past
4333
+ // the circular edge and the invert amplifies it into a visible glow/halo. So it is applied for `secondary` only.
4334
+ ...(variant === 'secondary' && {
4335
+ WebkitBackdropFilter: ref(blurFrosted),
4336
+ backdropFilter: ref(blurFrosted),
4337
+ }),
4338
+ transition: `${getTransition('background-color')}, ${getTransition('color')}`,
4339
+ ...forcedColorsMediaQuery({
4340
+ forcedColorAdjust: 'none',
4341
+ background: 'Canvas',
4342
+ boxShadow: 'inset 0 0 0 2px ButtonBorder',
4343
+ color: 'ButtonText',
4344
+ }),
4345
+ '&:focus-visible': getFocusBaseStyles(),
4346
+ ...hoverMediaQuery({
4347
+ '&:hover': {
4348
+ backgroundColor: backgroundColorHover,
4349
+ ...forcedColorsMediaQuery({
4350
+ background: 'Canvas',
4351
+ }),
4352
+ },
4353
+ }),
4354
+ '&::before': {
4355
+ content: '""',
4356
+ width: ref(leadingNormal$1),
4357
+ height: ref(leadingNormal$1),
4358
+ WebkitMask: `${iconClose} center/contain no-repeat`, // necessary for Sogou browser support :-)
4359
+ mask: `${iconClose} center/contain no-repeat`,
4360
+ background: 'currentColor', // follows the button's text color (variant + HCM `ButtonText`)
4361
+ },
4362
+ // visually-hidden accessible name (mirrors `hideLabel` on the former `p-button`)
4363
+ '& span': getHiddenTextJssStyle(),
4364
+ };
4365
+ };
4366
+
4290
4367
  const getFunctionalComponentNotificationBaseStyles = (state, hasAction, hasDismissButton, hasHeadingOrHeadingSlot) => {
4291
4368
  return {
4292
4369
  '@global': {
@@ -4337,6 +4414,8 @@ const getFunctionalComponentNotificationBaseStyles = (state, hasAction, hasDismi
4337
4414
  },
4338
4415
  ...(hasDismissButton && {
4339
4416
  dismiss: {
4417
+ // native dismiss button visual (secondary variant); grid positioning is applied on top
4418
+ ...getFCDismissButtonStyles('secondary'),
4340
4419
  gridArea: `1/4/-1`,
4341
4420
  alignSelf: 'flex-start',
4342
4421
  marginBlock: `calc(-6 * ${ref(spacingStatic2Xs)})`,
@@ -4377,12 +4456,12 @@ const cssVarInsetX = '--p-banner-inset-x';
4377
4456
  const cssVarPositionTop = '--p-banner-position-top'; // deprecated (aliased)
4378
4457
  const cssVarPositionBottom = '--p-banner-position-bottom'; // deprecated (aliased)
4379
4458
  const topBottomFallback = '56px';
4380
- const cssVariableZIndex = '--_p-banner-a';
4381
- const getComponentCss$18 = (isOpen, position, state, hasDismissButton, hasHeadingOrHeadingSlot) => {
4459
+ const cssVarTransform = '--_p-banner-a';
4460
+ const getComponentCss$18 = (isOpen, position, state, hasDismissButton, hasHeadingOrHeadingSlot, skipEntryTransition) => {
4382
4461
  const duration = isOpen ? 'moderate' : 'short';
4383
4462
  const easing = isOpen ? 'in' : 'out';
4384
- const transition = `visibility 0s linear ${ref(cssVariableTransitionDuration, isOpen ? '0s' : motionDurationMap[duration])},${getTransition('transform', duration, easing)}`;
4385
- return getCss({
4463
+ const transition = getTransition('transform', duration, easing);
4464
+ const css = getCss({
4386
4465
  ...mergeDeep({
4387
4466
  '@global': {
4388
4467
  ':host': {
@@ -4391,46 +4470,36 @@ const getComponentCss$18 = (isOpen, position, state, hasDismissButton, hasHeadin
4391
4470
  ...hostHiddenStyles,
4392
4471
  }),
4393
4472
  },
4394
- ...preventFoucOfNestedElementsStyles,
4395
4473
  '[popover]': {
4396
4474
  all: 'unset',
4397
4475
  position: 'fixed',
4398
- zIndex: ref(cssVariableZIndex, BANNER_Z_INDEX), // Fallback for browsers lacking `transition-behavior: allow-discrete` — keeps the banner visible during fade-out after leaving the top layer.
4399
4476
  ...buildResponsiveStyles(position, (v) => ({
4400
4477
  ...(v === 'top' && {
4478
+ [cssVarTransform]: `translate3d(-50%,calc(-100% - ${ref(cssVarTop, ref(cssVarPositionTop, topBottomFallback))}),0)`,
4401
4479
  insetBlock: `${ref(cssVarTop, ref(cssVarPositionTop, topBottomFallback))} auto`,
4402
- ...(!isOpen && {
4403
- transform: `translate3d(-50%,calc(-100% - ${ref(cssVarTop, ref(cssVarPositionTop, topBottomFallback))}),0)`,
4404
- }),
4405
4480
  }),
4406
4481
  ...(v === 'bottom' && {
4482
+ [cssVarTransform]: `translate3d(-50%,calc(${ref(cssVarBottom, ref(cssVarPositionBottom, topBottomFallback))} + 100%),0)`,
4407
4483
  insetBlock: `auto ${ref(cssVarBottom, ref(cssVarPositionBottom, topBottomFallback))}`,
4408
- ...(!isOpen && {
4409
- transform: `translate3d(-50%,calc(${ref(cssVarBottom, ref(cssVarPositionBottom, topBottomFallback))} + 100%),0)`,
4410
- }),
4411
4484
  }),
4412
4485
  })),
4413
4486
  left: '50vw',
4414
4487
  width: `min(calc(100vw - 2 * ${ref(cssVarInsetX, gridExtendedOffsetBase)}),${ref(cssVarMaxWidth, '100ch')})`,
4488
+ transform: isOpen ? 'translate3d(-50%,0,0)' : ref(cssVarTransform),
4489
+ transition,
4490
+ // keep the popover on the #top-layer while the fade-out runs (Chromium only; see `overlayTransitionSupportsQuery`)
4491
+ ...overlayTransitionSupportsQuery({
4492
+ transition: `${transition},${getTransition('overlay', duration, easing)} allow-discrete, ${getTransition('display', duration, easing)} allow-discrete`,
4493
+ }),
4415
4494
  overlay: 'none',
4495
+ display: 'none',
4416
4496
  '&:popover-open': {
4417
4497
  overlay: 'auto',
4498
+ display: 'grid',
4418
4499
  },
4419
4500
  '&::backdrop': {
4420
- display: 'none',
4501
+ display: 'none', // reset ua-style
4421
4502
  },
4422
- visibility: 'hidden', // element shall not be tabbable with keyboard after fade out transition has finished
4423
- pointerEvents: 'none', // element can't be interacted with mouse
4424
- ...(isOpen && {
4425
- visibility: 'inherit',
4426
- pointerEvents: 'inherit',
4427
- transform: 'translate3d(-50%,0,0)',
4428
- }),
4429
- transition,
4430
- // keep the popover on the #top-layer while the fade-out runs (Chromium only; see `overlayTransitionSupportsQuery`)
4431
- ...overlayTransitionSupportsQuery({
4432
- transition: `${transition},${getTransition('overlay', duration, easing)} allow-discrete`,
4433
- }),
4434
4503
  },
4435
4504
  },
4436
4505
  }, {
@@ -4441,6 +4510,17 @@ const getComponentCss$18 = (isOpen, position, state, hasDismissButton, hasHeadin
4441
4510
  },
4442
4511
  }, getFunctionalComponentNotificationBaseStyles(state, false, hasDismissButton, hasHeadingOrHeadingSlot)),
4443
4512
  });
4513
+ // Both the `[popover]` box (transform) and its nested `.notification` (opacity) need a `@starting-style`: while closed
4514
+ // the popover is `display: none`, so on open `.notification` renders fresh with a computed `opacity: 1` and has no
4515
+ // prior value to transition from — without the starting value it snaps to full opacity instead of fading in. The
4516
+ // opacity is split onto `.notification` (not `[popover]`) so the frosted-glass backdrop-filter renders correctly.
4517
+ //
4518
+ // `skipEntryTransition` omits the append on the component's FIRST render, so an initially-open banner (`open=true` on
4519
+ // page load) computes straight to its visible transform/opacity and appears instantly instead of sliding/fading in.
4520
+ // Every later render passes `false`, so a user-triggered open still animates normally.
4521
+ return isOpen && false
4522
+ ? `${css}\n@starting-style {\n [popover] {\n transform: ${ref(cssVarTransform)};\n }\n .notification {\n opacity: 0;\n }\n}`
4523
+ : css;
4444
4524
  };
4445
4525
 
4446
4526
  // Needed for slotted anchor and hidden label, which then enlarges the hidden label to equal host size and indents the text to be visually hidden.
@@ -5824,28 +5904,14 @@ const dialogHostJssStyle = (background) => {
5824
5904
  [cssVarBackgroundColor]: background === 'surface' ? ref(colorSurface) : ref(colorCanvas),
5825
5905
  };
5826
5906
  };
5907
+ // INTENTIONAL DIVERGENCE from `popover-styles.ts` (kept, not aligned — see the mirrored note there):
5908
+ // This dialog stays permanently rendered and collapses its CLOSED state via delayed `visibility: hidden` + `width/height: 0`
5909
+ // (driven by `isVisible`), so `opacity`/`background` fade in BOTH directions with NO `@starting-style`, and an initial
5910
+ // `open=true` computes straight to the visible state (no entry fade on load). `p-popover`/`p-banner` instead use the native
5911
+ // `[popover]` `display: none`/`:popover-open` toggle plus a `@starting-style` entry fade, because those components mimic the
5912
+ // native popover box model. Both share `createTopLayerController` + the Chromium-only `overlay allow-discrete` transition
5913
+ // (`overlayTransitionSupportsQuery`) and the `inert` toggle for tabbability; only the closed-state expression differs.
5827
5914
  const getFunctionalComponentDialogBaseStyles = (isVisible, backdrop = 'blur') => {
5828
- return {
5829
- dialog: {
5830
- ...dialogBackdropResetJssStyle,
5831
- ...getDialogBackdropTransitionJssStyle(isVisible, backdrop),
5832
- },
5833
- };
5834
- };
5835
- const dialogBackdropResetJssStyle = {
5836
- all: 'unset',
5837
- position: 'fixed',
5838
- inset: 0,
5839
- maxWidth: '100dvw',
5840
- maxHeight: '100dvh',
5841
- overflow: 'hidden',
5842
- display: 'block',
5843
- outline: 0, // we always expect a focusable element to be within the dialog
5844
- '&::backdrop': {
5845
- display: 'none', // ua-style (we can't use it atm because it's not animatable in all browsers)
5846
- },
5847
- };
5848
- const getDialogBackdropTransitionJssStyle = (isVisible, backdrop = 'blur') => {
5849
5915
  const isBackdropBlur = backdrop === 'blur';
5850
5916
  const duration = isVisible ? 'long' : 'moderate';
5851
5917
  const easing = isVisible ? 'in' : 'out';
@@ -5853,14 +5919,21 @@ const getDialogBackdropTransitionJssStyle = (isVisible, backdrop = 'blur') => {
5853
5919
  // as soon as all browsers are supporting `allow-discrete`, visibility transition shouldn't be necessary anymore
5854
5920
  const transition = `visibility 0s linear ${delay}, width 0s linear ${delay}, height 0s linear ${delay}, ${getTransition('background-color', duration, easing)}, ${getTransition('-webkit-backdrop-filter', duration, easing)}, ${getTransition('backdrop-filter', duration, easing)}`;
5855
5921
  return {
5856
- zIndex: 9999999, // fallback for fade out stacking until `overlay` + `allow-discrete` is supported in all browsers. It tries to mimic #top-layer positioning hierarchy.
5922
+ all: 'unset',
5923
+ position: 'fixed',
5924
+ inset: 0,
5925
+ maxWidth: '100dvw',
5926
+ maxHeight: '100dvh',
5927
+ overflow: 'hidden',
5928
+ display: 'block',
5929
+ userSelect: 'text', // allows text selection within dialog element (e.g. for copy & paste)
5930
+ outline: 0, // we always expect a focusable element to be within the dialog
5857
5931
  ...(isVisible
5858
5932
  ? {
5859
5933
  width: '100dvw',
5860
5934
  height: '100dvh',
5861
5935
  visibility: 'inherit',
5862
5936
  pointerEvents: 'auto',
5863
- overlay: 'auto',
5864
5937
  background: ref(colorBackdrop),
5865
5938
  ...(isBackdropBlur && {
5866
5939
  WebkitBackdropFilter: ref(blurFrosted),
@@ -5876,7 +5949,6 @@ const getDialogBackdropTransitionJssStyle = (isVisible, backdrop = 'blur') => {
5876
5949
  height: '0px',
5877
5950
  visibility: 'hidden', // element shall not be tabbable with keyboard after fade out transition has finished
5878
5951
  pointerEvents: 'none', // element can't be interacted with mouse
5879
- overlay: 'none',
5880
5952
  background: 'transparent',
5881
5953
  }),
5882
5954
  transition,
@@ -5884,6 +5956,13 @@ const getDialogBackdropTransitionJssStyle = (isVisible, backdrop = 'blur') => {
5884
5956
  ...overlayTransitionSupportsQuery({
5885
5957
  transition: `${transition}, ${getTransition('overlay', duration, easing)} allow-discrete`,
5886
5958
  }),
5959
+ overlay: 'none',
5960
+ '&:modal': {
5961
+ overlay: 'auto',
5962
+ },
5963
+ '&::backdrop': {
5964
+ display: 'none', // reset ua-style (we can't use it atm because it's not animatable in all browsers)
5965
+ },
5887
5966
  };
5888
5967
  };
5889
5968
  const getScrollerJssStyle = (position) => {
@@ -5963,6 +6042,9 @@ const getDialogTransitionJssStyle = (isVisible, slideIn) => {
5963
6042
  };
5964
6043
  const getDialogDismissButtonJssStyle = () => {
5965
6044
  return {
6045
+ // native dismiss button visual (primary variant); positioning + the `invert` filter (renders it light on the
6046
+ // dialog) are applied on top below
6047
+ ...getFCDismissButtonStyles('primary'),
5966
6048
  gridArea: '1/3',
5967
6049
  zIndex: 5, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
5968
6050
  position: 'sticky',
@@ -7087,7 +7169,6 @@ const getComponentCss$V = (isOpen, background, backdrop, position, hasHeader, ha
7087
7169
  ...hostHiddenStyles,
7088
7170
  }),
7089
7171
  },
7090
- ...preventFoucOfNestedElementsStyles,
7091
7172
  slot: {
7092
7173
  ...getSlotJssStyle(),
7093
7174
  '&:not([name])': getSlotMainJssStyle(),
@@ -7110,7 +7191,7 @@ const getComponentCss$V = (isOpen, background, backdrop, position, hasHeader, ha
7110
7191
  '&[name=sub-footer]': getSlotSubFooterJssStyle(),
7111
7192
  }),
7112
7193
  },
7113
- ...getFunctionalComponentDialogBaseStyles(isOpen, backdrop),
7194
+ dialog: getFunctionalComponentDialogBaseStyles(isOpen, backdrop),
7114
7195
  },
7115
7196
  scroller: {
7116
7197
  ...getScrollerJssStyle(isPositionStart ? 'start' : 'end'),
@@ -7940,7 +8021,6 @@ const getComponentCss$C = (isOpen, background, backdrop, fullscreen, hasDismissB
7940
8021
  ...hostHiddenStyles,
7941
8022
  }),
7942
8023
  },
7943
- ...preventFoucOfNestedElementsStyles,
7944
8024
  slot: {
7945
8025
  ...getSlotJssStyle(),
7946
8026
  '&:not([name])': getSlotMainJssStyle(),
@@ -7954,7 +8034,7 @@ const getComponentCss$C = (isOpen, background, backdrop, fullscreen, hasDismissB
7954
8034
  '&[name=footer]': getSlotFooterJssStyle(),
7955
8035
  }),
7956
8036
  },
7957
- ...getFunctionalComponentDialogBaseStyles(isOpen, backdrop),
8037
+ dialog: getFunctionalComponentDialogBaseStyles(isOpen, backdrop),
7958
8038
  },
7959
8039
  scroller: getScrollerJssStyle('fullscreen'),
7960
8040
  modal: {
@@ -8390,7 +8470,7 @@ const cssVariableMaxHeight = '--p-popover-max-h';
8390
8470
  */
8391
8471
  const cssVarPaddingInline = '--p-popover-px';
8392
8472
  /**
8393
- * @css-variable {"name": "--p-popover-py", "description": "Vertical padding of the popover. It is recommended to apply an existing Porsche Design System spacing token, e.g. the CSS declaration `--p-popover-py: var(--p-spacing-static-sm)`, the Tailwind CSS arbitrary property `[--p-popover-py:var(--spacing-static-sm)]` or the equivalent SCSS/JS token.", "defaultValue": "12px"}
8473
+ * @css-variable {"name": "--p-popover-py", "description": "Vertical padding of the popover. It is recommended to apply an existing Porsche Design System spacing token, e.g. the CSS declaration `--p-popover-py: var(--p-spacing-static-sm)`, the Tailwind CSS arbitrary property `[--p-popover-py:var(--spacing-static-sm)]` or the equivalent SCSS/JS token.", "defaultValue": "16px"}
8394
8474
  */
8395
8475
  const cssVarPaddingBlock = '--p-popover-py';
8396
8476
  /**
@@ -8402,14 +8482,19 @@ const iconInfo = getInlineSVGBackgroundImage(`<path d="M12.5 10v6h-1v-6zm0-2v1h-
8402
8482
  * Builds the popover's scoped CSS.
8403
8483
  * @param isOpen - The effective open state; drives the fade-in/fade-out direction and the `@starting-style` append.
8404
8484
  * @param isCompact - Reduces padding/spacing and uses smaller radii (mirrors the `compact` prop).
8405
- * @returns The component CSS string, with a trailing `@starting-style` rule appended while opening.
8485
+ * @param skipEntryTransition - Suppresses the `@starting-style` entry fade. Set on the component's first render so an
8486
+ * initially-open popover (`open=true` on page load) appears instantly instead of fading in. Later user-triggered opens
8487
+ * render with this `false`, so they keep the fade-in.
8488
+ * @returns The component CSS string, with a trailing `@starting-style` rule appended while opening (unless skipped).
8406
8489
  */
8407
- const getComponentCss$v = (isOpen, isCompact) => {
8490
+ const getComponentCss$v = (isOpen, isCompact, skipEntryTransition) => {
8408
8491
  // fade-in on open (via `@starting-style` below), fade-out on close. While closing, the panel keeps `display: grid`
8409
8492
  // (Chromium via `overlay` + `display` `allow-discrete`; Safari/Firefox via the deferred `hidePopover()`), so
8410
8493
  // `display: none` only describes the fully-closed terminal state. Tabbability / a11y-tree removal during the fade-out
8411
8494
  // is handled immediately via the `inert` attribute on the panel (see popover.tsx), so no `visibility` toggle is needed.
8412
- const transition = getTransition('opacity', 'short', isOpen ? 'in' : 'out');
8495
+ const duration = 'short';
8496
+ const easing = isOpen ? 'in' : 'out';
8497
+ const transition = getTransition('opacity', duration, easing);
8413
8498
  const css = getCss({
8414
8499
  '@global': {
8415
8500
  ':host': {
@@ -8428,7 +8513,8 @@ const getComponentCss$v = (isOpen, isCompact) => {
8428
8513
  maxWidth: 'inherit',
8429
8514
  maxHeight: 'inherit',
8430
8515
  boxSizing: 'border-box',
8431
- padding: `${ref(cssVarPaddingBlock, isCompact ? ref(spacingStaticXs$1) : `calc(12 * ${ref(spacingStatic2Xs)})`)} ${ref(cssVarPaddingInline, isCompact ? ref(spacingStaticSm$1) : ref(spacingStaticMd))}`,
8516
+ paddingBlock: `${ref(cssVarPaddingBlock, isCompact ? ref(spacingStaticSm$1) : ref(spacingStaticMd))}`,
8517
+ paddingInline: `${ref(cssVarPaddingInline, isCompact ? ref(spacingStaticSm$1) : ref(spacingStaticMd))}`,
8432
8518
  overflow: 'hidden auto',
8433
8519
  overscrollBehaviorY: 'none',
8434
8520
  },
@@ -8491,7 +8577,7 @@ const getComponentCss$v = (isOpen, isCompact) => {
8491
8577
  transition,
8492
8578
  // keep the popover on the #top-layer while the fade-out runs (Chromium only; see `overlayTransitionSupportsQuery`)
8493
8579
  ...overlayTransitionSupportsQuery({
8494
- transition: `${transition},${getTransition('overlay', 'short', isOpen ? 'in' : 'out')} allow-discrete,${getTransition('display', 'short', isOpen ? 'in' : 'out')} allow-discrete`,
8580
+ transition: `${transition},${getTransition('overlay', duration, easing)} allow-discrete, ${getTransition('display', duration, easing)} allow-discrete`,
8495
8581
  }),
8496
8582
  // Unlike `opacity` (driven by the `isOpen` render flag), `overlay` and `display` are toggled via the
8497
8583
  // `:popover-open` UA state instead of `isOpen`. Both are owned by the browser: they only flip once
@@ -8535,7 +8621,17 @@ const getComponentCss$v = (isOpen, isCompact) => {
8535
8621
  // engines (< Chromium 117 / Safari 17.5 / Firefox 129) ignore the unknown at-rule and skip the entry fade (graceful
8536
8622
  // degradation). Formatting mirrors JSS output so the unit-test CSS parser can read it.
8537
8623
  //
8538
- // ALTERNATIVE APPROACH (not implemented) mirror the `dialog-base` (p-modal/p-flyout) pattern and drop `@starting-style`:
8624
+ // `skipEntryTransition` omits the append on the component's FIRST render, so an initially-open popover (`open=true` on
8625
+ // page load) computes straight to `opacity: 1` and appears instantly instead of fading in. Every later render passes
8626
+ // `false`, so a user-triggered open still fades in normally.
8627
+ //
8628
+ // ALTERNATIVE APPROACH (INTENTIONALLY NOT IMPLEMENTED) — mirror the `dialog-base` (p-modal/p-flyout) pattern and drop `@starting-style`:
8629
+ // Decision: KEEP this divergence (see the mirrored note in `common/dialog-base/dialog-base-styles.ts`). `p-popover`/`p-banner`
8630
+ // mimic the native `[popover]` box model, so they use the native `display: none`/`:popover-open` toggle + `@starting-style`
8631
+ // entry fade rather than the dialog's permanently-rendered `visibility`/`width`/`height` collapse. Both approaches share
8632
+ // `createTopLayerController`, the Chromium-only `overlay allow-discrete` transition (`overlayTransitionSupportsQuery`) and
8633
+ // the `inert` toggle for tabbability; only the closed-state expression differs. The alternative below is documented for
8634
+ // context (and to record its one upside — no entry fade on initial `open=true`), but is deliberately left unimplemented.
8539
8635
  // • Keep the panel permanently rendered (never `display: none`); collapse the closed state via `visibility: hidden`
8540
8636
  // + `width/height: 0` instead. Because the element stays rendered, `opacity` fades normally in BOTH directions with
8541
8637
  // no `@starting-style`, and an initial `open=true` computes straight to `opacity: 1` (appears instantly, no entry
@@ -8551,7 +8647,7 @@ const getComponentCss$v = (isOpen, isCompact) => {
8551
8647
  // tabbable during the fade-out).
8552
8648
  // • Trade-off: removes the `@starting-style` raw-CSS append + the initial-load fade, at the cost of reintroducing the
8553
8649
  // delayed `visibility` plus delayed `width/height` and tighter coupling to the motion duration.
8554
- return isOpen ? `${css}\n@starting-style {\n [popover] {\n opacity: 0;\n }\n}` : css;
8650
+ return isOpen && !skipEntryTransition ? `${css}\n@starting-style {\n [popover] {\n opacity: 0;\n }\n}` : css;
8555
8651
  };
8556
8652
 
8557
8653
  const cssVarInternalRadioGroupOptionScaling = '--_p-radio-group-option-a';
@@ -9131,7 +9227,6 @@ const getComponentCss$n = (isOpen, background, hasDismissButton) => {
9131
9227
  ...hostHiddenStyles,
9132
9228
  }),
9133
9229
  },
9134
- ...preventFoucOfNestedElementsStyles,
9135
9230
  slot: {
9136
9231
  ...getSlotJssStyle(),
9137
9232
  '&:not([name])': getSlotMainJssStyle(),
@@ -9140,7 +9235,7 @@ const getComponentCss$n = (isOpen, background, hasDismissButton) => {
9140
9235
  zIndex: 0, // controls layering + creates new stacking context (prevents content within to be above other dialog areas)
9141
9236
  },
9142
9237
  },
9143
- ...getFunctionalComponentDialogBaseStyles(isOpen, 'shading'),
9238
+ dialog: getFunctionalComponentDialogBaseStyles(isOpen, 'shading'),
9144
9239
  },
9145
9240
  scroller: getScrollerJssStyle('fullscreen'),
9146
9241
  sheet: {
@@ -10278,7 +10373,7 @@ const getComponentCss$1 = () => {
10278
10373
  [cssVariablePositionBottomInternal]: ref(cssVariablePositionBottom, '56px'),
10279
10374
  position: 'fixed', // fallback for older browsers without native `popover` support
10280
10375
  inset: `auto ${gridExtendedOffsetBase} ${ref(cssVariablePositionBottomInternal)}`,
10281
- zIndex: TOAST_Z_INDEX, // fallback for older browsers without native `popover` support
10376
+ zIndex: 999999, // fallback for older browsers without native `popover` support
10282
10377
  [getMediaQueryMin('s')]: {
10283
10378
  [cssVariablePositionBottomInternal]: ref(cssVariablePositionBottom, '64px'),
10284
10379
  inset: `auto auto ${ref(cssVariablePositionBottomInternal)} 64px`,
@@ -10350,4 +10445,4 @@ const getComponentCss = (size) => {
10350
10445
  });
10351
10446
  };
10352
10447
 
10353
- export { cssVarButtonPureMargin, cssVarButtonPurePadding, cssVarInternalInputBaseScaling, dialogBorderRadius, dialogGridJssStyle, dialogHostJssStyle, dialogPaddingBottom, dialogPaddingInline, dialogPaddingTop, getComponentCss$1a as getAccordionCss, getComponentCss$19 as getAiTagCss, getComponentCss$18 as getBannerCss, getComponentCss$15 as getButtonCss, getComponentCss$17 as getButtonPureCss, getComponentCss$16 as getButtonTileCss, getComponentCss$14 as getCanvasCss, getComponentCss$13 as getCarouselCss, getComponentCss$12 as getCheckboxCss, getComponentCss$11 as getCrestCss, getDialogColorJssStyle, getDialogDismissButtonJssStyle, getDialogTransitionJssStyle, getComponentCss$10 as getDisplayCss, getComponentCss$$ as getDividerCss, getComponentCss$_ as getDrilldownCss, getComponentCss$Z as getDrilldownItemCss, getComponentCss$Y as getDrilldownLinkCss, getComponentCss$X as getFieldsetCss, getComponentCss$W as getFlagCss, getComponentCss$V as getFlyoutCss, getFunctionalComponentDialogBaseStyles, getFunctionalComponentInputBaseStyles, getFunctionalComponentLabelAfterStyles, getFunctionalComponentLabelStyles, getFunctionalComponentLoadingMessageStyles, getFunctionalComponentNoResultsOptionStyles, getFunctionalComponentNotificationBaseStyles, getFunctionalComponentRequiredStyles, getFunctionalComponentStateMessageStyles, getComponentCss$U as getHeadingCss, getComponentCss$T as getIconCss, getComponentCss$S as getInlineNotificationCss, getComponentCss$R as getInputDateCss, getComponentCss$Q as getInputEmailCss, getComponentCss$P as getInputMonthCss, getComponentCss$O as getInputNumberCss, getComponentCss$N as getInputPasswordCss, getComponentCss$M as getInputSearchCss, getComponentCss$L as getInputTelCss, getComponentCss$K as getInputTextCss, getComponentCss$J as getInputTimeCss, getComponentCss$I as getInputUrlCss, getComponentCss$H as getInputWeekCss, getComponentCss$D as getLinkCss, getComponentCss$G as getLinkPureCss, getComponentCss$E as getLinkTileCss, getComponentCss$F as getLinkTileProductCss, getComponentCss$C as getModalCss, getComponentCss$B as getModelSignatureCss, getComponentCss$y as getMultiSelectCss, getComponentCss$A as getMultiSelectOptionCss, getComponentCss$z as getOptgroupCss, getComponentCss$x as getPaginationCss, getComponentCss$w as getPinCodeCss, getComponentCss$v as getPopoverCss, getComponentCss$t as getRadioGroupCss, getComponentCss$u as getRadioGroupOptionCss, getComponentCss$s as getScrollerCss, getScrollerJssStyle, getComponentCss$q as getSegmentedControlCss, getComponentCss$r as getSegmentedControlItemCss, getComponentCss$o as getSelectCss, getComponentCss$p as getSelectOptionCss, getComponentCss$n as getSheetCss, getSlotFooterJssStyle, getSlotHeaderJssStyle, getSlotJssStyle, getSlotMainJssStyle, getSlotSubFooterJssStyle, getComponentCss$m as getSpinnerCss, getComponentCss$k as getStepperHorizontalCss, getComponentCss$l as getStepperHorizontalItemCss, getComponentCss$j as getSwitchCss, getComponentCss$i as getTableBodyCss, getComponentCss$g as getTableCellCss, getComponentCss$h as getTableCss, getComponentCss$f as getTableHeadCellCss, getComponentCss$d as getTableHeadCss, getComponentCss$e as getTableHeadRowCss, getComponentCss$c as getTableRowCss, getComponentCss$b as getTabsBarCss, getComponentCss$9 as getTabsCss, getComponentCss$a as getTabsItemCss, getComponentCss$7 as getTagCss, getComponentCss$8 as getTagDismissibleCss, getComponentCss$4 as getTextCss, getComponentCss$6 as getTextListCss, getComponentCss$5 as getTextListItemCss, getComponentCss$3 as getTextareaCss, getComponentCss$1 as getToastCss, getComponentCss as getWordmarkCss };
10448
+ export { cssVarButtonPureMargin, cssVarButtonPurePadding, cssVarInternalInputBaseScaling, dialogBorderRadius, dialogGridJssStyle, dialogHostJssStyle, dialogPaddingBottom, dialogPaddingInline, dialogPaddingTop, getComponentCss$1a as getAccordionCss, getComponentCss$19 as getAiTagCss, getComponentCss$18 as getBannerCss, getComponentCss$15 as getButtonCss, getComponentCss$17 as getButtonPureCss, getComponentCss$16 as getButtonTileCss, getComponentCss$14 as getCanvasCss, getComponentCss$13 as getCarouselCss, getComponentCss$12 as getCheckboxCss, getComponentCss$11 as getCrestCss, getDialogColorJssStyle, getDialogDismissButtonJssStyle, getDialogTransitionJssStyle, getComponentCss$10 as getDisplayCss, getComponentCss$$ as getDividerCss, getComponentCss$_ as getDrilldownCss, getComponentCss$Z as getDrilldownItemCss, getComponentCss$Y as getDrilldownLinkCss, getFCDismissButtonStyles, getComponentCss$X as getFieldsetCss, getComponentCss$W as getFlagCss, getComponentCss$V as getFlyoutCss, getFunctionalComponentDialogBaseStyles, getFunctionalComponentInputBaseStyles, getFunctionalComponentLabelAfterStyles, getFunctionalComponentLabelStyles, getFunctionalComponentLoadingMessageStyles, getFunctionalComponentNoResultsOptionStyles, getFunctionalComponentNotificationBaseStyles, getFunctionalComponentRequiredStyles, getFunctionalComponentStateMessageStyles, getComponentCss$U as getHeadingCss, getComponentCss$T as getIconCss, getComponentCss$S as getInlineNotificationCss, getComponentCss$R as getInputDateCss, getComponentCss$Q as getInputEmailCss, getComponentCss$P as getInputMonthCss, getComponentCss$O as getInputNumberCss, getComponentCss$N as getInputPasswordCss, getComponentCss$M as getInputSearchCss, getComponentCss$L as getInputTelCss, getComponentCss$K as getInputTextCss, getComponentCss$J as getInputTimeCss, getComponentCss$I as getInputUrlCss, getComponentCss$H as getInputWeekCss, getComponentCss$D as getLinkCss, getComponentCss$G as getLinkPureCss, getComponentCss$E as getLinkTileCss, getComponentCss$F as getLinkTileProductCss, getComponentCss$C as getModalCss, getComponentCss$B as getModelSignatureCss, getComponentCss$y as getMultiSelectCss, getComponentCss$A as getMultiSelectOptionCss, getComponentCss$z as getOptgroupCss, getComponentCss$x as getPaginationCss, getComponentCss$w as getPinCodeCss, getComponentCss$v as getPopoverCss, getComponentCss$t as getRadioGroupCss, getComponentCss$u as getRadioGroupOptionCss, getComponentCss$s as getScrollerCss, getScrollerJssStyle, getComponentCss$q as getSegmentedControlCss, getComponentCss$r as getSegmentedControlItemCss, getComponentCss$o as getSelectCss, getComponentCss$p as getSelectOptionCss, getComponentCss$n as getSheetCss, getSlotFooterJssStyle, getSlotHeaderJssStyle, getSlotJssStyle, getSlotMainJssStyle, getSlotSubFooterJssStyle, getComponentCss$m as getSpinnerCss, getComponentCss$k as getStepperHorizontalCss, getComponentCss$l as getStepperHorizontalItemCss, getComponentCss$j as getSwitchCss, getComponentCss$i as getTableBodyCss, getComponentCss$g as getTableCellCss, getComponentCss$h as getTableCss, getComponentCss$f as getTableHeadCellCss, getComponentCss$d as getTableHeadCss, getComponentCss$e as getTableHeadRowCss, getComponentCss$c as getTableRowCss, getComponentCss$b as getTabsBarCss, getComponentCss$9 as getTabsCss, getComponentCss$a as getTabsItemCss, getComponentCss$7 as getTagCss, getComponentCss$8 as getTagDismissibleCss, getComponentCss$4 as getTextCss, getComponentCss$6 as getTextListCss, getComponentCss$5 as getTextListItemCss, getComponentCss$3 as getTextareaCss, getComponentCss$1 as getToastCss, getComponentCss as getWordmarkCss };
@@ -3480,7 +3480,7 @@ const hasShowPickerSupport = () => (hasDocument &&
3480
3480
  'showPicker' in HTMLInputElement.prototype &&
3481
3481
  CSS.supports('selector(::-webkit-calendar-picker-indicator)'));
3482
3482
 
3483
- const prefix = `[Porsche Design System v${"4.4.0-rc.0"}]` // this part isn't covered by unit tests
3483
+ const prefix = `[Porsche Design System v${"4.4.0"}]` // this part isn't covered by unit tests
3484
3484
  ;
3485
3485
  const consoleError$1 = (...messages) => {
3486
3486
  console.error(prefix, ...messages);
@@ -1,12 +1,11 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { Component } from 'react';
3
- import '../../provider.mjs';
4
2
  import { splitChildren } from '../../splitChildren.mjs';
3
+ import { Component } from 'react';
5
4
  import { minifyCss } from '../../minifyCss.mjs';
6
5
  import { getBannerCss as getComponentCss$18 } from '../../../../../../components/dist/styles/esm/styles-entry.mjs';
7
6
  import { createTopLayerController, getBannerAriaAttributes } from '../../../../../../components/dist/utils/esm/utils-entry.mjs';
7
+ import { FCDismissButton } from './fc-dismiss-button.mjs';
8
8
  import { NotificationBase } from './notification-base.mjs';
9
- import { PButton } from '../components/button.wrapper.mjs';
10
9
 
11
10
  /**
12
11
  * @slot {"name": "heading", "description": "Defines the heading of the banner. Can be used as an alternative to the `heading` prop for rich content." }
@@ -21,6 +20,12 @@ class DSRBanner extends Component {
21
20
  refDismiss;
22
21
  hasHeadingSlot;
23
22
  hasDescriptionSlot;
23
+ // Tracks whether the document-level Escape listener is currently registered (guards the idempotent sync below).
24
+ hasKeydownListener = false;
25
+ // Tracks the component's first render. While `true`, the entry transition (`@starting-style`) is suppressed so an
26
+ // initially-open banner (`open=true` on page load) appears instantly instead of sliding/fading in; flipped to `false`
27
+ // in `componentDidLoad`, so every later (user-triggered) open keeps the entry animation.
28
+ isInitialRender = true;
24
29
  topLayer = createTopLayerController({
25
30
  getElement: () => this.props.refPopover,
26
31
  isShown: () => !!this.props.refPopover?.matches(':popover-open'),
@@ -33,8 +38,13 @@ class DSRBanner extends Component {
33
38
  const hasDescriptionSlot = namedSlotChildren.filter(({ props: { slot } }) => slot === 'description').length > 0;
34
39
  const headingText = this.props.heading ? this.props.heading : namedSlotChildren.find(({ props: { slot } }) => slot === 'heading')?.props.children;
35
40
  const style = minifyCss(getComponentCss$18(this.props.open, this.props.position, this.props.state, this.props.dismissButton, !!(this.props.heading || hasHeadingSlot)));
36
- return (jsxs(Fragment, { children: [jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsx("style", { dangerouslySetInnerHTML: { __html: style } }), jsx("div", { popover: "manual", "aria-hidden": this.props.open ? 'false' : 'true', ...getBannerAriaAttributes(this.props.state, headingText), children: jsx(NotificationBase, { heading: this.props.heading, headingTag: this.props.headingTag, hasHeadingSlot: hasHeadingSlot, description: this.props.description, hasDescriptionSlot: hasDescriptionSlot, ...(this.props.dismissButton && {
37
- dismissButton: (jsx(PButton, { className: "dismiss", type: "button", variant: "secondary", icon: "close", hideLabel: true, compact: true, ...(headingText ? { aria: { 'aria-description': headingText } } : {}), children: "Close banner" })),
41
+ return (jsxs(Fragment, { children: [jsxs("template", { shadowroot: "open", shadowrootmode: "open", children: [jsx("style", { dangerouslySetInnerHTML: { __html: style + (this.props.open ? '[popover]{display:grid!important}' : '') } }), jsx("div", { popover: "manual",
42
+ // `inert` (not `aria-hidden`) removes the panel from the a11y tree AND prevents focus while closed / during the
43
+ // fade-out. Using `aria-hidden` here triggers a browser warning when a focusable descendant still holds focus
44
+ // during the closing transition ("Blocked aria-hidden on an element because its descendant retained focus").
45
+ // `inert` avoids that and mirrors the pattern used by `p-modal` / `p-popover` / `p-drilldown`.
46
+ inert: !this.props.open, ...getBannerAriaAttributes(this.props.state, headingText), children: jsx(NotificationBase, { heading: this.props.heading, headingTag: this.props.headingTag, hasHeadingSlot: hasHeadingSlot, description: this.props.description, hasDescriptionSlot: hasDescriptionSlot, ...(this.props.dismissButton && {
47
+ dismissButton: (jsx(FCDismissButton, { label: "Close banner", ariaDescription: headingText || undefined })),
38
48
  }) }) })] }), this.props.children] }));
39
49
  }
40
50
  }