@hashicorp/design-system-components 4.19.0 → 4.20.0-rc-20250513142046

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.
@@ -47,52 +47,19 @@ export interface HdsCodeBlockSignature {
47
47
  }
48
48
  export default class HdsCodeBlock extends Component<HdsCodeBlockSignature> {
49
49
  private _prismCode;
50
- /**
51
- * Generates a unique ID for the code content
52
- *
53
- * @param _preCodeId
54
- */
50
+ private _isExpanded;
51
+ private _codeContentHeight;
52
+ private _codeContainerHeight;
55
53
  private _preCodeId;
56
- /**
57
- * @param code
58
- * @type {string}
59
- * @description code text content for the CodeBlock
60
- */
61
54
  get code(): string;
62
- /**
63
- * @param language
64
- * @type {string}
65
- * @default undefined
66
- * @description name of coding language used within CodeBlock for syntax highlighting
67
- */
55
+ get maxHeight(): string | undefined;
56
+ get showFooter(): boolean;
68
57
  get language(): HdsCodeBlockLanguages | undefined;
69
- /**
70
- * @param hasLineNumbers
71
- * @type {boolean}
72
- * @default true
73
- * @description Displays line numbers if true
74
- */
75
58
  get hasLineNumbers(): boolean;
76
- /**
77
- * @param isStandalone
78
- * @type {boolean}
79
- * @default true
80
- * @description Make CodeBlock container corners appear rounded
81
- */
82
59
  get isStandalone(): boolean;
83
- /**
84
- * @param hasLineWrapping
85
- * @type {boolean}
86
- * @default false
87
- * @description Make text content wrap on multiple lines
88
- */
89
60
  get hasLineWrapping(): boolean;
90
61
  get copyButtonText(): HdsCopyButtonSignature['Args']['text'];
91
62
  setPrismCode(element: HTMLElement): void;
92
- /**
93
- * Get the class names to apply to the component.
94
- * @method classNames
95
- * @return {string} The "class" attribute to apply to the component.
96
- */
63
+ toggleExpanded(): void;
97
64
  get classNames(): string;
98
65
  }
@@ -6,7 +6,7 @@ import { precompileTemplate } from '@ember/template-compilation';
6
6
  import { g, i, n } from 'decorator-transforms/runtime';
7
7
  import { setComponentTemplate } from '@ember/component';
8
8
 
9
- var TEMPLATE = precompileTemplate("{{!\n Copyright (c) HashiCorp, Inc.\n SPDX-License-Identifier: MPL-2.0\n}}\n{{! IMPORTANT: we need to add \"squishies\" here (~) because otherwise the whitespace added by Ember causes the empty element to still have visible padding - See https://handlebarsjs.com/guide/expressions.html#whitespace-control }}\n<div\n class={{this.classNames}}\n ...attributes\n {{on \"transitionstart\" (fn this.setTransition \"start\")}}\n {{on \"transitionend\" (fn this.setTransition \"end\")}}\n {{! @glint-expect-error - https://github.com/josemarluedke/ember-focus-trap/issues/86 }}\n {{focus-trap isActive=this.shouldTrapFocus}}\n {{did-insert this.didInsert}}\n>\n <h2 class=\"sr-only\" id=\"hds-app-side-nav-header\">Application local navigation</h2>\n\n <div class=\"hds-app-side-nav__wrapper\">\n {{#if this.showToggleButton}}\n {{! template-lint-disable no-invalid-interactive}}\n <div class=\"hds-app-side-nav__overlay\" {{on \"click\" this.toggleMinimizedStatus}} />\n {{! template-lint-enable no-invalid-interactive}}\n <Hds::AppSideNav::ToggleButton\n aria-labelledby=\"hds-app-side-nav-header\"\n aria-expanded={{if this._isMinimized \"false\" \"true\"}}\n @icon={{if this._isMinimized \"chevrons-right\" \"chevrons-left\"}}\n {{on \"click\" this.toggleMinimizedStatus}}\n />\n {{/if}}\n\n <div class=\"hds-app-side-nav__wrapper-body\">\n {{~yield~}}\n </div>\n </div>\n</div>");
9
+ var TEMPLATE = precompileTemplate("{{!\n Copyright (c) HashiCorp, Inc.\n SPDX-License-Identifier: MPL-2.0\n}}\n{{! IMPORTANT: we need to add \"squishies\" here (~) because otherwise the whitespace added by Ember causes the empty element to still have visible padding - See https://handlebarsjs.com/guide/expressions.html#whitespace-control }}\n<div\n class={{this.classNames}}\n ...attributes\n {{on \"transitionstart\" (fn this.setTransition \"start\")}}\n {{on \"transitionend\" (fn this.setTransition \"end\")}}\n {{! @glint-expect-error - https://github.com/josemarluedke/ember-focus-trap/issues/86 }}\n {{focus-trap isActive=this.shouldTrapFocus}}\n {{did-insert this.didInsert}}\n>\n <h2 class=\"sr-only\" id=\"hds-app-side-nav-header\">Application local navigation</h2>\n\n <div class=\"hds-app-side-nav__wrapper\">\n {{#if this.showToggleButton}}\n {{! template-lint-disable no-invalid-interactive}}\n <div class=\"hds-app-side-nav__overlay\" {{on \"click\" this.toggleMinimizedStatus}} />\n {{! template-lint-enable no-invalid-interactive}}\n <Hds::AppSideNav::ToggleButton\n aria-labelledby=\"hds-app-side-nav-header\"\n aria-expanded={{if this._isMinimized \"false\" \"true\"}}\n @icon={{if this._isMinimized \"chevrons-right\" \"chevrons-left\"}}\n {{on \"click\" this.toggleMinimizedStatus}}\n />\n {{/if}}\n\n <div class=\"hds-app-side-nav__wrapper-body hds-app-side-nav-hide-when-minimized\">\n {{~yield~}}\n </div>\n </div>\n</div>");
10
10
 
11
11
  /**
12
12
  * Copyright (c) HashiCorp, Inc.
@@ -137,6 +137,7 @@ class HdsAppSideNav extends Component {
137
137
  if (event.key === 'Escape' && !this._isMinimized && !this._isDesktop) {
138
138
  this._isMinimized = true;
139
139
  this.synchronizeInert();
140
+ this.unlockBodyScroll();
140
141
  }
141
142
  }
142
143
  static {
@@ -151,10 +152,12 @@ class HdsAppSideNav extends Component {
151
152
  if (typeof onToggleMinimizedStatus === 'function') {
152
153
  onToggleMinimizedStatus(this._isMinimized);
153
154
  }
154
- if (this._isMinimized) {
155
- this.unlockBodyScroll();
156
- } else {
157
- this.lockBodyScroll();
155
+ if (!this._isDesktop) {
156
+ if (this._isMinimized) {
157
+ this.unlockBodyScroll();
158
+ } else {
159
+ this.lockBodyScroll();
160
+ }
158
161
  }
159
162
  }
160
163
  static {
@@ -189,6 +192,10 @@ class HdsAppSideNav extends Component {
189
192
  // automatically minimize on narrow viewports (when not in desktop mode)
190
193
  this._isMinimized = !this._isDesktop;
191
194
  this.synchronizeInert();
195
+ if (this._isDesktop) {
196
+ // make sure scrolling is enabled if the user resizes the window from mobile to desktop
197
+ this.unlockBodyScroll();
198
+ }
192
199
  const {
193
200
  onDesktopViewportChange
194
201
  } = this.args;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/components/hds/app-side-nav/index.ts"],"sourcesContent":["/**\n * Copyright (c) HashiCorp, Inc.\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { action } from '@ember/object';\nimport { registerDestructor } from '@ember/destroyable';\nimport type Owner from '@ember/owner';\n\nexport interface HdsAppSideNavSignature {\n Args: {\n isResponsive?: boolean;\n isCollapsible?: boolean;\n isMinimized?: boolean;\n onToggleMinimizedStatus?: (arg: boolean) => void;\n onDesktopViewportChange?: (arg: boolean) => void;\n };\n Blocks: {\n default?: [];\n };\n Element: HTMLDivElement;\n}\n\nexport default class HdsAppSideNav extends Component<HdsAppSideNavSignature> {\n @tracked private _isMinimized;\n @tracked private _isAnimating = false;\n @tracked private _isDesktop = true;\n\n private _body!: HTMLElement;\n private _bodyInitialOverflowValue = '';\n private _desktopMQ: MediaQueryList;\n private _containersToHide!: NodeListOf<Element>;\n\n private _desktopMQVal = getComputedStyle(\n document.documentElement\n ).getPropertyValue('--hds-app-desktop-breakpoint');\n\n constructor(owner: Owner, args: HdsAppSideNavSignature['Args']) {\n super(owner, args);\n this._isMinimized = this.args.isMinimized ?? false; // sets the default state on 'desktop' viewports\n this._desktopMQ = window.matchMedia(`(min-width:${this._desktopMQVal})`);\n this.addEventListeners();\n registerDestructor(this, (): void => {\n this.removeEventListeners();\n });\n }\n\n addEventListeners(): void {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n document.addEventListener('keydown', this.escapePress, true);\n this._desktopMQ.addEventListener(\n 'change',\n // eslint-disable-next-line @typescript-eslint/unbound-method\n this.updateDesktopVariable,\n true\n );\n // if not instantiated as minimized via arguments\n if (!this.args.isMinimized) {\n // set initial state based on viewport using a \"synthetic\" event\n const syntheticEvent = new MediaQueryListEvent('change', {\n matches: this._desktopMQ.matches,\n media: this._desktopMQ.media,\n });\n this.updateDesktopVariable(syntheticEvent);\n }\n }\n\n removeEventListeners(): void {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n document.removeEventListener('keydown', this.escapePress, true);\n this._desktopMQ.removeEventListener(\n 'change',\n // eslint-disable-next-line @typescript-eslint/unbound-method\n this.updateDesktopVariable,\n true\n );\n }\n\n // controls if the component reacts to viewport changes\n get isResponsive(): boolean {\n return this.args.isResponsive ?? true;\n }\n\n // controls if users can collapse the appsidenav on 'desktop' viewports\n get isCollapsible(): boolean {\n return this.args.isCollapsible ?? false;\n }\n\n get shouldTrapFocus(): boolean {\n return this.isResponsive && !this._isDesktop && !this._isMinimized;\n }\n\n get showToggleButton(): boolean {\n return (this.isResponsive && !this._isDesktop) || this.isCollapsible;\n }\n\n get classNames(): string {\n const classes = [`hds-app-side-nav`];\n\n // add specific class names for the different possible states\n if (this.isResponsive) {\n classes.push('hds-app-side-nav--is-responsive');\n }\n if (!this._isDesktop && this.isResponsive) {\n classes.push('hds-app-side-nav--is-mobile');\n } else {\n classes.push('hds-app-side-nav--is-desktop');\n }\n if (this._isMinimized && this.isResponsive) {\n classes.push('hds-app-side-nav--is-minimized');\n } else {\n classes.push('hds-app-side-nav--is-not-minimized');\n }\n if (this._isAnimating) {\n classes.push('hds-app-side-nav--is-animating');\n }\n\n return classes.join(' ');\n }\n\n synchronizeInert(): void {\n this._containersToHide?.forEach((element): void => {\n if (this._isMinimized) {\n element.setAttribute('inert', '');\n } else {\n element.removeAttribute('inert');\n }\n });\n }\n\n lockBodyScroll(): void {\n if (this._body) {\n // Prevent page from scrolling when the dialog is open\n this._body.style.setProperty('overflow', 'hidden');\n }\n }\n\n unlockBodyScroll(): void {\n // Reset page `overflow` property\n if (this._body) {\n this._body.style.removeProperty('overflow');\n if (this._bodyInitialOverflowValue === '') {\n if (this._body.style.length === 0) {\n this._body.removeAttribute('style');\n }\n } else {\n this._body.style.setProperty(\n 'overflow',\n this._bodyInitialOverflowValue\n );\n }\n }\n }\n\n @action\n escapePress(event: KeyboardEvent): void {\n if (event.key === 'Escape' && !this._isMinimized && !this._isDesktop) {\n this._isMinimized = true;\n this.synchronizeInert();\n }\n }\n\n @action\n toggleMinimizedStatus(): void {\n this._isMinimized = !this._isMinimized;\n this.synchronizeInert();\n\n const { onToggleMinimizedStatus } = this.args;\n\n if (typeof onToggleMinimizedStatus === 'function') {\n onToggleMinimizedStatus(this._isMinimized);\n }\n\n if (this._isMinimized) {\n this.unlockBodyScroll();\n } else {\n this.lockBodyScroll();\n }\n }\n\n @action\n didInsert(element: HTMLElement): void {\n this._containersToHide = element.querySelectorAll(\n '.hds-app-side-nav-hide-when-minimized'\n );\n this._body = document.body;\n // Store the initial `overflow` value of `<body>` so we can reset to it\n this._bodyInitialOverflowValue =\n this._body.style.getPropertyValue('overflow');\n }\n\n @action\n setTransition(phase: string, event: TransitionEvent): void {\n // we only want to respond to `width` animation/transitions\n if (event.propertyName !== 'width') {\n return;\n }\n if (phase === 'start') {\n this._isAnimating = true;\n } else {\n this._isAnimating = false;\n }\n }\n\n @action\n updateDesktopVariable(event: MediaQueryListEvent): void {\n this._isDesktop = event.matches;\n\n // automatically minimize on narrow viewports (when not in desktop mode)\n this._isMinimized = !this._isDesktop;\n\n this.synchronizeInert();\n\n const { onDesktopViewportChange } = this.args;\n\n if (typeof onDesktopViewportChange === 'function') {\n onDesktopViewportChange(this._isDesktop);\n }\n }\n}\n"],"names":["HdsAppSideNav","Component","g","prototype","tracked","i","void 0","_body","_bodyInitialOverflowValue","_desktopMQ","_containersToHide","_desktopMQVal","getComputedStyle","document","documentElement","getPropertyValue","constructor","owner","args","_isMinimized","isMinimized","window","matchMedia","addEventListeners","registerDestructor","removeEventListeners","addEventListener","escapePress","updateDesktopVariable","syntheticEvent","MediaQueryListEvent","matches","media","removeEventListener","isResponsive","isCollapsible","shouldTrapFocus","_isDesktop","showToggleButton","classNames","classes","push","_isAnimating","join","synchronizeInert","forEach","element","setAttribute","removeAttribute","lockBodyScroll","style","setProperty","unlockBodyScroll","removeProperty","length","event","key","n","action","toggleMinimizedStatus","onToggleMinimizedStatus","didInsert","querySelectorAll","body","setTransition","phase","propertyName","onDesktopViewportChange","setComponentTemplate","TEMPLATE"],"mappings":";;;;;;;;;;AAAA;AACA;AACA;AACA;;AAsBe,MAAMA,aAAa,SAASC,SAAS,CAAyB;AAAA,EAAA;IAAAC,CAAA,CAAA,IAAA,CAAAC,SAAA,EAAA,cAAA,EAAA,CAC1EC,OAAO,CAAA,CAAA;AAAA;AAAA,EAAA,aAAA,IAAAC,CAAA,CAAA,IAAA,EAAA,cAAA,CAAA,EAAAC,MAAA;AAAA,EAAA;IAAAJ,CAAA,CAAA,IAAA,CAAAC,SAAA,EAAA,cAAA,EAAA,CACPC,OAAO,CAAA,EAAA,YAAA;AAAA,MAAA,OAAwB,KAAK;AAAA,KAAA,CAAA;AAAA;AAAA,EAAA,aAAA,IAAAC,CAAA,CAAA,IAAA,EAAA,cAAA,CAAA,EAAAC,MAAA;AAAA,EAAA;IAAAJ,CAAA,CAAA,IAAA,CAAAC,SAAA,EAAA,YAAA,EAAA,CACpCC,OAAO,CAAA,EAAA,YAAA;AAAA,MAAA,OAAsB,IAAI;AAAA,KAAA,CAAA;AAAA;AAAA,EAAA,WAAA,IAAAC,CAAA,CAAA,IAAA,EAAA,YAAA,CAAA,EAAAC,MAAA;EAE1BC,KAAK;AACLC,EAAAA,yBAAyB,GAAG,EAAE;EAC9BC,UAAU;EACVC,iBAAiB;EAEjBC,aAAa,GAAGC,gBAAgB,CACtCC,QAAQ,CAACC,eACX,CAAC,CAACC,gBAAgB,CAAC,8BAA8B,CAAC;AAElDC,EAAAA,WAAWA,CAACC,KAAY,EAAEC,IAAoC,EAAE;AAC9D,IAAA,KAAK,CAACD,KAAK,EAAEC,IAAI,CAAC;IAClB,IAAI,CAACC,YAAY,GAAG,IAAI,CAACD,IAAI,CAACE,WAAW,IAAI,KAAK,CAAC;AACnD,IAAA,IAAI,CAACX,UAAU,GAAGY,MAAM,CAACC,UAAU,CAAC,CAAA,WAAA,EAAc,IAAI,CAACX,aAAa,CAAA,CAAA,CAAG,CAAC;IACxE,IAAI,CAACY,iBAAiB,EAAE;IACxBC,kBAAkB,CAAC,IAAI,EAAE,MAAY;MACnC,IAAI,CAACC,oBAAoB,EAAE;AAC7B,KAAC,CAAC;AACJ;AAEAF,EAAAA,iBAAiBA,GAAS;AACxB;IACAV,QAAQ,CAACa,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAACC,WAAW,EAAE,IAAI,CAAC;AAC5D,IAAA,IAAI,CAAClB,UAAU,CAACiB,gBAAgB,CAC9B,QAAQ;AACR;AACA,IAAA,IAAI,CAACE,qBAAqB,EAC1B,IACF,CAAC;AACD;AACA,IAAA,IAAI,CAAC,IAAI,CAACV,IAAI,CAACE,WAAW,EAAE;AAC1B;AACA,MAAA,MAAMS,cAAc,GAAG,IAAIC,mBAAmB,CAAC,QAAQ,EAAE;AACvDC,QAAAA,OAAO,EAAE,IAAI,CAACtB,UAAU,CAACsB,OAAO;AAChCC,QAAAA,KAAK,EAAE,IAAI,CAACvB,UAAU,CAACuB;AACzB,OAAC,CAAC;AACF,MAAA,IAAI,CAACJ,qBAAqB,CAACC,cAAc,CAAC;AAC5C;AACF;AAEAJ,EAAAA,oBAAoBA,GAAS;AAC3B;IACAZ,QAAQ,CAACoB,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAACN,WAAW,EAAE,IAAI,CAAC;AAC/D,IAAA,IAAI,CAAClB,UAAU,CAACwB,mBAAmB,CACjC,QAAQ;AACR;AACA,IAAA,IAAI,CAACL,qBAAqB,EAC1B,IACF,CAAC;AACH;;AAEA;EACA,IAAIM,YAAYA,GAAY;AAC1B,IAAA,OAAO,IAAI,CAAChB,IAAI,CAACgB,YAAY,IAAI,IAAI;AACvC;;AAEA;EACA,IAAIC,aAAaA,GAAY;AAC3B,IAAA,OAAO,IAAI,CAACjB,IAAI,CAACiB,aAAa,IAAI,KAAK;AACzC;EAEA,IAAIC,eAAeA,GAAY;AAC7B,IAAA,OAAO,IAAI,CAACF,YAAY,IAAI,CAAC,IAAI,CAACG,UAAU,IAAI,CAAC,IAAI,CAAClB,YAAY;AACpE;EAEA,IAAImB,gBAAgBA,GAAY;IAC9B,OAAQ,IAAI,CAACJ,YAAY,IAAI,CAAC,IAAI,CAACG,UAAU,IAAK,IAAI,CAACF,aAAa;AACtE;EAEA,IAAII,UAAUA,GAAW;AACvB,IAAA,MAAMC,OAAO,GAAG,CAAC,CAAA,gBAAA,CAAkB,CAAC;;AAEpC;IACA,IAAI,IAAI,CAACN,YAAY,EAAE;AACrBM,MAAAA,OAAO,CAACC,IAAI,CAAC,iCAAiC,CAAC;AACjD;IACA,IAAI,CAAC,IAAI,CAACJ,UAAU,IAAI,IAAI,CAACH,YAAY,EAAE;AACzCM,MAAAA,OAAO,CAACC,IAAI,CAAC,6BAA6B,CAAC;AAC7C,KAAC,MAAM;AACLD,MAAAA,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC;AAC9C;AACA,IAAA,IAAI,IAAI,CAACtB,YAAY,IAAI,IAAI,CAACe,YAAY,EAAE;AAC1CM,MAAAA,OAAO,CAACC,IAAI,CAAC,gCAAgC,CAAC;AAChD,KAAC,MAAM;AACLD,MAAAA,OAAO,CAACC,IAAI,CAAC,oCAAoC,CAAC;AACpD;IACA,IAAI,IAAI,CAACC,YAAY,EAAE;AACrBF,MAAAA,OAAO,CAACC,IAAI,CAAC,gCAAgC,CAAC;AAChD;AAEA,IAAA,OAAOD,OAAO,CAACG,IAAI,CAAC,GAAG,CAAC;AAC1B;AAEAC,EAAAA,gBAAgBA,GAAS;AACvB,IAAA,IAAI,CAAClC,iBAAiB,EAAEmC,OAAO,CAAEC,OAAO,IAAW;MACjD,IAAI,IAAI,CAAC3B,YAAY,EAAE;AACrB2B,QAAAA,OAAO,CAACC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;AACnC,OAAC,MAAM;AACLD,QAAAA,OAAO,CAACE,eAAe,CAAC,OAAO,CAAC;AAClC;AACF,KAAC,CAAC;AACJ;AAEAC,EAAAA,cAAcA,GAAS;IACrB,IAAI,IAAI,CAAC1C,KAAK,EAAE;AACd;MACA,IAAI,CAACA,KAAK,CAAC2C,KAAK,CAACC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC;AACpD;AACF;AAEAC,EAAAA,gBAAgBA,GAAS;AACvB;IACA,IAAI,IAAI,CAAC7C,KAAK,EAAE;MACd,IAAI,CAACA,KAAK,CAAC2C,KAAK,CAACG,cAAc,CAAC,UAAU,CAAC;AAC3C,MAAA,IAAI,IAAI,CAAC7C,yBAAyB,KAAK,EAAE,EAAE;QACzC,IAAI,IAAI,CAACD,KAAK,CAAC2C,KAAK,CAACI,MAAM,KAAK,CAAC,EAAE;AACjC,UAAA,IAAI,CAAC/C,KAAK,CAACyC,eAAe,CAAC,OAAO,CAAC;AACrC;AACF,OAAC,MAAM;AACL,QAAA,IAAI,CAACzC,KAAK,CAAC2C,KAAK,CAACC,WAAW,CAC1B,UAAU,EACV,IAAI,CAAC3C,yBACP,CAAC;AACH;AACF;AACF;EAGAmB,WAAWA,CAAC4B,KAAoB,EAAQ;AACtC,IAAA,IAAIA,KAAK,CAACC,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAACrC,YAAY,IAAI,CAAC,IAAI,CAACkB,UAAU,EAAE;MACpE,IAAI,CAAClB,YAAY,GAAG,IAAI;MACxB,IAAI,CAACyB,gBAAgB,EAAE;AACzB;AACF;AAAC,EAAA;IAAAa,CAAA,CAAA,IAAA,CAAAtD,SAAA,EAAA,aAAA,EAAA,CANAuD,MAAM,CAAA,CAAA;AAAA;AASPC,EAAAA,qBAAqBA,GAAS;AAC5B,IAAA,IAAI,CAACxC,YAAY,GAAG,CAAC,IAAI,CAACA,YAAY;IACtC,IAAI,CAACyB,gBAAgB,EAAE;IAEvB,MAAM;AAAEgB,MAAAA;KAAyB,GAAG,IAAI,CAAC1C,IAAI;AAE7C,IAAA,IAAI,OAAO0C,uBAAuB,KAAK,UAAU,EAAE;AACjDA,MAAAA,uBAAuB,CAAC,IAAI,CAACzC,YAAY,CAAC;AAC5C;IAEA,IAAI,IAAI,CAACA,YAAY,EAAE;MACrB,IAAI,CAACiC,gBAAgB,EAAE;AACzB,KAAC,MAAM;MACL,IAAI,CAACH,cAAc,EAAE;AACvB;AACF;AAAC,EAAA;IAAAQ,CAAA,CAAA,IAAA,CAAAtD,SAAA,EAAA,uBAAA,EAAA,CAhBAuD,MAAM,CAAA,CAAA;AAAA;EAmBPG,SAASA,CAACf,OAAoB,EAAQ;IACpC,IAAI,CAACpC,iBAAiB,GAAGoC,OAAO,CAACgB,gBAAgB,CAC/C,uCACF,CAAC;AACD,IAAA,IAAI,CAACvD,KAAK,GAAGM,QAAQ,CAACkD,IAAI;AAC1B;AACA,IAAA,IAAI,CAACvD,yBAAyB,GAC5B,IAAI,CAACD,KAAK,CAAC2C,KAAK,CAACnC,gBAAgB,CAAC,UAAU,CAAC;AACjD;AAAC,EAAA;IAAA0C,CAAA,CAAA,IAAA,CAAAtD,SAAA,EAAA,WAAA,EAAA,CATAuD,MAAM,CAAA,CAAA;AAAA;AAYPM,EAAAA,aAAaA,CAACC,KAAa,EAAEV,KAAsB,EAAQ;AACzD;AACA,IAAA,IAAIA,KAAK,CAACW,YAAY,KAAK,OAAO,EAAE;AAClC,MAAA;AACF;IACA,IAAID,KAAK,KAAK,OAAO,EAAE;MACrB,IAAI,CAACvB,YAAY,GAAG,IAAI;AAC1B,KAAC,MAAM;MACL,IAAI,CAACA,YAAY,GAAG,KAAK;AAC3B;AACF;AAAC,EAAA;IAAAe,CAAA,CAAA,IAAA,CAAAtD,SAAA,EAAA,eAAA,EAAA,CAXAuD,MAAM,CAAA,CAAA;AAAA;EAcP9B,qBAAqBA,CAAC2B,KAA0B,EAAQ;AACtD,IAAA,IAAI,CAAClB,UAAU,GAAGkB,KAAK,CAACxB,OAAO;;AAE/B;AACA,IAAA,IAAI,CAACZ,YAAY,GAAG,CAAC,IAAI,CAACkB,UAAU;IAEpC,IAAI,CAACO,gBAAgB,EAAE;IAEvB,MAAM;AAAEuB,MAAAA;KAAyB,GAAG,IAAI,CAACjD,IAAI;AAE7C,IAAA,IAAI,OAAOiD,uBAAuB,KAAK,UAAU,EAAE;AACjDA,MAAAA,uBAAuB,CAAC,IAAI,CAAC9B,UAAU,CAAC;AAC1C;AACF;AAAC,EAAA;IAAAoB,CAAA,CAAA,IAAA,CAAAtD,SAAA,EAAA,uBAAA,EAAA,CAdAuD,MAAM,CAAA,CAAA;AAAA;AAeT;AAACU,oBAAA,CAAAC,QAAA,EApMoBrE,aAAa,CAAA;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/hds/app-side-nav/index.ts"],"sourcesContent":["/**\n * Copyright (c) HashiCorp, Inc.\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { action } from '@ember/object';\nimport { registerDestructor } from '@ember/destroyable';\nimport type Owner from '@ember/owner';\n\nexport interface HdsAppSideNavSignature {\n Args: {\n isResponsive?: boolean;\n isCollapsible?: boolean;\n isMinimized?: boolean;\n onToggleMinimizedStatus?: (arg: boolean) => void;\n onDesktopViewportChange?: (arg: boolean) => void;\n };\n Blocks: {\n default?: [];\n };\n Element: HTMLDivElement;\n}\n\nexport default class HdsAppSideNav extends Component<HdsAppSideNavSignature> {\n @tracked private _isMinimized;\n @tracked private _isAnimating = false;\n @tracked private _isDesktop = true;\n\n private _body!: HTMLElement;\n private _bodyInitialOverflowValue = '';\n private _desktopMQ: MediaQueryList;\n private _containersToHide!: NodeListOf<Element>;\n\n private _desktopMQVal = getComputedStyle(\n document.documentElement\n ).getPropertyValue('--hds-app-desktop-breakpoint');\n\n constructor(owner: Owner, args: HdsAppSideNavSignature['Args']) {\n super(owner, args);\n this._isMinimized = this.args.isMinimized ?? false; // sets the default state on 'desktop' viewports\n this._desktopMQ = window.matchMedia(`(min-width:${this._desktopMQVal})`);\n this.addEventListeners();\n registerDestructor(this, (): void => {\n this.removeEventListeners();\n });\n }\n\n addEventListeners(): void {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n document.addEventListener('keydown', this.escapePress, true);\n this._desktopMQ.addEventListener(\n 'change',\n // eslint-disable-next-line @typescript-eslint/unbound-method\n this.updateDesktopVariable,\n true\n );\n // if not instantiated as minimized via arguments\n if (!this.args.isMinimized) {\n // set initial state based on viewport using a \"synthetic\" event\n const syntheticEvent = new MediaQueryListEvent('change', {\n matches: this._desktopMQ.matches,\n media: this._desktopMQ.media,\n });\n this.updateDesktopVariable(syntheticEvent);\n }\n }\n\n removeEventListeners(): void {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n document.removeEventListener('keydown', this.escapePress, true);\n this._desktopMQ.removeEventListener(\n 'change',\n // eslint-disable-next-line @typescript-eslint/unbound-method\n this.updateDesktopVariable,\n true\n );\n }\n\n // controls if the component reacts to viewport changes\n get isResponsive(): boolean {\n return this.args.isResponsive ?? true;\n }\n\n // controls if users can collapse the appsidenav on 'desktop' viewports\n get isCollapsible(): boolean {\n return this.args.isCollapsible ?? false;\n }\n\n get shouldTrapFocus(): boolean {\n return this.isResponsive && !this._isDesktop && !this._isMinimized;\n }\n\n get showToggleButton(): boolean {\n return (this.isResponsive && !this._isDesktop) || this.isCollapsible;\n }\n\n get classNames(): string {\n const classes = [`hds-app-side-nav`];\n\n // add specific class names for the different possible states\n if (this.isResponsive) {\n classes.push('hds-app-side-nav--is-responsive');\n }\n if (!this._isDesktop && this.isResponsive) {\n classes.push('hds-app-side-nav--is-mobile');\n } else {\n classes.push('hds-app-side-nav--is-desktop');\n }\n if (this._isMinimized && this.isResponsive) {\n classes.push('hds-app-side-nav--is-minimized');\n } else {\n classes.push('hds-app-side-nav--is-not-minimized');\n }\n if (this._isAnimating) {\n classes.push('hds-app-side-nav--is-animating');\n }\n\n return classes.join(' ');\n }\n\n synchronizeInert(): void {\n this._containersToHide?.forEach((element): void => {\n if (this._isMinimized) {\n element.setAttribute('inert', '');\n } else {\n element.removeAttribute('inert');\n }\n });\n }\n\n lockBodyScroll(): void {\n if (this._body) {\n // Prevent page from scrolling when the dialog is open\n this._body.style.setProperty('overflow', 'hidden');\n }\n }\n\n unlockBodyScroll(): void {\n // Reset page `overflow` property\n if (this._body) {\n this._body.style.removeProperty('overflow');\n if (this._bodyInitialOverflowValue === '') {\n if (this._body.style.length === 0) {\n this._body.removeAttribute('style');\n }\n } else {\n this._body.style.setProperty(\n 'overflow',\n this._bodyInitialOverflowValue\n );\n }\n }\n }\n\n @action\n escapePress(event: KeyboardEvent): void {\n if (event.key === 'Escape' && !this._isMinimized && !this._isDesktop) {\n this._isMinimized = true;\n this.synchronizeInert();\n this.unlockBodyScroll();\n }\n }\n\n @action\n toggleMinimizedStatus(): void {\n this._isMinimized = !this._isMinimized;\n this.synchronizeInert();\n\n const { onToggleMinimizedStatus } = this.args;\n\n if (typeof onToggleMinimizedStatus === 'function') {\n onToggleMinimizedStatus(this._isMinimized);\n }\n\n if (!this._isDesktop) {\n if (this._isMinimized) {\n this.unlockBodyScroll();\n } else {\n this.lockBodyScroll();\n }\n }\n }\n\n @action\n didInsert(element: HTMLElement): void {\n this._containersToHide = element.querySelectorAll(\n '.hds-app-side-nav-hide-when-minimized'\n );\n this._body = document.body;\n // Store the initial `overflow` value of `<body>` so we can reset to it\n this._bodyInitialOverflowValue =\n this._body.style.getPropertyValue('overflow');\n }\n\n @action\n setTransition(phase: string, event: TransitionEvent): void {\n // we only want to respond to `width` animation/transitions\n if (event.propertyName !== 'width') {\n return;\n }\n if (phase === 'start') {\n this._isAnimating = true;\n } else {\n this._isAnimating = false;\n }\n }\n\n @action\n updateDesktopVariable(event: MediaQueryListEvent): void {\n this._isDesktop = event.matches;\n\n // automatically minimize on narrow viewports (when not in desktop mode)\n this._isMinimized = !this._isDesktop;\n\n this.synchronizeInert();\n\n if (this._isDesktop) {\n // make sure scrolling is enabled if the user resizes the window from mobile to desktop\n this.unlockBodyScroll();\n }\n\n const { onDesktopViewportChange } = this.args;\n\n if (typeof onDesktopViewportChange === 'function') {\n onDesktopViewportChange(this._isDesktop);\n }\n }\n}\n"],"names":["HdsAppSideNav","Component","g","prototype","tracked","i","void 0","_body","_bodyInitialOverflowValue","_desktopMQ","_containersToHide","_desktopMQVal","getComputedStyle","document","documentElement","getPropertyValue","constructor","owner","args","_isMinimized","isMinimized","window","matchMedia","addEventListeners","registerDestructor","removeEventListeners","addEventListener","escapePress","updateDesktopVariable","syntheticEvent","MediaQueryListEvent","matches","media","removeEventListener","isResponsive","isCollapsible","shouldTrapFocus","_isDesktop","showToggleButton","classNames","classes","push","_isAnimating","join","synchronizeInert","forEach","element","setAttribute","removeAttribute","lockBodyScroll","style","setProperty","unlockBodyScroll","removeProperty","length","event","key","n","action","toggleMinimizedStatus","onToggleMinimizedStatus","didInsert","querySelectorAll","body","setTransition","phase","propertyName","onDesktopViewportChange","setComponentTemplate","TEMPLATE"],"mappings":"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"}
@@ -23,7 +23,7 @@ import { precompileTemplate } from '@ember/template-compilation';
23
23
  import { g, i, n } from 'decorator-transforms/runtime';
24
24
  import { setComponentTemplate } from '@ember/component';
25
25
 
26
- var TEMPLATE = precompileTemplate("{{!\n Copyright (c) HashiCorp, Inc.\n SPDX-License-Identifier: MPL-2.0\n}}\n\n<div class={{this.classNames}} ...attributes>\n <div class=\"hds-code-block__header\">\n {{~yield (hash Title=(component \"hds/code-block/title\"))~}}\n {{~yield (hash Description=(component \"hds/code-block/description\"))~}}\n </div>\n <div class=\"hds-code-block__body\">\n {{! content within pre tag is whitespace-sensitive; do not add new lines! }}\n <pre\n class=\"hds-code-block__code\"\n {{style maxHeight=@maxHeight}}\n data-line={{@highlightLines}}\n data-start={{@lineNumberStart}}\n id={{this._preCodeId}}\n tabindex=\"0\"\n ><code {{did-insert this.setPrismCode}} {{did-update this.setPrismCode this.code @language}}>\n {{~this._prismCode~}}\n </code></pre>\n\n {{#if @hasCopyButton}}\n <Hds::CodeBlock::CopyButton\n @targetToCopy=\"#{{this._preCodeId}}\"\n aria-describedby={{this._preCodeId}}\n @text={{this.copyButtonText}}\n @onCopy={{@onCopy}}\n />\n {{/if}}\n </div>\n</div>");
26
+ var TEMPLATE = precompileTemplate("{{!\n Copyright (c) HashiCorp, Inc.\n SPDX-License-Identifier: MPL-2.0\n}}\n\n<div class={{this.classNames}} ...attributes>\n <div class=\"hds-code-block__header\">\n {{~yield (hash Title=(component \"hds/code-block/title\"))~}}\n {{~yield (hash Description=(component \"hds/code-block/description\"))~}}\n </div>\n <div class=\"hds-code-block__body\">\n {{! content within pre tag is whitespace-sensitive; do not add new lines! }}\n <pre\n class=\"hds-code-block__code\"\n {{style maxHeight=this.maxHeight}}\n data-line={{@highlightLines}}\n data-start={{@lineNumberStart}}\n id={{this._preCodeId}}\n tabindex=\"0\"\n ><code {{did-insert this.setPrismCode}} {{did-update this.setPrismCode this.code @language}}>\n {{~this._prismCode~}}\n </code></pre>\n\n {{#if @hasCopyButton}}\n <Hds::CodeBlock::CopyButton\n @targetToCopy=\"#{{this._preCodeId}}\"\n aria-describedby={{this._preCodeId}}\n @text={{this.copyButtonText}}\n @onCopy={{@onCopy}}\n />\n {{/if}}\n </div>\n {{#if this.showFooter}}\n <div class=\"hds-code-block__overlay-footer\">\n <Hds::Button\n class=\"hds-code-block__height-toggle-button\"\n @text={{if this._isExpanded \"Show less code\" \"Show more code\"}}\n @color=\"secondary\"\n @icon={{if this._isExpanded \"unfold-close\" \"unfold-open\"}}\n @size=\"small\"\n {{on \"click\" this.toggleExpanded}}\n />\n </div>\n {{/if}}\n</div>");
27
27
 
28
28
  /**
29
29
  * Copyright (c) HashiCorp, Inc.
@@ -38,18 +38,28 @@ class HdsCodeBlock extends Component {
38
38
  });
39
39
  }
40
40
  #_prismCode = (i(this, "_prismCode"), void 0);
41
- /**
42
- * Generates a unique ID for the code content
43
- *
44
- * @param _preCodeId
45
- */
41
+ static {
42
+ g(this.prototype, "_isExpanded", [tracked], function () {
43
+ return false;
44
+ });
45
+ }
46
+ #_isExpanded = (i(this, "_isExpanded"), void 0);
47
+ static {
48
+ g(this.prototype, "_codeContentHeight", [tracked], function () {
49
+ return 0;
50
+ });
51
+ }
52
+ #_codeContentHeight = (i(this, "_codeContentHeight"), void 0);
53
+ static {
54
+ g(this.prototype, "_codeContainerHeight", [tracked], function () {
55
+ return 0;
56
+ });
57
+ }
58
+ #_codeContainerHeight = (i(this, "_codeContainerHeight"), void 0);
59
+ // Generates a unique ID for the code content
46
60
  _preCodeId = 'pre-code-' + guidFor(this);
47
61
 
48
- /**
49
- * @param code
50
- * @type {string}
51
- * @description code text content for the CodeBlock
52
- */
62
+ // code text content for the CodeBlock
53
63
  get code() {
54
64
  const code = this.args.value;
55
65
  assert('@code for "Hds::CodeBlock" must have a valid value', code !== undefined);
@@ -59,43 +69,34 @@ class HdsCodeBlock extends Component {
59
69
  }
60
70
  return code;
61
71
  }
72
+ get maxHeight() {
73
+ return this._isExpanded ? 'none' : this.args.maxHeight;
74
+ }
62
75
 
63
- /**
64
- * @param language
65
- * @type {string}
66
- * @default undefined
67
- * @description name of coding language used within CodeBlock for syntax highlighting
68
- */
76
+ // Shows overlay footer if maxHeight is set and the pre tag content height is greater than the pre tag height
77
+ get showFooter() {
78
+ if (this.args.maxHeight) {
79
+ return this._codeContentHeight > this._codeContainerHeight;
80
+ }
81
+ return false;
82
+ }
83
+
84
+ // Name of coding language used within CodeBlock for syntax highlighting
69
85
  get language() {
70
86
  return this.args.language ?? undefined;
71
87
  }
72
88
 
73
- /**
74
- * @param hasLineNumbers
75
- * @type {boolean}
76
- * @default true
77
- * @description Displays line numbers if true
78
- */
89
+ // Displays line numbers if true
79
90
  get hasLineNumbers() {
80
91
  return this.args.hasLineNumbers ?? true;
81
92
  }
82
93
 
83
- /**
84
- * @param isStandalone
85
- * @type {boolean}
86
- * @default true
87
- * @description Make CodeBlock container corners appear rounded
88
- */
94
+ // Make CodeBlock container corners appear rounded (the standalone variation)
89
95
  get isStandalone() {
90
96
  return this.args.isStandalone ?? true;
91
97
  }
92
98
 
93
- /**
94
- * @param hasLineWrapping
95
- * @type {boolean}
96
- * @default false
97
- * @description Make text content wrap on multiple lines
98
- */
99
+ // Make text content wrap to multiple lines
99
100
  get hasLineWrapping() {
100
101
  return this.args.hasLineWrapping ?? false;
101
102
  }
@@ -123,6 +124,14 @@ class HdsCodeBlock extends Component {
123
124
  element
124
125
  });
125
126
 
127
+ // Get the actual height & the content height of the preCodeElement
128
+ // eslint-disable-next-line ember/no-runloop
129
+ schedule('afterRender', () => {
130
+ const preCodeElement = document.getElementById(this._preCodeId);
131
+ this._codeContentHeight = preCodeElement?.scrollHeight ?? 0;
132
+ this._codeContainerHeight = preCodeElement?.clientHeight ?? 0;
133
+ });
134
+
126
135
  // Force prism-line-highlight plugin initialization
127
136
  // Context: https://github.com/hashicorp/design-system/pull/1749#discussion_r1374288785
128
137
  if (this.args.highlightLines) {
@@ -136,15 +145,15 @@ class HdsCodeBlock extends Component {
136
145
  });
137
146
  }
138
147
  }
139
-
140
- /**
141
- * Get the class names to apply to the component.
142
- * @method classNames
143
- * @return {string} The "class" attribute to apply to the component.
144
- */
145
148
  static {
146
149
  n(this.prototype, "setPrismCode", [action]);
147
150
  }
151
+ toggleExpanded() {
152
+ this._isExpanded = !this._isExpanded;
153
+ }
154
+ static {
155
+ n(this.prototype, "toggleExpanded", [action]);
156
+ }
148
157
  get classNames() {
149
158
  // Currently there is only one theme so the class name is hard-coded.
150
159
  // In the future, additional themes such as a "light" theme could be added.
@@ -163,6 +172,12 @@ class HdsCodeBlock extends Component {
163
172
  if (this.hasLineNumbers) {
164
173
  classes.push('line-numbers');
165
174
  }
175
+ if (this.showFooter) {
176
+ classes.push('hds-code-block--has-overlay-footer');
177
+ }
178
+ if (this._isExpanded) {
179
+ classes.push('hds-code-block--is-expanded');
180
+ }
166
181
  return classes.join(' ');
167
182
  }
168
183
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/components/hds/code-block/index.ts"],"sourcesContent":["/**\n * Copyright (c) HashiCorp, Inc.\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport Component from '@glimmer/component';\nimport { action } from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\nimport { assert } from '@ember/debug';\nimport { next, schedule } from '@ember/runloop';\nimport { htmlSafe } from '@ember/template';\nimport { guidFor } from '@ember/object/internals';\n\nimport Prism from 'prismjs';\n\nimport type { SafeString } from '@ember/template';\nimport type { ComponentLike } from '@glint/template';\n\nimport type { HdsCodeBlockTitleSignature } from './title';\nimport type { HdsCodeBlockDescriptionSignature } from './description';\nimport { HdsCodeBlockLanguageValues } from './types.ts';\nimport type { HdsCodeBlockLanguages } from './types.ts';\nimport type { HdsCopyButtonSignature } from '../copy/button/index.ts';\n\nimport 'prismjs/plugins/line-numbers/prism-line-numbers';\nimport 'prismjs/plugins/line-highlight/prism-line-highlight';\n\nimport 'prismjs/components/prism-bash';\nimport 'prismjs/components/prism-go';\nimport 'prismjs/components/prism-hcl';\nimport 'prismjs/components/prism-json';\nimport 'prismjs/components/prism-log';\nimport 'prismjs/components/prism-ruby';\nimport 'prismjs/components/prism-shell-session';\nimport 'prismjs/components/prism-yaml';\n\n// These imports are required to overcome a global variable clash in Helios website\n// where language import are overriden by the Prism instance in `CodeBlock`\n// Note that `prism-handlebars` is dependant on `prism-markup-templating`\nimport 'prismjs/components/prism-markup-templating';\nimport 'prismjs/components/prism-handlebars';\n\nexport const LANGUAGES: string[] = Object.values(HdsCodeBlockLanguageValues);\n\nexport interface HdsCodeBlockSignature {\n Args: {\n hasCopyButton?: boolean;\n hasLineNumbers?: boolean;\n hasLineWrapping?: boolean;\n highlightLines?: string;\n lineNumberStart?: number;\n isStandalone?: boolean;\n language?: HdsCodeBlockLanguages;\n maxHeight?: string;\n value: string;\n copyButtonText?: HdsCopyButtonSignature['Args']['text'];\n onCopy?: HdsCopyButtonSignature['Args']['onSuccess'];\n };\n Blocks: {\n default: [\n {\n Title?: ComponentLike<HdsCodeBlockTitleSignature>;\n Description?: ComponentLike<HdsCodeBlockDescriptionSignature>;\n },\n ];\n };\n Element: HTMLDivElement;\n}\n\nexport default class HdsCodeBlock extends Component<HdsCodeBlockSignature> {\n @tracked private _prismCode: SafeString = htmlSafe('');\n\n /**\n * Generates a unique ID for the code content\n *\n * @param _preCodeId\n */\n private _preCodeId = 'pre-code-' + guidFor(this);\n\n /**\n * @param code\n * @type {string}\n * @description code text content for the CodeBlock\n */\n get code(): string {\n const code = this.args.value;\n\n assert(\n '@code for \"Hds::CodeBlock\" must have a valid value',\n code !== undefined\n );\n\n if (Prism?.plugins?.['NormalizeWhitespace']) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n return Prism.plugins['NormalizeWhitespace'].normalize(code);\n }\n\n return code;\n }\n\n /**\n * @param language\n * @type {string}\n * @default undefined\n * @description name of coding language used within CodeBlock for syntax highlighting\n */\n get language(): HdsCodeBlockLanguages | undefined {\n return this.args.language ?? undefined;\n }\n\n /**\n * @param hasLineNumbers\n * @type {boolean}\n * @default true\n * @description Displays line numbers if true\n */\n get hasLineNumbers(): boolean {\n return this.args.hasLineNumbers ?? true;\n }\n\n /**\n * @param isStandalone\n * @type {boolean}\n * @default true\n * @description Make CodeBlock container corners appear rounded\n */\n get isStandalone(): boolean {\n return this.args.isStandalone ?? true;\n }\n\n /**\n * @param hasLineWrapping\n * @type {boolean}\n * @default false\n * @description Make text content wrap on multiple lines\n */\n get hasLineWrapping(): boolean {\n return this.args.hasLineWrapping ?? false;\n }\n\n get copyButtonText(): HdsCopyButtonSignature['Args']['text'] {\n return this.args.copyButtonText ? this.args.copyButtonText : 'Copy';\n }\n\n @action\n setPrismCode(element: HTMLElement): void {\n const code = this.code;\n const language = this.language;\n const grammar = language ? Prism.languages[language] : undefined;\n\n if (code) {\n // eslint-disable-next-line ember/no-runloop\n next(() => {\n if (language && grammar) {\n this._prismCode = htmlSafe(Prism.highlight(code, grammar, language));\n } else {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n this._prismCode = htmlSafe(Prism.util.encode(code).toString());\n }\n\n // Force prism-line-numbers plugin initialization, required for Prism.highlight usage\n // See https://github.com/PrismJS/prism/issues/1234\n Prism.hooks.run('complete', {\n code,\n element,\n });\n\n // Force prism-line-highlight plugin initialization\n // Context: https://github.com/hashicorp/design-system/pull/1749#discussion_r1374288785\n if (this.args.highlightLines) {\n // we need to delay re-evaluating the context for prism-line-highlight for as much as possible, and `afterRender` is the 'latest' we can use in the component lifecycle\n // eslint-disable-next-line ember/no-runloop\n schedule('afterRender', () => {\n // we piggy-back on the plugin's `resize` event listener to trigger a new call of the `highlightLines` function: https://github.com/PrismJS/prism/blob/master/plugins/line-highlight/prism-line-highlight.js#L337\n if (window) window.dispatchEvent(new Event('resize'));\n });\n }\n });\n }\n }\n\n /**\n * Get the class names to apply to the component.\n * @method classNames\n * @return {string} The \"class\" attribute to apply to the component.\n */\n get classNames(): string {\n // Currently there is only one theme so the class name is hard-coded.\n // In the future, additional themes such as a \"light\" theme could be added.\n const classes = ['hds-code-block', 'hds-code-block--theme-dark'];\n\n if (this.language) {\n classes.push(`language-${this.language}`);\n }\n\n if (this.isStandalone === true) {\n classes.push('hds-code-block--is-standalone');\n }\n\n if (this.hasLineWrapping === true) {\n classes.push('hds-code-block--has-line-wrapping');\n }\n\n // Note: Prism.js is using the specific class name \"line-numbers\" to determine implementation of line numbers in the UI\n if (this.hasLineNumbers) {\n classes.push('line-numbers');\n }\n\n return classes.join(' ');\n }\n}\n"],"names":["LANGUAGES","Object","values","HdsCodeBlockLanguageValues","HdsCodeBlock","Component","g","prototype","tracked","htmlSafe","i","void 0","_preCodeId","guidFor","code","args","value","assert","undefined","Prism","plugins","normalize","language","hasLineNumbers","isStandalone","hasLineWrapping","copyButtonText","setPrismCode","element","grammar","languages","next","_prismCode","highlight","util","encode","toString","hooks","run","highlightLines","schedule","window","dispatchEvent","Event","n","action","classNames","classes","push","join","setComponentTemplate","TEMPLATE"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/hds/code-block/index.ts"],"sourcesContent":["/**\n * Copyright (c) HashiCorp, Inc.\n * SPDX-License-Identifier: MPL-2.0\n */\n\nimport Component from '@glimmer/component';\nimport { action } from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\nimport { assert } from '@ember/debug';\nimport { next, schedule } from '@ember/runloop';\nimport { htmlSafe } from '@ember/template';\nimport { guidFor } from '@ember/object/internals';\n\nimport Prism from 'prismjs';\n\nimport type { SafeString } from '@ember/template';\nimport type { ComponentLike } from '@glint/template';\n\nimport type { HdsCodeBlockTitleSignature } from './title';\nimport type { HdsCodeBlockDescriptionSignature } from './description';\nimport { HdsCodeBlockLanguageValues } from './types.ts';\nimport type { HdsCodeBlockLanguages } from './types.ts';\nimport type { HdsCopyButtonSignature } from '../copy/button/index.ts';\n\nimport 'prismjs/plugins/line-numbers/prism-line-numbers';\nimport 'prismjs/plugins/line-highlight/prism-line-highlight';\n\nimport 'prismjs/components/prism-bash';\nimport 'prismjs/components/prism-go';\nimport 'prismjs/components/prism-hcl';\nimport 'prismjs/components/prism-json';\nimport 'prismjs/components/prism-log';\nimport 'prismjs/components/prism-ruby';\nimport 'prismjs/components/prism-shell-session';\nimport 'prismjs/components/prism-yaml';\n\n// These imports are required to overcome a global variable clash in Helios website\n// where language import are overriden by the Prism instance in `CodeBlock`\n// Note that `prism-handlebars` is dependant on `prism-markup-templating`\nimport 'prismjs/components/prism-markup-templating';\nimport 'prismjs/components/prism-handlebars';\n\nexport const LANGUAGES: string[] = Object.values(HdsCodeBlockLanguageValues);\n\nexport interface HdsCodeBlockSignature {\n Args: {\n hasCopyButton?: boolean;\n hasLineNumbers?: boolean;\n hasLineWrapping?: boolean;\n highlightLines?: string;\n lineNumberStart?: number;\n isStandalone?: boolean;\n language?: HdsCodeBlockLanguages;\n maxHeight?: string;\n value: string;\n copyButtonText?: HdsCopyButtonSignature['Args']['text'];\n onCopy?: HdsCopyButtonSignature['Args']['onSuccess'];\n };\n Blocks: {\n default: [\n {\n Title?: ComponentLike<HdsCodeBlockTitleSignature>;\n Description?: ComponentLike<HdsCodeBlockDescriptionSignature>;\n },\n ];\n };\n Element: HTMLDivElement;\n}\n\nexport default class HdsCodeBlock extends Component<HdsCodeBlockSignature> {\n @tracked private _prismCode: SafeString = htmlSafe('');\n @tracked private _isExpanded: boolean = false;\n @tracked private _codeContentHeight: number = 0;\n @tracked private _codeContainerHeight: number = 0;\n\n // Generates a unique ID for the code content\n private _preCodeId = 'pre-code-' + guidFor(this);\n\n // code text content for the CodeBlock\n get code(): string {\n const code = this.args.value;\n\n assert(\n '@code for \"Hds::CodeBlock\" must have a valid value',\n code !== undefined\n );\n\n if (Prism?.plugins?.['NormalizeWhitespace']) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n return Prism.plugins['NormalizeWhitespace'].normalize(code);\n }\n\n return code;\n }\n\n get maxHeight(): string | undefined {\n return this._isExpanded ? 'none' : this.args.maxHeight;\n }\n\n // Shows overlay footer if maxHeight is set and the pre tag content height is greater than the pre tag height\n get showFooter(): boolean {\n if (this.args.maxHeight) {\n return this._codeContentHeight > this._codeContainerHeight;\n }\n return false;\n }\n\n // Name of coding language used within CodeBlock for syntax highlighting\n get language(): HdsCodeBlockLanguages | undefined {\n return this.args.language ?? undefined;\n }\n\n // Displays line numbers if true\n get hasLineNumbers(): boolean {\n return this.args.hasLineNumbers ?? true;\n }\n\n // Make CodeBlock container corners appear rounded (the standalone variation)\n get isStandalone(): boolean {\n return this.args.isStandalone ?? true;\n }\n\n // Make text content wrap to multiple lines\n get hasLineWrapping(): boolean {\n return this.args.hasLineWrapping ?? false;\n }\n\n get copyButtonText(): HdsCopyButtonSignature['Args']['text'] {\n return this.args.copyButtonText ? this.args.copyButtonText : 'Copy';\n }\n\n @action\n setPrismCode(element: HTMLElement): void {\n const code = this.code;\n const language = this.language;\n const grammar = language ? Prism.languages[language] : undefined;\n\n if (code) {\n // eslint-disable-next-line ember/no-runloop\n next((): void => {\n if (language && grammar) {\n this._prismCode = htmlSafe(Prism.highlight(code, grammar, language));\n } else {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n this._prismCode = htmlSafe(Prism.util.encode(code).toString());\n }\n\n // Force prism-line-numbers plugin initialization, required for Prism.highlight usage\n // See https://github.com/PrismJS/prism/issues/1234\n Prism.hooks.run('complete', {\n code,\n element,\n });\n\n // Get the actual height & the content height of the preCodeElement\n // eslint-disable-next-line ember/no-runloop\n schedule('afterRender', (): void => {\n const preCodeElement = document.getElementById(this._preCodeId);\n this._codeContentHeight = preCodeElement?.scrollHeight ?? 0;\n this._codeContainerHeight = preCodeElement?.clientHeight ?? 0;\n });\n\n // Force prism-line-highlight plugin initialization\n // Context: https://github.com/hashicorp/design-system/pull/1749#discussion_r1374288785\n if (this.args.highlightLines) {\n // we need to delay re-evaluating the context for prism-line-highlight for as much as possible, and `afterRender` is the 'latest' we can use in the component lifecycle\n // eslint-disable-next-line ember/no-runloop\n schedule('afterRender', (): void => {\n // we piggy-back on the plugin's `resize` event listener to trigger a new call of the `highlightLines` function: https://github.com/PrismJS/prism/blob/master/plugins/line-highlight/prism-line-highlight.js#L337\n if (window) window.dispatchEvent(new Event('resize'));\n });\n }\n });\n }\n }\n\n @action\n toggleExpanded(): void {\n this._isExpanded = !this._isExpanded;\n }\n\n get classNames(): string {\n // Currently there is only one theme so the class name is hard-coded.\n // In the future, additional themes such as a \"light\" theme could be added.\n const classes = ['hds-code-block', 'hds-code-block--theme-dark'];\n\n if (this.language) {\n classes.push(`language-${this.language}`);\n }\n\n if (this.isStandalone === true) {\n classes.push('hds-code-block--is-standalone');\n }\n\n if (this.hasLineWrapping === true) {\n classes.push('hds-code-block--has-line-wrapping');\n }\n\n // Note: Prism.js is using the specific class name \"line-numbers\" to determine implementation of line numbers in the UI\n if (this.hasLineNumbers) {\n classes.push('line-numbers');\n }\n\n if (this.showFooter) {\n classes.push('hds-code-block--has-overlay-footer');\n }\n\n if (this._isExpanded) {\n classes.push('hds-code-block--is-expanded');\n }\n\n return classes.join(' ');\n }\n}\n"],"names":["LANGUAGES","Object","values","HdsCodeBlockLanguageValues","HdsCodeBlock","Component","g","prototype","tracked","htmlSafe","i","void 0","_preCodeId","guidFor","code","args","value","assert","undefined","Prism","plugins","normalize","maxHeight","_isExpanded","showFooter","_codeContentHeight","_codeContainerHeight","language","hasLineNumbers","isStandalone","hasLineWrapping","copyButtonText","setPrismCode","element","grammar","languages","next","_prismCode","highlight","util","encode","toString","hooks","run","schedule","preCodeElement","document","getElementById","scrollHeight","clientHeight","highlightLines","window","dispatchEvent","Event","n","action","toggleExpanded","classNames","classes","push","join","setComponentTemplate","TEMPLATE"],"mappings":"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"}
@@ -2,7 +2,7 @@ import Component from '@glimmer/component';
2
2
  import { precompileTemplate } from '@ember/template-compilation';
3
3
  import { setComponentTemplate } from '@ember/component';
4
4
 
5
- var TEMPLATE = precompileTemplate("{{!\n Copyright (c) HashiCorp, Inc.\n SPDX-License-Identifier: MPL-2.0\n}}\n<label class={{this.classNames}} for={{@controlId}} id={{this.id}} ...attributes>\n {{yield}}\n <Hds::Form::Indicator @isRequired={{@isRequired}} @isOptional={{@isOptional}} />\n</label>");
5
+ var TEMPLATE = precompileTemplate("{{!\n Copyright (c) HashiCorp, Inc.\n SPDX-License-Identifier: MPL-2.0\n}}\n<label class={{this.classNames}} for=\"{{@controlId}}\" id={{this.id}} ...attributes>\n {{yield}}\n <Hds::Form::Indicator @isRequired={{@isRequired}} @isOptional={{@isOptional}} />\n</label>");
6
6
 
7
7
  /**
8
8
  * Copyright (c) HashiCorp, Inc.
@@ -3493,7 +3493,6 @@ button.hds-button[href]::after {
3493
3493
  word-spacing: normal;
3494
3494
  tab-size: 4;
3495
3495
  hyphens: none;
3496
- scrollbar-width: thin;
3497
3496
  }
3498
3497
  @media print {
3499
3498
  .hds-code-block pre,
@@ -3503,11 +3502,13 @@ button.hds-button[href]::after {
3503
3502
  }
3504
3503
 
3505
3504
  .hds-code-block--is-standalone {
3505
+ overflow: hidden;
3506
3506
  border-radius: var(--token-border-radius-medium);
3507
3507
  }
3508
3508
 
3509
3509
  .hds-code-block--has-line-wrapping .hds-code-block__code,
3510
3510
  .hds-code-block--has-line-wrapping .hds-code-block__code code {
3511
+ display: block;
3511
3512
  white-space: pre-wrap;
3512
3513
  overflow-wrap: break-word;
3513
3514
  }
@@ -3566,10 +3567,13 @@ button.hds-button[href]::after {
3566
3567
  .hds-code-block__code {
3567
3568
  outline-style: solid;
3568
3569
  outline-color: transparent;
3569
- display: block;
3570
+ position: relative;
3571
+ display: grid;
3570
3572
  margin: 0;
3571
- padding: 16px;
3573
+ padding: 16px 0 16px 16px;
3572
3574
  overflow: auto;
3575
+ scrollbar-width: thin;
3576
+ scrollbar-color: var(--token-color-palette-neutral-400) var(--token-color-palette-neutral-500);
3573
3577
  font-size: 0.8125rem;
3574
3578
  font-family: var(--token-typography-code-200-font-family);
3575
3579
  border-radius: inherit;
@@ -3590,38 +3594,60 @@ button.hds-button[href]::after {
3590
3594
  color: var(--hds-code-block-color-foreground-selection);
3591
3595
  background-color: var(--hds-code-block-color-surface-selection);
3592
3596
  }
3597
+ .hds-code-block__code code {
3598
+ display: inline-block;
3599
+ padding-right: 16px;
3600
+ }
3593
3601
 
3602
+ .hds-code-block__height-toggle-button,
3594
3603
  .hds-code-block__copy-button {
3595
- position: absolute;
3596
- top: 11px;
3597
- right: 12px;
3598
3604
  color: var(--hds-code-block-color-foreground-primary);
3599
3605
  background-color: var(--hds-code-block-color-surface-faint);
3600
3606
  border: 1px solid var(--hds-code-block-color-border-strong);
3601
3607
  }
3602
- .hds-code-block__copy-button:hover, .hds-code-block__copy-button.mock-hover {
3608
+ .hds-code-block__height-toggle-button:hover, .hds-code-block__height-toggle-button.mock-hover,
3609
+ .hds-code-block__copy-button:hover,
3610
+ .hds-code-block__copy-button.mock-hover {
3611
+ color: var(--hds-code-block-color-foreground-primary);
3603
3612
  background-color: var(--hds-code-block-color-surface-primary);
3604
3613
  border-color: var(--hds-code-block-color-border-strong);
3605
3614
  }
3606
- .hds-code-block__copy-button:active, .hds-code-block__copy-button.mock-active {
3615
+ .hds-code-block__height-toggle-button:active, .hds-code-block__height-toggle-button.mock-active,
3616
+ .hds-code-block__copy-button:active,
3617
+ .hds-code-block__copy-button.mock-active {
3618
+ color: var(--hds-code-block-color-foreground-primary);
3607
3619
  background-color: var(--hds-code-block-color-surface-interactive-active);
3608
3620
  }
3609
- .hds-code-block__copy-button:focus, .hds-code-block__copy-button.mock-focus, .hds-code-block__copy-button:focus-visible {
3621
+ .hds-code-block__height-toggle-button:focus, .hds-code-block__height-toggle-button.mock-focus, .hds-code-block__height-toggle-button:focus-visible,
3622
+ .hds-code-block__copy-button:focus,
3623
+ .hds-code-block__copy-button.mock-focus,
3624
+ .hds-code-block__copy-button:focus-visible {
3625
+ color: var(--hds-code-block-color-foreground-primary);
3610
3626
  background-color: var(--hds-code-block-color-surface-faint);
3611
3627
  border-color: var(--hds-code-block-color-focus-action-internal);
3612
3628
  }
3613
- .hds-code-block__copy-button:focus::before, .hds-code-block__copy-button.mock-focus::before, .hds-code-block__copy-button:focus-visible::before {
3629
+ .hds-code-block__height-toggle-button:focus::before, .hds-code-block__height-toggle-button.mock-focus::before, .hds-code-block__height-toggle-button:focus-visible::before,
3630
+ .hds-code-block__copy-button:focus::before,
3631
+ .hds-code-block__copy-button.mock-focus::before,
3632
+ .hds-code-block__copy-button:focus-visible::before {
3614
3633
  border-color: var(--hds-code-block-color-focus-action-external);
3615
3634
  }
3635
+ .hds-code-block__height-toggle-button .hds-icon,
3636
+ .hds-code-block__copy-button .hds-icon {
3637
+ color: var(--hds-code-block-color-foreground-primary);
3638
+ }
3639
+
3640
+ .hds-code-block__copy-button {
3641
+ position: absolute;
3642
+ top: 11px;
3643
+ right: 12px;
3644
+ }
3616
3645
  .hds-code-block__copy-button.hds-copy-button--status-success .hds-icon {
3617
3646
  color: var(--hds-code-block-color-foreground-success);
3618
3647
  }
3619
3648
  .hds-code-block__copy-button.hds-copy-button--status-error .hds-icon {
3620
3649
  color: var(--hds-code-block-color-foreground-critical);
3621
3650
  }
3622
- .hds-code-block__copy-button .hds-icon {
3623
- color: var(--hds-code-block-color-foreground-primary);
3624
- }
3625
3651
 
3626
3652
  .hds-code-block.line-numbers {
3627
3653
  counter-reset: linenumber;
@@ -3630,6 +3656,9 @@ button.hds-button[href]::after {
3630
3656
  position: relative;
3631
3657
  padding-left: calc(49px + 16px);
3632
3658
  }
3659
+ .hds-code-block.line-numbers .hds-code-block__overlay-footer {
3660
+ margin-left: 49px;
3661
+ }
3633
3662
  .hds-code-block.line-numbers .line-numbers-rows {
3634
3663
  position: absolute;
3635
3664
  top: 0;
@@ -3679,6 +3708,50 @@ button.hds-button[href]::after {
3679
3708
  font-style: italic;
3680
3709
  }
3681
3710
 
3711
+ .hds-code-block__overlay-footer {
3712
+ position: absolute;
3713
+ right: 0;
3714
+ bottom: 0;
3715
+ left: 0;
3716
+ display: flex;
3717
+ align-items: center;
3718
+ justify-content: center;
3719
+ padding: 10px 16px 10px 16px;
3720
+ pointer-events: none;
3721
+ }
3722
+ .hds-code-block__overlay-footer > * {
3723
+ pointer-events: auto;
3724
+ }
3725
+
3726
+ .hds-code-block--has-overlay-footer .hds-code-block__code::after {
3727
+ position: sticky;
3728
+ bottom: -16px;
3729
+ left: 0;
3730
+ display: block;
3731
+ height: 48px;
3732
+ margin: 0 0 -16px -1000px;
3733
+ background: linear-gradient(360deg, #0d0e12 37.07%, rgba(13, 14, 18, 0.25) 100%);
3734
+ content: "";
3735
+ pointer-events: none;
3736
+ }
3737
+ .hds-code-block--has-overlay-footer .line-numbers .line-numbers-rows {
3738
+ padding-bottom: 48px;
3739
+ }
3740
+ .hds-code-block--has-overlay-footer .line-numbers-rows {
3741
+ z-index: 1;
3742
+ isolation: isolate;
3743
+ }
3744
+
3745
+ .hds-code-block--is-expanded .hds-code-block__code {
3746
+ padding-bottom: 48px;
3747
+ }
3748
+ .hds-code-block--is-expanded .hds-code-block__code::after {
3749
+ content: none;
3750
+ }
3751
+ .hds-code-block--is-expanded .hds-code-block__overlay-footer {
3752
+ background: none;
3753
+ }
3754
+
3682
3755
  /**
3683
3756
  * Copyright (c) HashiCorp, Inc.
3684
3757
  * SPDX-License-Identifier: MPL-2.0
@@ -15,6 +15,7 @@
15
15
  // DIMENSIONS
16
16
  $hds-code-block-line-numbers-width: 49px; // 3em ≈ 49px
17
17
  $hds-code-block-code-padding: 16px;
18
+ $hds-code-block-code-footer-height: 48px;
18
19
 
19
20
  // CODE-BLOCK PARENT/WRAPPER
20
21
 
@@ -35,7 +36,6 @@ $hds-code-block-code-padding: 16px;
35
36
  word-spacing: normal;
36
37
  tab-size: 4;
37
38
  hyphens: none;
38
- scrollbar-width: thin;
39
39
 
40
40
  @media print {
41
41
  text-shadow: none;
@@ -47,6 +47,7 @@ $hds-code-block-code-padding: 16px;
47
47
 
48
48
  // isStandalone
49
49
  .hds-code-block--is-standalone {
50
+ overflow: hidden; // hide corners of scrollbar that poke out
50
51
  border-radius: var(--token-border-radius-medium);
51
52
  }
52
53
 
@@ -54,6 +55,7 @@ $hds-code-block-code-padding: 16px;
54
55
  .hds-code-block--has-line-wrapping {
55
56
  .hds-code-block__code,
56
57
  .hds-code-block__code code {
58
+ display: block;
57
59
  white-space: pre-wrap;
58
60
  overflow-wrap: break-word;
59
61
  }
@@ -128,10 +130,13 @@ $hds-code-block-code-padding: 16px;
128
130
  // Code
129
131
  .hds-code-block__code {
130
132
  @include hds-focus-ring-basic();
131
- display: block;
133
+ position: relative;
134
+ display: grid;
132
135
  margin: 0;
133
- padding: $hds-code-block-code-padding;
136
+ padding: $hds-code-block-code-padding 0 $hds-code-block-code-padding $hds-code-block-code-padding;
134
137
  overflow: auto;
138
+ scrollbar-width: thin;
139
+ scrollbar-color: var(--token-color-palette-neutral-400) var(--token-color-palette-neutral-500);
135
140
  font-size: 0.8125rem;
136
141
  font-family: var(--token-typography-code-200-font-family);
137
142
  border-radius: inherit;
@@ -140,13 +145,16 @@ $hds-code-block-code-padding: 16px;
140
145
  color: var(--hds-code-block-color-foreground-selection);
141
146
  background-color: var(--hds-code-block-color-surface-selection);
142
147
  }
148
+
149
+ code {
150
+ display: inline-block;
151
+ padding-right: $hds-code-block-code-padding;
152
+ }
143
153
  }
144
154
 
145
- // CopyButton
155
+ // General dark button styles
156
+ .hds-code-block__height-toggle-button,
146
157
  .hds-code-block__copy-button {
147
- position: absolute;
148
- top: 11px; // 12px -1px accounting for border
149
- right: 12px; // 12px -1px accounting for border
150
158
  // Overriding default colors
151
159
  color: var(--hds-code-block-color-foreground-primary);
152
160
  background-color: var(--hds-code-block-color-surface-faint);
@@ -154,18 +162,21 @@ $hds-code-block-code-padding: 16px;
154
162
 
155
163
  &:hover,
156
164
  &.mock-hover {
165
+ color: var(--hds-code-block-color-foreground-primary);
157
166
  background-color: var(--hds-code-block-color-surface-primary);
158
167
  border-color: var(--hds-code-block-color-border-strong);
159
168
  }
160
169
 
161
170
  &:active,
162
171
  &.mock-active {
172
+ color: var(--hds-code-block-color-foreground-primary);
163
173
  background-color: var(--hds-code-block-color-surface-interactive-active);
164
174
  }
165
175
 
166
176
  &:focus,
167
177
  &.mock-focus,
168
178
  &:focus-visible {
179
+ color: var(--hds-code-block-color-foreground-primary);
169
180
  background-color: var(--hds-code-block-color-surface-faint);
170
181
  border-color: var(--hds-code-block-color-focus-action-internal);
171
182
 
@@ -174,6 +185,17 @@ $hds-code-block-code-padding: 16px;
174
185
  }
175
186
  }
176
187
 
188
+ .hds-icon {
189
+ color: var(--hds-code-block-color-foreground-primary);
190
+ }
191
+ }
192
+
193
+ // CopyButton
194
+ .hds-code-block__copy-button {
195
+ position: absolute;
196
+ top: 11px; // 12px -1px accounting for border
197
+ right: 12px;
198
+
177
199
  &.hds-copy-button--status-success {
178
200
  .hds-icon {
179
201
  color: var(--hds-code-block-color-foreground-success);
@@ -185,12 +207,9 @@ $hds-code-block-code-padding: 16px;
185
207
  color: var(--hds-code-block-color-foreground-critical);
186
208
  }
187
209
  }
188
-
189
- .hds-icon {
190
- color: var(--hds-code-block-color-foreground-primary);
191
- }
192
210
  }
193
211
 
212
+ // Prism.js plugins
194
213
  .hds-code-block {
195
214
  // LineNumbers plugin styles ---------------
196
215
  // Note: Prism.js is using the specific class name "line-numbers" to determine implementation of line numbers in the UI
@@ -203,6 +222,11 @@ $hds-code-block-code-padding: 16px;
203
222
  padding-left: calc(#{$hds-code-block-line-numbers-width} + #{$hds-code-block-code-padding});
204
223
  }
205
224
 
225
+ .hds-code-block__overlay-footer {
226
+ // match horizontal padding of the code block
227
+ margin-left: $hds-code-block-line-numbers-width;
228
+ }
229
+
206
230
  .line-numbers-rows {
207
231
  position: absolute;
208
232
  top: 0;
@@ -262,3 +286,64 @@ $hds-code-block-code-padding: 16px;
262
286
  font-style: italic;
263
287
  }
264
288
  }
289
+
290
+ // Footer
291
+ .hds-code-block__overlay-footer {
292
+ position: absolute;
293
+ right: 0;
294
+ bottom: 0;
295
+ left: 0;
296
+ display: flex;
297
+ align-items: center;
298
+ justify-content: center;
299
+ padding: 10px $hds-code-block-code-padding 10px $hds-code-block-code-padding;
300
+ pointer-events: none; // fix issue with scrolling when hovering over the footer
301
+
302
+ // re-enable pointer events for the button (or any content inside the footer)
303
+ > * {
304
+ pointer-events: auto;
305
+ }
306
+ }
307
+
308
+ // Usage of sticky positioning, negative margins, and z-index are required to prevent styling issues
309
+ // when horizontal scrolling is present.
310
+ // https://hashicorp.slack.com/archives/C025N5V4PFZ/p1746659338984369
311
+ .hds-code-block--has-overlay-footer {
312
+ .hds-code-block__code::after {
313
+ // gradient element
314
+ position: sticky; // prevent gradient from scrolling together with content
315
+ bottom: -$hds-code-block-code-padding;
316
+ left: 0;
317
+ display: block;
318
+ height: $hds-code-block-code-footer-height;
319
+ margin: 0 0 -#{$hds-code-block-code-padding} -1000px; // cover line highlights when line numbers are enabled
320
+ background: linear-gradient(360deg, #0d0e12 37.07%, rgba(13, 14, 18, 25%) 100%);
321
+ content: "";
322
+ pointer-events: none;
323
+ }
324
+
325
+ .line-numbers .line-numbers-rows {
326
+ padding-bottom: $hds-code-block-code-footer-height;
327
+ }
328
+
329
+ // place line numbers on top of footer gradient
330
+ .line-numbers-rows {
331
+ z-index: 1;
332
+ isolation: isolate;
333
+ }
334
+ }
335
+
336
+ .hds-code-block--is-expanded {
337
+ .hds-code-block__code {
338
+ // account for the footer at the bottom of the code block
339
+ padding-bottom: $hds-code-block-code-footer-height;
340
+
341
+ &::after {
342
+ content: none;
343
+ }
344
+ }
345
+
346
+ .hds-code-block__overlay-footer {
347
+ background: none;
348
+ }
349
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hashicorp/design-system-components",
3
- "version": "4.19.0",
3
+ "version": "4.20.0-rc-20250513142046",
4
4
  "description": "Helios Design System Components",
5
5
  "keywords": [
6
6
  "hashicorp",