File

src/code-snippet/code-snippet.component.ts

Description

Get started with importing the module:

Example :
import { CodeSnippetModule } from 'carbon-components-angular';
Example :
<cds-code-snippet>Code</cds-code-snippet>

See demo

Extends

BaseIconButton

Implements

OnInit AfterViewInit

Metadata

Index

Properties
Methods
Inputs
HostBindings
Accessors

Constructor

constructor(i18n: I18n, eventService: EventService)

Creates an instance of CodeSnippet.

Parameters :
Name Type Optional
i18n I18n No
eventService EventService No

Inputs

copyButtonDescription
Type : string

copy button description to show on hover

disabled
Type : boolean
Default value : false

Set to true to disable the code snippet

display
Type : SnippetType
Default value : SnippetType.single

It can be "single", "multi" or "inline"

expanded
Type : boolean
Default value : false
feedbackText
Type : any
Default value : this.translations.COPIED

Text displayed in the tooltip when user clicks button to copy code.

feedbackTimeout
Type : number
Default value : 2000

Time in miliseconds to keep the feedback tooltip displayed. Defaults to 2 seconds

hideCopyButton
Type : boolean
Default value : false

Set to true to hide copy button

maxCollapsedNumberOfRows
Type : number
Default value : 15

Specify the max number of rows to show when collapsed Default is 15

maxExpandedNumberOfRows
Type : number
Default value : 0

Specify the max number of rows to show when expanded Default is 0, hence all content will be visible when expanded

minCollapsedNumberOfRows
Type : number
Default value : 3

Specify the min number of rows to show when collapsed Default is 3

minExpandedNumberOfRows
Type : number
Default value : 16

Specify the min number of rows to show when expanded Default is 16, hence height of expanded row will be 16 * rowHeightInPixel (16) = 256px

skeleton
Type : boolean
Default value : false
theme
Type : "light" | "dark"
Default value : "dark"
translations
Type : any
Default value : this.i18n.get().CODE_SNIPPET
wrapText
Type : boolean
Default value : false

Set to true to wrap the text

align
Type : "top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right" | "left" | "left-bottom" | "left-top" | "right" | "right-bottom" | "right-top"
Default value : "bottom"
Inherited from BaseIconButton
Defined in BaseIconButton:32

Set popover alignment

autoAlign
Type : boolean
Default value : false
Inherited from BaseIconButton
Defined in BaseIconButton:40

Experimental: Use floating-ui to position the tooltip This is not toggleable - should be assigned once

caret
Type : boolean
Default value : true
Inherited from BaseIconButton
Defined in BaseIconButton:16

Set to false to hide caret

dropShadow
Type : boolean
Default value : true
Inherited from BaseIconButton
Defined in BaseIconButton:20

Set to false to hide shadow

enterDelayMs
Type : number
Default value : 100
Inherited from BaseIconButton
Defined in BaseIconButton:44

Set delay before tooltip is shown

highContrast
Type : boolean
Default value : true
Inherited from BaseIconButton
Defined in BaseIconButton:24

Set to true to enable high contrast

isOpen
Type : boolean
Default value : false
Inherited from BaseIconButton
Defined in BaseIconButton:28

Set to true to have the popover open by default

leaveDelayMs
Type : number
Default value : 300
Inherited from BaseIconButton
Defined in BaseIconButton:48

Set delay when tooltip disappears

HostBindings

class.cds--snippet
Type : boolean
class.cds--snippet--disabled
Type : boolean
class.cds--snippet--light
Type : boolean
class.cds--snippet--multi
Type : boolean
class.cds--snippet--single
Type : boolean

Methods

calculateContainerHeight
calculateContainerHeight()
Returns : void
Protected canExpand
canExpand()
Returns : void
handleScroll
handleScroll()
Returns : void
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onCopyButtonClicked
onCopyButtonClicked()
Returns : void
toggleSnippetExpansion
toggleSnippetExpansion()
Returns : void

Properties

animating
Default value : false
code
Decorators :
@ViewChild('code')
codeContainer
Decorators :
@ViewChild('codeContainer')
codeContent
Decorators :
@ViewChild('codeContent')
hasExpandButton
Type : null
Default value : null
hasLeft
Default value : false
hasRight
Default value : false
hasRightOverflow
Default value : false
isExpandable
Default value : false
Readonly rowHeightInPixel
Type : number
Default value : 16
showFeedback
Default value : false
styles
Type : any
Default value : {}

Accessors

snippetClass
getsnippetClass()
snippetSingleClass
getsnippetSingleClass()
snippetMultiClass
getsnippetMultiClass()
snippetDisabledClass
getsnippetDisabledClass()
snippetInlineLightClass
getsnippetInlineLightClass()
import {
	Component,
	Input,
	HostBinding,
	ViewChild,
	AfterViewInit,
	OnInit
} from "@angular/core";

import { I18n } from "carbon-components-angular/i18n";
import { EventService } from "carbon-components-angular/utils";
import { BaseIconButton } from "carbon-components-angular/button";

export enum SnippetType {
	single = "single",
	multi = "multi",
	inline = "inline"
}

/**
 * Get started with importing the module:
 *
 * ```typescript
 * import { CodeSnippetModule } from 'carbon-components-angular';
 * ```
 *
 * ```html
 * <cds-code-snippet>Code</cds-code-snippet>
 * ```
 *
 * [See demo](../../?path=/story/components-code-snippet--basic)
 */
@Component({
	selector: "cds-code-snippet, ibm-code-snippet",
	template: `
		<ng-container *ngIf="display === 'inline'; else notInline">
			<ng-container *ngIf="!hideCopyButton; else noBtnInline">
				<ng-container *ngTemplateOutlet="buttonTemplate"></ng-container>
			</ng-container>
			<ng-template #noBtnInline>
				<span
					class="cds--snippet cds--snippet--inline cds--snippet--no-copy"
					[ngClass]="{
						'cds--snippet--light': theme === 'light'
					}">
					<code #code>
						<ng-container *ngTemplateOutlet="codeTemplate"></ng-container>
					</code>
				</span>
			</ng-template>
		</ng-container>

		<ng-template #notInline>
			<div
				#codeContainer
				class="cds--snippet-container"
				[attr.aria-label]="translations.CODE_SNIPPET_TEXT"
				[attr.tabindex]="display === 'single' && !disabled ? '0' : null"
				[attr.role]="display==='single' ? 'textarea' : null"
				[ngStyle]="styles"
				(scroll)="(display === 'single' ? handleScroll() : null)">
				<ng-container *ngIf="skeleton">
					<span *ngIf="display === 'single'; else multiSkeleton"></span>
					<ng-template #multiSkeleton>
						<span></span>
						<span></span>
						<span></span>
					</ng-template>
				</ng-container>
				<pre
					#codeContent
					*ngIf="!skeleton"
					(scroll)="(display === 'multi' ? handleScroll() : null)"><code #code><ng-container *ngTemplateOutlet="codeTemplate"></ng-container></code></pre>
			</div>
			<div *ngIf="hasLeft" class="cds--snippet__overflow-indicator--left"></div>
			<div *ngIf="hasRight" class="cds--snippet__overflow-indicator--right"></div>
			<ng-container *ngIf="!hideCopyButton;">
				<ng-container *ngTemplateOutlet="buttonTemplate"></ng-container>
			</ng-container>
			<button
				*ngIf="isExpandable"
				class="cds--btn cds--btn--ghost cds--btn--sm cds--snippet-btn--expand"
				(click)="toggleSnippetExpansion()"
				type="button">
				<span class="cds--snippet-btn--text">{{expanded ? translations.SHOW_LESS : translations.SHOW_MORE}}</span>
				<svg cdsIcon="chevron--down" size="16" class="cds--icon-chevron--down" [attr.aria-label]="translations.SHOW_MORE_ICON"></svg>
			</button>
		</ng-template>

		<ng-template #buttonTemplate>
			<cds-icon-button
				*ngIf="!skeleton"
				[description]="showFeedback ? feedbackText : copyButtonDescription"
				[align]="align"
				[autoAlign]="autoAlign"
				[dropShadow]="dropShadow"
				[caret]="caret"
				[highContrast]="highContrast"
				[isOpen]="isOpen"
				[enterDelayMs]="enterDelayMs"
				[leaveDelayMs]="leaveDelayMs"
				type="button"
				kind="primary"
				size="md"
				(click)="onCopyButtonClicked($event)"
				[buttonNgClass]="{
					'cds--snippet--light': theme === 'light',
					'cds--snippet--inline': display === 'inline',
					'cds--btn--icon-only': display !== 'inline',
					'cds--copy-btn': display !== 'inline',
					'cds--copy-btn--animating': animating,
					'cds--copy-btn--fade-in': showFeedback,
					'cds--copy-btn--fade-out': !showFeedback && animating,
					'cds--snippet cds--copy': true
				}"
				[buttonAttributes]="{
					'aria-label': translations.COPY_CODE,
					'aria-live': 'polite',
					'tabindex': '0'
				}">
				<ng-container *ngIf="display === 'inline'">
					<code #code>
						<ng-container *ngTemplateOutlet="codeTemplate"></ng-container>
					</code>
				</ng-container>
				<ng-container *ngIf="display !== 'inline'">
					<svg cdsIcon="copy" size="16" class="cds--snippet__icon"></svg>
				</ng-container>
			</cds-icon-button>
		</ng-template>

		<ng-template #codeTemplate>
			<ng-content></ng-content>
		</ng-template>
	`
})
export class CodeSnippet extends BaseIconButton implements OnInit, AfterViewInit {
	@HostBinding("class.cds--snippet") get snippetClass() {
		return this.display !== SnippetType.inline;
	}
	@HostBinding("class.cds--snippet--single") get snippetSingleClass() {
		return this.display === SnippetType.single;
	}
	@HostBinding("class.cds--snippet--multi") get snippetMultiClass() {
		return this.display === SnippetType.multi;
	}
	@HostBinding("class.cds--snippet--disabled") get snippetDisabledClass() {
		return this.display !== "inline" && this.disabled;
	}
	@HostBinding("class.cds--snippet--light") get snippetInlineLightClass() {
		return this.theme === "light";
	}

	readonly rowHeightInPixel: number = 16;

	/**
	 * It can be `"single"`, `"multi"` or `"inline"`
	 */
	@Input() display: SnippetType = SnippetType.single;
	@Input() translations = this.i18n.get().CODE_SNIPPET;
	/**
	 * copy button description to show on hover
	 */
	@Input() copyButtonDescription: string;
	/**
	 * Set to `true` to hide copy button
	 */
	@Input() hideCopyButton = false;
	/**
	 * Set to `true` to disable the code snippet
	 */
	@Input() disabled = false;
	/**
	 * Specify the max number of rows to show when collapsed
	 * Default is `15`
	 */
	@Input() maxCollapsedNumberOfRows = 15;
	/**
	 * Specify the min number of rows to show when collapsed
	 * Default is `3`
	 */
	@Input() minCollapsedNumberOfRows = 3;
	/**
	 * Specify the max number of rows to show when expanded
	 * Default is `0`, hence all content will be visible when expanded
	 */
	@Input() maxExpandedNumberOfRows = 0;
	/**
	 * Specify the min number of rows to show when expanded
	 * Default is `16`, hence height of expanded row will be 16 * rowHeightInPixel (16) =  256px
	 */
	@Input() minExpandedNumberOfRows = 16;
	/**
	 * Set to `true` to wrap the text
	 */
	@HostBinding("class.cds--snippet--wraptext") @Input() wrapText = false;
	/**
	 * @deprecated since v5 - Use `cdsLayer` directive instead
	 * Set to `"light"` to apply the light style
	 */
	@Input() theme: "light" | "dark" = "dark";
	/**
	 * Text displayed in the tooltip when user clicks button to copy code.
	 */
	@Input() feedbackText = this.translations.COPIED;
	/**
	 * Time in miliseconds to keep the feedback tooltip displayed.
	 * Defaults to 2 seconds
	 */
	@Input() feedbackTimeout = 2000;

	@HostBinding("class.cds--snippet--expand") @Input() expanded = false;
	@HostBinding("class.cds--skeleton") @Input() skeleton = false;
	styles: any = {};

	@ViewChild("code") code;
	@ViewChild("codeContent") codeContent;
	@ViewChild("codeContainer") codeContainer;

	showFeedback = false;
	animating = false;
	hasExpandButton = null;
	isExpandable = false;
	hasRightOverflow = false;

	hasRight = false;
	hasLeft = false;

	/**
	 * Creates an instance of CodeSnippet.
	 */
	constructor(protected i18n: I18n, protected eventService: EventService) {
		super();
		this.dropShadow = false;
	}

	handleScroll() {
		if (this.skeleton) {
			return;
		}

		let ref;
		switch (this.display) {
			case "multi":
				ref = this.codeContent.nativeElement;
				break;
			case "single":
				ref = this.codeContainer.nativeElement;
				break;
			default:
				return;
		}
		if (ref) {
			const {
				scrollWidth,
				clientWidth,
				scrollLeft
			} = ref;
			const horizontalOverflow = scrollWidth > clientWidth;
			this.hasLeft = horizontalOverflow && !!scrollLeft;
			this.hasRight = horizontalOverflow && scrollLeft + clientWidth !== scrollWidth;
		}
	}

	toggleSnippetExpansion() {
		this.expanded = !this.expanded;
		this.calculateContainerHeight();
	}

	onCopyButtonClicked() {
		if (!this.disabled) {
			window.navigator.clipboard
				.writeText(this.code.nativeElement.innerText || this.code.nativeElement.textContent).then(() => {
					this.showFeedback = true;
					this.animating = true;
					setTimeout(() => {
						this.showFeedback = false;
						this.animating = false;
					}, this.feedbackTimeout);
				});
		}
	}

	ngOnInit() {
		this.calculateContainerHeight();
	}

	ngAfterViewInit() {
		this.canExpand();
		this.handleScroll();
		if (window) {
			this.eventService.on(window as any, "resize", () => {
				this.canExpand();
				this.handleScroll();
			});
		}
	}

	calculateContainerHeight() {
		if (this.display === "multi" && !this.skeleton) {
			this.styles = {};
			if (this.expanded) {
				if (this.maxExpandedNumberOfRows > 0) {
					this.styles["max-height"] = `${this.maxExpandedNumberOfRows * this.rowHeightInPixel}px`;
				}
				if (this.minExpandedNumberOfRows > 0) {
					this.styles["min-height"] = `${this.minExpandedNumberOfRows * this.rowHeightInPixel}px`;
				}
			} else {
				if (this.maxCollapsedNumberOfRows > 0) {
					this.styles["max-height"] = `${this.maxCollapsedNumberOfRows * this.rowHeightInPixel}px`;
				}
				if (this.minCollapsedNumberOfRows > 0) {
					this.styles["min-height"] = `${this.minCollapsedNumberOfRows * this.rowHeightInPixel}px`;
				}
			}
		}
	}

	protected canExpand() {
		if (this.display === "multi" && !this.skeleton) {
			const height = this.codeContent.nativeElement.getBoundingClientRect().height;
			if (
				this.maxCollapsedNumberOfRows > 0 &&
				(this.maxExpandedNumberOfRows <= 0 ||
					this.maxExpandedNumberOfRows > this.maxCollapsedNumberOfRows) &&
				height > this.maxCollapsedNumberOfRows * this.rowHeightInPixel
			) {
				this.isExpandable = true;
			} else {
				this.isExpandable = false;
			}

			if (
				this.expanded &&
				this.minExpandedNumberOfRows > 0 &&
				height <= this.minExpandedNumberOfRows * this.rowHeightInPixel
			) {
				this.isExpandable = false;
			}
		}
	}
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""