mirror of
https://github.com/akveo/ngx-admin.git
synced 2025-12-16 23:40:14 +01:00
feat: docs app
This commit is contained in:
parent
713aff561e
commit
2129689f98
203 changed files with 15927 additions and 5 deletions
74
docs/app/blocks/blocks.module.ts
Normal file
74
docs/app/blocks/blocks.module.ts
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgxLandingThemeModule } from '../@theme/theme.module';
|
||||
|
||||
import {
|
||||
NgxMdBLockComponent,
|
||||
NgxTabbedBlockComponent,
|
||||
NgxOverviewBlockComponent,
|
||||
NgxExampleBlockComponent,
|
||||
NgxInlineExampleBlockComponent,
|
||||
NgxTabbedExampleBlockComponent,
|
||||
NgxLiveExampleBlockComponent,
|
||||
NgxStackedExampleComponent,
|
||||
NgxCodeBlockComponent,
|
||||
NgxMethodsBlockComponent,
|
||||
NgxPropsBlockComponent,
|
||||
NgxPropBlockComponent,
|
||||
NgxStylesBlockComponent,
|
||||
NgxThemeComponent,
|
||||
NgxComponentBlockComponent,
|
||||
NgxApiBlockComponent,
|
||||
NgxStylesTableBlockComponent,
|
||||
NgxExamplesBlockComponent,
|
||||
NgxPagerBlockComponent,
|
||||
NgxComponentsOverviewBlockComponent,
|
||||
} from './components/';
|
||||
|
||||
const blocks = [
|
||||
NgxMdBLockComponent,
|
||||
NgxTabbedBlockComponent,
|
||||
NgxOverviewBlockComponent,
|
||||
NgxExampleBlockComponent,
|
||||
NgxInlineExampleBlockComponent,
|
||||
NgxTabbedExampleBlockComponent,
|
||||
NgxLiveExampleBlockComponent,
|
||||
NgxStackedExampleComponent,
|
||||
NgxCodeBlockComponent,
|
||||
NgxMethodsBlockComponent,
|
||||
NgxPropsBlockComponent,
|
||||
NgxPropBlockComponent,
|
||||
NgxStylesBlockComponent,
|
||||
NgxThemeComponent,
|
||||
NgxComponentBlockComponent,
|
||||
NgxApiBlockComponent,
|
||||
NgxStylesTableBlockComponent,
|
||||
NgxExamplesBlockComponent,
|
||||
NgxPagerBlockComponent,
|
||||
NgxComponentsOverviewBlockComponent,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule,
|
||||
NgxLandingThemeModule,
|
||||
],
|
||||
declarations: [
|
||||
...blocks,
|
||||
],
|
||||
exports: [
|
||||
CommonModule,
|
||||
RouterModule,
|
||||
...blocks,
|
||||
],
|
||||
})
|
||||
export class NgxBlocksModule {
|
||||
}
|
||||
38
docs/app/blocks/components/api-block/api-block.component.ts
Normal file
38
docs/app/blocks/components/api-block/api-block.component.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { NgxTabbedService } from '../../../@theme/services/tabbed.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-api-block',
|
||||
template: `
|
||||
<nb-card [ngxFragment]="source.slag">
|
||||
<nb-card-body>
|
||||
<h2>{{ source.name }}</h2>
|
||||
<ngx-props-block [source]="source" *ngIf="hasProps(source)"></ngx-props-block>
|
||||
<ngx-methods-block [source]="source" *ngIf="hasMethods(source)"></ngx-methods-block>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxApiBlockComponent {
|
||||
|
||||
@Input('source') source;
|
||||
|
||||
constructor(private tabbedService: NgxTabbedService) {
|
||||
}
|
||||
|
||||
|
||||
hasMethods(component) {
|
||||
return this.tabbedService.componentHasMethods(component);
|
||||
}
|
||||
|
||||
hasProps(component) {
|
||||
return this.tabbedService.componentHasProps(component);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
|
||||
@include nb-install-component() {
|
||||
|
||||
$code-lines-fg: #515877;
|
||||
$code-block-bg: nb-theme(code-block-bg);
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
padding: 0;
|
||||
font-size: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background: $code-block-bg;
|
||||
overflow-x: auto;
|
||||
|
||||
.lines {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: end;
|
||||
font-size: 0.875rem;
|
||||
padding: 2rem 0.5rem 0.5rem;
|
||||
border-radius: 0.5rem 0 0 0.5rem;
|
||||
color: $code-lines-fg;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-bottom: 0;
|
||||
background: transparent;
|
||||
overflow: visible;
|
||||
|
||||
code.hljs {
|
||||
background: transparent;
|
||||
padding-left: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { SafeHtml } from '@angular/platform-browser';
|
||||
import { NgxHighlightService } from '../../../@theme/services/highlight.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-code-block',
|
||||
styleUrls: ['./code-block.component.scss'],
|
||||
template: `
|
||||
<div class="container">
|
||||
<div class="lines">
|
||||
<span *ngFor="let line of lines">{{ line }}</span>
|
||||
</div>
|
||||
<pre><code class="hljs" [innerHTML]="code"></code></pre>
|
||||
</div>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxCodeBlockComponent {
|
||||
|
||||
@Input() path = '';
|
||||
@Input() firstLine: number;
|
||||
@Input() lastLine: number;
|
||||
|
||||
@Input('code')
|
||||
set rawCode(value) {
|
||||
const highlighted = this.highlightService.highlight(value);
|
||||
this.code = this.getVisible(highlighted);
|
||||
this.lines = this.createLines(this.code);
|
||||
}
|
||||
|
||||
code: SafeHtml;
|
||||
lines: number[] = [];
|
||||
|
||||
constructor(private highlightService: NgxHighlightService) {
|
||||
}
|
||||
|
||||
getVisible(code): string {
|
||||
return code
|
||||
.split('\n')
|
||||
.slice(this.firstLine - 1, this.lastLine)
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
createLines(code): number[] {
|
||||
const length = code.split('\n').length;
|
||||
return Array(length).fill(0).map((_, i) => i + (this.firstLine || 1));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { NgxTabbedService } from '../../../@theme/services/tabbed.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-component-block',
|
||||
template: `
|
||||
<nb-card [ngxFragment]="source.slag">
|
||||
<nb-card-body>
|
||||
<ng-container class="description" *ngFor="let node of overview">
|
||||
<ng-container *ngIf="node.type === 'text'">
|
||||
<div *ngFor="let section of node.content" [innerHtml]="section.html"></div>
|
||||
</ng-container>
|
||||
<ngx-live-example-block *ngIf="node.type === 'live-example'" [id]="node.content" [title]="'example'"
|
||||
class="widget-block">
|
||||
</ngx-live-example-block>
|
||||
<ngx-inline-example-block *ngIf="node.type === 'inline-example'" [content]="node.content"
|
||||
class="widget-block">
|
||||
</ngx-inline-example-block>
|
||||
<ngx-stacked-example-block *ngIf="node.type === 'example'" [content]="node.content"
|
||||
class="widget-block">
|
||||
</ngx-stacked-example-block>
|
||||
</ng-container>
|
||||
<ngx-props-block [source]="source" *ngIf="hasProps(source)"></ngx-props-block>
|
||||
<ngx-methods-block [source]="source" *ngIf="hasMethods(source)"></ngx-methods-block>
|
||||
<ng-container *ngIf="hasTheme(source)">
|
||||
<h3>Theme</h3>
|
||||
<ngx-styles-table-block [source]="source"></ngx-styles-table-block>
|
||||
</ng-container>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxComponentBlockComponent {
|
||||
|
||||
source: any;
|
||||
overview: any[] = [];
|
||||
|
||||
@Input('source')
|
||||
set setSource(source: any) {
|
||||
this.source = source;
|
||||
this.overview = source.overview;
|
||||
}
|
||||
|
||||
constructor(private tabbedService: NgxTabbedService) {
|
||||
}
|
||||
|
||||
hasTheme(component) {
|
||||
return this.tabbedService.componentHasTheme(component);
|
||||
}
|
||||
|
||||
hasMethods(component) {
|
||||
return this.tabbedService.componentHasMethods(component);
|
||||
}
|
||||
|
||||
hasProps(component) {
|
||||
return this.tabbedService.componentHasProps(component);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<nb-card class="header-card">
|
||||
<nb-card-header>Components Overview</nb-card-header>
|
||||
</nb-card>
|
||||
|
||||
<div class="components-list">
|
||||
<ng-container *ngFor="let component of components">
|
||||
<h2 *ngIf="component.group">{{ component.name }}</h2>
|
||||
<div *ngIf="!component.group" class="component-card-wrapper">
|
||||
<a class="component-navigate-link" [routerLink]="component.link">
|
||||
<nb-card [attr.title]="component.name">
|
||||
<nb-card-body>
|
||||
<img class="component-icon" src="assets/images/components/{{ component.icon }}"
|
||||
[attr.alt]="component.name">
|
||||
<label class="component-name">{{ component.name }}</label>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
</a>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
@import '~@nebular/theme/styles/global/breakpoints';
|
||||
|
||||
@include nb-install-component() {
|
||||
|
||||
.components-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
h2 {
|
||||
flex: 1 1 100%;
|
||||
color: nb-theme(color-fg-heading-light);
|
||||
margin: 1rem 0 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.component-card-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.component-icon {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.component-name {
|
||||
color: nb-theme(color-fg-heading-light);
|
||||
font-weight: nb-theme(font-weight-bolder);
|
||||
}
|
||||
|
||||
.component-navigate-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
nb-card {
|
||||
box-shadow: 0 4px 27px 0 rgba(230, 234, 240, 0.2);
|
||||
transition: transform 0.25s ease;
|
||||
|
||||
> nb-card-body {
|
||||
height: 12.5rem;
|
||||
padding: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 15px 37px 0 #dbe2eb;
|
||||
transform: translateY(-1rem);
|
||||
.component-name {
|
||||
color: nb-theme(color-fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(is) {
|
||||
.components-list {
|
||||
|
||||
.component-card-wrapper {
|
||||
flex: 1 0 auto;
|
||||
width: 50%;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
.components-list {
|
||||
|
||||
.component-card-wrapper {
|
||||
flex: 1 0 auto;
|
||||
max-width: 33.3%;
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { NgxMenuService } from '../../../@theme/services/menu.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-components-overview-block',
|
||||
styleUrls: ['./components-overview-block.component.scss'],
|
||||
templateUrl: './components-overview-block.component.html',
|
||||
})
|
||||
export class NgxComponentsOverviewBlockComponent implements OnInit {
|
||||
components: { name: string; icon: string; link: string }[];
|
||||
|
||||
constructor(private menu: NgxMenuService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.components = this.menu
|
||||
.getPreparedMenu('/docs')
|
||||
.find(({ title }) => title === 'Components')
|
||||
.children
|
||||
.slice(1)
|
||||
.map(({ data: { name, icon, type }, link }) => ({ name, icon, link, group: type === 'group' }));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
} from '@angular/core';
|
||||
import { NgxCodeLoaderService } from '../../../@theme/services/code-loader.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-example-block',
|
||||
template: `
|
||||
<ngx-code-block *ngIf="code"
|
||||
[firstLine]="firstLine"
|
||||
[lastLine]="lastLine"
|
||||
[code]="code">
|
||||
</ngx-code-block>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxExampleBlockComponent {
|
||||
|
||||
code: string;
|
||||
firstLine: number;
|
||||
lastLine: number;
|
||||
|
||||
@Input('content')
|
||||
set setContent(content) {
|
||||
this.loadCode(content);
|
||||
}
|
||||
|
||||
constructor(private codeLoader: NgxCodeLoaderService, private cd: ChangeDetectorRef) {
|
||||
}
|
||||
|
||||
loadCode(content) {
|
||||
this.codeLoader.load(content.files[0])
|
||||
.subscribe((code: string) => {
|
||||
this.code = code;
|
||||
this.firstLine = content.firstLine || 1;
|
||||
this.lastLine = content.lastLine || code.split('\n').length;
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-examples-block',
|
||||
template: `
|
||||
<nb-card [ngxFragment]="source.slag">
|
||||
<nb-card-body>
|
||||
<h2>{{ source.name }}</h2>
|
||||
<ngx-stacked-example-block *ngFor="let example of source.liveExamples" [content]="example.content"
|
||||
class="widget-block">
|
||||
</ngx-stacked-example-block>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxExamplesBlockComponent {
|
||||
|
||||
@Input('source') source;
|
||||
|
||||
}
|
||||
20
docs/app/blocks/components/index.ts
Normal file
20
docs/app/blocks/components/index.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
export * from './md-block/md-block.component';
|
||||
export * from './tabbed-block/tabbed-block.component';
|
||||
export * from './overview-block/overview-block.component';
|
||||
export * from './code-block/code-block.component';
|
||||
export * from './tabbed-example-block/tabbed-example-block.component';
|
||||
export * from './example-block/example-block.component';
|
||||
export * from './inline-example-block/inline-example-block.component';
|
||||
export * from './live-example-block/live-example-block.component';
|
||||
export * from './stacked-example-block/stacked-examples.component';
|
||||
export * from './methods-block/methods-block.component';
|
||||
export * from './props-block/props-block.component';
|
||||
export * from './prop-block/prop-block.component';
|
||||
export * from './styles-block/styles-block.component';
|
||||
export * from './theme-block/theme-block.component';
|
||||
export * from './component-block/component-block.component';
|
||||
export * from './api-block/api-block.component';
|
||||
export * from './styles-table-block/styles-table-block.component';
|
||||
export * from './examples-block/examples-block.component';
|
||||
export * from './pager-block/pager-block.component';
|
||||
export * from './components-overview-block/components-overview-block.component';
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-inline-example-block',
|
||||
template: `
|
||||
<ngx-example-block *ngIf="isOneFile" [content]="content"></ngx-example-block>
|
||||
<ngx-tabbed-example-block *ngIf="isTabbed" [content]="content"></ngx-tabbed-example-block>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxInlineExampleBlockComponent {
|
||||
|
||||
@Input() content;
|
||||
|
||||
get isOneFile(): boolean {
|
||||
return !this.isTabbed;
|
||||
}
|
||||
|
||||
get isTabbed(): boolean {
|
||||
return this.content.files.length > 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<section class="header" >
|
||||
<strong class="title">{{ content.name }}</strong>
|
||||
<div class="actions">
|
||||
|
||||
<div class="action-selector">
|
||||
<select class="action-item" [(ngModel)]="currentTheme" (change)="switchTheme($event.target.value)">
|
||||
<option *ngFor="let theme of themes" [value]="theme.value">{{theme.label}}</option>
|
||||
</select>
|
||||
<i class="icon feather-aperture"></i>
|
||||
</div>
|
||||
<a class="btn action-item action-button" target="_blank" [href]="url">
|
||||
<i class="icon feather-external-link"></i>
|
||||
</a>
|
||||
<button type="button"
|
||||
*ngIf="hasViewSwitch"
|
||||
class="btn action-item action-button"
|
||||
(click)="switchToInlineVew()">
|
||||
<i class="icon feather-code"></i>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<div class="iframe-container">
|
||||
<iframe #iframe *ngIf="content.id" [style.height.px]="iframeHeight" [class.loading]="loading"></iframe>
|
||||
</div>
|
||||
<span class="icon-loading feather-more-vertical" *ngIf="loading"></span>
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
|
||||
@include nb-install-component() {
|
||||
|
||||
// TODO: move some variables in Nebular themes
|
||||
// colors
|
||||
$action-bg: white;
|
||||
$action-fg: nb-theme(color-fg-heading-light);
|
||||
$block-bg-default: #ebeff5;
|
||||
$block-bg-cosmic: #2f296b;
|
||||
$block-fg-cosmic: #7d838b;
|
||||
$block-bg-corporate: #f1f5f8;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.5rem 1rem 2.5rem 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
position: relative;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1.875rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.actions {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-right: 1rem;
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.icon {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
.action-item {
|
||||
background-color: $action-bg;
|
||||
border-radius: 0.375rem;
|
||||
height: 100%;
|
||||
line-height: 1;
|
||||
border: none;
|
||||
color: $action-fg;
|
||||
padding: 0.5rem 1rem;
|
||||
margin-left: 0.625rem;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&:hover, &:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.action-selector {
|
||||
position: relative;
|
||||
|
||||
.action-item {
|
||||
padding: 0;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: $action-fg;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
/* Target IE9 - IE11 */
|
||||
select::-ms-expand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
select {
|
||||
font-size: 0.875rem;
|
||||
appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.theme-default {
|
||||
background-color: $block-bg-default;
|
||||
}
|
||||
|
||||
&.theme-cosmic {
|
||||
background-color: $block-bg-cosmic;
|
||||
|
||||
.title {
|
||||
color: white;
|
||||
}
|
||||
.action-item {
|
||||
color: $block-fg-cosmic;
|
||||
}
|
||||
}
|
||||
|
||||
&.theme-corporate {
|
||||
background-color: $block-bg-corporate;
|
||||
}
|
||||
|
||||
.iframe-container {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
border: none;
|
||||
transform: translateZ(0);
|
||||
|
||||
&.loading {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-loading {
|
||||
animation: rotation 2s infinite linear;
|
||||
color: $action-fg;
|
||||
font-size: 1.5rem;
|
||||
font-weight: normal;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotation {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 23em) {
|
||||
.action-selector {
|
||||
.action-item {
|
||||
padding: 0.5rem 1rem;
|
||||
color: $action-fg;
|
||||
}
|
||||
select.action-item {
|
||||
padding: 0 2.5rem;
|
||||
}
|
||||
|
||||
.icon {
|
||||
left: 1.25rem;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
ViewChild,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
HostBinding,
|
||||
Output,
|
||||
EventEmitter,
|
||||
AfterViewInit,
|
||||
} from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { takeWhile } from 'rxjs/operators';
|
||||
import { NgxExampleView } from '../../enum.example-view';
|
||||
import { NgxIframeCommunicatorService } from '../../../@theme/services/iframe-communicator.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-live-example-block',
|
||||
styleUrls: ['./live-example-block.component.scss'],
|
||||
templateUrl: './live-example-block.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxLiveExampleBlockComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
@ViewChild('iframe', { static: false }) iframe: ElementRef;
|
||||
@Input() content: any;
|
||||
@Input() hasViewSwitch: boolean = false;
|
||||
@Output() changeView = new EventEmitter<NgxExampleView>();
|
||||
|
||||
/* tslint:disable:no-unused-variable */
|
||||
@HostBinding('class.theme-default')
|
||||
private get isDefault() {
|
||||
return this.currentTheme === 'default';
|
||||
}
|
||||
|
||||
@HostBinding('class.theme-cosmic')
|
||||
private get isCosmic() {
|
||||
return this.currentTheme === 'cosmic';
|
||||
}
|
||||
|
||||
@HostBinding('class.theme-corporate')
|
||||
private get isCorporate() {
|
||||
return this.currentTheme === 'corporate';
|
||||
}
|
||||
/* tslint:enable:no-unused-variable */
|
||||
|
||||
iframeHeight = 0;
|
||||
alive: boolean = true;
|
||||
|
||||
themes: {label: string; value: string}[] = [
|
||||
{ label: 'Default', value: 'default' },
|
||||
{ label: 'Cosmic', value: 'cosmic' },
|
||||
{ label: 'Corporate', value: 'corporate' },
|
||||
];
|
||||
|
||||
currentTheme: string = 'default';
|
||||
loading = true;
|
||||
|
||||
get url(): string {
|
||||
return this.location.prepareExternalUrl(`example/${this.content.id}`);
|
||||
}
|
||||
|
||||
get iframeWindow(): Window {
|
||||
return this.iframe.nativeElement.contentWindow;
|
||||
}
|
||||
|
||||
constructor(private changeDetection: ChangeDetectorRef,
|
||||
private location: Location,
|
||||
private communicator: NgxIframeCommunicatorService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.communicator.receive(this.content.id)
|
||||
.pipe(takeWhile(() => this.alive))
|
||||
.subscribe(it => {
|
||||
this.iframeHeight = it.height;
|
||||
this.loading = false;
|
||||
this.changeDetection.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
// we cannot set src using angular binding
|
||||
// as it will trigger change detection and reload iframe
|
||||
// which in its turn will send a new height
|
||||
// and we would need to set the height and trigger change detection again
|
||||
// resulting in infinite loop
|
||||
this.iframe.nativeElement.src = this.url;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.alive = false;
|
||||
}
|
||||
|
||||
switchTheme(theme: string) {
|
||||
this.communicator.send({ id: this.content.id, theme }, this.iframeWindow);
|
||||
}
|
||||
|
||||
switchToInlineVew() {
|
||||
this.changeView.emit(NgxExampleView.INLINE);
|
||||
}
|
||||
}
|
||||
23
docs/app/blocks/components/md-block/md-block.component.ts
Normal file
23
docs/app/blocks/components/md-block/md-block.component.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-md-block',
|
||||
template: `
|
||||
<nb-card *ngFor="let section of source;" [ngxFragment]="section.fragment">
|
||||
<nb-card-body>
|
||||
<div [innerHtml]="section.html"></div>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxMdBLockComponent {
|
||||
|
||||
@Input() source: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-methods-block',
|
||||
template: `
|
||||
<h3>Methods</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="25%">Name</td>
|
||||
<td>Description</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ng-container *ngFor="let method of methods">
|
||||
<tr *ngIf="method.shortDescription || method.description">
|
||||
<td>{{ method.name }}() <br><i *ngIf="method.isStatic">static method</i></td>
|
||||
<td>
|
||||
<div class="method-signature">
|
||||
<div *ngIf="method.params.length > 0">
|
||||
<i>parameters:</i>
|
||||
<span *ngFor="let param of method.params; let last = last">
|
||||
{{ param.name }}: <code>{{ param.type }}</code><span *ngIf="!last">,</span>
|
||||
</span>
|
||||
</div>
|
||||
<i>returns:</i>
|
||||
<code>{{ method.type.join(",\\n") }}</code>
|
||||
</div>
|
||||
<div *ngIf="method.shortDescription || method.description" class="method-description" ngxDescription>
|
||||
{{ method.shortDescription }} <br> {{ method.description }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
</tbody>
|
||||
</table>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxMethodsBlockComponent {
|
||||
|
||||
methods: any;
|
||||
|
||||
@Input('source')
|
||||
set setSource(source: any) {
|
||||
this.methods = source.methods;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-overview-block',
|
||||
template: `
|
||||
<nb-card [ngxFragment]="source.slag">
|
||||
<nb-card-body>
|
||||
<ng-container class="description" *ngFor="let node of overview">
|
||||
<ng-container *ngIf="node.type === 'text'">
|
||||
<div *ngFor="let section of node.content" [innerHtml]="section.html"></div>
|
||||
</ng-container>
|
||||
<ngx-live-example-block *ngIf="node.type === 'live-example'" [content]="node.content"
|
||||
class="widget-block">
|
||||
</ngx-live-example-block>
|
||||
<ngx-inline-example-block *ngIf="node.type === 'inline-example'" [content]="node.content"
|
||||
class="widget-block">
|
||||
</ngx-inline-example-block>
|
||||
<ngx-stacked-example-block *ngIf="node.type === 'stacked-example'" [content]="node.content"
|
||||
class="widget-block">
|
||||
</ngx-stacked-example-block>
|
||||
</ng-container>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxOverviewBlockComponent {
|
||||
|
||||
source: any;
|
||||
overview: any[] = [];
|
||||
|
||||
@Input('source')
|
||||
set setSource(source: any) {
|
||||
this.source = source;
|
||||
this.overview = source.overview;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
@import '../../../@theme/styles/themes';
|
||||
@import '~@nebular/theme/styles/global/breakpoints';
|
||||
|
||||
|
||||
@include nb-install-component() {
|
||||
|
||||
$title-fg: nb-theme(color-fg-heading);
|
||||
$text-fg: nb-theme(color-fg-text);
|
||||
$arrow-fg: nb-theme(color-fg-highlight);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
::ng-deep nb-card {
|
||||
font-weight: 300;
|
||||
flex: 1;
|
||||
|
||||
&.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 2rem;
|
||||
text-decoration: none;
|
||||
color: $text-fg;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: $title-fg;
|
||||
font-weight: 500;
|
||||
font-size: 1.2rem;
|
||||
|
||||
i {
|
||||
color: $arrow-fg;
|
||||
margin-top: 0.3rem;
|
||||
font-weight: bold;
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
span {
|
||||
word-wrap: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.left-block {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
::ng-deep nb-card {
|
||||
margin-left: 1rem;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 2rem 3rem 2rem 2rem;
|
||||
}
|
||||
.page-title {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
.description {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import {Component, ChangeDetectionStrategy, Input} from '@angular/core';
|
||||
import { NgxPaginationService } from '../../../@theme/services/pagination.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-pager-block',
|
||||
styleUrls: ['./pager-block.component.scss'],
|
||||
template: `
|
||||
<ng-container *ngIf="paginationItem">
|
||||
<nb-card [class.invisible]="!paginationItem.prev" class="left-block">
|
||||
<a *ngIf="paginationItem.prev" [routerLink]="paginationItem.prev.link"
|
||||
[attr.title]="paginationItem.prev.title">
|
||||
<div class="page-title">
|
||||
<i class="icon nb-arrow-thin-left"></i>
|
||||
<span>{{ paginationItem.prev.title }}</span>
|
||||
</div>
|
||||
<div class="description">Previous page</div>
|
||||
</a>
|
||||
</nb-card>
|
||||
|
||||
<nb-card [class.invisible]="!paginationItem.next" class="right-block">
|
||||
<a *ngIf="paginationItem.next" [routerLink]="paginationItem.next.link"
|
||||
[attr.title]="paginationItem.next.title">
|
||||
<div class="page-title">
|
||||
<span>{{ paginationItem.next.title }}</span>
|
||||
<i class="icon nb-arrow-thin-right"></i>
|
||||
</div>
|
||||
<div class="description">Next page</div>
|
||||
</a>
|
||||
</nb-card>
|
||||
</ng-container>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxPagerBlockComponent {
|
||||
paginationItem;
|
||||
|
||||
@Input('currentItemSlag')
|
||||
set setPaginationItem(currentItemSlag: string) {
|
||||
this.paginationItem = this.getPaginationItem(currentItemSlag);
|
||||
}
|
||||
|
||||
constructor(private paginationService: NgxPaginationService) {
|
||||
}
|
||||
|
||||
getPaginationItem(currentItemSlag) {
|
||||
return this.paginationService.getPaginationItem(currentItemSlag);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-prop-block',
|
||||
template: `
|
||||
<h3>{{ name }}</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td width="25%">Name</td>
|
||||
<td width="20%">Type</td>
|
||||
<td>Description</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let prop of properties">
|
||||
<td>{{ prop.name }}</td>
|
||||
<td><code *ngIf="prop.type">{{ prop.type }}</code></td>
|
||||
<td>
|
||||
<div *ngIf="prop.shortDescription" ngxDescription>{{ prop.shortDescription }}</div>
|
||||
<div *ngIf="prop.description" ngxDescription>{{ prop.description }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxPropBlockComponent {
|
||||
|
||||
@Input() properties = [];
|
||||
@Input() name;
|
||||
@Input() slag;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-props-block',
|
||||
template: `
|
||||
<ngx-prop-block *ngIf="inputs.length > 0"
|
||||
[properties]="inputs"
|
||||
name="Inputs"
|
||||
[slag]="slag"
|
||||
class="widget-block">
|
||||
</ngx-prop-block>
|
||||
|
||||
<ngx-prop-block *ngIf="outputs.length > 0"
|
||||
[properties]="outputs"
|
||||
name="Outputs"
|
||||
[slag]="slag"
|
||||
class="widget-block">
|
||||
</ngx-prop-block>
|
||||
|
||||
<ngx-prop-block *ngIf="props.length > 0"
|
||||
[properties]="props"
|
||||
name="Properties"
|
||||
[slag]="slag"
|
||||
class="widget-block">
|
||||
</ngx-prop-block>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxPropsBlockComponent {
|
||||
outputs: any = [];
|
||||
inputs: any = [];
|
||||
props: any = [];
|
||||
name: string;
|
||||
slag: string;
|
||||
|
||||
@Input('source')
|
||||
set setSource(source: any) {
|
||||
this.inputs = source.props.filter(item => item.kind === 'input');
|
||||
this.outputs = source.props.filter(item => item.kind === 'output');
|
||||
this.props = source.props.filter(item => item.kind === 'property');
|
||||
this.name = source.name;
|
||||
this.slag = source.slag;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import { Component, Input } from '@angular/core';
|
||||
|
||||
import { NgxExampleView } from '../../enum.example-view';
|
||||
import { animate, animation, keyframes, style, transition, trigger, useAnimation } from '@angular/animations';
|
||||
|
||||
export const pulse = animation(
|
||||
animate(
|
||||
'{{ timing }}s {{ delay }}s',
|
||||
keyframes([
|
||||
style({ transform: 'scale3d(1, 1, 1)' }),
|
||||
style({ transform: 'scale3d({{ scale }}, {{ scale }}, {{ scale }})' }),
|
||||
style({ transform: 'scale3d(1, 1, 1)' }),
|
||||
]),
|
||||
),
|
||||
{ params: { scale: 1.02, timing: 0.5, delay: 0 } },
|
||||
);
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-stacked-example-block',
|
||||
template: `
|
||||
<div>
|
||||
<ngx-live-example-block [hidden]="!isLive"
|
||||
[@exampleState]="isLive ? 'live': 'code'"
|
||||
[content]="content"
|
||||
hasViewSwitch="true"
|
||||
(changeView)="changeView($event)">
|
||||
</ngx-live-example-block>
|
||||
|
||||
<ngx-tabbed-example-block [hidden]="isLive"
|
||||
[@exampleState]="isLive ? 'live': 'code'"
|
||||
[content]="content"
|
||||
hasViewSwitch="true"
|
||||
(changeView)="changeView($event)">
|
||||
</ngx-tabbed-example-block>
|
||||
</div>
|
||||
`,
|
||||
animations: [
|
||||
trigger('exampleState', [
|
||||
transition('live => code', [
|
||||
useAnimation(pulse),
|
||||
]),
|
||||
transition('code => live', [
|
||||
useAnimation(pulse),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class NgxStackedExampleComponent {
|
||||
|
||||
@Input() content: any;
|
||||
isLive = true;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
changeView(view: NgxExampleView) {
|
||||
this.isLive = view === NgxExampleView.LIVE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-styles-block',
|
||||
template: `
|
||||
<nb-card [ngxFragment]="source.slag">
|
||||
<nb-card-body>
|
||||
<h2>{{ source.name }}</h2>
|
||||
<ngx-styles-table-block [source]="source"></ngx-styles-table-block>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxStylesBlockComponent {
|
||||
|
||||
@Input() source;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { NgxStylesService } from '../../../@theme/services/styles.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-styles-table-block',
|
||||
template: `
|
||||
<table class="striped" *ngFor="let style of classStyles">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td *ngFor="let themedValue of style.styles[0].themedValues">{{ themedValue.theme }}</td>
|
||||
<td>Description</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let item of style.styles">
|
||||
<td>{{ item.name }}</td>
|
||||
<td *ngFor="let themedValue of item.themedValues" ngxColorSwatch>{{ themedValue.value }}</td>
|
||||
<td>
|
||||
<p *ngIf="item.shortDescription" ngxDescription>{{ item.shortDescription}}</p>
|
||||
<p *ngIf="item.description" ngxDescription>{{ item.description }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxStylesTableBlockComponent {
|
||||
|
||||
classStyles: any;
|
||||
|
||||
@Input('source')
|
||||
set setSource(source: any) {
|
||||
this.classStyles = this.stylesService.mapThemedValues(source.styles);
|
||||
}
|
||||
|
||||
constructor(private stylesService: NgxStylesService) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<ng-container [ngSwitch]="currentTab?.tab">
|
||||
<ng-container *ngFor="let component of source">
|
||||
|
||||
<ng-container *ngSwitchCase="'overview'">
|
||||
<ngx-overview-block *ngIf="hasOverview(component)" [source]="component"></ngx-overview-block>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'theme'">
|
||||
<ngx-styles-block *ngIf="hasTheme(component)" [source]="component"></ngx-styles-block>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'api'">
|
||||
<ngx-api-block *ngIf="hasAPI(component)" [source]="component" ></ngx-api-block>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'examples'">
|
||||
<ngx-examples-block *ngIf="hasExamples(component)" [source]="component" ></ngx-examples-block>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { BehaviorSubject, combineLatest } from 'rxjs';
|
||||
import { filter, takeWhile } from 'rxjs/operators';
|
||||
import { NgxTabbedService } from '../../../@theme/services/tabbed.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-tabbed-block',
|
||||
templateUrl: './tabbed-block.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxTabbedBlockComponent implements OnDestroy {
|
||||
|
||||
currentTab;
|
||||
|
||||
@Input() source;
|
||||
|
||||
@Input()
|
||||
set tabs(value) {
|
||||
if (value) {
|
||||
value = Object
|
||||
.entries(value)
|
||||
.filter(([key, val]) => val)
|
||||
.map(([key, val]) => ({ tab: key }));
|
||||
|
||||
this.tabs$.next(value);
|
||||
}
|
||||
}
|
||||
|
||||
private tabs$ = new BehaviorSubject(null);
|
||||
private alive = true;
|
||||
|
||||
constructor(private activatedRoute: ActivatedRoute,
|
||||
private router: Router,
|
||||
private cd: ChangeDetectorRef,
|
||||
private titleService: Title,
|
||||
private tabbedService: NgxTabbedService) {
|
||||
|
||||
combineLatest([
|
||||
this.activatedRoute.params.pipe(filter((params) => !params.tab)),
|
||||
this.tabs$.pipe(filter((tabs) => tabs && tabs.length)),
|
||||
])
|
||||
.pipe(takeWhile(() => this.alive))
|
||||
.subscribe(([params, tabs]) => {
|
||||
this.router.navigate([tabs[0].tab], { relativeTo: activatedRoute, replaceUrl: true });
|
||||
});
|
||||
|
||||
combineLatest([
|
||||
this.activatedRoute.params.pipe(filter((params) => params.tab)),
|
||||
this.tabs$.pipe(filter((tabs) => tabs && tabs.length)),
|
||||
])
|
||||
.pipe(takeWhile(() => this.alive))
|
||||
.subscribe(([params, tabs]) => {
|
||||
this.currentTab = tabs.find(tab => tab.tab === params.tab);
|
||||
if (this.currentTab) {
|
||||
this.titleService.setTitle(`${this.titleService.getTitle()} - component ${this.currentTab.tab}`);
|
||||
}
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
hasOverview(component) {
|
||||
return this.tabbedService.componentHasOverview(component);
|
||||
}
|
||||
|
||||
hasExamples(component) {
|
||||
return this.tabbedService.componentHasExamples(component);
|
||||
}
|
||||
|
||||
hasTheme(component) {
|
||||
return this.tabbedService.componentHasTheme(component);
|
||||
}
|
||||
|
||||
hasMethods(component) {
|
||||
return this.tabbedService.componentHasMethods(component);
|
||||
}
|
||||
|
||||
hasProps(component) {
|
||||
return this.tabbedService.componentHasProps(component);
|
||||
}
|
||||
|
||||
hasAPI(component) {
|
||||
return this.hasMethods(component) || this.hasProps(component);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.alive = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<button type="button"
|
||||
*ngIf="hasViewSwitch"
|
||||
class="btn action-item action-button"
|
||||
(click)="switchToLiveView()">
|
||||
<i class="icon feather-image"></i>
|
||||
<span class="text">Live view</span>
|
||||
</button>
|
||||
|
||||
<nb-tabset class="tabs-container">
|
||||
<nb-tab *ngFor="let example of examples" tabTitle="{{ example.extension }}" [active]="example.active">
|
||||
<ngx-code-block [path]="example.path" [code]="example.code"></ngx-code-block>
|
||||
</nb-tab>
|
||||
</nb-tabset>
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
@import '~@nebular/theme/styles/global/breakpoints';
|
||||
|
||||
@include nb-install-component() {
|
||||
|
||||
$tab-fg: nb-theme(color-fg-heading-light);
|
||||
$tab-active-fg: #ffffff;
|
||||
$tab-active-bg: linear-gradient(225deg, #333c66 0%, #1d2447 100%);
|
||||
$tabs-bb: #ebeff5;
|
||||
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
button {
|
||||
background: transparent;
|
||||
color: $tab-fg;
|
||||
text-transform: inherit;
|
||||
padding: 0.45rem 1.5rem;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
font-weight: normal;
|
||||
font-size: 0.9rem;
|
||||
|
||||
.icon {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
&:focus, &:active, &:hover {
|
||||
cursor: pointer;
|
||||
color: $tab-fg;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.text {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep nb-tabset.tabs-container {
|
||||
border-radius: 0.5rem 0.5rem 0 0;
|
||||
|
||||
> ul {
|
||||
padding: 0;
|
||||
margin-bottom: 0!important; // TODO: check selectors
|
||||
border-radius: 0.5rem 0.5rem 0 0;
|
||||
background-color: $tabs-bb;
|
||||
overflow: hidden;
|
||||
|
||||
li {
|
||||
padding: 0.4rem;
|
||||
width: 20%;
|
||||
margin-bottom: 0!important; // TODO: check selectors
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $tab-fg;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: $tab-active-bg;
|
||||
|
||||
a {
|
||||
color: $tab-active-fg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.container {
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(is) {
|
||||
button .text {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
} from '@angular/core';
|
||||
import { forkJoin, of as observableOf, Observable } from 'rxjs';
|
||||
import { map, catchError } from 'rxjs/operators';
|
||||
import { NgxExampleView } from '../../enum.example-view';
|
||||
import { NgxCodeLoaderService } from '../../../@theme/services/code-loader.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-tabbed-example-block',
|
||||
styleUrls: ['./tabbed-example-block.component.scss'],
|
||||
templateUrl: './tabbed-example-block.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxTabbedExampleBlockComponent {
|
||||
|
||||
|
||||
@Input() hasViewSwitch = false;
|
||||
@Output() changeView = new EventEmitter<NgxExampleView>();
|
||||
examples = [];
|
||||
|
||||
@Input()
|
||||
set content({ files }) {
|
||||
forkJoin(files.map(file => this.load(file)))
|
||||
.subscribe(loadedFiles => {
|
||||
(loadedFiles[0] as any).active = true;
|
||||
this.examples = loadedFiles;
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
constructor(private codeLoader: NgxCodeLoaderService, private cd: ChangeDetectorRef) {
|
||||
}
|
||||
|
||||
switchToLiveView() {
|
||||
this.changeView.emit(NgxExampleView.LIVE);
|
||||
}
|
||||
|
||||
private load(path): Observable<any> {
|
||||
const extension = path.split('.').pop();
|
||||
return this.codeLoader.load(path)
|
||||
.pipe(
|
||||
map(code => ({ code, path, extension })),
|
||||
catchError(e => observableOf('')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<nb-card>
|
||||
<nb-card-body>
|
||||
<h2>{{ vm.themeTitle }} Theme</h2>
|
||||
<p *ngIf="vm.parentTheme">inherited from {{ vm.parentTheme }} theme</p>
|
||||
|
||||
<div class="search-wrapper">
|
||||
<input class="search-control" placeholder="Search for..." [formControl]="searchControl">
|
||||
</div>
|
||||
|
||||
<table class="striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Value</td>
|
||||
<td>Parent</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr *ngFor="let prop of vm.filteredThemeProperties | async"
|
||||
[ngxFragment]="prop.name"
|
||||
[ngxFragmentSync]="false"
|
||||
ngxFragmentClass="highlighted-row">
|
||||
<td>
|
||||
<a [routerLink]="" fragment="{{ prop.name }}">{{ prop.name }}</a>
|
||||
</td>
|
||||
|
||||
<td ngxColorSwatch>{{ prop.value }}</td>
|
||||
|
||||
<td>
|
||||
<a [routerLink]="['/docs/themes', parent.theme]" fragment="{{ parent.prop }}"
|
||||
[class.inheritance-property]="index > 0"
|
||||
*ngFor="let parent of prop.parents; let index = index">
|
||||
<i *ngIf="index > 0" class="inheritance-icon feather-arrow-left"></i>
|
||||
<span>{{ parent.prop }}</span>
|
||||
<span *ngIf="parent.theme !== vm.themeName" class="parent-theme-name">({{ parent.theme }})</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</nb-card-body>
|
||||
</nb-card>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
@import '../../../@theme/styles/themes';
|
||||
|
||||
@include nb-install-component() {
|
||||
|
||||
$inherited-fg: nb-theme(color-fg);
|
||||
$search-fg: nb-theme(color-fg);
|
||||
$search-bg: nb-theme(color-white);
|
||||
$search-border: 1px solid nb-theme(color-gray-light);
|
||||
$selected-row-bg: nb-theme(color-gray-light);
|
||||
|
||||
.inheritance-icon {
|
||||
margin: 0 0.25rem;
|
||||
}
|
||||
|
||||
.inheritance-property {
|
||||
color: $inherited-fg;
|
||||
}
|
||||
|
||||
.parent-theme-name {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
.highlighted-row {
|
||||
background-color: $selected-row-bg !important;
|
||||
}
|
||||
|
||||
.search-control {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
color: $search-fg;
|
||||
background-color: $search-bg;
|
||||
background-clip: padding-box;
|
||||
border: $search-border;
|
||||
border-radius: 0.25rem;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Akveo. All Rights Reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { takeWhile, skip, distinctUntilChanged, debounceTime } from 'rxjs/operators';
|
||||
|
||||
import { ThemeBlockModel } from './theme-block.model';
|
||||
import { ThemeBlockViewModel } from './theme-block.viewmodel';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-theme-block',
|
||||
styleUrls: ['./theme-block.component.scss'],
|
||||
templateUrl: './theme-block.component.html',
|
||||
providers: [ThemeBlockModel, ThemeBlockViewModel],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NgxThemeComponent implements OnInit, OnDestroy {
|
||||
searchControl = new FormControl();
|
||||
|
||||
private alive: boolean = true;
|
||||
|
||||
@Input('block')
|
||||
set setBlock(block: any) {
|
||||
this.vm.themeTitle = block.name;
|
||||
this.vm.themeName = block.source.name;
|
||||
this.vm.parentTheme = block.source.parent;
|
||||
this.vm.themeProperties = block.source.data;
|
||||
}
|
||||
|
||||
constructor(public vm: ThemeBlockViewModel) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.searchControl.valueChanges
|
||||
.pipe(skip(1), distinctUntilChanged(), debounceTime(300), takeWhile(() => this.alive))
|
||||
.subscribe(value => this.vm.changeSearch(value));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.alive = false;
|
||||
}
|
||||
}
|
||||
25
docs/app/blocks/components/theme-block/theme-block.model.ts
Normal file
25
docs/app/blocks/components/theme-block/theme-block.model.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class ThemeBlockModel {
|
||||
themeTitle: string;
|
||||
themeName: string;
|
||||
parentTheme: string;
|
||||
themeProperties: any[];
|
||||
|
||||
setThemeTitle(value) {
|
||||
this.themeTitle = value;
|
||||
}
|
||||
|
||||
setThemeName(value) {
|
||||
this.themeName = value;
|
||||
}
|
||||
|
||||
setParentTheme(value) {
|
||||
this.parentTheme = value;
|
||||
}
|
||||
|
||||
setThemeProperties(value) {
|
||||
this.themeProperties = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Observable, BehaviorSubject, of as observableOf } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
|
||||
import { ThemeBlockModel } from './theme-block.model';
|
||||
|
||||
@Injectable()
|
||||
export class ThemeBlockViewModel {
|
||||
private searchChanges$ = new BehaviorSubject<string>(null);
|
||||
|
||||
constructor(private model: ThemeBlockModel) {}
|
||||
|
||||
changeSearch(value) {
|
||||
this.searchChanges$.next(value);
|
||||
}
|
||||
|
||||
get themeTitle(): string {
|
||||
return this.model.themeTitle;
|
||||
}
|
||||
|
||||
set themeTitle(value) {
|
||||
this.model.setThemeTitle(value);
|
||||
}
|
||||
|
||||
get themeName(): string {
|
||||
return this.model.themeName;
|
||||
}
|
||||
|
||||
set themeName(value) {
|
||||
this.model.setThemeName(value);
|
||||
}
|
||||
|
||||
get parentTheme(): string {
|
||||
return this.model.parentTheme;
|
||||
}
|
||||
|
||||
set parentTheme(value) {
|
||||
this.model.setParentTheme(value);
|
||||
}
|
||||
|
||||
get themeProperties(): any[] {
|
||||
return this.model.themeProperties;
|
||||
}
|
||||
|
||||
set themeProperties(value) {
|
||||
const result = Object.entries(value).map(([key, data]) => {
|
||||
const propertyValue = data['value'];
|
||||
return {
|
||||
name: key,
|
||||
value: Array.isArray(propertyValue) ? propertyValue.join(' ') : propertyValue,
|
||||
parents: data['parents'],
|
||||
};
|
||||
});
|
||||
this.model.setThemeProperties(result);
|
||||
}
|
||||
|
||||
get filteredThemeProperties(): Observable<any[]> {
|
||||
return this.searchChanges$.asObservable().pipe(
|
||||
switchMap(value => {
|
||||
if (value) {
|
||||
return observableOf(
|
||||
this.themeProperties.filter(({ name }) => name.toLowerCase().includes(value.toLowerCase())),
|
||||
);
|
||||
}
|
||||
return observableOf(this.themeProperties);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
4
docs/app/blocks/enum.example-view.ts
Normal file
4
docs/app/blocks/enum.example-view.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export enum NgxExampleView {
|
||||
LIVE = 'live',
|
||||
INLINE = 'inline',
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue