diff --git a/src/plus/webviews/timeline/protocol.ts b/src/plus/webviews/timeline/protocol.ts index 52257f9..30c2a1a 100644 --- a/src/plus/webviews/timeline/protocol.ts +++ b/src/plus/webviews/timeline/protocol.ts @@ -5,9 +5,8 @@ export interface State { timestamp: number; dataset?: Commit[]; - emptyMessage?: string; period: Period; - title: string; + title?: string; sha?: string; uri?: string; diff --git a/src/plus/webviews/timeline/registration.ts b/src/plus/webviews/timeline/registration.ts index 7b8b14f..957cb20 100644 --- a/src/plus/webviews/timeline/registration.ts +++ b/src/plus/webviews/timeline/registration.ts @@ -16,7 +16,7 @@ export function registerTimelineWebviewPanel(controller: WebviewsController) { plusFeature: true, column: ViewColumn.Active, webviewHostOptions: { - retainContextWhenHidden: true, + retainContextWhenHidden: false, enableFindWidget: false, }, }, diff --git a/src/plus/webviews/timeline/timelineWebview.ts b/src/plus/webviews/timeline/timelineWebview.ts index d2fcc0c..3c9996e 100644 --- a/src/plus/webviews/timeline/timelineWebview.ts +++ b/src/plus/webviews/timeline/timelineWebview.ts @@ -55,7 +55,6 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { etagSubscription: this.container.subscription.etag, }; - this.updatePendingEditor(window.activeTextEditor); this._context = { ...this._context, ...this._pendingContext }; this._pendingContext = undefined; @@ -134,6 +133,10 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { onVisibilityChanged(visible: boolean) { if (!visible) return; + if (this.host.isView()) { + this.updatePendingEditor(window.activeTextEditor); + } + // Since this gets called even the first time the webview is shown, avoid sending an update, because the bootstrap has the data if (this._bootstraping) { this._bootstraping = false; @@ -257,44 +260,32 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { const shortDateFormat = configuration.get('defaultDateShortFormat') ?? 'short'; const period = current.period ?? defaultPeriod; - if (current.uri == null) { - const access = await this.container.git.access(PlusFeatures.Timeline); - return { - timestamp: Date.now(), - emptyMessage: 'There are no editors open that can provide file history information', - period: period, - title: '', - dateFormat: dateFormat, - shortDateFormat: shortDateFormat, - access: access, - }; - } + const gitUri = current.uri != null ? await GitUri.fromUri(current.uri) : undefined; + const repoPath = gitUri?.repoPath; - const gitUri = await GitUri.fromUri(current.uri); - const repoPath = gitUri.repoPath!; + if (this.host.isEditor()) { + this.host.title = + gitUri == null ? this.host.originalTitle : `${this.host.originalTitle}: ${gitUri.fileName}`; + } else { + this.host.description = gitUri?.fileName ?? '✨'; + } const access = await this.container.git.access(PlusFeatures.Timeline, repoPath); - if (access.allowed === false) { - const dataset = generateRandomTimelineDataset(); + + if (current.uri == null || gitUri == null || repoPath == null || access.allowed === false) { + const access = await this.container.git.access(PlusFeatures.Timeline, repoPath); return { timestamp: Date.now(), - dataset: dataset.sort((a, b) => b.sort - a.sort), period: period, - title: 'src/app/index.ts', - uri: Uri.file('src/app/index.ts').toString(), + title: gitUri?.relativePath, + sha: gitUri?.shortSha, + uri: current.uri?.toString(), dateFormat: dateFormat, shortDateFormat: shortDateFormat, access: access, }; } - const title = gitUri.relativePath; - if (this.host.isEditor()) { - this.host.title = `${this.host.originalTitle}: ${gitUri.fileName}`; - } else { - this.host.description = gitUri.fileName; - } - const [currentUser, log] = await Promise.all([ this.container.git.getCurrentUser(repoPath), this.container.git.getLogForFile(repoPath, gitUri.fsPath, { @@ -308,9 +299,8 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { return { timestamp: Date.now(), dataset: [], - emptyMessage: 'No commits found for the specified time period', period: period, - title: title, + title: gitUri.relativePath, sha: gitUri.shortSha, uri: current.uri.toString(), dateFormat: dateFormat, @@ -368,7 +358,7 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { timestamp: Date.now(), dataset: dataset, period: period, - title: title, + title: gitUri.relativePath, sha: gitUri.shortSha, uri: current.uri.toString(), dateFormat: dateFormat, @@ -377,8 +367,8 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { }; } - private updatePendingContext(context: Partial<Context>): boolean { - const [changed, pending] = updatePendingContext(this._context, this._pendingContext, context); + private updatePendingContext(context: Partial<Context>, force?: boolean): boolean { + const [changed, pending] = updatePendingContext(this._context, this._pendingContext, context, force); if (changed) { this._pendingContext = pending; } @@ -386,14 +376,14 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { return changed; } - private updatePendingEditor(editor: TextEditor | undefined): boolean { - if (editor == null && hasVisibleTextEditor()) return false; + private updatePendingEditor(editor: TextEditor | undefined, force?: boolean): boolean { + if (editor == null && hasVisibleTextEditor(this._context.uri ?? this._pendingContext?.uri)) return false; if (editor != null && !isTextEditor(editor)) return false; - return this.updatePendingUri(editor?.document.uri); + return this.updatePendingUri(editor?.document.uri, force); } - private updatePendingUri(uri: Uri | undefined): boolean { + private updatePendingUri(uri: Uri | undefined, force?: boolean): boolean { let etag; if (uri != null) { const repository = this.container.git.getRepository(uri); @@ -402,19 +392,13 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { etag = 0; } - return this.updatePendingContext({ uri: uri, etagRepository: etag }); + return this.updatePendingContext({ uri: uri, etagRepository: etag }, force); } private _notifyDidChangeStateDebounced: Deferrable<() => void> | undefined = undefined; @debug() private updateState(immediate: boolean = false) { - if (!this.host.ready || !this.host.visible) return; - - if (this._pendingContext == null && this.host.isView()) { - this.updatePendingEditor(window.activeTextEditor); - } - if (immediate) { void this.notifyDidChangeState(); return; @@ -429,22 +413,17 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { @debug() private async notifyDidChangeState() { - if (!this.host.ready || !this.host.visible) return false; - this._notifyDidChangeStateDebounced?.cancel(); if (this._pendingContext == null) return false; const context = { ...this._context, ...this._pendingContext }; + this._context = context; + this._pendingContext = undefined; - const task = async () => { - const success = await this.host.notify(DidChangeNotificationType, { + const task = async () => + this.host.notify(DidChangeNotificationType, { state: await this.getState(context), }); - if (success) { - this._context = context; - this._pendingContext = undefined; - } - }; if (!this.host.isView()) return task(); return window.withProgress({ location: { viewId: this.host.id } }, task); @@ -458,30 +437,6 @@ export class TimelineWebviewProvider implements WebviewProvider<State> { } } -function generateRandomTimelineDataset(): Commit[] { - const dataset: Commit[] = []; - const authors = ['Eric Amodio', 'Justin Roberts', 'Ada Lovelace', 'Grace Hopper']; - - const count = 10; - for (let i = 0; i < count; i++) { - // Generate a random date between now and 3 months ago - const date = new Date(new Date().getTime() - Math.floor(Math.random() * (3 * 30 * 24 * 60 * 60 * 1000))); - - dataset.push({ - commit: String(i), - author: authors[Math.floor(Math.random() * authors.length)], - date: date.toISOString(), - message: '', - // Generate random additions/deletions between 1 and 20, but ensure we have a tiny and large commit - additions: i === 0 ? 2 : i === count - 1 ? 50 : Math.floor(Math.random() * 20) + 1, - deletions: i === 0 ? 1 : i === count - 1 ? 25 : Math.floor(Math.random() * 20) + 1, - sort: date.getTime(), - }); - } - - return dataset; -} - function getPeriodDate(period: Period): Date | undefined { if (period == 'all') return undefined; diff --git a/src/subscription.ts b/src/subscription.ts index f53078c..845e38c 100644 --- a/src/subscription.ts +++ b/src/subscription.ts @@ -190,3 +190,11 @@ export function isSubscriptionPreviewTrialExpired(subscription: Optional<Subscri const remaining = getTimeRemaining(subscription.previewTrial?.expiresOn); return remaining != null ? remaining <= 0 : undefined; } + +export function isSubscriptionStatePaidOrTrial(state: SubscriptionState): boolean { + return ( + state === SubscriptionState.Paid || + state === SubscriptionState.FreeInPreviewTrial || + state === SubscriptionState.FreePlusInTrial + ); +} diff --git a/src/system/utils.ts b/src/system/utils.ts index ab33f6f..f595fa8 100644 --- a/src/system/utils.ts +++ b/src/system/utils.ts @@ -67,10 +67,13 @@ export function getQuickPickIgnoreFocusOut() { return !configuration.get('advanced.quickPick.closeOnFocusOut'); } -export function hasVisibleTextEditor(): boolean { +export function hasVisibleTextEditor(uri?: Uri): boolean { if (window.visibleTextEditors.length === 0) return false; - return window.visibleTextEditors.some(e => isTextEditor(e)); + if (uri == null) return window.visibleTextEditors.some(e => isTextEditor(e)); + + const url = uri.toString(); + return window.visibleTextEditors.some(e => e.document.uri.toString() === url && isTextEditor(e)); } export function isActiveDocument(document: TextDocument): boolean { diff --git a/src/webviews/apps/plus/shared/components/plus-feature-gate.ts b/src/webviews/apps/plus/shared/components/plus-feature-gate.ts new file mode 100644 index 0000000..cf5e647 --- /dev/null +++ b/src/webviews/apps/plus/shared/components/plus-feature-gate.ts @@ -0,0 +1,88 @@ +import { css, html, LitElement, nothing } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { SubscriptionState } from '../../../../../subscription'; +import '../../../shared/components/button'; +import { linkStyles } from './vscode.css'; + +@customElement('plus-feature-gate') +export class PlusFeatureGate extends LitElement { + static override styles = [ + linkStyles, + css` + :host { + container-type: inline-size; + } + + gk-button { + width: 100%; + max-width: 300px; + } + + @container (max-width: 640px) { + gk-button { + display: block; + margin-left: auto; + margin-right: auto; + } + } + `, + ]; + + @property({ type: String }) + appearance?: 'alert' | 'welcome'; + + @property({ type: Number }) + state?: SubscriptionState; + + override render() { + const appearance = (this.appearance ?? 'alert') === 'alert' ? 'alert' : nothing; + + switch (this.state) { + case SubscriptionState.VerificationRequired: + return html` + <p>You must verify your email before you can continue.</p> + <gk-button appearance="${appearance}" href="command:gitlens.plus.resendVerification" + >Resend verification email</gk-button + > + <gk-button appearance="${appearance}" href="command:gitlens.plus.validate" + >Refresh verification status</gk-button + > + `; + + case SubscriptionState.Free: + return html` + <gk-button appearance="${appearance}" href="command:gitlens.plus.startPreviewTrial" + >Start Free Pro Trial</gk-button + > + <p> + Instantly start a free 3-day Pro trial, or + <a href="command:gitlens.plus.loginOrSignUp">sign in</a>. + </p> + <p>✨ A trial or subscription is required to use this on privately hosted repos.</p> + `; + + case SubscriptionState.FreePreviewTrialExpired: + return html` + <p> + Your free 3-day Pro trial has ended, extend your free trial to get an additional 7-days, or + <a href="command:gitlens.plus.loginOrSignUp">sign in</a>. + </p> + <gk-button appearance="${appearance}" href="command:gitlens.plus.loginOrSignUp" + >Extend Free Pro Trial</gk-button + > + <p>✨ A trial or subscription is required to use this on privately hosted repos.</p> + `; + + case SubscriptionState.FreePlusTrialExpired: + return html` + <p>Your Pro trial has ended, please upgrade to continue to use this on privately hosted repos.</p> + <gk-button appearance="${appearance}" href="command:gitlens.plus.purchase" + >Upgrade to Pro</gk-button + > + <p>✨ A subscription is required to use this on privately hosted repos.</p> + `; + } + + return undefined; + } +} diff --git a/src/webviews/apps/plus/shared/components/plus-feature-welcome.ts b/src/webviews/apps/plus/shared/components/plus-feature-welcome.ts new file mode 100644 index 0000000..6c46815 --- /dev/null +++ b/src/webviews/apps/plus/shared/components/plus-feature-welcome.ts @@ -0,0 +1,92 @@ +import { css, html, LitElement, nothing } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { isSubscriptionStatePaidOrTrial, SubscriptionState } from '../../../../../subscription'; +import './plus-feature-gate'; + +@customElement('plus-feature-welcome') +export class PlusFeatureWelcome extends LitElement { + static override styles = css` + :host { + --background: var(--vscode-sideBar-background); + --foreground: var(--vscode-sideBar-foreground); + --link-foreground: var(--vscode-textLink-foreground); + --link-foreground-active: var(--vscode-textLink-activeForeground); + + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + font-size: 1.3rem; + overflow: auto; + z-index: 100; + + box-sizing: border-box; + } + + :host-context(body[data-placement='editor']) { + --background: transparent; + --foreground: var(--vscode-editor-foreground); + + backdrop-filter: blur(3px) saturate(0.8); + padding: 0 2rem; + } + + section { + --section-foreground: var(--foreground); + --section-background: var(--background); + --section-border-color: transparent; + + display: flex; + flex-direction: column; + padding: 0 2rem 1.3rem 2rem; + background: var(--section-background); + color: var(--section-foreground); + border: 1px solid var(--section-border-color); + + height: min-content; + } + + :host-context(body[data-placement='editor']) section { + --section-foreground: var(--color-alert-foreground); + --section-background: var(--color-alert-infoBackground); + --section-border-color: var(--color-alert-infoBorder); + + --link-decoration-default: underline; + --link-foreground: var(--vscode-foreground); + --link-foreground-active: var(--vscode-foreground); + + border-radius: 0.3rem; + max-width: 600px; + max-height: min-content; + margin: 0.2rem auto; + padding: 0 1.3rem; + } + `; + + @property({ type: Boolean }) + allowed?: boolean; + + @property({ type: Number }) + state?: SubscriptionState; + + @property({ reflect: true }) + get appearance() { + return (document.body.getAttribute('data-placement') ?? 'editor') === 'editor' ? 'alert' : 'welcome'; + } + + override render() { + if (this.allowed || this.state == null || isSubscriptionStatePaidOrTrial(this.state)) { + this.hidden = true; + return undefined; + } + + this.hidden = false; + return html` + <section> + <slot hidden=${this.state === SubscriptionState.Free ? nothing : ''}></slot> + <plus-feature-gate appearance=${this.appearance} state=${this.state}></plus-feature-gate> + </section> + `; + } +} diff --git a/src/webviews/apps/plus/shared/components/vscode.css.ts b/src/webviews/apps/plus/shared/components/vscode.css.ts new file mode 100644 index 0000000..c06e645 --- /dev/null +++ b/src/webviews/apps/plus/shared/components/vscode.css.ts @@ -0,0 +1,15 @@ +import { css } from 'lit'; + +export const linkStyles = css` + a { + color: var(--link-foreground); + text-decoration: var(--link-decoration-default, none); + } + a:focus { + outline-color: var(--focus-border); + } + a:hover { + color: var(--link-foreground-active); + text-decoration: underline; + } +`; diff --git a/src/webviews/apps/plus/timeline/chart.ts b/src/webviews/apps/plus/timeline/chart.ts index 5db72cb..3216059 100644 --- a/src/webviews/apps/plus/timeline/chart.ts +++ b/src/webviews/apps/plus/timeline/chart.ts @@ -5,7 +5,7 @@ import { bar, bb, bubble, zoom } from 'billboard.js'; // import { scaleSqrt } from 'd3-scale'; import type { Commit, State } from '../../../../plus/webviews/timeline/protocol'; import { formatDate, fromNow } from '../../shared/date'; -import type { Event } from '../../shared/events'; +import type { Disposable, Event } from '../../shared/events'; import { Emitter } from '../../shared/events'; export interface DataPointClickEvent { @@ -15,7 +15,7 @@ export interface DataPointClickEvent { }; } -export class TimelineChart { +export class TimelineChart implements Disposable { private _onDidClickDataPoint = new Emitter<DataPointClickEvent>(); get onDidClickDataPoint(): Event<DataPointClickEvent> { return this._onDidClickDataPoint.event; @@ -23,9 +23,9 @@ export class TimelineChart { private readonly $container: HTMLElement; private _chart: Chart | undefined; - private _chartDimensions: { height: number; width: number }; private readonly _resizeObserver: ResizeObserver; private readonly _selector: string; + private _size: { height: number; width: number }; private readonly _commitsByTimestamp = new Map<string, Commit>(); private readonly _authorsByIndex = new Map<number, string>(); @@ -34,48 +34,48 @@ export class TimelineChart { private _dateFormat: string = undefined!; private _shortDateFormat: string = undefined!; - constructor(selector: string) { - this._selector = selector; + private get compact(): boolean { + return this.placement !== 'editor'; + } - let idleRequest: number | undefined; + constructor(selector: string, private readonly placement: 'editor' | 'view') { + this._selector = selector; const fn = () => { - idleRequest = undefined; - - const dimensions = this._chartDimensions; + const size = this._size; this._chart?.resize({ - width: dimensions.width, - height: dimensions.height - 10, + width: size.width, + height: size.height, }); }; + const widthOffset = this.compact ? 32 : 0; + const heightOffset = this.compact ? 16 : 0; + + this.$container = document.querySelector(selector)!.parentElement!; this._resizeObserver = new ResizeObserver(entries => { - const size = entries[0].borderBoxSize[0]; - const dimensions = { - width: Math.floor(size.inlineSize), - height: Math.floor(size.blockSize), + const boxSize = entries[0].borderBoxSize[0]; + const size = { + width: Math.floor(boxSize.inlineSize) + widthOffset, + height: Math.floor(boxSize.blockSize) + heightOffset, }; - if ( - this._chartDimensions.height === dimensions.height && - this._chartDimensions.width === dimensions.width - ) { - return; - } - - this._chartDimensions = dimensions; - if (idleRequest != null) { - cancelIdleCallback(idleRequest); - idleRequest = undefined; - } - idleRequest = requestIdleCallback(fn, { timeout: 1000 }); + this._size = size; + requestAnimationFrame(fn); }); - this.$container = document.querySelector(selector)!.parentElement!; const rect = this.$container.getBoundingClientRect(); - this._chartDimensions = { height: Math.floor(rect.height), width: Math.floor(rect.width) }; + this._size = { + height: Math.floor(rect.height) + widthOffset, + width: Math.floor(rect.width) + heightOffset, + }; - this._resizeObserver.observe(this.$container); + this._resizeObserver.observe(this.$container, { box: 'border-box' }); + } + + dispose(): void { + this._resizeObserver.disconnect(); + this._chart?.destroy(); } reset() { @@ -83,6 +83,28 @@ export class TimelineChart { this._chart?.unzoom(); } + private setEmptyState(dataset: Commit[] | undefined, state: State) { + const $empty = document.getElementById('empty')!; + const $header = document.getElementById('header')!; + + if (state.uri != null) { + if (dataset?.length === 0) { + $empty.innerHTML = '<p>No commits found for the specified time period.</p>'; + $empty.removeAttribute('hidden'); + } else { + $empty.setAttribute('hidden', ''); + } + $header.removeAttribute('hidden'); + } else if (dataset == null) { + $empty.innerHTML = '<p>There are no editors open that can provide file history information.</p>'; + $empty.removeAttribute('hidden'); + $header.setAttribute('hidden', ''); + } else { + $empty.setAttribute('hidden', ''); + $header.removeAttribute('hidden'); + } + } + updateChart(state: State) { this._dateFormat = state.dateFormat; this._shortDateFormat = state.shortDateFormat; @@ -91,22 +113,19 @@ export class TimelineChart { this._authorsByIndex.clear(); this._indexByAuthors.clear(); - if (state?.dataset == null || state.dataset.length === 0) { + let dataset = state?.dataset; + if (dataset == null && !state.access.allowed && this.placement === 'editor') { + dataset = generateRandomTimelineDataset(); + } + + this.setEmptyState(dataset, state); + if (dataset == null || dataset.length === 0) { this._chart?.destroy(); this._chart = undefined; - const $overlay = document.getElementById('chart-empty-overlay') as HTMLDivElement; - $overlay?.classList.toggle('hidden', false); - - const $emptyMessage = $overlay.querySelector<HTMLHeadingElement>('[data-bind="empty"]')!; - $emptyMessage.textContent = state.emptyMessage ?? ''; - return; } - const $overlay = document.getElementById('chart-empty-overlay') as HTMLDivElement; - $overlay?.classList.toggle('hidden', true); - const xs: { [key: string]: string } = {}; const colors: { [key: string]: string } = {}; const names: { [key: string]: string } = {}; @@ -128,7 +147,7 @@ export class TimelineChart { // let minChanges = Infinity; // let maxChanges = -Infinity; - // for (const commit of state.dataset) { + // for (const commit of dataset) { // const changes = commit.additions + commit.deletions; // if (changes < minChanges) { // minChanges = changes; @@ -140,7 +159,7 @@ export class TimelineChart { // const bubbleScale = scaleSqrt([minChanges, maxChanges], [6, 100]); - for (commit of state.dataset) { + for (commit of dataset) { ({ author, date, additions, deletions } = commit); if (!this._indexByAuthors.has(author)) { @@ -211,48 +230,52 @@ export class TimelineChart { // eslint-disable-next-line @typescript-eslint/no-unsafe-return const columns = Object.entries(series).map(([key, value]) => [key, ...value]); - if (this._chart == null) { - const options = this.getChartOptions(); - - if (options.axis == null) { - options.axis = { y: { tick: {} } }; + try { + if (this._chart == null) { + const options = this.getChartOptions(); + + if (options.axis == null) { + options.axis = { y: { tick: {} } }; + } + if (options.axis.y == null) { + options.axis.y = { tick: {} }; + } + if (options.axis.y.tick == null) { + options.axis.y.tick = {}; + } + + options.axis.y.min = index - 2; + options.axis.y.tick.values = [...this._authorsByIndex.keys()]; + + options.data = { + ...options.data, + axes: axes, + colors: colors, + columns: columns, + groups: groups, + names: names, + types: types, + xs: xs, + }; + + this._chart = bb.generate(options); + } else { + this._chart.config('axis.y.tick.values', [...this._authorsByIndex.keys()], false); + this._chart.config('axis.y.min', index - 2, false); + this._chart.groups(groups); + + this._chart.load({ + axes: axes, + colors: colors, + columns: columns, + names: names, + types: types, + xs: xs, + unload: true, + }); } - if (options.axis.y == null) { - options.axis.y = { tick: {} }; - } - if (options.axis.y.tick == null) { - options.axis.y.tick = {}; - } - - options.axis.y.min = index - 2; - options.axis.y.tick.values = [...this._authorsByIndex.keys()]; - - options.data = { - ...options.data, - axes: axes, - colors: colors, - columns: columns, - groups: groups, - names: names, - types: types, - xs: xs, - }; - - this._chart = bb.generate(options); - } else { - this._chart.config('axis.y.tick.values', [...this._authorsByIndex.keys()], false); - this._chart.config('axis.y.min', index - 2, false); - this._chart.groups(groups); - - this._chart.load({ - axes: axes, - colors: colors, - columns: columns, - names: names, - types: types, - xs: xs, - unload: true, - }); + } catch (ex) { + debugger; } } @@ -275,16 +298,20 @@ export class TimelineChart { type: 'timeseries', clipPath: false, localtime: true, + show: true, tick: { - // autorotate: true, centered: true, culling: false, fit: false, format: (x: number | Date) => - typeof x === 'number' ? x : formatDate(x, this._shortDateFormat ?? 'short'), + this.compact + ? '' + : typeof x === 'number' + ? x + : formatDate(x, this._shortDateFormat ?? 'short'), multiline: false, - // rotate: 15, show: false, + outer: !this.compact, }, }, y: { @@ -295,22 +322,30 @@ export class TimelineChart { }, show: true, tick: { - format: (y: number) => this._authorsByIndex.get(y) ?? '', - outer: false, + format: (y: number) => (this.compact ? '' : this._authorsByIndex.get(y) ?? ''), + outer: !this.compact, + show: this.compact, }, }, y2: { - label: { - text: 'Lines changed', - position: 'outer-middle', - }, + padding: this.compact + ? { + top: 0, + bottom: 0, + } + : undefined, + label: this.compact + ? undefined + : { + text: 'Lines changed', + position: 'outer-middle', + }, // min: 0, show: true, - // tick: { - // outer: true, - // // culling: true, - // // stepSize: 1, - // }, + tick: { + format: (y: number) => (this.compact ? '' : y), + outer: !this.compact, + }, }, }, bar: { @@ -340,16 +375,14 @@ export class TimelineChart { }, }, legend: { - show: true, + show: !this.compact, + // hide: this.compact ? [...this._authorsByIndex.values()] : undefined, padding: 10, }, resize: { auto: false, }, - size: { - height: this._chartDimensions.height - 10, - width: this._chartDimensions.width, - }, + size: this._size, tooltip: { grouped: true, format: { @@ -436,3 +469,27 @@ export class TimelineChart { function capitalize(s: string): string { return s.charAt(0).toUpperCase() + s.slice(1); } + +function generateRandomTimelineDataset(): Commit[] { + const dataset: Commit[] = []; + const authors = ['Eric Amodio', 'Justin Roberts', 'Keith Daulton', 'Ramin Tadayon', 'Ada Lovelace', 'Grace Hopper']; + + const count = 10; + for (let i = 0; i < count; i++) { + // Generate a random date between now and 3 months ago + const date = new Date(new Date().getTime() - Math.floor(Math.random() * (3 * 30 * 24 * 60 * 60 * 1000))); + + dataset.push({ + commit: String(i), + author: authors[Math.floor(Math.random() * authors.length)], + date: date.toISOString(), + message: '', + // Generate random additions/deletions between 1 and 20, but ensure we have a tiny and large commit + additions: i === 0 ? 2 : i === count - 1 ? 50 : Math.floor(Math.random() * 20) + 1, + deletions: i === 0 ? 1 : i === count - 1 ? 25 : Math.floor(Math.random() * 20) + 1, + sort: date.getTime(), + }); + } + + return dataset.sort((a, b) => b.sort - a.sort); +} diff --git a/src/webviews/apps/plus/timeline/partials/state.free-preview-trial-expired.html b/src/webviews/apps/plus/timeline/partials/state.free-preview-trial-expired.html deleted file mode 100644 index 2f5a717..0000000 --- a/src/webviews/apps/plus/timeline/partials/state.free-preview-trial-expired.html +++ /dev/null @@ -1,9 +0,0 @@ -<template id="state:free-preview-trial-expired"> - <section> - <vscode-button data-action="command:gitlens.plus.loginOrSignUp">Extend Pro Trial</vscode-button> - <p> - Your free 3-day GitLens Pro trial has ended, extend your trial to get an additional free 7-days of the - Visual File History and other <a href="command:gitlens.plus.learn">GitLens+ features</a> on private repos. - </p> - </section> -</template> diff --git a/src/webviews/apps/plus/timeline/partials/state.free.html b/src/webviews/apps/plus/timeline/partials/state.free.html deleted file mode 100644 index 6b99c87..0000000 --- a/src/webviews/apps/plus/timeline/partials/state.free.html +++ /dev/null @@ -1,12 +0,0 @@ -<template id="state:free"> - <section> - <vscode-button data-action="command:gitlens.plus.startPreviewTrial" - >Try the Visual File History on private repos</vscode-button - > - <p> - To use the Visual File History and other <a href="command:gitlens.plus.learn">GitLens+ features</a> on - private repos, start a free trial of GitLens Pro, without an account, or - <a href="command:gitlens.plus.loginOrSignUp">sign in</a>. - </p> - </section> -</template> diff --git a/src/webviews/apps/plus/timeline/partials/state.plus-trial-expired.html b/src/webviews/apps/plus/timeline/partials/state.plus-trial-expired.html deleted file mode 100644 index a62db4e..0000000 --- a/src/webviews/apps/plus/timeline/partials/state.plus-trial-expired.html +++ /dev/null @@ -1,9 +0,0 @@ -<template id="state:plus-trial-expired"> - <section> - <vscode-button data-action="command:gitlens.plus.purchase">Upgrade to Pro</vscode-button> - <p> - Your GitLens Pro trial has ended, please upgrade to GitLens Pro to continue to use the Visual File History - and other <a href="command:gitlens.plus.learn">GitLens+ features</a> on private repos. - </p> - </section> -</template> diff --git a/src/webviews/apps/plus/timeline/partials/state.verify-email.html b/src/webviews/apps/plus/timeline/partials/state.verify-email.html deleted file mode 100644 index 2a54697..0000000 --- a/src/webviews/apps/plus/timeline/partials/state.verify-email.html +++ /dev/null @@ -1,8 +0,0 @@ -<template id="state:verify-email"> - <section> - <h3>Please verify your email</h3> - <p>To use the Visual File History, please verify your email address.</p> - <vscode-button data-action="command:gitlens.plus.resendVerification">Resend verification email</vscode-button> - <vscode-button data-action="command:gitlens.plus.validate">Refresh verification status</vscode-button> - </section> -</template> diff --git a/src/webviews/apps/plus/timeline/timeline.html b/src/webviews/apps/plus/timeline/timeline.html index 0d94b30..27e1086 100644 --- a/src/webviews/apps/plus/timeline/timeline.html +++ b/src/webviews/apps/plus/timeline/timeline.html @@ -10,12 +10,20 @@ </head> <body class="preload" data-placement="#{placement}"> + <plus-feature-welcome class="scrollable"> + <p> + Visualize the evolution of a file, including when changes were made, how large they were, and who made + them. + </p> + </plus-feature-welcome> <div class="container"> <progress-indicator id="spinner" position="top" active="true"></progress-indicator> - <section class="header"> - <h2 data-bind="title"></h2> - <h2 data-bind="sha"></h2> - <h2 data-bind="description"></h2> + <section id="header" class="header"> + <div class="header--context"> + <h2 data-bind="title"></h2> + <h2 data-bind="sha"></h2> + <h2 data-bind="description"></h2> + </div> <div class="toolbox"> <div class="select-container"> <label for="periods">Timeframe</label> @@ -31,40 +39,26 @@ <vscode-option value="all">Full history</vscode-option> </vscode-dropdown> </div> + <gk-button + data-placement-visible="view" + href="command:gitlens.views.timeline.openInTab" + title="Open in Editor Area" + aria-label="Open in Editor Area" + appearance="toolbar" + > + <code-icon icon="link-external"></code-icon> + </gk-button> </div> </section> <section id="content"> + <div id="empty" hidden></div> <div id="chart"></div> - <div id="chart-empty-overlay" class="hidden"> - <h1 data-bind="empty"></h1> - </div> </section> <section id="footer"></section> </div> - <div id="overlay" class="hidden"> - <div class="modal"> - <p> - The Visual File History, a - <a title="Learn more about GitLens+ features" href="command:gitlens.plus.learn" - >✨GitLens+ feature</a - >, allows you to quickly see the evolution of a file, including when changes were made, how large - they were, and who made them. - </p> - <p> - Use it to quickly find when the most impactful changes were made to a file or who best to talk to - about file changes and more. - </p> - <div id="overlay-slot"></div> - </div> - </div> #{endOfBody} <style nonce="#{cspNonce}"> - :root { - --gl-plus-bg: url(#{webroot}/media/gitlens-backdrop.webp); - } - </style> - <style nonce="#{cspNonce}"> @font-face { font-family: 'codicon'; font-display: block; @@ -77,10 +71,4 @@ } </style> </body> - - <!-- prettier-ignore --> - <%= require('html-loader?{"esModule":false}!./partials/state.free.html') %> - <%= require('html-loader?{"esModule":false}!./partials/state.free-preview-trial-expired.html') %> - <%= require('html-loader?{"esModule":false}!./partials/state.plus-trial-expired.html') %> - <%= require('html-loader?{"esModule":false}!./partials/state.verify-email.html') %> </html> diff --git a/src/webviews/apps/plus/timeline/timeline.scss b/src/webviews/apps/plus/timeline/timeline.scss index 1471a72..357aaae 100644 --- a/src/webviews/apps/plus/timeline/timeline.scss +++ b/src/webviews/apps/plus/timeline/timeline.scss @@ -1,3 +1,5 @@ +@use '../../shared/styles/properties'; + * { box-sizing: border-box; } @@ -14,11 +16,8 @@ body { line-height: 1.4; font-size: 100% !important; overflow: hidden; - margin: 0 20px 20px 20px; + margin: 0; padding: 0; - - min-width: 400px; - overflow-x: scroll; } body[data-placement='editor'] { @@ -57,72 +56,38 @@ h4 { margin: 0.5rem 0 1rem 0; } -a { - text-decoration: none; - - &:focus { - outline-color: var(--focus-border); - } - - &:hover { - text-decoration: underline; - } -} - -b { - font-weight: 600; -} - -p { - margin-bottom: 0; -} - -vscode-button:not([appearance='icon']) { - align-self: center; - margin-top: 1.5rem; - max-width: 300px; - width: 100%; -} - -span.button-subaction { - align-self: center; - margin-top: 0.75rem; -} - -@media (min-width: 640px) { - vscode-button:not([appearance='icon']) { - align-self: flex-start; - } - span.button-subaction { - align-self: flex-start; - } -} - .header { display: grid; - grid-template-columns: max-content min-content minmax(min-content, 1fr) max-content; + grid-template-columns: 1fr min-content; align-items: baseline; - grid-template-areas: 'title sha description toolbox'; - justify-content: start; - margin-bottom: 1rem; - - @media all and (max-width: 500px) { - grid-template-areas: - 'title sha description' - 'empty toolbox'; - grid-template-columns: max-content min-content minmax(min-content, 1fr); + grid-template-areas: 'context toolbox'; + margin: 1rem; + + body[data-placement='editor'] & { + margin-top: 0; } - h2[data-bind='title'] { - grid-area: title; - margin-bottom: 0; + &--context { + grid-area: context; + display: grid; + grid-template-columns: minmax(0, min-content) minmax(0, min-content) minmax(0, 1fr); + gap: 0.5rem; + align-items: baseline; + + h2 { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + + body:not([data-placement='editor']) & { + display: none; + } } h2[data-bind='sha'] { - grid-area: sha; font-size: 1.3em; font-weight: 200; - margin-left: 1.5rem; opacity: 0.7; white-space: nowrap; @@ -132,17 +97,16 @@ span.button-subaction { } h2[data-bind='description'] { - grid-area: description; font-size: 1.3em; font-weight: 200; - margin-left: 1.5rem; + margin-left: 0.5rem; opacity: 0.7; - overflow-wrap: anywhere; } .toolbox { grid-area: toolbox; display: flex; + gap: 0.3rem; } } @@ -160,30 +124,32 @@ span.button-subaction { #content { position: relative; - overflow: hidden; width: 100%; + height: 100%; } #chart { + position: absolute !important; height: 100%; width: 100%; - overflow: hidden; -} -#chart-empty-overlay { - display: flex; - align-items: center; - justify-content: center; + body:not([data-placement='editor']) & { + left: -16px; + } +} +#empty { position: absolute; top: 0; left: 0; - width: 100vw; - height: 60vh; + bottom: 0; + right: 0; + padding: 0.4rem 2rem 1.3rem 2rem; - h1 { - font-size: var(--font-size); - font-weight: 400; + font-size: var(--font-size); + + p { + margin-top: 0; } } @@ -191,60 +157,28 @@ span.button-subaction { display: none; } -#overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - font-size: 1.3em; - min-height: 100%; - padding: 0 2rem 2rem 2rem; - - backdrop-filter: blur(3px) saturate(0.8); - - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; +body[data-placement='editor'] { + [data-placement-hidden='editor'], + [data-placement-visible]:not([data-placement-visible='editor']) { + display: none !important; + } } -.modal { - max-width: 600px; - background: var(--color-hover-background) no-repeat left top; - background-image: var(--gl-plus-bg); - border: 1px solid var(--color-hover-border); - border-radius: 0.4rem; - margin: 1rem; - padding: 1.2rem; - - > p:first-child { - margin-top: 0; +body[data-placement='view'] { + [data-placement-hidden='view'], + [data-placement-visible]:not([data-placement-visible='view']) { + display: none !important; } +} - vscode-button:not([appearance='icon']) { - align-self: center !important; +body:not([data-placement='editor']) { + .bb-tooltip-container { + padding-left: 16px; } } -.hidden { +[hidden] { display: none !important; } @import './chart'; -@import '../../shared/codicons.scss'; -@import '../../shared/glicons.scss'; - -.glicon { - vertical-align: middle; -} - -.glicon, -.codicon { - position: relative; - top: -1px; -} - -.mt-tight { - margin-top: 0.3rem; -} diff --git a/src/webviews/apps/plus/timeline/timeline.ts b/src/webviews/apps/plus/timeline/timeline.ts index 656a75f..7036e5c 100644 --- a/src/webviews/apps/plus/timeline/timeline.ts +++ b/src/webviews/apps/plus/timeline/timeline.ts @@ -1,22 +1,23 @@ /*global*/ import './timeline.scss'; -import { provideVSCodeDesignSystem, vsCodeButton, vsCodeDropdown, vsCodeOption } from '@vscode/webview-ui-toolkit'; -import { GlyphChars } from '../../../../constants'; +import { provideVSCodeDesignSystem, vsCodeDropdown, vsCodeOption } from '@vscode/webview-ui-toolkit'; import type { Period, State } from '../../../../plus/webviews/timeline/protocol'; import { DidChangeNotificationType, OpenDataPointCommandType, UpdatePeriodCommandType, } from '../../../../plus/webviews/timeline/protocol'; -import { SubscriptionPlanId, SubscriptionState } from '../../../../subscription'; import type { IpcMessage } from '../../../protocol'; -import { ExecuteCommandType, onIpc } from '../../../protocol'; +import { onIpc } from '../../../protocol'; import { App } from '../../shared/appBase'; import { DOM } from '../../shared/dom'; +import type { PlusFeatureWelcome } from '../shared/components/plus-feature-welcome'; import type { DataPointClickEvent } from './chart'; import { TimelineChart } from './chart'; import '../../shared/components/code-icon'; import '../../shared/components/progress'; +import '../../shared/components/button'; +import '../shared/components/plus-feature-welcome'; export class TimelineApp extends App<State> { private _chart: TimelineChart | undefined; @@ -26,7 +27,7 @@ export class TimelineApp extends App<State> { } protected override onInitialize() { - provideVSCodeDesignSystem().register(vsCodeButton(), vsCodeDropdown(), vsCodeOption()); + provideVSCodeDesignSystem().register(vsCodeDropdown(), vsCodeOption()); this.updateState(); } @@ -35,11 +36,11 @@ export class TimelineApp extends App<State> { const disposables = super.onBind?.() ?? []; disposables.push( - DOM.on('[data-action]', 'click', (e, target: HTMLElement) => this.onActionClicked(e, target)), DOM.on(document, 'keydown', (e: KeyboardEvent) => this.onKeyDown(e)), DOM.on(document.getElementById('periods')! as HTMLSelectElement, 'change', (e, target) => this.onPeriodChanged(e, target), ), + { dispose: () => this._chart?.dispose() }, ); return disposables; @@ -64,17 +65,6 @@ export class TimelineApp extends App<State> { } } - protected override setState(state: Partial<State>) { - super.setState({ period: state.period, uri: state.uri }); - } - - private onActionClicked(e: MouseEvent, target: HTMLElement) { - const action = target.dataset.action; - if (action?.startsWith('command:')) { - this.sendCommand(ExecuteCommandType, { command: action.slice(8) }); - } - } - private onChartDataPointClicked(e: DataPointClickEvent) { this.sendCommand(OpenDataPointCommandType, e); } @@ -96,69 +86,39 @@ export class TimelineApp extends App<State> { } private updateState(): void { - const $overlay = document.getElementById('overlay') as HTMLDivElement; - $overlay.classList.toggle('hidden', this.state.access.allowed === true); - - const $slot = document.getElementById('overlay-slot') as HTMLDivElement; - - if (this.state.access.allowed === false) { - const { current: subscription, required } = this.state.access.subscription; - - const requiresPublic = required === SubscriptionPlanId.FreePlus; - const options = { visible: { public: requiresPublic, private: !requiresPublic } }; - - if (subscription.account?.verified === false) { - DOM.insertTemplate('state:verify-email', $slot, options); - return; - } - - switch (subscription.state) { - case SubscriptionState.Free: - DOM.insertTemplate('state:free', $slot, options); - break; - case SubscriptionState.FreePreviewTrialExpired: - DOM.insertTemplate('state:free-preview-trial-expired', $slot, options); - break; - case SubscriptionState.FreePlusTrialExpired: - DOM.insertTemplate('state:plus-trial-expired', $slot, options); - break; - } - - if (this.state.dataset == null) return; - } else { - $slot.innerHTML = ''; + const $welcome = document.getElementsByTagName('plus-feature-welcome')?.[0] as PlusFeatureWelcome; + if ($welcome != null) { + $welcome.state = this.state.access.subscription.current.state; + $welcome.allowed = this.state.access.allowed === true || this.state.uri == null; } if (this._chart == null) { - this._chart = new TimelineChart('#chart'); + this._chart = new TimelineChart('#chart', this.placement); this._chart.onDidClickDataPoint(this.onChartDataPointClicked, this); } let { title, sha } = this.state; let description = ''; - const index = title.lastIndexOf('/'); - if (index >= 0) { - const name = title.substring(index + 1); - description = title.substring(0, index); - title = name; + if (title != null) { + const index = title.lastIndexOf('/'); + if (index >= 0) { + const name = title.substring(index + 1); + description = title.substring(0, index); + title = name; + } + } else if (this.placement === 'editor' && this.state.dataset == null && !this.state.access.allowed) { + title = 'index.ts'; + description = 'src/app'; } - function updateBoundData( - key: string, - value: string | undefined, - options?: { hideIfEmpty?: boolean; html?: boolean }, - ) { + function updateBoundData(key: string, value: string | undefined, options?: { html?: boolean }) { const $el = document.querySelector(`[data-bind="${key}"]`); if ($el != null) { - const empty = value == null || value.length === 0; - if (options?.hideIfEmpty) { - $el.classList.toggle('hidden', empty); - } - if (options?.html && !empty) { - $el.innerHTML = value; + if (options?.html) { + $el.innerHTML = value ?? ''; } else { - $el.textContent = String(value) || GlyphChars.Space; + $el.textContent = value ?? ''; } } } @@ -171,7 +131,6 @@ export class TimelineApp extends App<State> { ? /*html*/ `<code-icon icon="git-commit" size="16"></code-icon><span class="sha">${sha}</span>` : undefined, { - hideIfEmpty: true, html: true, }, ); diff --git a/src/webviews/apps/shared/components/button.ts b/src/webviews/apps/shared/components/button.ts new file mode 100644 index 0000000..e9112a4 --- /dev/null +++ b/src/webviews/apps/shared/components/button.ts @@ -0,0 +1,106 @@ +import { css, html, LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { focusOutline } from './styles/lit/a11y.css'; +import { elementBase } from './styles/lit/base.css'; + +@customElement('gk-button') +export class GKButton extends LitElement { + static override styles = [ + elementBase, + css` + :host { + --button-foreground: var(--vscode-button-foreground); + --button-background: var(--vscode-button-background); + --button-hover-background: var(--vscode-button-hoverBackground); + --button-padding: 0.4rem 1.1rem; + --button-border: var(--vscode-button-border, transparent); + + display: inline-block; + border: none; + font-family: inherit; + font-size: inherit; + line-height: 1.694; + text-align: center; + text-decoration: none; + user-select: none; + background: var(--button-background); + color: var(--button-foreground); + cursor: pointer; + border: 1px solid var(--button-border); + border-radius: var(--gk-action-radius); + } + + :host(:not([href])) { + padding: var(--button-padding); + } + + :host([href]) > a { + display: inline-block; + padding: var(--button-padding); + + color: inherit; + text-decoration: none; + + width: 100%; + height: 100%; + } + + :host(:hover) { + background: var(--button-hover-background); + } + + :host(:focus) { + ${focusOutline} + } + + :host([full]) { + width: 100%; + } + + :host([appearance='secondary']) { + --button-background: var(--vscode-button-secondaryBackground); + --button-foreground: var(--vscode-button-secondaryForeground); + --button-hover-background: var(--vscode-button-secondaryHoverBackground); + } + + :host([appearance='toolbar']) { + --button-background: transparent; + --button-foreground: var(--vscode-foreground); + --button-hover-background: var(--vscode-toolbar-hoverBackground); + --button-padding: 0.45rem 0.4rem 0.14rem 0.4rem; + line-height: 1.64; + } + + :host([appearance='alert']) { + --button-background: transparent; + --button-border: var(--color-alert-infoBorder); + --button-foreground: var(--color-button-foreground); + --button-hover-background: var(--color-alert-infoBorder); + --button-padding: 0.4rem; + line-height: 1.64; + } + `, + ]; + + @property({ type: Boolean, reflect: true }) + full = false; + + @property() + href?: string; + + @property({ reflect: true }) + override get role() { + return this.href ? 'link' : 'button'; + } + + @property() + appearance?: string; + + @property({ type: Number, reflect: true }) + override tabIndex = 0; + + override render() { + const main = html`<slot></slot>`; + return this.href != null ? html`<a href=${this.href}>${main}</a>` : main; + } +} diff --git a/src/webviews/apps/shared/components/code-icon.ts b/src/webviews/apps/shared/components/code-icon.ts index 7edf875..f469001 100644 --- a/src/webviews/apps/shared/components/code-icon.ts +++ b/src/webviews/apps/shared/components/code-icon.ts @@ -1,1551 +1,1646 @@ -import { attr, css, customElement, FASTElement } from '@microsoft/fast-element'; +import { css, LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; -const styles = css` - :host { - font: normal normal normal var(--code-icon-size, 16px) / 1 codicon; - display: inline-block; - text-decoration: none; - text-rendering: auto; - text-align: center; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - color: inherit; - vertical-align: text-bottom; - letter-spacing: normal; - } +@customElement('code-icon') +export class CodeIcon extends LitElement { + static override styles = css` + :host { + font: normal normal normal var(--code-icon-size, 16px) / 1 codicon; + display: inline-block; + text-decoration: none; + text-rendering: auto; + text-align: center; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + color: inherit; + vertical-align: text-bottom; + letter-spacing: normal; + } - :host([icon='add']):before { - content: '\\ea60'; - } - :host([icon='plus']):before { - content: '\\ea60'; - } - :host([icon='gist-new']):before { - content: '\\ea60'; - } - :host([icon='repo-create']):before { - content: '\\ea60'; - } - :host([icon='lightbulb']):before { - content: '\\ea61'; - } - :host([icon='light-bulb']):before { - content: '\\ea61'; - } - :host([icon='repo']):before { - content: '\\ea62'; - } - :host([icon='repo-delete']):before { - content: '\\ea62'; - } - :host([icon='gist-fork']):before { - content: '\\ea63'; - } - :host([icon='repo-forked']):before { - content: '\\ea63'; - } - :host([icon='git-pull-request']):before { - content: '\\ea64'; - } - :host([icon='git-pull-request-abandoned']):before { - content: '\\ea64'; - } - :host([icon='record-keys']):before { - content: '\\ea65'; - } - :host([icon='keyboard']):before { - content: '\\ea65'; - } - :host([icon='tag']):before { - content: '\\ea66'; - } - :host([icon='tag-add']):before { - content: '\\ea66'; - } - :host([icon='tag-remove']):before { - content: '\\ea66'; - } - :host([icon='person']):before { - content: '\\ea67'; - } - :host([icon='person-follow']):before { - content: '\\ea67'; - } - :host([icon='person-outline']):before { - content: '\\ea67'; - } - :host([icon='person-filled']):before { - content: '\\ea67'; - } - :host([icon='git-branch']):before { - content: '\\ea68'; - } - :host([icon='git-branch-create']):before { - content: '\\ea68'; - } - :host([icon='git-branch-delete']):before { - content: '\\ea68'; - } - :host([icon='source-control']):before { - content: '\\ea68'; - } - :host([icon='mirror']):before { - content: '\\ea69'; - } - :host([icon='mirror-public']):before { - content: '\\ea69'; - } - :host([icon='star']):before { - content: '\\ea6a'; - } - :host([icon='star-add']):before { - content: '\\ea6a'; - } - :host([icon='star-delete']):before { - content: '\\ea6a'; - } - :host([icon='star-empty']):before { - content: '\\ea6a'; - } - :host([icon='comment']):before { - content: '\\ea6b'; - } - :host([icon='comment-add']):before { - content: '\\ea6b'; - } - :host([icon='alert']):before { - content: '\\ea6c'; - } - :host([icon='warning']):before { - content: '\\ea6c'; - } - :host([icon='search']):before { - content: '\\ea6d'; - } - :host([icon='search-save']):before { - content: '\\ea6d'; - } - :host([icon='log-out']):before { - content: '\\ea6e'; - } - :host([icon='sign-out']):before { - content: '\\ea6e'; - } - :host([icon='log-in']):before { - content: '\\ea6f'; - } - :host([icon='sign-in']):before { - content: '\\ea6f'; - } - :host([icon='eye']):before { - content: '\\ea70'; - } - :host([icon='eye-unwatch']):before { - content: '\\ea70'; - } - :host([icon='eye-watch']):before { - content: '\\ea70'; - } - :host([icon='circle-filled']):before { - content: '\\ea71'; - } - :host([icon='primitive-dot']):before { - content: '\\ea71'; - } - :host([icon='close-dirty']):before { - content: '\\ea71'; - } - :host([icon='debug-breakpoint']):before { - content: '\\ea71'; - } - :host([icon='debug-breakpoint-disabled']):before { - content: '\\ea71'; - } - :host([icon='debug-hint']):before { - content: '\\ea71'; - } - :host([icon='primitive-square']):before { - content: '\\ea72'; - } - :host([icon='edit']):before { - content: '\\ea73'; - } - :host([icon='pencil']):before { - content: '\\ea73'; - } - :host([icon='info']):before { - content: '\\ea74'; - } - :host([icon='issue-opened']):before { - content: '\\ea74'; - } - :host([icon='gist-private']):before { - content: '\\ea75'; - } - :host([icon='git-fork-private']):before { - content: '\\ea75'; - } - :host([icon='lock']):before { - content: '\\ea75'; - } - :host([icon='mirror-private']):before { - content: '\\ea75'; - } - :host([icon='close']):before { - content: '\\ea76'; - } - :host([icon='remove-close']):before { - content: '\\ea76'; - } - :host([icon='x']):before { - content: '\\ea76'; - } - :host([icon='repo-sync']):before { - content: '\\ea77'; - } - :host([icon='sync']):before { - content: '\\ea77'; - } - :host([icon='clone']):before { - content: '\\ea78'; - } - :host([icon='desktop-download']):before { - content: '\\ea78'; - } - :host([icon='beaker']):before { - content: '\\ea79'; - } - :host([icon='microscope']):before { - content: '\\ea79'; - } - :host([icon='vm']):before { - content: '\\ea7a'; - } - :host([icon='device-desktop']):before { - content: '\\ea7a'; - } - :host([icon='file']):before { - content: '\\ea7b'; - } - :host([icon='file-text']):before { - content: '\\ea7b'; - } - :host([icon='more']):before { - content: '\\ea7c'; - } - :host([icon='ellipsis']):before { - content: '\\ea7c'; - } - :host([icon='kebab-horizontal']):before { - content: '\\ea7c'; - } - :host([icon='mail-reply']):before { - content: '\\ea7d'; - } - :host([icon='reply']):before { - content: '\\ea7d'; - } - :host([icon='organization']):before { - content: '\\ea7e'; - } - :host([icon='organization-filled']):before { - content: '\\ea7e'; - } - :host([icon='organization-outline']):before { - content: '\\ea7e'; - } - :host([icon='new-file']):before { - content: '\\ea7f'; - } - :host([icon='file-add']):before { - content: '\\ea7f'; - } - :host([icon='new-folder']):before { - content: '\\ea80'; - } - :host([icon='file-directory-create']):before { - content: '\\ea80'; - } - :host([icon='trash']):before { - content: '\\ea81'; - } - :host([icon='trashcan']):before { - content: '\\ea81'; - } - :host([icon='history']):before { - content: '\\ea82'; - } - :host([icon='clock']):before { - content: '\\ea82'; - } - :host([icon='folder']):before { - content: '\\ea83'; - } - :host([icon='file-directory']):before { - content: '\\ea83'; - } - :host([icon='symbol-folder']):before { - content: '\\ea83'; - } - :host([icon='logo-github']):before { - content: '\\ea84'; - } - :host([icon='mark-github']):before { - content: '\\ea84'; - } - :host([icon='github']):before { - content: '\\ea84'; - } - :host([icon='terminal']):before { - content: '\\ea85'; - } - :host([icon='console']):before { - content: '\\ea85'; - } - :host([icon='repl']):before { - content: '\\ea85'; - } - :host([icon='zap']):before { - content: '\\ea86'; - } - :host([icon='symbol-event']):before { - content: '\\ea86'; - } - :host([icon='error']):before { - content: '\\ea87'; - } - :host([icon='stop']):before { - content: '\\ea87'; - } - :host([icon='variable']):before { - content: '\\ea88'; - } - :host([icon='symbol-variable']):before { - content: '\\ea88'; - } - :host([icon='array']):before { - content: '\\ea8a'; - } - :host([icon='symbol-array']):before { - content: '\\ea8a'; - } - :host([icon='symbol-module']):before { - content: '\\ea8b'; - } - :host([icon='symbol-package']):before { - content: '\\ea8b'; - } - :host([icon='symbol-namespace']):before { - content: '\\ea8b'; - } - :host([icon='symbol-object']):before { - content: '\\ea8b'; - } - :host([icon='symbol-method']):before { - content: '\\ea8c'; - } - :host([icon='symbol-function']):before { - content: '\\ea8c'; - } - :host([icon='symbol-constructor']):before { - content: '\\ea8c'; - } - :host([icon='symbol-boolean']):before { - content: '\\ea8f'; - } - :host([icon='symbol-null']):before { - content: '\\ea8f'; - } - :host([icon='symbol-numeric']):before { - content: '\\ea90'; - } - :host([icon='symbol-number']):before { - content: '\\ea90'; - } - :host([icon='symbol-structure']):before { - content: '\\ea91'; - } - :host([icon='symbol-struct']):before { - content: '\\ea91'; - } - :host([icon='symbol-parameter']):before { - content: '\\ea92'; - } - :host([icon='symbol-type-parameter']):before { - content: '\\ea92'; - } - :host([icon='symbol-key']):before { - content: '\\ea93'; - } - :host([icon='symbol-text']):before { - content: '\\ea93'; - } - :host([icon='symbol-reference']):before { - content: '\\ea94'; - } - :host([icon='go-to-file']):before { - content: '\\ea94'; - } - :host([icon='symbol-enum']):before { - content: '\\ea95'; - } - :host([icon='symbol-value']):before { - content: '\\ea95'; - } - :host([icon='symbol-ruler']):before { - content: '\\ea96'; - } - :host([icon='symbol-unit']):before { - content: '\\ea96'; - } - :host([icon='activate-breakpoints']):before { - content: '\\ea97'; - } - :host([icon='archive']):before { - content: '\\ea98'; - } - :host([icon='arrow-both']):before { - content: '\\ea99'; - } - :host([icon='arrow-down']):before { - content: '\\ea9a'; - } - :host([icon='arrow-left']):before { - content: '\\ea9b'; - } - :host([icon='arrow-right']):before { - content: '\\ea9c'; - } - :host([icon='arrow-small-down']):before { - content: '\\ea9d'; - } - :host([icon='arrow-small-left']):before { - content: '\\ea9e'; - } - :host([icon='arrow-small-right']):before { - content: '\\ea9f'; - } - :host([icon='arrow-small-up']):before { - content: '\\eaa0'; - } - :host([icon='arrow-up']):before { - content: '\\eaa1'; - } - :host([icon='bell']):before { - content: '\\eaa2'; - } - :host([icon='bold']):before { - content: '\\eaa3'; - } - :host([icon='book']):before { - content: '\\eaa4'; - } - :host([icon='bookmark']):before { - content: '\\eaa5'; - } - :host([icon='debug-breakpoint-conditional-unverified']):before { - content: '\\eaa6'; - } - :host([icon='debug-breakpoint-conditional']):before { - content: '\\eaa7'; - } - :host([icon='debug-breakpoint-conditional-disabled']):before { - content: '\\eaa7'; - } - :host([icon='debug-breakpoint-data-unverified']):before { - content: '\\eaa8'; - } - :host([icon='debug-breakpoint-data']):before { - content: '\\eaa9'; - } - :host([icon='debug-breakpoint-data-disabled']):before { - content: '\\eaa9'; - } - :host([icon='debug-breakpoint-log-unverified']):before { - content: '\\eaaa'; - } - :host([icon='debug-breakpoint-log']):before { - content: '\\eaab'; - } - :host([icon='debug-breakpoint-log-disabled']):before { - content: '\\eaab'; - } - :host([icon='briefcase']):before { - content: '\\eaac'; - } - :host([icon='broadcast']):before { - content: '\\eaad'; - } - :host([icon='browser']):before { - content: '\\eaae'; - } - :host([icon='bug']):before { - content: '\\eaaf'; - } - :host([icon='calendar']):before { - content: '\\eab0'; - } - :host([icon='case-sensitive']):before { - content: '\\eab1'; - } - :host([icon='check']):before { - content: '\\eab2'; - } - :host([icon='checklist']):before { - content: '\\eab3'; - } - :host([icon='chevron-down']):before { - content: '\\eab4'; - } - :host([icon='chevron-left']):before { - content: '\\eab5'; - } - :host([icon='chevron-right']):before { - content: '\\eab6'; - } - :host([icon='chevron-up']):before { - content: '\\eab7'; - } - :host([icon='chrome-close']):before { - content: '\\eab8'; - } - :host([icon='chrome-maximize']):before { - content: '\\eab9'; - } - :host([icon='chrome-minimize']):before { - content: '\\eaba'; - } - :host([icon='chrome-restore']):before { - content: '\\eabb'; - } - :host([icon='circle-outline']):before { - content: '\\eabc'; - } - :host([icon='debug-breakpoint-unverified']):before { - content: '\\eabc'; - } - :host([icon='circle-slash']):before { - content: '\\eabd'; - } - :host([icon='circuit-board']):before { - content: '\\eabe'; - } - :host([icon='clear-all']):before { - content: '\\eabf'; - } - :host([icon='clippy']):before { - content: '\\eac0'; - } - :host([icon='close-all']):before { - content: '\\eac1'; - } - :host([icon='cloud-download']):before { - content: '\\eac2'; - } - :host([icon='cloud-upload']):before { - content: '\\eac3'; - } - :host([icon='code']):before { - content: '\\eac4'; - } - :host([icon='collapse-all']):before { - content: '\\eac5'; - } - :host([icon='color-mode']):before { - content: '\\eac6'; - } - :host([icon='comment-discussion']):before { - content: '\\eac7'; - } - :host([icon='credit-card']):before { - content: '\\eac9'; - } - :host([icon='dash']):before { - content: '\\eacc'; - } - :host([icon='dashboard']):before { - content: '\\eacd'; - } - :host([icon='database']):before { - content: '\\eace'; - } - :host([icon='debug-continue']):before { - content: '\\eacf'; - } - :host([icon='debug-disconnect']):before { - content: '\\ead0'; - } - :host([icon='debug-pause']):before { - content: '\\ead1'; - } - :host([icon='debug-restart']):before { - content: '\\ead2'; - } - :host([icon='debug-start']):before { - content: '\\ead3'; - } - :host([icon='debug-step-into']):before { - content: '\\ead4'; - } - :host([icon='debug-step-out']):before { - content: '\\ead5'; - } - :host([icon='debug-step-over']):before { - content: '\\ead6'; - } - :host([icon='debug-stop']):before { - content: '\\ead7'; - } - :host([icon='debug']):before { - content: '\\ead8'; - } - :host([icon='device-camera-video']):before { - content: '\\ead9'; - } - :host([icon='device-camera']):before { - content: '\\eada'; - } - :host([icon='device-mobile']):before { - content: '\\eadb'; - } - :host([icon='diff-added']):before { - content: '\\eadc'; - } - :host([icon='diff-ignored']):before { - content: '\\eadd'; - } - :host([icon='diff-modified']):before { - content: '\\eade'; - } - :host([icon='diff-removed']):before { - content: '\\eadf'; - } - :host([icon='diff-renamed']):before { - content: '\\eae0'; - } - :host([icon='diff']):before { - content: '\\eae1'; - } - :host([icon='discard']):before { - content: '\\eae2'; - } - :host([icon='editor-layout']):before { - content: '\\eae3'; - } - :host([icon='empty-window']):before { - content: '\\eae4'; - } - :host([icon='exclude']):before { - content: '\\eae5'; - } - :host([icon='extensions']):before { - content: '\\eae6'; - } - :host([icon='eye-closed']):before { - content: '\\eae7'; - } - :host([icon='file-binary']):before { - content: '\\eae8'; - } - :host([icon='file-code']):before { - content: '\\eae9'; - } - :host([icon='file-media']):before { - content: '\\eaea'; - } - :host([icon='file-pdf']):before { - content: '\\eaeb'; - } - :host([icon='file-submodule']):before { - content: '\\eaec'; - } - :host([icon='file-symlink-directory']):before { - content: '\\eaed'; - } - :host([icon='file-symlink-file']):before { - content: '\\eaee'; - } - :host([icon='file-zip']):before { - content: '\\eaef'; - } - :host([icon='files']):before { - content: '\\eaf0'; - } - :host([icon='filter']):before { - content: '\\eaf1'; - } - :host([icon='flame']):before { - content: '\\eaf2'; - } - :host([icon='fold-down']):before { - content: '\\eaf3'; - } - :host([icon='fold-up']):before { - content: '\\eaf4'; - } - :host([icon='fold']):before { - content: '\\eaf5'; - } - :host([icon='folder-active']):before { - content: '\\eaf6'; - } - :host([icon='folder-opened']):before { - content: '\\eaf7'; - } - :host([icon='gear']):before { - content: '\\eaf8'; - } - :host([icon='gift']):before { - content: '\\eaf9'; - } - :host([icon='gist-secret']):before { - content: '\\eafa'; - } - :host([icon='gist']):before { - content: '\\eafb'; - } - :host([icon='git-commit']):before { - content: '\\eafc'; - } - :host([icon='git-compare']):before { - content: '\\eafd'; - } - :host([icon='compare-changes']):before { - content: '\\eafd'; - } - :host([icon='git-merge']):before { - content: '\\eafe'; - } - :host([icon='github-action']):before { - content: '\\eaff'; - } - :host([icon='github-alt']):before { - content: '\\eb00'; - } - :host([icon='globe']):before { - content: '\\eb01'; - } - :host([icon='grabber']):before { - content: '\\eb02'; - } - :host([icon='graph']):before { - content: '\\eb03'; - } - :host([icon='gripper']):before { - content: '\\eb04'; - } - :host([icon='heart']):before { - content: '\\eb05'; - } - :host([icon='home']):before { - content: '\\eb06'; - } - :host([icon='horizontal-rule']):before { - content: '\\eb07'; - } - :host([icon='hubot']):before { - content: '\\eb08'; - } - :host([icon='inbox']):before { - content: '\\eb09'; - } - :host([icon='issue-reopened']):before { - content: '\\eb0b'; - } - :host([icon='issues']):before { - content: '\\eb0c'; - } - :host([icon='italic']):before { - content: '\\eb0d'; - } - :host([icon='jersey']):before { - content: '\\eb0e'; - } - :host([icon='json']):before { - content: '\\eb0f'; - } - :host([icon='kebab-vertical']):before { - content: '\\eb10'; - } - :host([icon='key']):before { - content: '\\eb11'; - } - :host([icon='law']):before { - content: '\\eb12'; - } - :host([icon='lightbulb-autofix']):before { - content: '\\eb13'; - } - :host([icon='link-external']):before { - content: '\\eb14'; - } - :host([icon='link']):before { - content: '\\eb15'; - } - :host([icon='list-ordered']):before { - content: '\\eb16'; - } - :host([icon='list-unordered']):before { - content: '\\eb17'; - } - :host([icon='live-share']):before { - content: '\\eb18'; - } - :host([icon='loading']):before { - content: '\\eb19'; - } - :host([icon='location']):before { - content: '\\eb1a'; - } - :host([icon='mail-read']):before { - content: '\\eb1b'; - } - :host([icon='mail']):before { - content: '\\eb1c'; - } - :host([icon='markdown']):before { - content: '\\eb1d'; - } - :host([icon='megaphone']):before { - content: '\\eb1e'; - } - :host([icon='mention']):before { - content: '\\eb1f'; - } - :host([icon='milestone']):before { - content: '\\eb20'; - } - :host([icon='mortar-board']):before { - content: '\\eb21'; - } - :host([icon='move']):before { - content: '\\eb22'; - } - :host([icon='multiple-windows']):before { - content: '\\eb23'; - } - :host([icon='mute']):before { - content: '\\eb24'; - } - :host([icon='no-newline']):before { - content: '\\eb25'; - } - :host([icon='note']):before { - content: '\\eb26'; - } - :host([icon='octoface']):before { - content: '\\eb27'; - } - :host([icon='open-preview']):before { - content: '\\eb28'; - } - :host([icon='package']):before { - content: '\\eb29'; - } - :host([icon='paintcan']):before { - content: '\\eb2a'; - } - :host([icon='pin']):before { - content: '\\eb2b'; - } - :host([icon='play']):before { - content: '\\eb2c'; - } - :host([icon='run']):before { - content: '\\eb2c'; - } - :host([icon='plug']):before { - content: '\\eb2d'; - } - :host([icon='preserve-case']):before { - content: '\\eb2e'; - } - :host([icon='preview']):before { - content: '\\eb2f'; - } - :host([icon='project']):before { - content: '\\eb30'; - } - :host([icon='pulse']):before { - content: '\\eb31'; - } - :host([icon='question']):before { - content: '\\eb32'; - } - :host([icon='quote']):before { - content: '\\eb33'; - } - :host([icon='radio-tower']):before { - content: '\\eb34'; - } - :host([icon='reactions']):before { - content: '\\eb35'; - } - :host([icon='references']):before { - content: '\\eb36'; - } - :host([icon='refresh']):before { - content: '\\eb37'; - } - :host([icon='regex']):before { - content: '\\eb38'; - } - :host([icon='remote-explorer']):before { - content: '\\eb39'; - } - :host([icon='remote']):before { - content: '\\eb3a'; - } - :host([icon='remove']):before { - content: '\\eb3b'; - } - :host([icon='replace-all']):before { - content: '\\eb3c'; - } - :host([icon='replace']):before { - content: '\\eb3d'; - } - :host([icon='repo-clone']):before { - content: '\\eb3e'; - } - :host([icon='repo-force-push']):before { - content: '\\eb3f'; - } - :host([icon='repo-pull']):before { - content: '\\eb40'; - } - :host([icon='repo-push']):before { - content: '\\eb41'; - } - :host([icon='report']):before { - content: '\\eb42'; - } - :host([icon='request-changes']):before { - content: '\\eb43'; - } - :host([icon='rocket']):before { - content: '\\eb44'; - } - :host([icon='root-folder-opened']):before { - content: '\\eb45'; - } - :host([icon='root-folder']):before { - content: '\\eb46'; - } - :host([icon='rss']):before { - content: '\\eb47'; - } - :host([icon='ruby']):before { - content: '\\eb48'; - } - :host([icon='save-all']):before { - content: '\\eb49'; - } - :host([icon='save-as']):before { - content: '\\eb4a'; - } - :host([icon='save']):before { - content: '\\eb4b'; - } - :host([icon='screen-full']):before { - content: '\\eb4c'; - } - :host([icon='screen-normal']):before { - content: '\\eb4d'; - } - :host([icon='search-stop']):before { - content: '\\eb4e'; - } - :host([icon='server']):before { - content: '\\eb50'; - } - :host([icon='settings-gear']):before { - content: '\\eb51'; - } - :host([icon='settings']):before { - content: '\\eb52'; - } - :host([icon='shield']):before { - content: '\\eb53'; - } - :host([icon='smiley']):before { - content: '\\eb54'; - } - :host([icon='sort-precedence']):before { - content: '\\eb55'; - } - :host([icon='split-horizontal']):before { - content: '\\eb56'; - } - :host([icon='split-vertical']):before { - content: '\\eb57'; - } - :host([icon='squirrel']):before { - content: '\\eb58'; - } - :host([icon='star-full']):before { - content: '\\eb59'; - } - :host([icon='star-half']):before { - content: '\\eb5a'; - } - :host([icon='symbol-class']):before { - content: '\\eb5b'; - } - :host([icon='symbol-color']):before { - content: '\\eb5c'; - } - :host([icon='symbol-constant']):before { - content: '\\eb5d'; - } - :host([icon='symbol-enum-member']):before { - content: '\\eb5e'; - } - :host([icon='symbol-field']):before { - content: '\\eb5f'; - } - :host([icon='symbol-file']):before { - content: '\\eb60'; - } - :host([icon='symbol-interface']):before { - content: '\\eb61'; - } - :host([icon='symbol-keyword']):before { - content: '\\eb62'; - } - :host([icon='symbol-misc']):before { - content: '\\eb63'; - } - :host([icon='symbol-operator']):before { - content: '\\eb64'; - } - :host([icon='symbol-property']):before { - content: '\\eb65'; - } - :host([icon='wrench']):before { - content: '\\eb65'; - } - :host([icon='wrench-subaction']):before { - content: '\\eb65'; - } - :host([icon='symbol-snippet']):before { - content: '\\eb66'; - } - :host([icon='tasklist']):before { - content: '\\eb67'; - } - :host([icon='telescope']):before { - content: '\\eb68'; - } - :host([icon='text-size']):before { - content: '\\eb69'; - } - :host([icon='three-bars']):before { - content: '\\eb6a'; - } - :host([icon='thumbsdown']):before { - content: '\\eb6b'; - } - :host([icon='thumbsup']):before { - content: '\\eb6c'; - } - :host([icon='tools']):before { - content: '\\eb6d'; - } - :host([icon='triangle-down']):before { - content: '\\eb6e'; - } - :host([icon='triangle-left']):before { - content: '\\eb6f'; - } - :host([icon='triangle-right']):before { - content: '\\eb70'; - } - :host([icon='triangle-up']):before { - content: '\\eb71'; - } - :host([icon='twitter']):before { - content: '\\eb72'; - } - :host([icon='unfold']):before { - content: '\\eb73'; - } - :host([icon='unlock']):before { - content: '\\eb74'; - } - :host([icon='unmute']):before { - content: '\\eb75'; - } - :host([icon='unverified']):before { - content: '\\eb76'; - } - :host([icon='verified']):before { - content: '\\eb77'; - } - :host([icon='versions']):before { - content: '\\eb78'; - } - :host([icon='vm-active']):before { - content: '\\eb79'; - } - :host([icon='vm-outline']):before { - content: '\\eb7a'; - } - :host([icon='vm-running']):before { - content: '\\eb7b'; - } - :host([icon='watch']):before { - content: '\\eb7c'; - } - :host([icon='whitespace']):before { - content: '\\eb7d'; - } - :host([icon='whole-word']):before { - content: '\\eb7e'; - } - :host([icon='window']):before { - content: '\\eb7f'; - } - :host([icon='word-wrap']):before { - content: '\\eb80'; - } - :host([icon='zoom-in']):before { - content: '\\eb81'; - } - :host([icon='zoom-out']):before { - content: '\\eb82'; - } - :host([icon='list-filter']):before { - content: '\\eb83'; - } - :host([icon='list-flat']):before { - content: '\\eb84'; - } - :host([icon='list-selection']):before { - content: '\\eb85'; - } - :host([icon='selection']):before { - content: '\\eb85'; - } - :host([icon='list-tree']):before { - content: '\\eb86'; - } - :host([icon='debug-breakpoint-function-unverified']):before { - content: '\\eb87'; - } - :host([icon='debug-breakpoint-function']):before { - content: '\\eb88'; - } - :host([icon='debug-breakpoint-function-disabled']):before { - content: '\\eb88'; - } - :host([icon='debug-stackframe-active']):before { - content: '\\eb89'; - } - :host([icon='debug-stackframe-dot']):before { - content: '\\eb8a'; - } - :host([icon='debug-stackframe']):before { - content: '\\eb8b'; - } - :host([icon='debug-stackframe-focused']):before { - content: '\\eb8b'; - } - :host([icon='debug-breakpoint-unsupported']):before { - content: '\\eb8c'; - } - :host([icon='symbol-string']):before { - content: '\\eb8d'; - } - :host([icon='debug-reverse-continue']):before { - content: '\\eb8e'; - } - :host([icon='debug-step-back']):before { - content: '\\eb8f'; - } - :host([icon='debug-restart-frame']):before { - content: '\\eb90'; - } - :host([icon='debug-alt']):before { - content: '\\eb91'; - } - :host([icon='call-incoming']):before { - content: '\\eb92'; - } - :host([icon='call-outgoing']):before { - content: '\\eb93'; - } - :host([icon='menu']):before { - content: '\\eb94'; - } - :host([icon='expand-all']):before { - content: '\\eb95'; - } - :host([icon='feedback']):before { - content: '\\eb96'; - } - :host([icon='group-by-ref-type']):before { - content: '\\eb97'; - } - :host([icon='ungroup-by-ref-type']):before { - content: '\\eb98'; - } - :host([icon='account']):before { - content: '\\eb99'; - } - :host([icon='bell-dot']):before { - content: '\\eb9a'; - } - :host([icon='debug-console']):before { - content: '\\eb9b'; - } - :host([icon='library']):before { - content: '\\eb9c'; - } - :host([icon='output']):before { - content: '\\eb9d'; - } - :host([icon='run-all']):before { - content: '\\eb9e'; - } - :host([icon='sync-ignored']):before { - content: '\\eb9f'; - } - :host([icon='pinned']):before { - content: '\\eba0'; - } - :host([icon='github-inverted']):before { - content: '\\eba1'; - } - :host([icon='server-process']):before { - content: '\\eba2'; - } - :host([icon='server-environment']):before { - content: '\\eba3'; - } - :host([icon='pass']):before { - content: '\\eba4'; - } - :host([icon='issue-closed']):before { - content: '\\eba4'; - } - :host([icon='stop-circle']):before { - content: '\\eba5'; - } - :host([icon='play-circle']):before { - content: '\\eba6'; - } - :host([icon='record']):before { - content: '\\eba7'; - } - :host([icon='debug-alt-small']):before { - content: '\\eba8'; - } - :host([icon='vm-connect']):before { - content: '\\eba9'; - } - :host([icon='cloud']):before { - content: '\\ebaa'; - } - :host([icon='merge']):before { - content: '\\ebab'; - } - :host([icon='export']):before { - content: '\\ebac'; - } - :host([icon='graph-left']):before { - content: '\\ebad'; - } - :host([icon='magnet']):before { - content: '\\ebae'; - } - :host([icon='notebook']):before { - content: '\\ebaf'; - } - :host([icon='redo']):before { - content: '\\ebb0'; - } - :host([icon='check-all']):before { - content: '\\ebb1'; - } - :host([icon='pinned-dirty']):before { - content: '\\ebb2'; - } - :host([icon='pass-filled']):before { - content: '\\ebb3'; - } - :host([icon='circle-large-filled']):before { - content: '\\ebb4'; - } - :host([icon='circle-large-outline']):before { - content: '\\ebb5'; - } - :host([icon='combine']):before { - content: '\\ebb6'; - } - :host([icon='gather']):before { - content: '\\ebb6'; - } - :host([icon='table']):before { - content: '\\ebb7'; - } - :host([icon='variable-group']):before { - content: '\\ebb8'; - } - :host([icon='type-hierarchy']):before { - content: '\\ebb9'; - } - :host([icon='type-hierarchy-sub']):before { - content: '\\ebba'; - } - :host([icon='type-hierarchy-super']):before { - content: '\\ebbb'; - } - :host([icon='git-pull-request-create']):before { - content: '\\ebbc'; - } - :host([icon='run-above']):before { - content: '\\ebbd'; - } - :host([icon='run-below']):before { - content: '\\ebbe'; - } - :host([icon='notebook-template']):before { - content: '\\ebbf'; - } - :host([icon='debug-rerun']):before { - content: '\\ebc0'; - } - :host([icon='workspace-trusted']):before { - content: '\\ebc1'; - } - :host([icon='workspace-untrusted']):before { - content: '\\ebc2'; - } - :host([icon='workspace-unknown']):before { - content: '\\ebc3'; - } - :host([icon='terminal-cmd']):before { - content: '\\ebc4'; - } - :host([icon='terminal-debian']):before { - content: '\\ebc5'; - } - :host([icon='terminal-linux']):before { - content: '\\ebc6'; - } - :host([icon='terminal-powershell']):before { - content: '\\ebc7'; - } - :host([icon='terminal-tmux']):before { - content: '\\ebc8'; - } - :host([icon='terminal-ubuntu']):before { - content: '\\ebc9'; - } - :host([icon='terminal-bash']):before { - content: '\\ebca'; - } - :host([icon='arrow-swap']):before { - content: '\\ebcb'; - } - :host([icon='copy']):before { - content: '\\ebcc'; - } - :host([icon='person-add']):before { - content: '\\ebcd'; - } - :host([icon='filter-filled']):before { - content: '\\ebce'; - } - :host([icon='wand']):before { - content: '\\ebcf'; - } - :host([icon='debug-line-by-line']):before { - content: '\\ebd0'; - } - :host([icon='inspect']):before { - content: '\\ebd1'; - } - :host([icon='layers']):before { - content: '\\ebd2'; - } - :host([icon='layers-dot']):before { - content: '\\ebd3'; - } - :host([icon='layers-active']):before { - content: '\\ebd4'; - } - :host([icon='compass']):before { - content: '\\ebd5'; - } - :host([icon='compass-dot']):before { - content: '\\ebd6'; - } - :host([icon='compass-active']):before { - content: '\\ebd7'; - } - :host([icon='azure']):before { - content: '\\ebd8'; - } - :host([icon='issue-draft']):before { - content: '\\ebd9'; - } - :host([icon='git-pull-request-closed']):before { - content: '\\ebda'; - } - :host([icon='git-pull-request-draft']):before { - content: '\\ebdb'; - } - :host([icon='debug-all']):before { - content: '\\ebdc'; - } - :host([icon='debug-coverage']):before { - content: '\\ebdd'; - } - :host([icon='run-errors']):before { - content: '\\ebde'; - } - :host([icon='folder-library']):before { - content: '\\ebdf'; - } - :host([icon='debug-continue-small']):before { - content: '\\ebe0'; - } - :host([icon='beaker-stop']):before { - content: '\\ebe1'; - } - :host([icon='graph-line']):before { - content: '\\ebe2'; - } - :host([icon='graph-scatter']):before { - content: '\\ebe3'; - } - :host([icon='pie-chart']):before { - content: '\\ebe4'; - } - :host([icon='bracket']):before { - content: '\\eb0f'; - } - :host([icon='bracket-dot']):before { - content: '\\ebe5'; - } - :host([icon='bracket-error']):before { - content: '\\ebe6'; - } - :host([icon='lock-small']):before { - content: '\\ebe7'; - } - :host([icon='azure-devops']):before { - content: '\\ebe8'; - } - :host([icon='verified-filled']):before { - content: '\\ebe9'; - } - :host([icon='newline']):before { - content: '\\ebea'; - } - :host([icon='layout']):before { - content: '\\ebeb'; - } - :host([icon='layout-activitybar-left']):before { - content: '\\ebec'; - } - :host([icon='layout-activitybar-right']):before { - content: '\\ebed'; - } - :host([icon='layout-panel-left']):before { - content: '\\ebee'; - } - :host([icon='layout-panel-center']):before { - content: '\\ebef'; - } - :host([icon='layout-panel-justify']):before { - content: '\\ebf0'; - } - :host([icon='layout-panel-right']):before { - content: '\\ebf1'; - } - :host([icon='layout-panel']):before { - content: '\\ebf2'; - } - :host([icon='layout-sidebar-left']):before { - content: '\\ebf3'; - } - :host([icon='layout-sidebar-right']):before { - content: '\\ebf4'; - } - :host([icon='layout-statusbar']):before { - content: '\\ebf5'; - } - :host([icon='layout-menubar']):before { - content: '\\ebf6'; - } - :host([icon='layout-centered']):before { - content: '\\ebf7'; - } - :host([icon='target']):before { - content: '\\ebf8'; - } - :host([icon^='gl-']) { - font-family: 'glicons'; - } - :host([icon='gl-pinned-filled']):before { - content: '\\f11c'; - /* TODO: see relative positioning needed in every use-case */ - position: relative; - left: 1px; - } - :host([icon='gl-graph']):before { - content: '\\f102'; - } - :host([icon='gl-list-auto']):before { - content: '\\f11a'; - } - :host([icon='gl-clock']):before { - content: '\\f11d'; - } - :host([icon='gl-worktrees-view']):before { - content: '\\f112'; - } - :host([icon='gl-switch']):before { - content: '\\f118'; - } + :host([icon='add']):before { + content: '\\ea60'; + } + :host([icon='plus']):before { + content: '\\ea60'; + } + :host([icon='gist-new']):before { + content: '\\ea60'; + } + :host([icon='repo-create']):before { + content: '\\ea60'; + } + :host([icon='lightbulb']):before { + content: '\\ea61'; + } + :host([icon='light-bulb']):before { + content: '\\ea61'; + } + :host([icon='repo']):before { + content: '\\ea62'; + } + :host([icon='repo-delete']):before { + content: '\\ea62'; + } + :host([icon='gist-fork']):before { + content: '\\ea63'; + } + :host([icon='repo-forked']):before { + content: '\\ea63'; + } + :host([icon='git-pull-request']):before { + content: '\\ea64'; + } + :host([icon='git-pull-request-abandoned']):before { + content: '\\ea64'; + } + :host([icon='record-keys']):before { + content: '\\ea65'; + } + :host([icon='keyboard']):before { + content: '\\ea65'; + } + :host([icon='tag']):before { + content: '\\ea66'; + } + :host([icon='tag-add']):before { + content: '\\ea66'; + } + :host([icon='tag-remove']):before { + content: '\\ea66'; + } + :host([icon='person']):before { + content: '\\ea67'; + } + :host([icon='person-follow']):before { + content: '\\ea67'; + } + :host([icon='person-outline']):before { + content: '\\ea67'; + } + :host([icon='person-filled']):before { + content: '\\ea67'; + } + :host([icon='git-branch']):before { + content: '\\ea68'; + } + :host([icon='git-branch-create']):before { + content: '\\ea68'; + } + :host([icon='git-branch-delete']):before { + content: '\\ea68'; + } + :host([icon='source-control']):before { + content: '\\ea68'; + } + :host([icon='mirror']):before { + content: '\\ea69'; + } + :host([icon='mirror-public']):before { + content: '\\ea69'; + } + :host([icon='star']):before { + content: '\\ea6a'; + } + :host([icon='star-add']):before { + content: '\\ea6a'; + } + :host([icon='star-delete']):before { + content: '\\ea6a'; + } + :host([icon='star-empty']):before { + content: '\\ea6a'; + } + :host([icon='comment']):before { + content: '\\ea6b'; + } + :host([icon='comment-add']):before { + content: '\\ea6b'; + } + :host([icon='alert']):before { + content: '\\ea6c'; + } + :host([icon='warning']):before { + content: '\\ea6c'; + } + :host([icon='search']):before { + content: '\\ea6d'; + } + :host([icon='search-save']):before { + content: '\\ea6d'; + } + :host([icon='log-out']):before { + content: '\\ea6e'; + } + :host([icon='sign-out']):before { + content: '\\ea6e'; + } + :host([icon='log-in']):before { + content: '\\ea6f'; + } + :host([icon='sign-in']):before { + content: '\\ea6f'; + } + :host([icon='eye']):before { + content: '\\ea70'; + } + :host([icon='eye-unwatch']):before { + content: '\\ea70'; + } + :host([icon='eye-watch']):before { + content: '\\ea70'; + } + :host([icon='circle-filled']):before { + content: '\\ea71'; + } + :host([icon='primitive-dot']):before { + content: '\\ea71'; + } + :host([icon='close-dirty']):before { + content: '\\ea71'; + } + :host([icon='debug-breakpoint']):before { + content: '\\ea71'; + } + :host([icon='debug-breakpoint-disabled']):before { + content: '\\ea71'; + } + :host([icon='debug-hint']):before { + content: '\\ea71'; + } + :host([icon='primitive-square']):before { + content: '\\ea72'; + } + :host([icon='edit']):before { + content: '\\ea73'; + } + :host([icon='pencil']):before { + content: '\\ea73'; + } + :host([icon='info']):before { + content: '\\ea74'; + } + :host([icon='issue-opened']):before { + content: '\\ea74'; + } + :host([icon='gist-private']):before { + content: '\\ea75'; + } + :host([icon='git-fork-private']):before { + content: '\\ea75'; + } + :host([icon='lock']):before { + content: '\\ea75'; + } + :host([icon='mirror-private']):before { + content: '\\ea75'; + } + :host([icon='close']):before { + content: '\\ea76'; + } + :host([icon='remove-close']):before { + content: '\\ea76'; + } + :host([icon='x']):before { + content: '\\ea76'; + } + :host([icon='repo-sync']):before { + content: '\\ea77'; + } + :host([icon='sync']):before { + content: '\\ea77'; + } + :host([icon='clone']):before { + content: '\\ea78'; + } + :host([icon='desktop-download']):before { + content: '\\ea78'; + } + :host([icon='beaker']):before { + content: '\\ea79'; + } + :host([icon='microscope']):before { + content: '\\ea79'; + } + :host([icon='vm']):before { + content: '\\ea7a'; + } + :host([icon='device-desktop']):before { + content: '\\ea7a'; + } + :host([icon='file']):before { + content: '\\ea7b'; + } + :host([icon='file-text']):before { + content: '\\ea7b'; + } + :host([icon='more']):before { + content: '\\ea7c'; + } + :host([icon='ellipsis']):before { + content: '\\ea7c'; + } + :host([icon='kebab-horizontal']):before { + content: '\\ea7c'; + } + :host([icon='mail-reply']):before { + content: '\\ea7d'; + } + :host([icon='reply']):before { + content: '\\ea7d'; + } + :host([icon='organization']):before { + content: '\\ea7e'; + } + :host([icon='organization-filled']):before { + content: '\\ea7e'; + } + :host([icon='organization-outline']):before { + content: '\\ea7e'; + } + :host([icon='new-file']):before { + content: '\\ea7f'; + } + :host([icon='file-add']):before { + content: '\\ea7f'; + } + :host([icon='new-folder']):before { + content: '\\ea80'; + } + :host([icon='file-directory-create']):before { + content: '\\ea80'; + } + :host([icon='trash']):before { + content: '\\ea81'; + } + :host([icon='trashcan']):before { + content: '\\ea81'; + } + :host([icon='history']):before { + content: '\\ea82'; + } + :host([icon='clock']):before { + content: '\\ea82'; + } + :host([icon='folder']):before { + content: '\\ea83'; + } + :host([icon='file-directory']):before { + content: '\\ea83'; + } + :host([icon='symbol-folder']):before { + content: '\\ea83'; + } + :host([icon='logo-github']):before { + content: '\\ea84'; + } + :host([icon='mark-github']):before { + content: '\\ea84'; + } + :host([icon='github']):before { + content: '\\ea84'; + } + :host([icon='terminal']):before { + content: '\\ea85'; + } + :host([icon='console']):before { + content: '\\ea85'; + } + :host([icon='repl']):before { + content: '\\ea85'; + } + :host([icon='zap']):before { + content: '\\ea86'; + } + :host([icon='symbol-event']):before { + content: '\\ea86'; + } + :host([icon='error']):before { + content: '\\ea87'; + } + :host([icon='stop']):before { + content: '\\ea87'; + } + :host([icon='variable']):before { + content: '\\ea88'; + } + :host([icon='symbol-variable']):before { + content: '\\ea88'; + } + :host([icon='array']):before { + content: '\\ea8a'; + } + :host([icon='symbol-array']):before { + content: '\\ea8a'; + } + :host([icon='symbol-module']):before { + content: '\\ea8b'; + } + :host([icon='symbol-package']):before { + content: '\\ea8b'; + } + :host([icon='symbol-namespace']):before { + content: '\\ea8b'; + } + :host([icon='symbol-object']):before { + content: '\\ea8b'; + } + :host([icon='symbol-method']):before { + content: '\\ea8c'; + } + :host([icon='symbol-function']):before { + content: '\\ea8c'; + } + :host([icon='symbol-constructor']):before { + content: '\\ea8c'; + } + :host([icon='symbol-boolean']):before { + content: '\\ea8f'; + } + :host([icon='symbol-null']):before { + content: '\\ea8f'; + } + :host([icon='symbol-numeric']):before { + content: '\\ea90'; + } + :host([icon='symbol-number']):before { + content: '\\ea90'; + } + :host([icon='symbol-structure']):before { + content: '\\ea91'; + } + :host([icon='symbol-struct']):before { + content: '\\ea91'; + } + :host([icon='symbol-parameter']):before { + content: '\\ea92'; + } + :host([icon='symbol-type-parameter']):before { + content: '\\ea92'; + } + :host([icon='symbol-key']):before { + content: '\\ea93'; + } + :host([icon='symbol-text']):before { + content: '\\ea93'; + } + :host([icon='symbol-reference']):before { + content: '\\ea94'; + } + :host([icon='go-to-file']):before { + content: '\\ea94'; + } + :host([icon='symbol-enum']):before { + content: '\\ea95'; + } + :host([icon='symbol-value']):before { + content: '\\ea95'; + } + :host([icon='symbol-ruler']):before { + content: '\\ea96'; + } + :host([icon='symbol-unit']):before { + content: '\\ea96'; + } + :host([icon='activate-breakpoints']):before { + content: '\\ea97'; + } + :host([icon='archive']):before { + content: '\\ea98'; + } + :host([icon='arrow-both']):before { + content: '\\ea99'; + } + :host([icon='arrow-down']):before { + content: '\\ea9a'; + } + :host([icon='arrow-left']):before { + content: '\\ea9b'; + } + :host([icon='arrow-right']):before { + content: '\\ea9c'; + } + :host([icon='arrow-small-down']):before { + content: '\\ea9d'; + } + :host([icon='arrow-small-left']):before { + content: '\\ea9e'; + } + :host([icon='arrow-small-right']):before { + content: '\\ea9f'; + } + :host([icon='arrow-small-up']):before { + content: '\\eaa0'; + } + :host([icon='arrow-up']):before { + content: '\\eaa1'; + } + :host([icon='bell']):before { + content: '\\eaa2'; + } + :host([icon='bold']):before { + content: '\\eaa3'; + } + :host([icon='book']):before { + content: '\\eaa4'; + } + :host([icon='bookmark']):before { + content: '\\eaa5'; + } + :host([icon='debug-breakpoint-conditional-unverified']):before { + content: '\\eaa6'; + } + :host([icon='debug-breakpoint-conditional']):before { + content: '\\eaa7'; + } + :host([icon='debug-breakpoint-conditional-disabled']):before { + content: '\\eaa7'; + } + :host([icon='debug-breakpoint-data-unverified']):before { + content: '\\eaa8'; + } + :host([icon='debug-breakpoint-data']):before { + content: '\\eaa9'; + } + :host([icon='debug-breakpoint-data-disabled']):before { + content: '\\eaa9'; + } + :host([icon='debug-breakpoint-log-unverified']):before { + content: '\\eaaa'; + } + :host([icon='debug-breakpoint-log']):before { + content: '\\eaab'; + } + :host([icon='debug-breakpoint-log-disabled']):before { + content: '\\eaab'; + } + :host([icon='briefcase']):before { + content: '\\eaac'; + } + :host([icon='broadcast']):before { + content: '\\eaad'; + } + :host([icon='browser']):before { + content: '\\eaae'; + } + :host([icon='bug']):before { + content: '\\eaaf'; + } + :host([icon='calendar']):before { + content: '\\eab0'; + } + :host([icon='case-sensitive']):before { + content: '\\eab1'; + } + :host([icon='check']):before { + content: '\\eab2'; + } + :host([icon='checklist']):before { + content: '\\eab3'; + } + :host([icon='chevron-down']):before { + content: '\\eab4'; + } + :host([icon='chevron-left']):before { + content: '\\eab5'; + } + :host([icon='chevron-right']):before { + content: '\\eab6'; + } + :host([icon='chevron-up']):before { + content: '\\eab7'; + } + :host([icon='chrome-close']):before { + content: '\\eab8'; + } + :host([icon='chrome-maximize']):before { + content: '\\eab9'; + } + :host([icon='chrome-minimize']):before { + content: '\\eaba'; + } + :host([icon='chrome-restore']):before { + content: '\\eabb'; + } + :host([icon='circle-outline']):before { + content: '\\eabc'; + } + :host([icon='debug-breakpoint-unverified']):before { + content: '\\eabc'; + } + :host([icon='circle-slash']):before { + content: '\\eabd'; + } + :host([icon='circuit-board']):before { + content: '\\eabe'; + } + :host([icon='clear-all']):before { + content: '\\eabf'; + } + :host([icon='clippy']):before { + content: '\\eac0'; + } + :host([icon='close-all']):before { + content: '\\eac1'; + } + :host([icon='cloud-download']):before { + content: '\\eac2'; + } + :host([icon='cloud-upload']):before { + content: '\\eac3'; + } + :host([icon='code']):before { + content: '\\eac4'; + } + :host([icon='collapse-all']):before { + content: '\\eac5'; + } + :host([icon='color-mode']):before { + content: '\\eac6'; + } + :host([icon='comment-discussion']):before { + content: '\\eac7'; + } + :host([icon='credit-card']):before { + content: '\\eac9'; + } + :host([icon='dash']):before { + content: '\\eacc'; + } + :host([icon='dashboard']):before { + content: '\\eacd'; + } + :host([icon='database']):before { + content: '\\eace'; + } + :host([icon='debug-continue']):before { + content: '\\eacf'; + } + :host([icon='debug-disconnect']):before { + content: '\\ead0'; + } + :host([icon='debug-pause']):before { + content: '\\ead1'; + } + :host([icon='debug-restart']):before { + content: '\\ead2'; + } + :host([icon='debug-start']):before { + content: '\\ead3'; + } + :host([icon='debug-step-into']):before { + content: '\\ead4'; + } + :host([icon='debug-step-out']):before { + content: '\\ead5'; + } + :host([icon='debug-step-over']):before { + content: '\\ead6'; + } + :host([icon='debug-stop']):before { + content: '\\ead7'; + } + :host([icon='debug']):before { + content: '\\ead8'; + } + :host([icon='device-camera-video']):before { + content: '\\ead9'; + } + :host([icon='device-camera']):before { + content: '\\eada'; + } + :host([icon='device-mobile']):before { + content: '\\eadb'; + } + :host([icon='diff-added']):before { + content: '\\eadc'; + } + :host([icon='diff-ignored']):before { + content: '\\eadd'; + } + :host([icon='diff-modified']):before { + content: '\\eade'; + } + :host([icon='diff-removed']):before { + content: '\\eadf'; + } + :host([icon='diff-renamed']):before { + content: '\\eae0'; + } + :host([icon='diff']):before { + content: '\\eae1'; + } + :host([icon='discard']):before { + content: '\\eae2'; + } + :host([icon='editor-layout']):before { + content: '\\eae3'; + } + :host([icon='empty-window']):before { + content: '\\eae4'; + } + :host([icon='exclude']):before { + content: '\\eae5'; + } + :host([icon='extensions']):before { + content: '\\eae6'; + } + :host([icon='eye-closed']):before { + content: '\\eae7'; + } + :host([icon='file-binary']):before { + content: '\\eae8'; + } + :host([icon='file-code']):before { + content: '\\eae9'; + } + :host([icon='file-media']):before { + content: '\\eaea'; + } + :host([icon='file-pdf']):before { + content: '\\eaeb'; + } + :host([icon='file-submodule']):before { + content: '\\eaec'; + } + :host([icon='file-symlink-directory']):before { + content: '\\eaed'; + } + :host([icon='file-symlink-file']):before { + content: '\\eaee'; + } + :host([icon='file-zip']):before { + content: '\\eaef'; + } + :host([icon='files']):before { + content: '\\eaf0'; + } + :host([icon='filter']):before { + content: '\\eaf1'; + } + :host([icon='flame']):before { + content: '\\eaf2'; + } + :host([icon='fold-down']):before { + content: '\\eaf3'; + } + :host([icon='fold-up']):before { + content: '\\eaf4'; + } + :host([icon='fold']):before { + content: '\\eaf5'; + } + :host([icon='folder-active']):before { + content: '\\eaf6'; + } + :host([icon='folder-opened']):before { + content: '\\eaf7'; + } + :host([icon='gear']):before { + content: '\\eaf8'; + } + :host([icon='gift']):before { + content: '\\eaf9'; + } + :host([icon='gist-secret']):before { + content: '\\eafa'; + } + :host([icon='gist']):before { + content: '\\eafb'; + } + :host([icon='git-commit']):before { + content: '\\eafc'; + } + :host([icon='git-compare']):before { + content: '\\eafd'; + } + :host([icon='compare-changes']):before { + content: '\\eafd'; + } + :host([icon='git-merge']):before { + content: '\\eafe'; + } + :host([icon='github-action']):before { + content: '\\eaff'; + } + :host([icon='github-alt']):before { + content: '\\eb00'; + } + :host([icon='globe']):before { + content: '\\eb01'; + } + :host([icon='grabber']):before { + content: '\\eb02'; + } + :host([icon='graph']):before { + content: '\\eb03'; + } + :host([icon='gripper']):before { + content: '\\eb04'; + } + :host([icon='heart']):before { + content: '\\eb05'; + } + :host([icon='home']):before { + content: '\\eb06'; + } + :host([icon='horizontal-rule']):before { + content: '\\eb07'; + } + :host([icon='hubot']):before { + content: '\\eb08'; + } + :host([icon='inbox']):before { + content: '\\eb09'; + } + :host([icon='issue-reopened']):before { + content: '\\eb0b'; + } + :host([icon='issues']):before { + content: '\\eb0c'; + } + :host([icon='italic']):before { + content: '\\eb0d'; + } + :host([icon='jersey']):before { + content: '\\eb0e'; + } + :host([icon='json']):before { + content: '\\eb0f'; + } + :host([icon='kebab-vertical']):before { + content: '\\eb10'; + } + :host([icon='key']):before { + content: '\\eb11'; + } + :host([icon='law']):before { + content: '\\eb12'; + } + :host([icon='lightbulb-autofix']):before { + content: '\\eb13'; + } + :host([icon='link-external']):before { + content: '\\eb14'; + } + :host([icon='link']):before { + content: '\\eb15'; + } + :host([icon='list-ordered']):before { + content: '\\eb16'; + } + :host([icon='list-unordered']):before { + content: '\\eb17'; + } + :host([icon='live-share']):before { + content: '\\eb18'; + } + :host([icon='loading']):before { + content: '\\eb19'; + } + :host([icon='location']):before { + content: '\\eb1a'; + } + :host([icon='mail-read']):before { + content: '\\eb1b'; + } + :host([icon='mail']):before { + content: '\\eb1c'; + } + :host([icon='markdown']):before { + content: '\\eb1d'; + } + :host([icon='megaphone']):before { + content: '\\eb1e'; + } + :host([icon='mention']):before { + content: '\\eb1f'; + } + :host([icon='milestone']):before { + content: '\\eb20'; + } + :host([icon='mortar-board']):before { + content: '\\eb21'; + } + :host([icon='move']):before { + content: '\\eb22'; + } + :host([icon='multiple-windows']):before { + content: '\\eb23'; + } + :host([icon='mute']):before { + content: '\\eb24'; + } + :host([icon='no-newline']):before { + content: '\\eb25'; + } + :host([icon='note']):before { + content: '\\eb26'; + } + :host([icon='octoface']):before { + content: '\\eb27'; + } + :host([icon='open-preview']):before { + content: '\\eb28'; + } + :host([icon='package']):before { + content: '\\eb29'; + } + :host([icon='paintcan']):before { + content: '\\eb2a'; + } + :host([icon='pin']):before { + content: '\\eb2b'; + } + :host([icon='play']):before { + content: '\\eb2c'; + } + :host([icon='run']):before { + content: '\\eb2c'; + } + :host([icon='plug']):before { + content: '\\eb2d'; + } + :host([icon='preserve-case']):before { + content: '\\eb2e'; + } + :host([icon='preview']):before { + content: '\\eb2f'; + } + :host([icon='project']):before { + content: '\\eb30'; + } + :host([icon='pulse']):before { + content: '\\eb31'; + } + :host([icon='question']):before { + content: '\\eb32'; + } + :host([icon='quote']):before { + content: '\\eb33'; + } + :host([icon='radio-tower']):before { + content: '\\eb34'; + } + :host([icon='reactions']):before { + content: '\\eb35'; + } + :host([icon='references']):before { + content: '\\eb36'; + } + :host([icon='refresh']):before { + content: '\\eb37'; + } + :host([icon='regex']):before { + content: '\\eb38'; + } + :host([icon='remote-explorer']):before { + content: '\\eb39'; + } + :host([icon='remote']):before { + content: '\\eb3a'; + } + :host([icon='remove']):before { + content: '\\eb3b'; + } + :host([icon='replace-all']):before { + content: '\\eb3c'; + } + :host([icon='replace']):before { + content: '\\eb3d'; + } + :host([icon='repo-clone']):before { + content: '\\eb3e'; + } + :host([icon='repo-force-push']):before { + content: '\\eb3f'; + } + :host([icon='repo-pull']):before { + content: '\\eb40'; + } + :host([icon='repo-push']):before { + content: '\\eb41'; + } + :host([icon='report']):before { + content: '\\eb42'; + } + :host([icon='request-changes']):before { + content: '\\eb43'; + } + :host([icon='rocket']):before { + content: '\\eb44'; + } + :host([icon='root-folder-opened']):before { + content: '\\eb45'; + } + :host([icon='root-folder']):before { + content: '\\eb46'; + } + :host([icon='rss']):before { + content: '\\eb47'; + } + :host([icon='ruby']):before { + content: '\\eb48'; + } + :host([icon='save-all']):before { + content: '\\eb49'; + } + :host([icon='save-as']):before { + content: '\\eb4a'; + } + :host([icon='save']):before { + content: '\\eb4b'; + } + :host([icon='screen-full']):before { + content: '\\eb4c'; + } + :host([icon='screen-normal']):before { + content: '\\eb4d'; + } + :host([icon='search-stop']):before { + content: '\\eb4e'; + } + :host([icon='server']):before { + content: '\\eb50'; + } + :host([icon='settings-gear']):before { + content: '\\eb51'; + } + :host([icon='settings']):before { + content: '\\eb52'; + } + :host([icon='shield']):before { + content: '\\eb53'; + } + :host([icon='smiley']):before { + content: '\\eb54'; + } + :host([icon='sort-precedence']):before { + content: '\\eb55'; + } + :host([icon='split-horizontal']):before { + content: '\\eb56'; + } + :host([icon='split-vertical']):before { + content: '\\eb57'; + } + :host([icon='squirrel']):before { + content: '\\eb58'; + } + :host([icon='star-full']):before { + content: '\\eb59'; + } + :host([icon='star-half']):before { + content: '\\eb5a'; + } + :host([icon='symbol-class']):before { + content: '\\eb5b'; + } + :host([icon='symbol-color']):before { + content: '\\eb5c'; + } + :host([icon='symbol-constant']):before { + content: '\\eb5d'; + } + :host([icon='symbol-enum-member']):before { + content: '\\eb5e'; + } + :host([icon='symbol-field']):before { + content: '\\eb5f'; + } + :host([icon='symbol-file']):before { + content: '\\eb60'; + } + :host([icon='symbol-interface']):before { + content: '\\eb61'; + } + :host([icon='symbol-keyword']):before { + content: '\\eb62'; + } + :host([icon='symbol-misc']):before { + content: '\\eb63'; + } + :host([icon='symbol-operator']):before { + content: '\\eb64'; + } + :host([icon='symbol-property']):before { + content: '\\eb65'; + } + :host([icon='wrench']):before { + content: '\\eb65'; + } + :host([icon='wrench-subaction']):before { + content: '\\eb65'; + } + :host([icon='symbol-snippet']):before { + content: '\\eb66'; + } + :host([icon='tasklist']):before { + content: '\\eb67'; + } + :host([icon='telescope']):before { + content: '\\eb68'; + } + :host([icon='text-size']):before { + content: '\\eb69'; + } + :host([icon='three-bars']):before { + content: '\\eb6a'; + } + :host([icon='thumbsdown']):before { + content: '\\eb6b'; + } + :host([icon='thumbsup']):before { + content: '\\eb6c'; + } + :host([icon='tools']):before { + content: '\\eb6d'; + } + :host([icon='triangle-down']):before { + content: '\\eb6e'; + } + :host([icon='triangle-left']):before { + content: '\\eb6f'; + } + :host([icon='triangle-right']):before { + content: '\\eb70'; + } + :host([icon='triangle-up']):before { + content: '\\eb71'; + } + :host([icon='twitter']):before { + content: '\\eb72'; + } + :host([icon='unfold']):before { + content: '\\eb73'; + } + :host([icon='unlock']):before { + content: '\\eb74'; + } + :host([icon='unmute']):before { + content: '\\eb75'; + } + :host([icon='unverified']):before { + content: '\\eb76'; + } + :host([icon='verified']):before { + content: '\\eb77'; + } + :host([icon='versions']):before { + content: '\\eb78'; + } + :host([icon='vm-active']):before { + content: '\\eb79'; + } + :host([icon='vm-outline']):before { + content: '\\eb7a'; + } + :host([icon='vm-running']):before { + content: '\\eb7b'; + } + :host([icon='watch']):before { + content: '\\eb7c'; + } + :host([icon='whitespace']):before { + content: '\\eb7d'; + } + :host([icon='whole-word']):before { + content: '\\eb7e'; + } + :host([icon='window']):before { + content: '\\eb7f'; + } + :host([icon='word-wrap']):before { + content: '\\eb80'; + } + :host([icon='zoom-in']):before { + content: '\\eb81'; + } + :host([icon='zoom-out']):before { + content: '\\eb82'; + } + :host([icon='list-filter']):before { + content: '\\eb83'; + } + :host([icon='list-flat']):before { + content: '\\eb84'; + } + :host([icon='list-selection']):before { + content: '\\eb85'; + } + :host([icon='selection']):before { + content: '\\eb85'; + } + :host([icon='list-tree']):before { + content: '\\eb86'; + } + :host([icon='debug-breakpoint-function-unverified']):before { + content: '\\eb87'; + } + :host([icon='debug-breakpoint-function']):before { + content: '\\eb88'; + } + :host([icon='debug-breakpoint-function-disabled']):before { + content: '\\eb88'; + } + :host([icon='debug-stackframe-active']):before { + content: '\\eb89'; + } + :host([icon='debug-stackframe-dot']):before { + content: '\\eb8a'; + } + :host([icon='debug-stackframe']):before { + content: '\\eb8b'; + } + :host([icon='debug-stackframe-focused']):before { + content: '\\eb8b'; + } + :host([icon='debug-breakpoint-unsupported']):before { + content: '\\eb8c'; + } + :host([icon='symbol-string']):before { + content: '\\eb8d'; + } + :host([icon='debug-reverse-continue']):before { + content: '\\eb8e'; + } + :host([icon='debug-step-back']):before { + content: '\\eb8f'; + } + :host([icon='debug-restart-frame']):before { + content: '\\eb90'; + } + :host([icon='debug-alt']):before { + content: '\\eb91'; + } + :host([icon='call-incoming']):before { + content: '\\eb92'; + } + :host([icon='call-outgoing']):before { + content: '\\eb93'; + } + :host([icon='menu']):before { + content: '\\eb94'; + } + :host([icon='expand-all']):before { + content: '\\eb95'; + } + :host([icon='feedback']):before { + content: '\\eb96'; + } + :host([icon='group-by-ref-type']):before { + content: '\\eb97'; + } + :host([icon='ungroup-by-ref-type']):before { + content: '\\eb98'; + } + :host([icon='account']):before { + content: '\\eb99'; + } + :host([icon='bell-dot']):before { + content: '\\eb9a'; + } + :host([icon='debug-console']):before { + content: '\\eb9b'; + } + :host([icon='library']):before { + content: '\\eb9c'; + } + :host([icon='output']):before { + content: '\\eb9d'; + } + :host([icon='run-all']):before { + content: '\\eb9e'; + } + :host([icon='sync-ignored']):before { + content: '\\eb9f'; + } + :host([icon='pinned']):before { + content: '\\eba0'; + } + :host([icon='github-inverted']):before { + content: '\\eba1'; + } + :host([icon='server-process']):before { + content: '\\eba2'; + } + :host([icon='server-environment']):before { + content: '\\eba3'; + } + :host([icon='pass']):before { + content: '\\eba4'; + } + :host([icon='issue-closed']):before { + content: '\\eba4'; + } + :host([icon='stop-circle']):before { + content: '\\eba5'; + } + :host([icon='play-circle']):before { + content: '\\eba6'; + } + :host([icon='record']):before { + content: '\\eba7'; + } + :host([icon='debug-alt-small']):before { + content: '\\eba8'; + } + :host([icon='vm-connect']):before { + content: '\\eba9'; + } + :host([icon='cloud']):before { + content: '\\ebaa'; + } + :host([icon='merge']):before { + content: '\\ebab'; + } + :host([icon='export']):before { + content: '\\ebac'; + } + :host([icon='graph-left']):before { + content: '\\ebad'; + } + :host([icon='magnet']):before { + content: '\\ebae'; + } + :host([icon='notebook']):before { + content: '\\ebaf'; + } + :host([icon='redo']):before { + content: '\\ebb0'; + } + :host([icon='check-all']):before { + content: '\\ebb1'; + } + :host([icon='pinned-dirty']):before { + content: '\\ebb2'; + } + :host([icon='pass-filled']):before { + content: '\\ebb3'; + } + :host([icon='circle-large-filled']):before { + content: '\\ebb4'; + } + :host([icon='circle-large-outline']):before { + content: '\\ebb5'; + } + :host([icon='combine']):before { + content: '\\ebb6'; + } + :host([icon='gather']):before { + content: '\\ebb6'; + } + :host([icon='table']):before { + content: '\\ebb7'; + } + :host([icon='variable-group']):before { + content: '\\ebb8'; + } + :host([icon='type-hierarchy']):before { + content: '\\ebb9'; + } + :host([icon='type-hierarchy-sub']):before { + content: '\\ebba'; + } + :host([icon='type-hierarchy-super']):before { + content: '\\ebbb'; + } + :host([icon='git-pull-request-create']):before { + content: '\\ebbc'; + } + :host([icon='run-above']):before { + content: '\\ebbd'; + } + :host([icon='run-below']):before { + content: '\\ebbe'; + } + :host([icon='notebook-template']):before { + content: '\\ebbf'; + } + :host([icon='debug-rerun']):before { + content: '\\ebc0'; + } + :host([icon='workspace-trusted']):before { + content: '\\ebc1'; + } + :host([icon='workspace-untrusted']):before { + content: '\\ebc2'; + } + :host([icon='workspace-unknown']):before { + content: '\\ebc3'; + } + :host([icon='terminal-cmd']):before { + content: '\\ebc4'; + } + :host([icon='terminal-debian']):before { + content: '\\ebc5'; + } + :host([icon='terminal-linux']):before { + content: '\\ebc6'; + } + :host([icon='terminal-powershell']):before { + content: '\\ebc7'; + } + :host([icon='terminal-tmux']):before { + content: '\\ebc8'; + } + :host([icon='terminal-ubuntu']):before { + content: '\\ebc9'; + } + :host([icon='terminal-bash']):before { + content: '\\ebca'; + } + :host([icon='arrow-swap']):before { + content: '\\ebcb'; + } + :host([icon='copy']):before { + content: '\\ebcc'; + } + :host([icon='person-add']):before { + content: '\\ebcd'; + } + :host([icon='filter-filled']):before { + content: '\\ebce'; + } + :host([icon='wand']):before { + content: '\\ebcf'; + } + :host([icon='debug-line-by-line']):before { + content: '\\ebd0'; + } + :host([icon='inspect']):before { + content: '\\ebd1'; + } + :host([icon='layers']):before { + content: '\\ebd2'; + } + :host([icon='layers-dot']):before { + content: '\\ebd3'; + } + :host([icon='layers-active']):before { + content: '\\ebd4'; + } + :host([icon='compass']):before { + content: '\\ebd5'; + } + :host([icon='compass-dot']):before { + content: '\\ebd6'; + } + :host([icon='compass-active']):before { + content: '\\ebd7'; + } + :host([icon='azure']):before { + content: '\\ebd8'; + } + :host([icon='issue-draft']):before { + content: '\\ebd9'; + } + :host([icon='git-pull-request-closed']):before { + content: '\\ebda'; + } + :host([icon='git-pull-request-draft']):before { + content: '\\ebdb'; + } + :host([icon='debug-all']):before { + content: '\\ebdc'; + } + :host([icon='debug-coverage']):before { + content: '\\ebdd'; + } + :host([icon='run-errors']):before { + content: '\\ebde'; + } + :host([icon='folder-library']):before { + content: '\\ebdf'; + } + :host([icon='debug-continue-small']):before { + content: '\\ebe0'; + } + :host([icon='beaker-stop']):before { + content: '\\ebe1'; + } + :host([icon='graph-line']):before { + content: '\\ebe2'; + } + :host([icon='graph-scatter']):before { + content: '\\ebe3'; + } + :host([icon='pie-chart']):before { + content: '\\ebe4'; + } + :host([icon='bracket']):before { + content: '\\eb0f'; + } + :host([icon='bracket-dot']):before { + content: '\\ebe5'; + } + :host([icon='bracket-error']):before { + content: '\\ebe6'; + } + :host([icon='lock-small']):before { + content: '\\ebe7'; + } + :host([icon='azure-devops']):before { + content: '\\ebe8'; + } + :host([icon='verified-filled']):before { + content: '\\ebe9'; + } + :host([icon='newline']):before { + content: '\\ebea'; + } + :host([icon='layout']):before { + content: '\\ebeb'; + } + :host([icon='layout-activitybar-left']):before { + content: '\\ebec'; + } + :host([icon='layout-activitybar-right']):before { + content: '\\ebed'; + } + :host([icon='layout-panel-left']):before { + content: '\\ebee'; + } + :host([icon='layout-panel-center']):before { + content: '\\ebef'; + } + :host([icon='layout-panel-justify']):before { + content: '\\ebf0'; + } + :host([icon='layout-panel-right']):before { + content: '\\ebf1'; + } + :host([icon='layout-panel']):before { + content: '\\ebf2'; + } + :host([icon='layout-sidebar-left']):before { + content: '\\ebf3'; + } + :host([icon='layout-sidebar-right']):before { + content: '\\ebf4'; + } + :host([icon='layout-statusbar']):before { + content: '\\ebf5'; + } + :host([icon='layout-menubar']):before { + content: '\\ebf6'; + } + :host([icon='layout-centered']):before { + content: '\\ebf7'; + } + :host([icon='target']):before { + content: '\\ebf8'; + } - @keyframes codicon-spin { - 100% { - transform: rotate(360deg); + :host([icon^='gl-']) { + font-family: 'glicons'; + } + :host([icon='gl-commit-horizontal']):before { + content: '\\f101'; + } + :host([icon='gl-graph']):before { + content: '\\f102'; + } + :host([icon='gl-next-commit']):before { + content: '\\f103'; + } + :host([icon='gl-prev-commit-menu']):before { + content: '\\f104'; + } + :host([icon='gl-prev-commit']):before { + content: '\\f105'; + } + :host([icon='gl-compare-ref-working']):before { + content: '\\f106'; + } + :host([icon='gl-branches-view']):before { + content: '\\f107'; + } + :host([icon='gl-commit-view']):before { + content: '\\f108'; + } + :host([icon='gl-commits-view']):before { + content: '\\f109'; + } + :host([icon='gl-compare-view']):before { + content: '\\f10a'; + } + :host([icon='gl-contributors-view']):before { + content: '\\f10b'; + } + :host([icon='gl-history-view']):before { + content: '\\f10c'; + } + :host([icon='gl-remotes-view']):before { + content: '\\f10d'; + } + :host([icon='gl-repositories-view']):before { + content: '\\f10e'; + } + :host([icon='gl-search-view']):before { + content: '\\f10f'; + } + :host([icon='gl-stashes-view']):before { + content: '\\f110'; + } + :host([icon='gl-tags-view']):before { + content: '\\f111'; + } + :host([icon='gl-worktrees-view']):before { + content: '\\f112'; + } + :host([icon='gl-gitlens']):before { + content: '\\f113'; + } + :host([icon='gl-stash-pop']):before { + content: '\\f114'; + } + :host([icon='gl-stash-save']):before { + content: '\\f115'; + } + :host([icon='gl-unplug']):before { + content: '\\f116'; + } + :host([icon='gl-open-revision']):before { + content: '\\f117'; + } + :host([icon='gl-switch']):before { + content: '\\f118'; + } + :host([icon='gl-expand']):before { + content: '\\f119'; + } + :host([icon='gl-list-auto']):before { + content: '\\f11a'; + } + :host([icon='gl-arrow-up-force']):before { + content: '\\f11b'; + } + :host([icon='gl-pinned-filled']):before { + content: '\\f11c'; + /* TODO: see relative positioning needed in every use-case */ + position: relative; + left: 1px; + } + :host([icon='gl-clock']):before { + content: '\\f11d'; + } + :host([icon='gl-provider-azdo']):before { + content: '\\f11e'; + } + :host([icon='gl-provider-bitbucket']):before { + content: '\\f11f'; + } + :host([icon='gl-provider-gerrit']):before { + content: '\\f120'; + } + :host([icon='gl-provider-gitea']):before { + content: '\\f121'; + } + :host([icon='gl-provider-github']):before { + content: '\\f122'; + } + :host([icon='gl-provider-gitlab']):before { + content: '\\f123'; + } + :host([icon='gl-gitlens-inspect']):before { + content: '\\f124'; } - } - :host([modifier='spin']) { - /* Use steps to throttle FPS to reduce CPU usage */ - animation: codicon-spin 1.5s steps(30) infinite; - } - :host([icon='loading'][modifier='spin']) { - /* Use steps to throttle FPS to reduce CPU usage */ - animation: codicon-spin 1.5s steps(30) infinite; + @keyframes codicon-spin { + 100% { + transform: rotate(360deg); + } + } - /* custom speed & easing for loading icon */ - animation-duration: 1s !important; - animation-timing-function: cubic-bezier(0.53, 0.21, 0.29, 0.67) !important; - } -`; + :host([modifier='spin']) { + /* Use steps to throttle FPS to reduce CPU usage */ + animation: codicon-spin 1.5s steps(30) infinite; + } + :host([icon='loading'][modifier='spin']) { + /* Use steps to throttle FPS to reduce CPU usage */ + animation: codicon-spin 1.5s steps(30) infinite; -@customElement({ name: 'code-icon', styles: styles }) -export class CodeIcon extends FASTElement { - @attr + /* custom speed & easing for loading icon */ + animation-duration: 1s !important; + animation-timing-function: cubic-bezier(0.53, 0.21, 0.29, 0.67) !important; + } + `; + @property() icon = ''; - @attr + @property() modifier = ''; - @attr + @property({ type: Number }) size = 16; - sizeChanged() { - this.style.setProperty('--code-icon-size', `${this.size}px`); + + override updated(changedProperties: Map<string, unknown>) { + if (changedProperties.has('size')) { + this.style.setProperty('--code-icon-size', `${this.size}px`); + } + super.update(changedProperties); } } diff --git a/src/webviews/apps/shared/components/styles/lit/a11y.css.ts b/src/webviews/apps/shared/components/styles/lit/a11y.css.ts new file mode 100644 index 0000000..5f2ead3 --- /dev/null +++ b/src/webviews/apps/shared/components/styles/lit/a11y.css.ts @@ -0,0 +1,19 @@ +import { css } from 'lit'; + +export const srOnly = css` + .sr-only, + .sr-only-focusable:not(:active):not(:focus) { + clip: rect(0 0 0 0); + clip-path: inset(50%); + width: 1px; + height: 1px; + overflow: hidden; + position: absolute; + white-space: nowrap; + } +`; + +export const focusOutline = css` + outline: 1px solid var(--color-focus-border); + outline-offset: -1px; +`; diff --git a/src/webviews/apps/shared/components/styles/lit/base.css.ts b/src/webviews/apps/shared/components/styles/lit/base.css.ts new file mode 100644 index 0000000..28aeaaa --- /dev/null +++ b/src/webviews/apps/shared/components/styles/lit/base.css.ts @@ -0,0 +1,15 @@ +import { css } from 'lit'; + +export const elementBase = css` + :host { + box-sizing: border-box; + } + :host *, + :host *::before, + :host *::after { + box-sizing: inherit; + } + [hidden] { + display: none !important; + } +`; diff --git a/src/webviews/apps/shared/styles/properties.scss b/src/webviews/apps/shared/styles/properties.scss new file mode 100644 index 0000000..b4bdc21 --- /dev/null +++ b/src/webviews/apps/shared/styles/properties.scss @@ -0,0 +1,17 @@ +:root { + --gitlens-gutter-width: 20px; + --gk-action-radius: 0.2rem; + --gk-card-radius: 0.4rem; +} + +.vscode-high-contrast, +.vscode-dark { + --gk-card-background: var(--color-background--lighten-05); + --gk-card-hover-background: var(--color-background--lighten-075); +} + +.vscode-high-contrast-light, +.vscode-light { + --gk-card-background: var(--color-background--darken-05); + --gk-card-hover-background: var(--color-background--darken-075); +}