{"version":3,"names":["panelCss","CalcitePanelStyle0","Panel","this","resizeObserver","createObserver","resizeHandler","panelScrollEl","scrollHeight","offsetHeight","hasScrollingContent","setAttribute","removeAttribute","setContainerRef","node","containerEl","panelKeyDownHandler","event","closable","key","defaultPrevented","handleUserClose","preventDefault","closed","calcitePanelClose","emit","open","isClosed","close","async","beforeClose","Promise","resolve","_error","requestAnimationFrame","collapse","collapsed","calcitePanelToggle","panelScrollHandler","calcitePanelScroll","handleHeaderActionsStartSlotChange","hasStartActions","slotChangeHasAssignedElement","handleHeaderActionsEndSlotChange","hasEndActions","handleHeaderMenuActionsSlotChange","hasMenuItems","handleActionBarSlotChange","actionBars","slotChangeGetAssignedElements","filter","el","matches","forEach","actionBar","layout","hasActionBar","length","handleHeaderContentSlotChange","hasHeaderContent","handleFabSlotChange","hasFab","handleFooterActionsSlotChange","hasFooterActions","handleFooterEndSlotChange","hasFooterEndContent","handleFooterStartSlotChange","hasFooterStartContent","handleFooterSlotChange","hasFooterContent","contentBottomSlotChangeHandler","hasContentBottom","contentTopSlotChangeHandler","hasContentTop","setPanelScrollEl","disconnect","observe","handleAlertsSlotChange","map","nodeName","embedded","defaultEndMenuPlacement","toggleDialog","value","onMessagesChange","connectedCallback","connectLocalized","connectMessages","componentWillLoad","setUpLoadableComponent","setUpMessages","componentDidLoad","setComponentLoaded","componentDidRender","updateHostInteraction","disconnectedCallback","disconnectLocalized","disconnectMessages","effectiveLocaleChange","updateMessages","effectiveLocale","setFocus","componentFocusable","focusFirstTabbable","scrollContentTo","options","scrollTo","renderHeaderContent","heading","headingLevel","description","headingNode","h","Heading","class","CSS","level","descriptionNode","headerContent","renderActionBar","actionBarContainer","hidden","name","SLOTS","onSlotchange","renderHeaderSlottedContent","renderHeaderStartActions","headerActionsStart","headerActions","renderHeaderActionsEnd","messages","collapseDirection","collapsible","expand","icons","ICONS","reverse","collapseNode","toAriaBoolean","icon","id","IDS","onClick","scale","text","title","closeNode","slotNode","headerActionsEnd","showContainer","renderMenu","menuOpen","menuFlipPlacements","menuPlacement","flipPlacements","label","overlayPositioning","placement","menu","slot","ACTION_MENU_SLOTS","trigger","headerMenuActions","renderHeaderNode","headerContentNode","showHeaderContent","header","headerContainer","headerContainerBorderEnd","renderContentTop","renderFooterNode","showFooter","footer","footerContent","footerStart","footerEnd","footerActions","renderContent","contentWrapper","onScroll","ref","renderFab","renderContentBottom","contentBottom","contentTop","fabContainer","fab","render","disabled","loading","panelNode","container","alerts","Host","onKeyDown","InteractiveContainer"],"sources":["src/components/panel/panel.scss?tag=calcite-panel&encapsulation=shadow","src/components/panel/panel.tsx"],"sourcesContent":["/**\n * CSS Custom Properties\n *\n * These properties can be overridden using the component's tag as selector.\n *\n * @prop --calcite-panel-content-space: Specifies the padding of the component's content.\n * @prop --calcite-panel-footer-padding: Specifies the padding of the component's footer.\n * @prop --calcite-panel-header-border-block-end: Specifies the component header's block end border.\n * @prop --calcite-panel-background-color: Specifies the background color of the component.\n */\n\n:host {\n @extend %component-host;\n @apply relative flex w-full h-full flex-auto overflow-hidden;\n\n --calcite-min-header-height: calc(var(--calcite-icon-size) * 3);\n}\n\n@include disabled();\n\n@import \"../../assets/styles/header\";\n\n:host([scale=\"s\"]) {\n --calcite-internal-panel-default-padding: var(--calcite-spacing-sm);\n --calcite-internal-panel-header-vertical-padding: 10px; // this should use a spacing token once made available\n\n .header-content {\n .heading {\n @apply text-n1h;\n }\n\n .description {\n @apply text-n2h;\n }\n }\n}\n\n:host([scale=\"m\"]) {\n --calcite-internal-panel-default-padding: var(--calcite-spacing-md);\n --calcite-internal-panel-header-vertical-padding: var(--calcite-spacing-lg);\n\n .header-content {\n .heading {\n @apply text-0h;\n }\n\n .description {\n @apply text-n1h;\n }\n }\n}\n\n:host([scale=\"l\"]) {\n --calcite-internal-panel-default-padding: var(--calcite-spacing-xl);\n --calcite-internal-panel-header-vertical-padding: var(--calcite-spacing-xxl);\n\n .header-content {\n .heading {\n @apply text-1h;\n }\n\n .description {\n @apply text-0h;\n }\n }\n}\n\n.content-top,\n.content-bottom {\n @apply flex items-start self-stretch;\n\n border-block-start: 1px solid var(--calcite-color-border-3);\n background-color: var(--calcite-color-foreground-1);\n}\n\n.container {\n @apply relative bg-background m-0 flex w-full flex-auto flex-col items-stretch p-0;\n\n transition:\n max-block-size var(--calcite-animation-timing),\n inline-size var(--calcite-animation-timing);\n}\n\n.container[hidden] {\n @apply hidden;\n}\n\n.header {\n @apply bg-foreground-1 flex flex-col z-header;\n border-block-end: var(--calcite-panel-header-border-block-end, 1px solid var(--calcite-color-border-3));\n}\n\n.header-container {\n @apply flex flex-row w-full\n items-stretch\n justify-start;\n flex: 0 0 auto;\n}\n\n.header-container--border-end {\n border-block-end: 1px solid var(--calcite-color-border-3);\n}\n\n.action-bar-container {\n @apply w-full;\n}\n\n.action-bar-container ::slotted(calcite-action-bar) {\n @apply w-full;\n}\n\n.header-content {\n @apply flex\n flex-col\n overflow-hidden\n px-3\n py-3.5;\n\n margin-inline-end: auto;\n\n .heading,\n .description {\n @apply block\n break-words\n p-0;\n }\n\n .heading {\n @apply mx-0 mt-0 mb-1 font-medium text-color-1;\n\n &:only-child {\n @apply mb-0;\n }\n }\n\n .description {\n @apply text-color-2;\n }\n}\n\n.back-button {\n @apply border-color-3\n border-0\n border-solid;\n border-inline-end-width: theme(\"borderWidth.DEFAULT\");\n}\n\n.header-actions {\n @apply flex\n flex-row\n flex-nowrap\n items-stretch;\n}\n\n.header-actions--end {\n margin-inline-start: theme(\"margin.auto\");\n}\n\n.content-wrapper {\n @apply flex\n flex-auto\n flex-col\n flex-nowrap\n items-stretch\n overflow-auto\n h-full\n focus-base\n relative;\n padding: var(--calcite-panel-content-space, 0);\n background: var(--calcite-panel-background-color, var(--calcite-color-background));\n}\n\n.content-wrapper:focus-visible {\n @apply focus-inset;\n}\n\n.content-top,\n.content-bottom {\n padding: var(--calcite-internal-panel-default-padding);\n}\n\n.header-content {\n flex: 1 1 auto;\n padding-block: var(--calcite-internal-panel-header-vertical-padding);\n padding-inline: var(--calcite-internal-panel-default-padding);\n}\n\n.footer {\n @apply flex mt-auto flex-row content-between justify-center items-center bg-foreground-1 text-n2-wrap;\n border-block-start: 1px solid var(--calcite-color-border-3);\n padding: var(--calcite-panel-footer-padding, var(--calcite-internal-panel-default-padding));\n}\n\n.footer-content {\n @apply flex flex-row items-center justify-center flex-1;\n}\n\n.footer-actions {\n @apply flex flex-row items-center justify-evenly flex-1;\n gap: var(--calcite-internal-panel-default-padding);\n}\n\n.footer-start {\n @apply flex flex-row items-center justify-start flex-1;\n margin-inline-end: auto;\n gap: var(--calcite-internal-panel-default-padding);\n}\n\n.footer-end {\n @apply flex flex-row items-center justify-end flex-1;\n margin-inline-start: auto;\n gap: var(--calcite-internal-panel-default-padding);\n}\n\n.fab-container {\n @apply sticky\n bottom-0\n my-0\n mx-auto\n block\n p-2\n z-sticky;\n inset-inline: 0;\n inline-size: fit-content;\n}\n\n@include base-component();\n","import {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n State,\n VNode,\n Watch,\n} from \"@stencil/core\";\nimport {\n focusFirstTabbable,\n slotChangeGetAssignedElements,\n slotChangeHasAssignedElement,\n toAriaBoolean,\n} from \"../../utils/dom\";\nimport {\n InteractiveComponent,\n InteractiveContainer,\n updateHostInteraction,\n} from \"../../utils/interactive\";\nimport {\n componentFocusable,\n LoadableComponent,\n setComponentLoaded,\n setUpLoadableComponent,\n} from \"../../utils/loadable\";\nimport { createObserver } from \"../../utils/observers\";\nimport { SLOTS as ACTION_MENU_SLOTS } from \"../action-menu/resources\";\nimport { Heading, HeadingLevel } from \"../functional/Heading\";\nimport { connectLocalized, disconnectLocalized, LocalizedComponent } from \"../../utils/locale\";\nimport {\n connectMessages,\n disconnectMessages,\n setUpMessages,\n T9nComponent,\n updateMessages,\n} from \"../../utils/t9n\";\nimport {\n defaultEndMenuPlacement,\n FlipPlacement,\n LogicalPlacement,\n OverlayPositioning,\n} from \"../../utils/floating-ui\";\nimport { CollapseDirection } from \"../interfaces\";\nimport { Scale } from \"../interfaces\";\nimport { PanelMessages } from \"./assets/panel/t9n\";\nimport { CSS, ICONS, IDS, SLOTS } from \"./resources\";\n\n/**\n * @slot - A slot for adding custom content.\n * @slot action-bar - A slot for adding a `calcite-action-bar` to the component.\n * @slot alerts - A slot for adding `calcite-alert`s to the component.\n * @slot content-bottom - A slot for adding content below the unnamed (default) slot and above the footer slot (if populated)\n * @slot content-top - A slot for adding content above the unnamed (default) slot and below the action-bar slot (if populated).\n * @slot header-actions-start - A slot for adding actions or content to the start side of the header.\n * @slot header-actions-end - A slot for adding actions or content to the end side of the header.\n * @slot header-content - A slot for adding custom content to the header.\n * @slot header-menu-actions - A slot for adding an overflow menu with actions inside a `calcite-dropdown`.\n * @slot fab - A slot for adding a `calcite-fab` (floating action button) to perform an action.\n * @slot footer - A slot for adding custom content to the component's footer. Should not be used with the `\"footer-start\"` or `\"footer-end\"` slots.\n * @slot footer-actions - [Deprecated] Use the `footer-start` and `footer-end` slots instead. A slot for adding `calcite-button`s to the component's footer.\n * @slot footer-end - A slot for adding a trailing footer custom content. Should not be used with the `\"footer\"` slot.\n * @slot footer-start - A slot for adding a leading footer custom content. Should not be used with the `\"footer\"` slot.\n */\n@Component({\n tag: \"calcite-panel\",\n styleUrl: \"panel.scss\",\n shadow: true,\n assetsDirs: [\"assets\"],\n})\nexport class Panel\n implements InteractiveComponent, LoadableComponent, LocalizedComponent, T9nComponent\n{\n // --------------------------------------------------------------------------\n //\n // Properties\n //\n // --------------------------------------------------------------------------\n\n /** Passes a function to run before the component closes. */\n @Prop() beforeClose: () => Promise;\n\n /** When `true`, the component will be hidden. */\n @Prop({ mutable: true, reflect: true }) closed = false;\n\n @Watch(\"closed\")\n toggleDialog(value: boolean): void {\n value ? this.close() : this.open();\n }\n\n /**\n * When `true`, interaction is prevented and the component is displayed with lower opacity.\n */\n @Prop({ reflect: true }) disabled = false;\n\n /** When `true`, displays a close button in the trailing side of the header. */\n @Prop({ reflect: true }) closable = false;\n\n /**\n * When `true`, hides the component's content area.\n */\n @Prop({ reflect: true }) collapsed = false;\n\n /**\n * Specifies the direction of the collapse.\n *\n * @internal\n */\n @Prop() collapseDirection: CollapseDirection = \"down\";\n\n /**\n * When `true`, the component is collapsible.\n */\n @Prop({ reflect: true }) collapsible = false;\n\n /**\n * Specifies the heading level of the component's `heading` for proper document structure, without affecting visual styling.\n */\n @Prop({ reflect: true }) headingLevel: HeadingLevel;\n\n /**\n * When `true`, a busy indicator is displayed.\n */\n @Prop({ reflect: true }) loading = false;\n\n /**\n * The component header text.\n */\n @Prop() heading: string;\n\n /** A description for the component. */\n @Prop() description: string;\n\n /**\n * Specifies the component's fallback menu `placement` when it's initial or specified `placement` has insufficient space available.\n */\n @Prop() menuFlipPlacements: FlipPlacement[];\n\n /**\n * When `true`, the action menu items in the `header-menu-actions` slot are open.\n */\n @Prop({ reflect: true }) menuOpen = false;\n\n /**\n * Determines where the action menu will be positioned.\n */\n @Prop({ reflect: true }) menuPlacement: LogicalPlacement = defaultEndMenuPlacement;\n\n /**\n * Use this property to override individual strings used by the component.\n */\n // eslint-disable-next-line @stencil-community/strict-mutable -- updated by t9n module\n @Prop({ mutable: true }) messageOverrides: Partial;\n\n /**\n * Made into a prop for testing purposes only\n *\n * @internal\n */\n // eslint-disable-next-line @stencil-community/strict-mutable -- updated by t9n module\n @Prop({ mutable: true }) messages: PanelMessages;\n\n @Watch(\"messageOverrides\")\n onMessagesChange(): void {\n /* wired up by t9n util */\n }\n\n /**\n * Determines the type of positioning to use for the overlaid content.\n *\n * Using `\"absolute\"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout.\n *\n * `\"fixed\"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `\"fixed\"`.\n *\n */\n @Prop({ reflect: true }) overlayPositioning: OverlayPositioning = \"absolute\";\n\n /** Specifies the size of the component. */\n @Prop({ reflect: true }) scale: Scale = \"m\";\n\n //--------------------------------------------------------------------------\n //\n // Lifecycle\n //\n //--------------------------------------------------------------------------\n\n connectedCallback(): void {\n connectLocalized(this);\n connectMessages(this);\n }\n\n async componentWillLoad(): Promise {\n setUpLoadableComponent(this);\n this.isClosed = this.closed;\n await setUpMessages(this);\n }\n\n componentDidLoad(): void {\n setComponentLoaded(this);\n }\n\n componentDidRender(): void {\n updateHostInteraction(this);\n }\n\n disconnectedCallback(): void {\n disconnectLocalized(this);\n disconnectMessages(this);\n this.resizeObserver?.disconnect();\n }\n\n // --------------------------------------------------------------------------\n //\n // Private Properties\n //\n // --------------------------------------------------------------------------\n\n @Element() el: HTMLCalcitePanelElement;\n\n containerEl: HTMLElement;\n\n panelScrollEl: HTMLElement;\n\n resizeObserver = createObserver(\"resize\", () => this.resizeHandler());\n\n @State() isClosed = false;\n\n @State() hasStartActions = false;\n\n @State() hasEndActions = false;\n\n @State() hasMenuItems = false;\n\n @State() hasHeaderContent = false;\n\n @State() hasActionBar = false;\n\n @State() hasContentBottom = false;\n\n @State() hasContentTop = false;\n\n @State() hasFab = false;\n\n @State() hasFooterActions = false;\n\n @State() hasFooterContent = false;\n\n @State() hasFooterEndContent = false;\n\n @State() hasFooterStartContent = false;\n\n @State() defaultMessages: PanelMessages;\n\n @State() effectiveLocale = \"\";\n\n @State() showHeaderContent = false;\n\n @Watch(\"effectiveLocale\")\n effectiveLocaleChange(): void {\n updateMessages(this, this.effectiveLocale);\n }\n\n // --------------------------------------------------------------------------\n //\n // Events\n //\n // --------------------------------------------------------------------------\n\n /**\n * Fires when the close button is clicked.\n */\n @Event({ cancelable: false }) calcitePanelClose: EventEmitter;\n\n /**\n * Fires when the collapse button is clicked.\n */\n @Event({ cancelable: false }) calcitePanelToggle: EventEmitter;\n\n /**\n * Fires when the content is scrolled.\n */\n @Event({ cancelable: false }) calcitePanelScroll: EventEmitter;\n\n // --------------------------------------------------------------------------\n //\n // Private Methods\n //\n // --------------------------------------------------------------------------\n\n resizeHandler = (): void => {\n const { panelScrollEl } = this;\n\n if (\n !panelScrollEl ||\n typeof panelScrollEl.scrollHeight !== \"number\" ||\n typeof panelScrollEl.offsetHeight !== \"number\"\n ) {\n return;\n }\n\n const hasScrollingContent = panelScrollEl.scrollHeight > panelScrollEl.offsetHeight;\n\n // intentionally using setAttribute to avoid reflecting -1 so default browser behavior will occur\n if (hasScrollingContent) {\n panelScrollEl.setAttribute(\"tabindex\", \"0\");\n } else {\n panelScrollEl.removeAttribute(\"tabindex\");\n }\n };\n\n setContainerRef = (node: HTMLElement): void => {\n this.containerEl = node;\n };\n\n panelKeyDownHandler = (event: KeyboardEvent): void => {\n if (this.closable && event.key === \"Escape\" && !event.defaultPrevented) {\n this.handleUserClose();\n event.preventDefault();\n }\n };\n\n private handleUserClose = (): void => {\n this.closed = true;\n this.calcitePanelClose.emit();\n };\n\n open = (): void => {\n this.isClosed = false;\n };\n\n close = async (): Promise => {\n const beforeClose = this.beforeClose ?? (() => Promise.resolve());\n\n try {\n await beforeClose();\n } catch (_error) {\n // close prevented\n requestAnimationFrame(() => {\n this.closed = false;\n });\n return;\n }\n\n this.isClosed = true;\n };\n\n collapse = (): void => {\n this.collapsed = !this.collapsed;\n this.calcitePanelToggle.emit();\n };\n\n panelScrollHandler = (): void => {\n this.calcitePanelScroll.emit();\n };\n\n handleHeaderActionsStartSlotChange = (event: Event): void => {\n this.hasStartActions = slotChangeHasAssignedElement(event);\n };\n\n handleHeaderActionsEndSlotChange = (event: Event): void => {\n this.hasEndActions = slotChangeHasAssignedElement(event);\n };\n\n handleHeaderMenuActionsSlotChange = (event: Event): void => {\n this.hasMenuItems = slotChangeHasAssignedElement(event);\n };\n\n handleActionBarSlotChange = (event: Event): void => {\n const actionBars = slotChangeGetAssignedElements(event).filter(\n (el): el is HTMLCalciteActionBarElement => el?.matches(\"calcite-action-bar\"),\n );\n\n actionBars.forEach((actionBar) => (actionBar.layout = \"horizontal\"));\n\n this.hasActionBar = !!actionBars.length;\n };\n\n handleHeaderContentSlotChange = (event: Event): void => {\n this.hasHeaderContent = slotChangeHasAssignedElement(event);\n };\n\n handleFabSlotChange = (event: Event): void => {\n this.hasFab = slotChangeHasAssignedElement(event);\n };\n\n handleFooterActionsSlotChange = (event: Event): void => {\n this.hasFooterActions = slotChangeHasAssignedElement(event);\n };\n\n handleFooterEndSlotChange = (event: Event): void => {\n this.hasFooterEndContent = slotChangeHasAssignedElement(event);\n };\n\n handleFooterStartSlotChange = (event: Event): void => {\n this.hasFooterStartContent = slotChangeHasAssignedElement(event);\n };\n\n handleFooterSlotChange = (event: Event): void => {\n this.hasFooterContent = slotChangeHasAssignedElement(event);\n };\n\n private contentBottomSlotChangeHandler = (event: Event): void => {\n this.hasContentBottom = slotChangeHasAssignedElement(event);\n };\n\n private contentTopSlotChangeHandler = (event: Event): void => {\n this.hasContentTop = slotChangeHasAssignedElement(event);\n };\n\n // --------------------------------------------------------------------------\n //\n // Methods\n //\n // --------------------------------------------------------------------------\n\n /**\n * Sets focus on the component's first focusable element.\n */\n @Method()\n async setFocus(): Promise {\n await componentFocusable(this);\n focusFirstTabbable(this.containerEl);\n }\n\n /**\n * Scrolls the component's content to a specified set of coordinates.\n *\n * @example\n * myCalciteFlowItem.scrollContentTo({\n * left: 0, // Specifies the number of pixels along the X axis to scroll the window or element.\n * top: 0, // Specifies the number of pixels along the Y axis to scroll the window or element\n * behavior: \"auto\" // Specifies whether the scrolling should animate smoothly (smooth), or happen instantly in a single jump (auto, the default value).\n * });\n * @param options - allows specific coordinates to be defined.\n * @returns - promise that resolves once the content is scrolled to.\n */\n @Method()\n async scrollContentTo(options?: ScrollToOptions): Promise {\n this.panelScrollEl?.scrollTo(options);\n }\n\n // --------------------------------------------------------------------------\n //\n // Render Methods\n //\n // --------------------------------------------------------------------------\n\n renderHeaderContent(): VNode {\n const { heading, headingLevel, description, hasHeaderContent } = this;\n const headingNode = heading ? (\n \n {heading}\n \n ) : null;\n\n const descriptionNode = description ? {description} : null;\n\n return !hasHeaderContent && (headingNode || descriptionNode) ? (\n
\n {headingNode}\n {descriptionNode}\n
\n ) : null;\n }\n\n renderActionBar(): VNode {\n return (\n \n );\n }\n\n renderHeaderSlottedContent(): VNode {\n return (\n \n );\n }\n\n renderHeaderStartActions(): VNode {\n const { hasStartActions } = this;\n\n return (\n