├── src ├── assets │ └── .gitkeep ├── favicon.ico ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── app │ ├── features │ │ ├── home │ │ │ ├── home.ts │ │ │ └── home.html │ │ ├── spinner │ │ │ ├── spinner-demo.ts │ │ │ └── spinner-demo.html │ │ ├── snackbar │ │ │ ├── snackbar-demo.html │ │ │ └── snackbar-demo.ts │ │ ├── progress-bar │ │ │ ├── progress-bar-demo.ts │ │ │ └── progress-bar-demo.html │ │ ├── modal-search │ │ │ ├── modal-search-demo.ts │ │ │ └── modal-search-demo.html │ │ ├── paginator │ │ │ ├── paginator-demo.ts │ │ │ └── paginator-demo.html │ │ ├── debounce │ │ │ ├── debounce-demo.ts │ │ │ └── debounce-demo.html │ │ ├── sort │ │ │ ├── sort-demo.scss │ │ │ ├── sort-demo.html │ │ │ └── sort-demo.ts │ │ ├── table │ │ │ ├── table-demo.scss │ │ │ ├── table-demo.html │ │ │ └── table-demo.ts │ │ ├── tooltip │ │ │ ├── tooltip-demo.ts │ │ │ └── tooltip-demo.html │ │ ├── tabs │ │ │ ├── tabs-demo.component.ts │ │ │ └── tabs-demo.component.html │ │ ├── dialog │ │ │ ├── edit-user-dialog-demo.component.html │ │ │ ├── fake-dialog-demo.component.ts │ │ │ ├── edit-user-dialog-demo.component.ts │ │ │ ├── dialog-demo.html │ │ │ └── dialog-demo.ts │ │ ├── animated-card │ │ │ ├── animated-card-demo.ts │ │ │ └── animated-card-demo.html │ │ ├── switch │ │ │ ├── switch-demo.ts │ │ │ └── switch-demo.html │ │ ├── alert │ │ │ ├── alert-demo.ts │ │ │ └── alert-demo.html │ │ ├── dropdown │ │ │ ├── dropdown-demo.html │ │ │ └── dropdown-demo.ts │ │ └── edit-in-place │ │ │ ├── edit-in-place-demo.html │ │ │ └── edit-in-place-demo.ts │ ├── app.component.scss │ ├── doc-preview │ │ ├── doc-preview.component.ts │ │ ├── doc-preview.component.html │ │ └── doc-preview.component.scss │ ├── app.component.ts │ ├── app.component.spec.ts │ ├── app.component.html │ ├── app-routing.module.ts │ ├── app.module.ts │ └── services │ │ └── modal-search.service.ts ├── tslint.json ├── main.ts ├── index.html ├── test.ts ├── styles.scss └── polyfills.ts ├── .husky └── pre-commit ├── .prettierrc.json ├── .firebaserc ├── projects └── ng-wizi-bulma │ ├── src │ ├── lib │ │ ├── shared │ │ │ ├── pipes │ │ │ │ ├── index.ts │ │ │ │ └── safe-html.pipe.ts │ │ │ ├── components │ │ │ │ ├── index.ts │ │ │ │ └── spinner │ │ │ │ │ ├── spinner.component.html │ │ │ │ │ ├── spinner.component.ts │ │ │ │ │ └── spinner.component.scss │ │ │ ├── directives │ │ │ │ ├── index.ts │ │ │ │ ├── tooltip │ │ │ │ │ └── tooltip.directive.ts │ │ │ │ └── debounce │ │ │ │ │ └── debounce.directive.ts │ │ │ ├── services │ │ │ │ ├── index.ts │ │ │ │ └── filter-routing │ │ │ │ │ ├── model.ts │ │ │ │ │ └── filter-routing-group.service.ts │ │ │ ├── index.ts │ │ │ ├── portal │ │ │ │ └── portal-injector.ts │ │ │ ├── util │ │ │ │ ├── object-extend.ts │ │ │ │ └── object-extend.spec.ts │ │ │ ├── common-module.ts │ │ │ ├── overlay │ │ │ │ └── overlay-container.ts │ │ │ └── dom │ │ │ │ └── dom.service.ts │ │ ├── switch │ │ │ ├── switch.component.scss │ │ │ ├── index.ts │ │ │ ├── switch.component.html │ │ │ ├── switch-module.ts │ │ │ └── switch.component.ts │ │ ├── progress-bar │ │ │ ├── index.ts │ │ │ ├── progress-bar-module.ts │ │ │ ├── progress-bar.component.html │ │ │ └── progress-bar.component.ts │ │ ├── animated-card │ │ │ ├── index.ts │ │ │ ├── animated-card-module.ts │ │ │ ├── animated-card.component.ts │ │ │ └── animated-card.component.scss │ │ ├── edit-in-place │ │ │ ├── index.ts │ │ │ ├── edit-in-place-module.ts │ │ │ ├── edit-in-place.component.html │ │ │ └── edit-in-place.component.scss │ │ ├── alert │ │ │ ├── index.ts │ │ │ ├── alert.component.html │ │ │ ├── alert-module.ts │ │ │ ├── alert.service.ts │ │ │ ├── alert.component.ts │ │ │ └── alert.component.scss │ │ ├── tabs │ │ │ ├── index.ts │ │ │ ├── tab.component.ts │ │ │ ├── tabs-module.ts │ │ │ └── tabs.component.ts │ │ ├── dialog │ │ │ ├── index.ts │ │ │ ├── dialog-module.ts │ │ │ ├── dialog.component.scss │ │ │ ├── dialog.component.html │ │ │ └── dialog.service.ts │ │ ├── dropdown │ │ │ ├── index.ts │ │ │ ├── dropdown.component.scss │ │ │ ├── dropdown-module.ts │ │ │ ├── dropdown.component.html │ │ │ └── option.component.ts │ │ ├── paginator │ │ │ ├── index.ts │ │ │ ├── paginator-module.ts │ │ │ ├── paginator.component.scss │ │ │ ├── paginator-intl.ts │ │ │ └── paginator.component.html │ │ ├── snackbar │ │ │ ├── index.ts │ │ │ ├── snackbar-module.ts │ │ │ ├── snackbar.component.html │ │ │ ├── snackbar.component.scss │ │ │ ├── snackbar.service.ts │ │ │ └── snackbar.component.ts │ │ ├── date-picker │ │ │ ├── date-picker.component.scss │ │ │ ├── date-picker.component.html │ │ │ ├── date-picker-intl.ts │ │ │ ├── index.ts │ │ │ ├── date-picker-input-date-type.directive.ts │ │ │ ├── date-picker-format.ts │ │ │ ├── date-picker-module.ts │ │ │ ├── date-picker-input-start.directive.ts │ │ │ ├── date-picker-input-end.directive.ts │ │ │ ├── date-picker-default-settings.ts │ │ │ └── date-picker-input-base.directive.ts │ │ ├── modal-search │ │ │ ├── index.ts │ │ │ ├── modal-search-module.ts │ │ │ ├── modal-search.component.html │ │ │ ├── modal-search.component.scss │ │ │ └── modal-search.service.ts │ │ ├── sort │ │ │ ├── sort-header.component.scss │ │ │ ├── index.ts │ │ │ ├── sort-direction.ts │ │ │ ├── sort-module.ts │ │ │ ├── sort-header.component.html │ │ │ ├── sort-errors.ts │ │ │ └── sort-animation.ts │ │ └── nwb-all-module.ts │ ├── test.ts │ └── public_api.ts │ ├── ng-package.prod.json │ ├── tsconfig.lib.prod.json │ ├── ng-package.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── package.json │ ├── .eslintrc.json │ └── karma.conf.js ├── tsconfig.app.json ├── tsconfig.spec.json ├── .editorconfig ├── .browserslistrc ├── firebase.json ├── scripts └── scss-bundle.js ├── .gitignore ├── protractor.conf.js ├── tsconfig.json ├── LICENSE ├── karma.conf.js ├── .eslintrc.json ├── README.md └── package.json /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx pretty-quick --staged 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 140, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "ng-wizi-bulma" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WiziShop/ng-wizi-bulma/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/pipes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './safe-html.pipe'; 2 | 3 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './spinner/spinner.component'; 2 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/switch/switch.component.scss: -------------------------------------------------------------------------------- 1 | .switch[type=checkbox] { 2 | max-width: 0; 3 | } 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/switch/index.ts: -------------------------------------------------------------------------------- 1 | export * from './switch.component'; 2 | export * from './switch-module'; 3 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/progress-bar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './progress-bar.component'; 2 | export * from './progress-bar-module'; 3 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/animated-card/index.ts: -------------------------------------------------------------------------------- 1 | export * from './animated-card.component'; 2 | export * from './animated-card-module'; 3 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/edit-in-place/index.ts: -------------------------------------------------------------------------------- 1 | export * from './edit-in-place.component'; 2 | export * from './edit-in-place-module'; 3 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/alert/index.ts: -------------------------------------------------------------------------------- 1 | export * from './alert.service'; 2 | export * from './alert.component'; 3 | export * from './alert-module'; 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/components/spinner/spinner.component.html: -------------------------------------------------------------------------------- 1 |
4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/directives/index.ts: -------------------------------------------------------------------------------- 1 | export * from './debounce/debounce.directive'; 2 | export * from './tooltip/tooltip.directive'; 3 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/tabs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tab.component'; 2 | export * from './tabs.component'; 3 | export * from './tabs-module'; 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dialog.component'; 2 | export * from './dialog.service'; 3 | export * from './dialog-module'; 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './filter-routing/model'; 2 | export * from './filter-routing/filter-routing-group.service'; 3 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dropdown/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dropdown.component'; 2 | export * from './option.component'; 3 | export * from './dropdown-module'; 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/paginator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './paginator-intl'; 2 | export * from './paginator.component'; 3 | export * from './paginator-module'; 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/snackbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './snackbar.service'; 2 | export * from './snackbar.component'; 3 | export * from './snackbar-module'; 4 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker.component.scss: -------------------------------------------------------------------------------- 1 | .datetimepicker-footer-validate { 2 | // These buttons are useless, so hide them 3 | display: none; 4 | } 5 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/modal-search/index.ts: -------------------------------------------------------------------------------- 1 | export * from './modal-search.component'; 2 | export * from './modal-search.service'; 3 | export * from './modal-search-module'; 4 | -------------------------------------------------------------------------------- /src/app/features/home/home.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | providers: [], 5 | templateUrl: './home.html' 6 | }) 7 | export class Home {} 8 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/sort/sort-header.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-sort-header-container { 2 | cursor: pointer; 3 | 4 | .nwb-sort-header-arrow { 5 | padding-left: 5px; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | -------------------------------------------------------------------------------- /src/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tslint.json", 3 | "rules": { 4 | "directive-selector": [true, "attribute", "", "camelCase"], 5 | "component-selector": [true, "element", "", "kebab-case"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 5px; 3 | } 4 | 5 | // Material icon fix 6 | .icon.is-small i { 7 | font-size: 0.75rem; 8 | } 9 | 10 | .icon.is-texttop { 11 | vertical-align: text-top; 12 | } 13 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components/index'; 2 | export * from './directives/index'; 3 | export * from './services/index'; 4 | export * from './pipes/index'; 5 | export * from './common-module'; 6 | 7 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/@wizishop/ng-wizi-bulma", 4 | "lib": { 5 | "entryFile": "src/public_api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/sort/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sort-animation'; 2 | export * from './sort-direction'; 3 | export * from './sort-errors'; 4 | export * from './sort-header.component'; 5 | export * from './sort'; 6 | export * from './sort-module'; 7 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/@wizishop/ng-wizi-bulma", 4 | "deleteDestPath": false, 5 | "lib": { 6 | "entryFile": "src/public_api.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/app/features/spinner/spinner-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | providers: [], 5 | templateUrl: './spinner-demo.html' 6 | }) 7 | export class SpinnerDemo { 8 | customColor = '#f49a00'; 9 | 10 | constructor() {} 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": ["jasmine", "node"] 6 | }, 7 | "files": ["src/test.ts", "src/polyfills.ts"], 8 | "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": ["jasmine", "node"] 6 | }, 7 | "files": ["src/test.ts"], 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/sort/sort-direction.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google LLC All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | export type SortDirection = 'asc' | 'desc' | ''; 10 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-intl.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ providedIn: 'root' }) 4 | export class NwbDatePickerIntl { 5 | closeLabel = 'Close'; 6 | clearLabel = 'Clear'; 7 | todayLabel = 'Today'; 8 | nowLabel = 'Now'; 9 | labelFrom = ''; 10 | labelTo = ''; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/features/snackbar/snackbar-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Snackbar 5 |

6 |
7 |
8 |
9 | 10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /src/app/features/progress-bar/progress-bar-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | providers: [], 5 | templateUrl: './progress-bar-demo.html' 6 | }) 7 | export class ProgressBarDemo { 8 | color: 'primary' | 'info' | 'warning' | 'danger' = 'primary'; 9 | mode: 'indeterminate' | 'determinate' = 'indeterminate'; 10 | value = 50; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/doc-preview/doc-preview.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'nwb-doc-preview', 5 | templateUrl: './doc-preview.component.html', 6 | styleUrls: ['./doc-preview.component.scss'] 7 | }) 8 | export class DocPreviewComponent { 9 | @Input() 10 | content: string; 11 | @Input() 12 | revertSize = false; 13 | } 14 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/switch/switch.component.html: -------------------------------------------------------------------------------- 1 |
2 | 7 | 11 |
12 | -------------------------------------------------------------------------------- /src/app/doc-preview/doc-preview.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 |
 8 |         {{content}}
 9 |       
10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch(err => console.error(err)); 14 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/pipes/safe-html.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { DomSanitizer } from '@angular/platform-browser'; 3 | 4 | @Pipe({ name: 'safeHtml' }) 5 | export class SafeHtmlPipe implements PipeTransform { 6 | constructor(private sanitized: DomSanitizer) {} 7 | 8 | transform(value: string) { 9 | return this.sanitized.bypassSecurityTrustHtml(value); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ModalSearchService } from './services/modal-search.service'; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | templateUrl: './app.component.html', 7 | styleUrls: ['./app.component.scss'] 8 | }) 9 | export class AppComponent { 10 | constructor(private modalSearchService: ModalSearchService) {} 11 | 12 | openModalSearch() { 13 | this.modalSearchService.modalSearch.open(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './date-picker.component'; 2 | export * from './date-picker-default-settings'; 3 | export * from './date-picker-format'; 4 | export * from './date-picker-input-base.directive'; 5 | export * from './date-picker-input-end.directive'; 6 | export * from './date-picker-input-start.directive'; 7 | export * from './date-picker-input-date-type.directive'; 8 | export * from './date-picker-intl'; 9 | export * from './date-picker-module'; 10 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/alert/alert.component.html: -------------------------------------------------------------------------------- 1 |
5 |
6 | 7 | 8 | 9 |

10 |
11 |
12 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/tabs/tab.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'nwb-tab', 5 | template: ` 6 | 7 | 8 | ` 9 | }) 10 | export class NwbTabComponent { 11 | @Input() 12 | label: string; 13 | @Input() 14 | icon: string; 15 | index: number; 16 | 17 | isSelected: boolean; 18 | 19 | setSelected(isSelected: boolean) { 20 | this.isSelected = isSelected; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/features/modal-search/modal-search-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ModalSearchService } from '../../services/modal-search.service'; 3 | 4 | @Component({ 5 | providers: [], 6 | templateUrl: './modal-search-demo.html' 7 | }) 8 | export class ModalSearchDemo { 9 | constructor(public modalSearchService: ModalSearchService) {} 10 | 11 | toggleEnabled() { 12 | this.modalSearchService.modalSearch.enabled = !this.modalSearchService.modalSearch.enabled; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/app/features/paginator/paginator-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NwbPageEvent } from 'projects/ng-wizi-bulma/src/public_api'; 3 | 4 | @Component({ 5 | providers: [], 6 | templateUrl: './paginator-demo.html' 7 | }) 8 | export class PaginatorDemo { 9 | length = 10000; 10 | pageSize = 25; 11 | pageSizeOptions = [5, 10, 25, 100]; 12 | 13 | constructor() {} 14 | 15 | pageChange(pageEvent: NwbPageEvent) { 16 | console.log('Page change', pageEvent); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dropdown/dropdown.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-dropdown { 2 | a.is-disabled { 3 | pointer-events: none; 4 | background-color: whitesmoke; 5 | color: #7a7a7a; 6 | } 7 | .right-to-left { 8 | .dropdown-menu { 9 | left: auto; 10 | right: 0; 11 | } 12 | } 13 | .dropdown-content { 14 | padding-top: 0; 15 | padding-bottom: 0; 16 | } 17 | a.dropdown-item.is-active, button.dropdown-item.is-active { 18 | background-color: #329cc0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ng Wizi Bulma 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/progress-bar/progress-bar-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { NwbCommonModule } from '../shared/common-module'; 4 | import { NwbProgressBarComponent } from './progress-bar.component'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule, NwbCommonModule], 8 | providers: [], 9 | declarations: [NwbProgressBarComponent], 10 | exports: [NwbProgressBarComponent] 11 | }) 12 | export class NwbProgressBarModule {} 13 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/animated-card/animated-card-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NwbCommonModule } from '../shared/common-module'; 4 | import { NwbAnimatedCardComponent } from './animated-card.component'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule, NwbCommonModule], 8 | providers: [], 9 | declarations: [NwbAnimatedCardComponent], 10 | exports: [NwbAnimatedCardComponent] 11 | }) 12 | export class NwbAnimatedCardModule {} 13 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 6 | 7 | // First, initialize the Angular testing environment. 8 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { 9 | teardown: { destroyAfterEach: false } 10 | }); 11 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/alert/alert-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NwbAlertService } from './alert.service'; 4 | import { NwbAlertComponent } from './alert.component'; 5 | import { NwbCommonModule } from '../shared/common-module'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, NwbCommonModule], 9 | providers: [NwbAlertService], 10 | declarations: [NwbAlertComponent], 11 | exports: [NwbAlertComponent] 12 | }) 13 | export class NwbAlertModule {} 14 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/switch/switch-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { NwbCommonModule } from '../shared/common-module'; 4 | import { NwbSwitchComponent } from './switch.component'; 5 | import { FormsModule } from '@angular/forms'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, FormsModule, NwbCommonModule], 9 | providers: [], 10 | declarations: [NwbSwitchComponent], 11 | exports: [NwbSwitchComponent] 12 | }) 13 | export class NwbSwitchModule {} 14 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/progress-bar/progress-bar.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dialog/dialog-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NwbDialogComponent } from './dialog.component'; 4 | import { NwbDialogService } from './dialog.service'; 5 | import { NwbCommonModule } from '../shared/common-module'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, NwbCommonModule], 9 | providers: [NwbDialogService], 10 | declarations: [NwbDialogComponent], 11 | exports: [NwbDialogComponent] 12 | }) 13 | export class NwbDialogModule {} 14 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/tabs/tabs-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { NwbTabComponent } from './tab.component'; 4 | import { NwbTabsComponent } from './tabs.component'; 5 | import { NwbCommonModule } from '../shared/common-module'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, NwbCommonModule], 9 | providers: [], 10 | declarations: [NwbTabsComponent, NwbTabComponent], 11 | exports: [NwbTabsComponent, NwbTabComponent] 12 | }) 13 | export class NwbTabsModule {} 14 | -------------------------------------------------------------------------------- /src/app/doc-preview/doc-preview.component.scss: -------------------------------------------------------------------------------- 1 | figure { 2 | display: flex; 3 | align-items: center; 4 | align-content: center; 5 | } 6 | 7 | pre { 8 | padding: 0; 9 | } 10 | 11 | code { 12 | display: flex; 13 | align-content: flex-start; 14 | align-items: flex-start; 15 | justify-content: flex-start; 16 | text-align: left; 17 | } 18 | 19 | .bd-snippet.bd-is-vertical.bd-is-one-third.revert-size .bd-snippet-preview { 20 | width: 50%; 21 | } 22 | 23 | .bd-snippet.bd-is-vertical.bd-is-one-third.revert-size .bd-snippet-code { 24 | width: 50%; 25 | } 26 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist/demo/browser", 4 | "rewrites": [ 5 | { 6 | "source": "/**/!(*.@(js|ts|html|css|json|svg|png|jpg|jpeg))", 7 | "destination": "/index.html" 8 | } 9 | ], 10 | "headers": [ 11 | { 12 | "source": "*", 13 | "headers": [ 14 | { 15 | "key": "Cache-Control", 16 | "value": "no-cache" 17 | } 18 | ] 19 | } 20 | ], 21 | "ignore": ["firebase.json", "**/.*", "**/node_modules/**", "tmp", "deploy"] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/paginator/paginator-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { NwbPaginatorComponent } from './paginator.component'; 4 | import { NwbPaginatorIntl } from './paginator-intl'; 5 | import { NwbCommonModule } from '../shared/common-module'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, NwbCommonModule], 9 | providers: [NwbPaginatorIntl], 10 | declarations: [NwbPaginatorComponent], 11 | exports: [NwbPaginatorComponent] 12 | }) 13 | export class NwbPaginatorModule {} 14 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/snackbar/snackbar-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { NwbSnackbarService } from './snackbar.service'; 4 | import { NwbSnackbarComponent } from './snackbar.component'; 5 | import { NwbCommonModule } from '../shared/common-module'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, NwbCommonModule], 9 | providers: [NwbSnackbarService], 10 | declarations: [NwbSnackbarComponent], 11 | exports: [NwbSnackbarComponent] 12 | }) 13 | export class NwbSnackbarModule {} 14 | -------------------------------------------------------------------------------- /src/app/features/debounce/debounce-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | providers: [], 5 | templateUrl: './debounce-demo.html' 6 | }) 7 | export class DebounceDemo { 8 | inputValue = 'Default Value'; 9 | 10 | valueFromNwbDebounceChangeEvent = ''; 11 | 12 | constructor() {} 13 | 14 | valueChange(value: any) { 15 | console.log('Value change from nwbDebounceChange event', value); 16 | this.valueFromNwbDebounceChangeEvent = value; 17 | } 18 | 19 | setRandomValue() { 20 | this.inputValue += Math.random().toString(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-input-date-type.directive.ts: -------------------------------------------------------------------------------- 1 | /** Directive used to connect an input to a MatDatepicker. */ 2 | import { Directive, ElementRef, Input } from '@angular/core'; 3 | import { NwbDatePickerInputBaseDirective } from './date-picker-input-base.directive'; 4 | 5 | @Directive({ 6 | selector: 'input[nwbDateType]', 7 | }) 8 | export class NwbDatePickerInputDateTypeDirective extends NwbDatePickerInputBaseDirective { 9 | @Input() override nwbDateType; 10 | 11 | constructor(public override elementRef: ElementRef) { 12 | super(elementRef); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dropdown/dropdown-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NwbCommonModule } from '../shared/common-module'; 4 | import { NwbDropdownComponent } from './dropdown.component'; 5 | import { NwbOptionComponent } from './option.component'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, NwbCommonModule], 9 | providers: [], 10 | declarations: [NwbDropdownComponent, NwbOptionComponent], 11 | exports: [NwbDropdownComponent, NwbOptionComponent] 12 | }) 13 | export class NwbDropdownModule {} 14 | -------------------------------------------------------------------------------- /src/app/features/home/home.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Ng Wizi Bulma 5 |

6 |
7 |
8 |
9 |

Bulma components for Angular

10 |

This is the demo website of all Ng Wizi Bulma components.

11 |

For more information about each one check out the 12 | project's code on GitHub

13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js'; 5 | import 'zone.js/testing'; 6 | import { getTestBed } from '@angular/core/testing'; 7 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 8 | 9 | // First, initialize the Angular testing environment. 10 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { 11 | teardown: { destroyAfterEach: false } 12 | }); 13 | -------------------------------------------------------------------------------- /src/app/features/sort/sort-demo.scss: -------------------------------------------------------------------------------- 1 | /* Structure */ 2 | .example-container { 3 | position: relative; 4 | } 5 | 6 | .example-table-container { 7 | position: relative; 8 | max-height: 400px; 9 | overflow: auto; 10 | } 11 | 12 | .example-loading-shade { 13 | position: absolute; 14 | top: 0; 15 | left: 0; 16 | bottom: 56px; 17 | right: 0; 18 | background: rgba(0, 0, 0, 0.05); 19 | z-index: 1; 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | 25 | .example-rate-limit-reached { 26 | color: #980000; 27 | max-width: 360px; 28 | text-align: center; 29 | } 30 | -------------------------------------------------------------------------------- /src/app/features/table/table-demo.scss: -------------------------------------------------------------------------------- 1 | /* Structure */ 2 | .example-container { 3 | position: relative; 4 | } 5 | 6 | .example-table-container { 7 | position: relative; 8 | max-height: 400px; 9 | overflow: auto; 10 | } 11 | 12 | .example-loading-shade { 13 | position: absolute; 14 | top: 0; 15 | left: 0; 16 | bottom: 56px; 17 | right: 0; 18 | background: rgba(0, 0, 0, 0.05); 19 | z-index: 1; 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | 25 | .example-rate-limit-reached { 26 | color: #980000; 27 | max-width: 360px; 28 | text-align: center; 29 | } 30 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/sort/sort-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { CdkTableModule } from '@angular/cdk/table'; 4 | import { NwbSortHeaderComponent } from './sort-header.component'; 5 | import { NwbSort } from './sort'; 6 | import { NwbCommonModule } from '../shared/common-module'; 7 | 8 | @NgModule({ 9 | imports: [CommonModule, NwbCommonModule, CdkTableModule], 10 | providers: [], 11 | declarations: [NwbSort, NwbSortHeaderComponent], 12 | exports: [NwbSort, NwbSortHeaderComponent] 13 | }) 14 | export class NwbSortModule {} 15 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/edit-in-place/edit-in-place-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { NwbEditInPlaceComponent } from './edit-in-place.component'; 4 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 5 | import { NwbCommonModule } from '../shared/common-module'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule, NwbCommonModule, FormsModule, ReactiveFormsModule], 9 | providers: [], 10 | declarations: [NwbEditInPlaceComponent], 11 | exports: [NwbEditInPlaceComponent] 12 | }) 13 | export class NwbEditInPlaceModule {} 14 | -------------------------------------------------------------------------------- /scripts/scss-bundle.js: -------------------------------------------------------------------------------- 1 | const bundleScss = require('bundle-scss'); 2 | const colors = require('colors'); 3 | 4 | function ScssBundlePlugin(options) { 5 | options.paths.forEach(v => { 6 | const bundle = async () => { 7 | await bundleScss(options.glob, v, options.scss); 8 | }; 9 | bundle().then(() => { 10 | console.log(colors.green('Main scss prepared with success.' + colors.rainbow("It's time to be beautiful !"))); 11 | }); 12 | }); 13 | } 14 | 15 | new ScssBundlePlugin({ 16 | glob: './projects/ng-wizi-bulma/src/**/*.scss', 17 | paths: ['./dist/@wizishop/ng-wizi-bulma/ng-wizi-bulma.scss'], 18 | scss: ['colors'] 19 | }); 20 | -------------------------------------------------------------------------------- /src/app/features/tooltip/tooltip-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | providers: [], 5 | templateUrl: './tooltip-demo.html' 6 | }) 7 | export class TooltipDemo { 8 | sample1 = ``; 9 | sample2 = ``; 10 | sample3 = ``; 11 | } 12 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/modal-search/modal-search-module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { NwbModalSearchComponent } from './modal-search.component'; 4 | import { NwbModalSearchService } from './modal-search.service'; 5 | import { NwbCommonModule } from '../shared/common-module'; 6 | import { FormsModule } from '@angular/forms'; 7 | 8 | @NgModule({ 9 | imports: [CommonModule, FormsModule, NwbCommonModule], 10 | providers: [NwbModalSearchService], 11 | declarations: [NwbModalSearchComponent], 12 | exports: [NwbModalSearchComponent] 13 | }) 14 | export class NwbModalSearchModule {} 15 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/sort/sort-header.component.html: -------------------------------------------------------------------------------- 1 |
5 | 6 | 12 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/components/spinner/spinner.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'nwb-spinner', 5 | templateUrl: './spinner.component.html', 6 | host: { 7 | class: 'nwb-spinner' 8 | }, 9 | encapsulation: ViewEncapsulation.None 10 | }) 11 | export class NwbSpinnerComponent implements OnInit { 12 | @Input() 13 | color: string; 14 | 15 | private availableColors = ['#a2c739', '#dbdbdb', '#00d1b2', '#4baed0']; 16 | 17 | ngOnInit() { 18 | if (!this.color) { 19 | this.color = this.availableColors[Math.floor(Math.random() * this.availableColors.length)]; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/snackbar/snackbar.component.html: -------------------------------------------------------------------------------- 1 |
5 |
6 |
8 |
9 |
10 | 13 | 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/edit-in-place/edit-in-place.component.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | {{currentValue}} 7 | 8 | 9 | 22 | 23 | 24 |
25 | -------------------------------------------------------------------------------- /src/app/features/spinner/spinner-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Spinner with random color 5 |

6 |
7 |
8 |
9 | 10 |
11 |
12 |
13 | 14 |
15 |
16 |

17 | Spinner with custom color : {{customColor}} 18 |

19 |
20 |
21 |
22 | 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/public_api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ng-wizi-bulma 3 | */ 4 | 5 | export * from './lib/shared/index'; 6 | 7 | export * from './lib/alert/index'; 8 | export * from './lib/animated-card/index'; 9 | export * from './lib/dialog/index'; 10 | export * from './lib/dropdown/index'; 11 | export * from './lib/edit-in-place/index'; 12 | export * from './lib/modal-search/index'; 13 | export * from './lib/paginator/index'; 14 | export * from './lib/progress-bar/index'; 15 | export * from './lib/snackbar/index'; 16 | export * from './lib/sort/index'; 17 | export * from './lib/switch/index'; 18 | export * from './lib/tabs/index'; 19 | export * from './lib/date-picker/index'; 20 | 21 | export * from './lib/nwb-all-module'; 22 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "declarationMap": true, 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "experimentalDecorators": true, 12 | "importHelpers": true, 13 | "types": [], 14 | "lib": ["dom", "es2018"] 15 | }, 16 | "angularCompilerOptions": { 17 | "skipTemplateCodegen": true, 18 | "strictMetadataEmit": true, 19 | "fullTemplateTypeCheck": true, 20 | "strictInjectionParameters": true, 21 | "enableResourceInlining": true 22 | }, 23 | "exclude": ["src/test.ts", "**/*.spec.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.angular/cache 29 | /.sass-cache 30 | /connect.lock 31 | /coverage 32 | /libpeerconnection.log 33 | npm-debug.log 34 | testem.log 35 | /typings 36 | 37 | # e2e 38 | /e2e/*.js 39 | /e2e/*.map 40 | 41 | # System Files 42 | .DS_Store 43 | Thumbs.db 44 | /src/ng-wizi-bulma/ 45 | 46 | .firebase 47 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/components/spinner/spinner.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-spinner { 2 | display: block; 3 | .is-spinning { 4 | animation: spinIt 500ms infinite linear; 5 | border: 2px solid white; 6 | border-radius: 290486px; 7 | border-right-color: transparent !important; 8 | border-top-color: transparent !important; 9 | content: ''; 10 | display: block; 11 | height: 2rem; 12 | width: 2rem; 13 | left: 50%; 14 | margin-left: -8px; 15 | margin-top: -8px; 16 | top: 50%; 17 | position: relative !important; 18 | padding-top: 10px; 19 | padding-bottom: 10px; 20 | } 21 | 22 | @keyframes spinIt { 23 | from { 24 | transform: rotate(0deg); 25 | } 26 | to { 27 | transform: rotate(359deg); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/features/tabs/tabs-demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Params, Router } from '@angular/router'; 3 | 4 | @Component({ 5 | selector: 'demo-tabs', 6 | templateUrl: './tabs-demo.component.html', 7 | styleUrls: [] 8 | }) 9 | export class TabsDemo implements OnInit { 10 | tabBasicIndex = 2; 11 | 12 | constructor(private route: ActivatedRoute, private router: Router) {} 13 | 14 | ngOnInit() { 15 | this.route.params.forEach((params: Params) => { 16 | if (params['basicTabIndex']) { 17 | this.tabBasicIndex = +params['basicTabIndex']; 18 | } 19 | }); 20 | } 21 | 22 | tabBasicIndexChange(index) { 23 | console.log('tabBasicIndexChange', index); 24 | this.router.navigate(['/tabs/' + index]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/features/snackbar/snackbar-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NwbSnackbarConfig, NwbSnackbarService } from 'projects/ng-wizi-bulma/src/public_api'; 3 | 4 | @Component({ 5 | providers: [], 6 | templateUrl: './snackbar-demo.html' 7 | }) 8 | export class SnackbarDemo { 9 | snackBarNewVersionConfig: NwbSnackbarConfig = { 10 | message: 'My snackbar message with bold', 11 | action: 'My button', 12 | duration: 3000 13 | }; 14 | 15 | constructor(private nwbSnackbar: NwbSnackbarService) {} 16 | 17 | openSnackbar() { 18 | console.log('openSnackbar'); 19 | this.nwbSnackbar 20 | .open(this.snackBarNewVersionConfig) 21 | .afterClosed() 22 | .subscribe(manualClose => console.log('snackBarClose, manualClose', manualClose)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/app/features/dialog/edit-user-dialog-demo.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

6 | Add User 7 |

8 |
9 | 10 |
11 |
12 | 13 |
14 | 15 |
16 |
17 | 18 |
19 | 20 |
21 | 22 |
23 |
24 | 25 |
26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/snackbar/snackbar.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-snack-bar { 2 | .notification { 3 | position: fixed; 4 | bottom: 0; 5 | width: 600px; 6 | color: #fff; 7 | font-size: 15px; 8 | font-weight: 300; 9 | margin: 0 auto; 10 | left: 0; 11 | right: 0; 12 | z-index: 10; 13 | } 14 | 15 | .notification.is-transparent { 16 | background-color: rgba(0, 0, 0, 0.8); 17 | } 18 | 19 | .notification button { 20 | word-wrap: break-word; 21 | word-break: break-all; 22 | white-space: normal; 23 | height: 100%; 24 | } 25 | 26 | .notification .column:nth-child(2) { 27 | text-align: right; 28 | } 29 | 30 | .notification .column:nth-child(1) { 31 | text-align: left; 32 | } 33 | 34 | .notification--message { 35 | align-self: center; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dialog/dialog.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-dialog { 2 | .modal-card { 3 | min-width: 640px; 4 | width: auto; 5 | } 6 | 7 | .modal-card-head, 8 | .modal-card-foot { 9 | border: 0; 10 | border-radius: 0; 11 | } 12 | 13 | .modal-card-foot a { 14 | max-width: 50%; 15 | white-space: initial; 16 | word-wrap: break-word; 17 | } 18 | 19 | .modal-card-head { 20 | background-color: #eaeaea; 21 | font-weight: 200; 22 | } 23 | 24 | .modal-card-body { 25 | background-color: #f5f5f5; 26 | } 27 | 28 | button.delete { 29 | padding: 10px; 30 | } 31 | 32 | @media screen and (max-width: 640px) { 33 | .modal-content, 34 | .modal-card { 35 | min-width: inherit; 36 | width: 100%; 37 | margin: 0; 38 | } 39 | } 40 | 41 | .button.column { 42 | height: auto; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wizishop/ng-wizi-bulma", 3 | "version": "18.0.0", 4 | "description": "Angular Components using Bulma.io css", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/WiziShop/ng-wizi-bulma.git" 8 | }, 9 | "keywords": [ 10 | "angular", 11 | "wizishop", 12 | "bulma", 13 | "components" 14 | ], 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/WiziShop/ng-wizi-bulma/issues" 18 | }, 19 | "homepage": "https://ng-wizi-bulma.firebaseapp.com", 20 | "peerDependencies": { 21 | "@angular/animations": ">=18.0.0", 22 | "@angular/cdk": ">=18.0.0", 23 | "@angular/common": ">=18.0.0", 24 | "@angular/core": ">=18.0.0", 25 | "bulma": "^0.9.4", 26 | "bulma-extensions": "^6.2.7" 27 | }, 28 | "dependencies": { 29 | "tslib": "^2.3.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "forceConsistentCasingInFileNames": true, 7 | "esModuleInterop": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "sourceMap": true, 13 | "declaration": false, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "target": "ES2022", 18 | "module": "es2020", 19 | "lib": ["es2020", "dom"], 20 | "useDefineForClassFields": false 21 | }, 22 | "angularCompilerOptions": { 23 | "enableI18nLegacyMessageIdFormat": false, 24 | "strictInjectionParameters": true, 25 | "strictInputAccessModifiers": true, 26 | "strictTemplates": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/paginator/paginator.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-paginator { 2 | .pagination-list { 3 | justify-content: flex-end; 4 | list-style-type: none; 5 | align-content: center; 6 | } 7 | 8 | .pagination-list li { 9 | margin-right: 10px; 10 | } 11 | 12 | .pagination-list li:last-child { 13 | margin-right: 0; 14 | } 15 | 16 | .pagination-list li > .nwb-paginator-range-label { 17 | font-size: 12px; 18 | min-width: 90px; 19 | text-align: center; 20 | display: block; 21 | } 22 | 23 | .pagination-list li > span:not(.nwb-paginator-range-label) { 24 | font-size: 12px; 25 | min-width: 90px; 26 | text-align: center; 27 | display: block; 28 | } 29 | 30 | .pagination-list li:first-child { 31 | font-size: 12px; 32 | } 33 | 34 | .pagination-list .button[aria-controls='dropdown-menu'] { 35 | font-size: 12px; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-format.ts: -------------------------------------------------------------------------------- 1 | import { Inject, inject, Injectable, InjectionToken, LOCALE_ID } from '@angular/core'; 2 | 3 | /** InjectionToken for datepicker that can be used to override default locale code. */ 4 | export const NWB_DATE_LOCALE = new InjectionToken('NWB_DATE_LOCALE', { 5 | providedIn: 'root', 6 | factory: NWB_DATE_LOCALE_FACTORY 7 | }); 8 | 9 | /** @docs-private */ 10 | export function NWB_DATE_LOCALE_FACTORY(): string { 11 | return inject(LOCALE_ID); 12 | } 13 | 14 | @Injectable({ providedIn: 'root' }) 15 | export class NwbDatePickerFormat { 16 | /** The lang to use for all dates. */ 17 | lang: string; 18 | 19 | dateFormat = 'MM/DD/YYYY'; 20 | 21 | timeFormat = 'HH:mm'; 22 | 23 | constructor(@Inject(NWB_DATE_LOCALE) locale: string) { 24 | this.lang = locale && locale.match('-') ? locale.split('-')[1].toLowerCase() : 'en'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/portal/portal-injector.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Injector } from '@angular/core'; 10 | 11 | /** 12 | * Custom injector to be used when providing custom 13 | * injection tokens to components inside a portal. 14 | * @docs-private 15 | */ 16 | export class PortalInjector implements Injector { 17 | constructor(private _parentInjector: Injector, private _customTokens: WeakMap) {} 18 | 19 | get(token: any, notFoundValue?: any): any { 20 | const value = this._customTokens.get(token); 21 | 22 | if (typeof value !== 'undefined') { 23 | return value; 24 | } 25 | 26 | return this._parentInjector.get(token, notFoundValue); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/features/debounce/debounce-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Input value change will fire with 500ms nwbDebounceDelay 5 |

6 |
7 |
8 |
9 |
10 | 11 |
12 | 16 |
17 |
18 | 19 |

My value is: {{inputValue}}

20 |

Value from nwbDebounceChange event: {{valueFromNwbDebounceChangeEvent}}

21 | 22 | 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/animated-card/animated-card.component.ts: -------------------------------------------------------------------------------- 1 | import { OnInit, ElementRef, Component, ViewEncapsulation } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'div[nwbAnimatedCardClosed], div[nwbAnimatedCardOpened]', 5 | template: ` 6 | 7 | `, 8 | encapsulation: ViewEncapsulation.None 9 | }) 10 | export class NwbAnimatedCardComponent implements OnInit { 11 | constructor(private elementRef: ElementRef) { 12 | this.elementRef.nativeElement.classList.toggle('is-animate'); 13 | if (this.elementRef.nativeElement.getAttribute('nwbAnimatedCardOpened') !== null) { 14 | this.elementRef.nativeElement.classList.toggle('is-active'); 15 | } 16 | } 17 | 18 | ngOnInit() { 19 | this.elementRef.nativeElement.querySelector('header').addEventListener('click', () => { 20 | this.elementRef.nativeElement.classList.toggle('is-active'); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/animated-card/animated-card.component.scss: -------------------------------------------------------------------------------- 1 | .card.is-animate { 2 | .card-header { 3 | cursor: pointer; 4 | 5 | i { 6 | transition: 200ms all; 7 | } 8 | 9 | &-title { 10 | margin-bottom: 0; 11 | 12 | i { 13 | font-size: 1.4rem; 14 | margin-right: 1rem; 15 | border-right: #ddd 0.1rem solid; 16 | padding-right: 1rem; 17 | } 18 | } 19 | } 20 | 21 | .card-content { 22 | opacity: 0; 23 | max-height: 0; 24 | padding: 0.04px; 25 | pointer-events: none; 26 | transition: 200ms all; 27 | } 28 | 29 | &.is-active { 30 | .card-content { 31 | opacity: 1; 32 | max-height: 1000px; 33 | padding: 1.5rem; 34 | pointer-events: auto; 35 | } 36 | 37 | .card-header { 38 | &-icon { 39 | i { 40 | transform: rotate(180deg); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/app/features/paginator/paginator-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Paginator with page size options 5 |

6 |
7 |
8 |
9 | 15 |
16 |
17 |
18 | 19 |
20 |
21 |

22 | Paginator without page size options 23 |

24 |
25 |
26 |
27 | 33 |
34 |
35 |
36 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/sort/sort-errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google LLC All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | /** @docs-private */ 10 | export function getSortDuplicateSortableIdError(id: string): Error { 11 | return Error(`Cannot have two NwbSortables with the same id (${id}).`); 12 | } 13 | 14 | /** @docs-private */ 15 | export function getSortHeaderNotContainedWithinSortError(): Error { 16 | return Error(`NwbSortHeader must be placed within a parent element with the NwbSort directive.`); 17 | } 18 | 19 | /** @docs-private */ 20 | export function getSortHeaderMissingIdError(): Error { 21 | return Error(`NwbSortHeader must be provided with a unique id.`); 22 | } 23 | 24 | /** @docs-private */ 25 | export function getSortInvalidDirectionError(direction: string): Error { 26 | return Error(`${direction} is not a valid sort direction ('asc' or 'desc').`); 27 | } 28 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/util/object-extend.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | /** 10 | * Extends an object with the *enumerable* and *own* properties of one or more source objects, 11 | * similar to Object.assign. 12 | * 13 | * @param dest The object which will have properties copied to it. 14 | * @param sources The source objects from which properties will be copied. 15 | */ 16 | export function extendObject(dest: any, ...sources: any[]): any { 17 | if (dest == null) { 18 | throw TypeError('Cannot convert undefined or null to object'); 19 | } 20 | 21 | for (let source of sources) { 22 | if (source != null) { 23 | for (let key in source) { 24 | if (source.hasOwnProperty(key)) { 25 | dest[key] = source[key]; 26 | } 27 | } 28 | } 29 | } 30 | 31 | return dest; 32 | } 33 | -------------------------------------------------------------------------------- /src/app/features/modal-search/modal-search-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Modal search 5 |

6 |
7 |
8 |
9 |

The modal search is a component to search wherever you are on the page.

10 |

You can open it via cmd+k (on mac) or ctrl+e. You can also open it via the search button on 11 | the top left corner. Then search any NgWiziBulma component to keyboardNavigate to it. 12 |

13 |

You can give to the service an array of strings to search to and use you own filter method. See the demo 14 | app file

15 |
16 | 17 | 18 | 19 |
20 |
21 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NwbCommonModule } from '../shared/common-module'; 4 | import { NwbDatePickerComponent } from './date-picker.component'; 5 | import { NwbDatePickerInputStartDirective } from './date-picker-input-start.directive'; 6 | import { NwbDatePickerInputEndDirective } from './date-picker-input-end.directive'; 7 | import { NwbDatePickerInputDateTypeDirective } from './date-picker-input-date-type.directive'; 8 | 9 | @NgModule({ 10 | imports: [CommonModule, NwbCommonModule], 11 | providers: [], 12 | declarations: [ 13 | NwbDatePickerComponent, 14 | NwbDatePickerInputStartDirective, 15 | NwbDatePickerInputEndDirective, 16 | NwbDatePickerInputDateTypeDirective, 17 | ], 18 | exports: [NwbDatePickerComponent, NwbDatePickerInputStartDirective, NwbDatePickerInputEndDirective, NwbDatePickerInputDateTypeDirective] 19 | }) 20 | export class NwbDatePickerModule {} 21 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/snackbar/snackbar.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { NwbSnackbarComponent } from './snackbar.component'; 3 | import { DomService } from '../shared/dom/dom.service'; 4 | 5 | @Injectable() 6 | export class NwbSnackbarService { 7 | constructor(private domService: DomService) {} 8 | 9 | open(config: NwbSnackbarConfig): NwbSnackbarComponent { 10 | const componentRef = this.getComponentRef(config); 11 | 12 | return componentRef.instance; 13 | } 14 | 15 | private getComponentRef(config: NwbSnackbarConfig) { 16 | const componentRef = this.domService.attachComponentPortal(NwbSnackbarComponent); 17 | 18 | componentRef.instance.config = config; 19 | 20 | componentRef.instance.afterClosed().subscribe(() => { 21 | componentRef.destroy(); 22 | }); 23 | 24 | return componentRef; 25 | } 26 | } 27 | 28 | export interface NwbSnackbarConfig { 29 | message: string; 30 | action?: string; 31 | duration?: number; 32 | color?: string; 33 | buttonColor?: string; 34 | } 35 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.json", 3 | "ignorePatterns": [ 4 | "!**/*" 5 | ], 6 | "overrides": [ 7 | { 8 | "files": [ 9 | "*.ts" 10 | ], 11 | "parserOptions": { 12 | "project": [ 13 | "projects/ng-wizi-bulma/tsconfig.lib.json", 14 | "projects/ng-wizi-bulma/tsconfig.spec.json" 15 | ], 16 | "createDefaultProgram": true 17 | }, 18 | "rules": { 19 | "@angular-eslint/directive-selector": [ 20 | "error", 21 | { 22 | "type": "attribute", 23 | "prefix": "nwb", 24 | "style": "camelCase" 25 | } 26 | ], 27 | "@angular-eslint/component-selector": [ 28 | "error", 29 | { 30 | "type": "element", 31 | "prefix": "nwb", 32 | "style": "kebab-case" 33 | } 34 | ] 35 | } 36 | }, 37 | { 38 | "files": [ 39 | "*.html" 40 | ], 41 | "rules": {} 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-input-start.directive.ts: -------------------------------------------------------------------------------- 1 | /** Directive used to connect an input to a MatDatepicker. */ 2 | import { Directive, ElementRef, Input } from '@angular/core'; 3 | import { NG_VALUE_ACCESSOR } from '@angular/forms'; 4 | import { NwbDatePickerComponent } from './date-picker.component'; 5 | import { NwbDatePickerInputBaseDirective } from './date-picker-input-base.directive'; 6 | 7 | @Directive({ 8 | selector: 'input[nwbDatepickerStart]', 9 | providers: [ 10 | { 11 | provide: NG_VALUE_ACCESSOR, 12 | useExisting: NwbDatePickerInputStartDirective, 13 | multi: true 14 | } 15 | ] 16 | }) 17 | export class NwbDatePickerInputStartDirective extends NwbDatePickerInputBaseDirective { 18 | /** The datepicker that this input is associated with. */ 19 | @Input() 20 | set nwbDatepickerStart(datePickerComponent: NwbDatePickerComponent) { 21 | this.registerInput(datePickerComponent, 'startDate'); 22 | } 23 | 24 | constructor(public override elementRef: ElementRef) { 25 | super(elementRef); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-input-end.directive.ts: -------------------------------------------------------------------------------- 1 | /** Directive used to connect an input to a MatDatepicker. */ 2 | import { Directive, ElementRef, Input } from '@angular/core'; 3 | import { NG_VALUE_ACCESSOR } from '@angular/forms'; 4 | import { NwbDatePickerComponent } from './date-picker.component'; 5 | import { NwbDatePickerInputBaseDirective } from './date-picker-input-base.directive'; 6 | 7 | @Directive({ 8 | selector: 'input[nwbDatepickerEnd]', 9 | providers: [ 10 | { 11 | provide: NG_VALUE_ACCESSOR, 12 | useExisting: NwbDatePickerInputEndDirective, 13 | multi: true, 14 | }, 15 | ], 16 | }) 17 | export class NwbDatePickerInputEndDirective extends NwbDatePickerInputBaseDirective { 18 | /** The datepicker that this input is associated with. */ 19 | @Input() 20 | set nwbDatepickerEnd(datePickerComponent: NwbDatePickerComponent) { 21 | this.registerInput(datePickerComponent, 'endDate'); 22 | } 23 | 24 | @Input() override nwbDateType; 25 | 26 | constructor(public override elementRef: ElementRef) { 27 | super(elementRef); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/app/features/dialog/fake-dialog-demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, EventEmitter, ViewChild } from '@angular/core'; 2 | 3 | @Component({ 4 | providers: [], 5 | template: ` 6 |
7 | 8 |

9 | 10 |

11 | 12 |

13 | 14 |

15 | 16 |

17 | 18 |

19 |
20 | ` 21 | }) 22 | export class FakeDialogDemoComponent { 23 | @ViewChild('myInput', { static: true }) 24 | myInput: ElementRef; 25 | 26 | loading = new EventEmitter(); 27 | 28 | ngOnInit() { 29 | console.log('FakeDialogDemoComponent'); 30 | 31 | console.log('myInput', this.myInput); 32 | 33 | setTimeout(() => this.loading.next(false), 3000); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 WiziShop 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/common-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { OVERLAY_CONTAINER_PROVIDER } from './overlay/overlay-container'; 5 | import { DOM_SERVICE_PROVIDER } from './dom/dom.service'; 6 | import { NwbDebounceDirective } from './directives/debounce/debounce.directive'; 7 | import { NwbToolTipDirective } from './directives/tooltip/tooltip.directive'; 8 | import { NwbSpinnerComponent } from './components/spinner/spinner.component'; 9 | import { NwbFilterRoutingBuilder } from './services/filter-routing/filter-routing-group.service'; 10 | import { SafeHtmlPipe } from './pipes/safe-html.pipe'; 11 | 12 | @NgModule({ 13 | imports: [CommonModule, FormsModule], 14 | providers: [OVERLAY_CONTAINER_PROVIDER, DOM_SERVICE_PROVIDER, NwbFilterRoutingBuilder], 15 | declarations: [NwbSpinnerComponent, NwbDebounceDirective, NwbToolTipDirective, SafeHtmlPipe], 16 | exports: [NwbSpinnerComponent, NwbDebounceDirective, NwbToolTipDirective, SafeHtmlPipe] 17 | }) 18 | export class NwbCommonModule {} 19 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, './coverage/testAngular'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | restartOnFileChange: true 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/alert/alert.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { NwbAlertComponent } from './alert.component'; 3 | import { DomService } from '../shared/dom/dom.service'; 4 | 5 | @Injectable() 6 | export class NwbAlertService { 7 | constructor(private domService: DomService) {} 8 | 9 | open(config: NwbAlertConfig): NwbAlertComponent { 10 | const componentRef = this.getComponentRef(config); 11 | 12 | return componentRef.instance; 13 | } 14 | 15 | private getComponentRef(config: NwbAlertConfig) { 16 | const componentRef = this.domService.attachComponentPortal(NwbAlertComponent); 17 | 18 | config = Object.assign( 19 | { 20 | position: 'is-top' 21 | }, 22 | config 23 | ); 24 | 25 | componentRef.instance.config = config; 26 | 27 | componentRef.instance.afterClosed().subscribe(() => { 28 | componentRef.destroy(); 29 | }); 30 | 31 | return componentRef; 32 | } 33 | } 34 | 35 | export interface NwbAlertConfig { 36 | message: string; 37 | icon?: string; 38 | color?: string; 39 | position?: string; 40 | duration?: number; 41 | extraClasses?: string; 42 | } 43 | -------------------------------------------------------------------------------- /src/app/features/tooltip/tooltip-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Switch 5 |

6 |
7 |
8 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 25 |
26 |
27 |
28 | 29 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/directives/tooltip/tooltip.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, Input } from '@angular/core'; 2 | 3 | @Directive({ 4 | selector: '[nwbToolTip]' 5 | }) 6 | export class NwbToolTipDirective { 7 | @Input() 8 | set nwbToolTip(value) { 9 | this.el.nativeElement.setAttribute('data-tooltip', value); 10 | } 11 | 12 | @Input() 13 | set nwbToolTipPosition(value: 'left' | 'right' | 'top' | 'bottom') { 14 | this.el.nativeElement.classList.remove('is-tooltip-top'); 15 | this.el.nativeElement.classList.remove('is-tooltip-left'); 16 | this.el.nativeElement.classList.remove('is-tooltip-right'); 17 | this.el.nativeElement.classList.remove('is-tooltip-bottom'); 18 | 19 | this.el.nativeElement.classList.add('is-tooltip-' + value); 20 | } 21 | 22 | @Input() 23 | set nwbToolTipIsMultiline(value: boolean) { 24 | if (value) { 25 | this.el.nativeElement.classList.add('is-tooltip-multiline'); 26 | } else { 27 | this.el.nativeElement.classList.remove('is-tooltip-multiline'); 28 | } 29 | } 30 | 31 | constructor(private el: ElementRef) { 32 | this.el.nativeElement.classList.add('tooltip'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dropdown/dropdown.component.html: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": [ 4 | "projects/**/*" 5 | ], 6 | "overrides": [ 7 | { 8 | "files": [ 9 | "*.ts" 10 | ], 11 | "parserOptions": { 12 | "project": [ 13 | "tsconfig.json", 14 | "e2e/tsconfig.json" 15 | ], 16 | "createDefaultProgram": true 17 | }, 18 | "extends": [ 19 | "plugin:@angular-eslint/recommended", 20 | "plugin:@angular-eslint/template/process-inline-templates" 21 | ], 22 | "rules": { 23 | "@angular-eslint/component-selector": [ 24 | "error", 25 | { 26 | "prefix": "nwb", 27 | "style": "kebab-case", 28 | "type": "element" 29 | } 30 | ], 31 | "@angular-eslint/directive-selector": [ 32 | "error", 33 | { 34 | "prefix": "nwb", 35 | "style": "camelCase", 36 | "type": "attribute" 37 | } 38 | ] 39 | } 40 | }, 41 | { 42 | "files": [ 43 | "*.html" 44 | ], 45 | "extends": [ 46 | "plugin:@angular-eslint/template/recommended" 47 | ], 48 | "rules": {} 49 | } 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | describe('AppComponent', () => { 4 | beforeEach( 5 | waitForAsync(() => { 6 | TestBed.configureTestingModule({ 7 | declarations: [AppComponent], 8 | }).compileComponents(); 9 | }) 10 | ); 11 | it( 12 | 'should create the app', 13 | waitForAsync(() => { 14 | const fixture = TestBed.createComponent(AppComponent); 15 | const app = fixture.debugElement.componentInstance; 16 | expect(app).toBeTruthy(); 17 | }) 18 | ); 19 | it( 20 | `should have as title 'app'`, 21 | waitForAsync(() => { 22 | const fixture = TestBed.createComponent(AppComponent); 23 | const app = fixture.debugElement.componentInstance; 24 | expect(app.title).toEqual('app'); 25 | }) 26 | ); 27 | it( 28 | 'should render title in a h1 tag', 29 | waitForAsync(() => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.debugElement.nativeElement; 33 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); 34 | }) 35 | ); 36 | }); 37 | -------------------------------------------------------------------------------- /src/app/features/sort/sort-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Sort Header 5 |

6 |
7 |
8 |
9 | 10 |

This is an adaptation from the sort 11 | header component from angular material 12 |

13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
Dessert (100g)CaloriesFat (g)Carbs (g)Protein (g)
{{dessert.name}}{{dessert.calories}}{{dessert.fat}}{{dessert.carbs}}{{dessert.protein}}
33 | 34 |
35 |
36 | 37 | 38 |
39 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/alert/alert.component.ts: -------------------------------------------------------------------------------- 1 | import { Observable, Subject } from 'rxjs'; 2 | import { NwbAlertConfig } from './alert.service'; 3 | import { Component, OnInit, ViewEncapsulation } from '@angular/core'; 4 | 5 | @Component({ 6 | selector: 'nwb-alert', 7 | templateUrl: './alert.component.html', 8 | host: { 9 | class: 'nwb-alert' 10 | }, 11 | encapsulation: ViewEncapsulation.None 12 | }) 13 | export class NwbAlertComponent implements OnInit { 14 | config: NwbAlertConfig; 15 | 16 | /** Subject for notifying the user that the dialog has finished closing. */ 17 | private _afterClosed: Subject = new Subject(); 18 | 19 | open = false; 20 | 21 | private timer: any; 22 | 23 | ngOnInit() { 24 | setTimeout(() => { 25 | this.open = true; 26 | }, 50); 27 | 28 | if (this.config.duration > 0) { 29 | this.timer = setTimeout(() => this.dismiss(), this.config.duration); 30 | } 31 | } 32 | 33 | dismiss() { 34 | this.open = false; 35 | 36 | setTimeout(() => { 37 | this._afterClosed.next(true); 38 | this._afterClosed.complete(); 39 | }, 200); 40 | } 41 | 42 | /** 43 | * Gets an observable that is notified when the dialog is finished closing. 44 | */ 45 | afterClosed(): Observable { 46 | return this._afterClosed.asObservable(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-default-settings.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ providedIn: 'root' }) 4 | export class NwbDatePickerDefaultSettings implements NwbDatePickerDefaultSettings { 5 | color = 'primary'; 6 | allowSameDayRange = true; 7 | displayMode: 'default' | 'dialog' | 'inline' = 'default'; 8 | showHeader = true; 9 | headerPosition: 'top' | 'bottom' = 'top'; 10 | showFooter = true; 11 | showButtons = true; 12 | showTodayButton = true; 13 | showClearButton = true; 14 | enableMonthSwitch = true; 15 | enableYearSwitch = true; 16 | weekStart = 0; 17 | minuteSteps = 1; 18 | closeOnOverlayClick = true; 19 | closeOnSelect = true; 20 | toggleOnInputClick = true; 21 | } 22 | 23 | export interface NwbDatePickerSettings { 24 | color?: string; 25 | allowSameDayRange?: boolean; 26 | displayMode?: 'default' | 'dialog' | 'inline'; 27 | showHeader?: boolean; 28 | headerPosition?: 'top' | 'bottom'; 29 | showFooter?: boolean; 30 | showButtons?: boolean; 31 | showTodayButton?: boolean; 32 | showClearButton?: boolean; 33 | enableMonthSwitch?: boolean; 34 | enableYearSwitch?: boolean; 35 | weekStart?: number; 36 | minuteSteps?: number; 37 | closeOnOverlayClick?: boolean; 38 | closeOnSelect?: boolean; 39 | toggleOnInputClick?: boolean; 40 | } 41 | -------------------------------------------------------------------------------- /src/app/features/animated-card/animated-card-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | providers: [], 5 | templateUrl: './animated-card-demo.html' 6 | }) 7 | export class AnimatedCardDemo { 8 | sample1 = ` 9 |
10 |
11 |

12 | Click me ! 13 |

14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 |

My Awesome hidden content

23 |
24 |
25 |
26 | `; 27 | 28 | sample2 = ` 29 |
30 |
31 |

32 | Click me ! 33 |

34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |

My Awesome content

43 |
44 |
45 |
46 | `; 47 | } 48 | -------------------------------------------------------------------------------- /src/app/features/switch/switch-demo.ts: -------------------------------------------------------------------------------- 1 | import { UntypedFormBuilder, FormGroup } from '@angular/forms'; 2 | import { Component } from '@angular/core'; 3 | 4 | @Component({ 5 | providers: [], 6 | templateUrl: './switch-demo.html', 7 | }) 8 | export class SwitchDemo { 9 | sample1Value = true; 10 | 11 | sample1 = ` 15 | Switch example 16 | `; 17 | 18 | sample2 = ` 22 | Switch example 23 | `; 24 | 25 | sample3 = `
26 | 30 | 31 |
`; 32 | 33 | sample4 = ` 34 | myForm = this.fb.group({ 35 | mySwitch: [ 36 | { 37 | value: true, 38 | disabled: true, 39 | }, 40 | ], 41 | 42 | 43 |
44 |

Switch with Reactive Form

45 | 46 |
47 | 48 | `; 49 | myForm = this.fb.group({ 50 | mySwitch: [ 51 | { 52 | value: true, 53 | disabled: true, 54 | }, 55 | ], 56 | }); 57 | 58 | constructor(private fb: UntypedFormBuilder) {} 59 | 60 | model1Change(value) { 61 | console.log('model3Change', value); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/app/features/animated-card/animated-card-demo.html: -------------------------------------------------------------------------------- 1 |
2 |

Animated Card

3 |
4 |
5 |

Closed by default use nwbAnimatedCardClosed attribute

6 | 7 |
8 |
9 |

Click me !

10 | 11 | 12 | 13 |
14 |
15 |

My Awesome hidden content

16 |
17 |
18 |
19 |
20 |

Opened by default use nwbAnimatedCardOpened attribute

21 | 22 |
23 |
24 |

Click me !

25 | 26 | 27 | 28 |
29 |
30 |

My Awesome content

31 |
32 |
33 |
34 |
35 |
36 |
37 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/nwb-all-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { NwbPaginatorModule } from './paginator/paginator-module'; 3 | import { NwbSortModule } from './sort/sort-module'; 4 | import { NwbModalSearchModule } from './modal-search/modal-search-module'; 5 | import { NwbAlertModule } from './alert/alert-module'; 6 | import { NwbDialogModule } from './dialog/dialog-module'; 7 | import { NwbSnackbarModule } from './snackbar/snackbar-module'; 8 | import { NwbCommonModule } from './shared/common-module'; 9 | import { NwbAnimatedCardModule } from './animated-card/animated-card-module'; 10 | import { NwbDropdownModule } from './dropdown/dropdown-module'; 11 | import { NwbProgressBarModule } from './progress-bar/progress-bar-module'; 12 | import { NwbSwitchModule } from './switch/switch-module'; 13 | import { NwbTabsModule } from './tabs/tabs-module'; 14 | import { NwbEditInPlaceModule } from './edit-in-place/edit-in-place-module'; 15 | import { NwbDatePickerModule } from './date-picker/date-picker-module'; 16 | 17 | const EXPORTED_EXPORTS = [ 18 | NwbCommonModule, 19 | 20 | NwbAlertModule, 21 | NwbAnimatedCardModule, 22 | NwbDialogModule, 23 | NwbDropdownModule, 24 | NwbModalSearchModule, 25 | NwbPaginatorModule, 26 | NwbProgressBarModule, 27 | NwbSnackbarModule, 28 | NwbSortModule, 29 | NwbSwitchModule, 30 | NwbTabsModule, 31 | NwbEditInPlaceModule, 32 | NwbDatePickerModule 33 | ]; 34 | 35 | @NgModule({ 36 | imports: [], 37 | providers: [], 38 | declarations: [], 39 | exports: EXPORTED_EXPORTS 40 | }) 41 | export class NwbAllModule {} 42 | -------------------------------------------------------------------------------- /src/app/features/switch/switch-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Switch 5 |

6 |
7 |
8 | 9 |
10 | 11 | 12 | Switch example 13 | 14 | 15 | sample1Value = {{sample1Value}} 16 | 17 |
18 |
19 | 20 | 21 | Switch example 22 | 23 | 24 |
25 |
26 | 27 |

Switch with tooltip

28 |
29 | 30 |
31 |
32 |
33 |
34 | 35 |
36 |

Switch with Reactive Form

37 | 38 |
39 |
40 |
41 |
42 |
43 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dialog/dialog.component.html: -------------------------------------------------------------------------------- 1 | 36 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/paginator/paginator-intl.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Injectable } from '@angular/core'; 10 | import { Subject } from 'rxjs'; 11 | 12 | /** 13 | * 14 | * Copy from angular material 15 | * 16 | * To modify the labels and text displayed, create a new instance of NwbPaginatorIntl and 17 | * include it in a custom provider 18 | */ 19 | @Injectable() 20 | export class NwbPaginatorIntl { 21 | /** 22 | * Stream that emits whenever the labels here are changed. Use this to notify 23 | * components if the labels have changed after initialization. 24 | */ 25 | changes: Subject = new Subject(); 26 | 27 | /** A label for the page size selector. */ 28 | itemsPerPageLabel = 'Items per page:'; 29 | 30 | /** A label for the page size selector. */ 31 | ofLabel = 'of'; 32 | 33 | /** A label for the range of items within the current page and the length of the whole list. */ 34 | getRangeLabel = (page: number, pageSize: number, length: number) => { 35 | if (length == 0 || pageSize == 0) { 36 | return `0 ${this.ofLabel} ${length}`; 37 | } 38 | 39 | length = Math.max(length, 0); 40 | 41 | const startIndex = page * pageSize; 42 | 43 | // If the start index exceeds the list length, do not try and fix the end index to the end. 44 | const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize; 45 | 46 | return `${startIndex + 1} - ${endIndex} ${this.ofLabel} ${length}`; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/util/object-extend.spec.ts: -------------------------------------------------------------------------------- 1 | import { extendObject } from './object-extend'; 2 | 3 | describe('extendObject', () => { 4 | it('should extend an object', () => { 5 | let extended = extendObject({}, { x: 123 }); 6 | 7 | expect(extended).toEqual({ x: 123 }); 8 | }); 9 | 10 | it('should overwrite existing properties', () => { 11 | let extended = extendObject({ x: 456 }, { x: 123 }); 12 | 13 | expect(extended).toEqual({ x: 123 }); 14 | }); 15 | 16 | it('should add additional properties', () => { 17 | let extended = extendObject({ x: 456 }, { y: 123 }); 18 | 19 | expect(extended).toEqual({ x: 456, y: 123 }); 20 | }); 21 | 22 | it('should extend from multiple sources', () => { 23 | let extended = extendObject({}, { x: 123 }, { y: 456 }); 24 | 25 | expect(extended).toEqual({ x: 123, y: 456 }); 26 | }); 27 | 28 | it('should overwrite properties from the later source', () => { 29 | let extended = extendObject({}, { x: 123 }, { x: 456 }); 30 | 31 | expect(extended).toEqual({ x: 456 }); 32 | }); 33 | 34 | it('should treat null and undefined sources as empty objects', () => { 35 | let extended = extendObject({}, null, { x: 123 }, undefined, { y: 456 }); 36 | 37 | expect(extended).toEqual({ x: 123, y: 456 }); 38 | }); 39 | 40 | it('should throw an error when the dest object is null', () => { 41 | expect(() => extendObject(null, { x: 123 })).toThrowError('Cannot convert undefined or null to object'); 42 | }); 43 | 44 | it('should throw an error when the dest object is undefined', () => { 45 | expect(() => extendObject(undefined, { x: 123 })).toThrowError('Cannot convert undefined or null to object'); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/overlay/overlay-container.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Optional, SkipSelf } from '@angular/core'; 2 | 3 | /** 4 | * The OverlayContainer is the container in which all overlays will load. 5 | * It should be provided in the root component to ensure it is properly shared. 6 | */ 7 | @Injectable() 8 | export class OverlayContainer { 9 | protected _containerElement: HTMLElement; 10 | 11 | /** 12 | * This method returns the overlay container element. It will lazily 13 | * create the element the first time it is called to facilitate using 14 | * the container in non-browser environments. 15 | * @returns the container element 16 | */ 17 | getContainerElement(): HTMLElement { 18 | if (!this._containerElement) { 19 | this._createContainer(); 20 | } 21 | return this._containerElement; 22 | } 23 | 24 | /** 25 | * Create the overlay container element, which is simply a div 26 | * with the 'cdk-overlay-container' class on the document body. 27 | */ 28 | protected _createContainer(): void { 29 | let container = document.createElement('div'); 30 | container.classList.add('nwb-overlay-container'); 31 | 32 | document.body.appendChild(container); 33 | this._containerElement = container; 34 | } 35 | } 36 | 37 | export function OVERLAY_CONTAINER_PROVIDER_FACTORY(parentContainer: OverlayContainer) { 38 | return parentContainer || new OverlayContainer(); 39 | } 40 | 41 | export const OVERLAY_CONTAINER_PROVIDER = { 42 | // If there is already an OverlayContainer available, use that. Otherwise, provide a new one. 43 | provide: OverlayContainer, 44 | deps: [[new Optional(), new SkipSelf(), OverlayContainer]], 45 | useFactory: OVERLAY_CONTAINER_PROVIDER_FACTORY 46 | }; 47 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | @import 'node_modules/bulma/bulma.sass'; 4 | @import 'node_modules/bulma-extensions/bulma-switch/src/sass/index'; 5 | @import 'node_modules/bulma-extensions/bulma-tooltip/src/sass/index'; 6 | @import 'node_modules/bulma-extensions/bulma-calendar/src/sass/index'; 7 | 8 | @import 'bulma-docs.css'; 9 | 10 | @import '../dist/@wizishop/ng-wizi-bulma/ng-wizi-bulma'; 11 | 12 | .textarea:not([rows]).textarea--exampleBulmaCalendar { 13 | min-height: 200px; 14 | cursor: default; 15 | resize: none; 16 | } 17 | 18 | .textarea:not([rows]).textarea--settingDefault { 19 | min-height: 470px; 20 | cursor: default; 21 | resize: none; 22 | } 23 | 24 | .textarea:not([rows]).textarea--settingClass { 25 | min-height: 800px; 26 | cursor: default; 27 | resize: none; 28 | } 29 | 30 | .textarea:not([rows]).textarea--settingComp { 31 | min-height: 150px; 32 | cursor: default; 33 | resize: none; 34 | } 35 | 36 | .textarea:not([rows]).textarea--formatDefault { 37 | min-height: 340px; 38 | cursor: default; 39 | resize: none; 40 | } 41 | 42 | .textarea:not([rows]).textarea--formatClass { 43 | min-height: 480px; 44 | cursor: default; 45 | resize: none; 46 | } 47 | .textarea:not([rows]).textarea--formatIntl { 48 | min-height: 280px; 49 | cursor: default; 50 | resize: none; 51 | } 52 | 53 | .textarea:not([rows]).textarea--formatIntl2 { 54 | min-height: 580px; 55 | cursor: default; 56 | resize: none; 57 | } 58 | 59 | .textarea:not([rows]).textarea--formatComp { 60 | min-height: 150px; 61 | cursor: default; 62 | resize: none; 63 | } 64 | 65 | .textarea:not([rows]).textarea--formatUse { 66 | min-height: 150px; 67 | cursor: default; 68 | resize: none; 69 | } 70 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/modal-search/modal-search.component.html: -------------------------------------------------------------------------------- 1 | 37 | -------------------------------------------------------------------------------- /src/app/features/dialog/edit-user-dialog-demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core'; 2 | import { NwbDialogComponent, NwbDialogService } from 'projects/ng-wizi-bulma/src/public_api'; 3 | 4 | @Component({ 5 | selector: 'demo-add-user-dialog', 6 | templateUrl: './edit-user-dialog-demo.component.html' 7 | }) 8 | export class EditUserDialogDemoComponent implements OnInit { 9 | private _id: number; 10 | 11 | @Input() 12 | set id(id: number) { 13 | this._id = id; 14 | this.fetch(); 15 | } 16 | 17 | get id() { 18 | return this._id; 19 | } 20 | 21 | @Output() 22 | userChange = new EventEmitter(); 23 | 24 | @Output() 25 | close = new EventEmitter(); 26 | 27 | user: User; 28 | 29 | @ViewChild('dialogTemplateRef', { static: true }) 30 | dialogTemplateRef: TemplateRef; 31 | 32 | private dialog: NwbDialogComponent; 33 | 34 | constructor(private nwbDialog: NwbDialogService) {} 35 | 36 | ngOnInit() { 37 | setTimeout(() => { 38 | this.dialog = this.nwbDialog.openFromComponent(this.dialogTemplateRef, { 39 | title: 'Edit User ' + this._id, 40 | okButtonText: 'OK', 41 | cancelButtonText: 'Cancel', 42 | loading: true, 43 | okHandler: () => { 44 | return this.setUser(); 45 | } 46 | }); 47 | 48 | this.dialog.afterClosed().subscribe(fromOk => { 49 | this.close.emit(fromOk); 50 | }); 51 | }); 52 | } 53 | 54 | private fetch() { 55 | setTimeout(() => { 56 | this.user = new User(); 57 | this.user.name = 'Joe'; 58 | this.user.userName = 'bulma'; 59 | 60 | this.dialog.hideSpinner(); 61 | }, 2000); 62 | } 63 | 64 | private setUser() { 65 | this.userChange.emit(this.user); 66 | this.dialog.dismiss(false); 67 | } 68 | } 69 | 70 | export class User { 71 | name: string; 72 | userName: string; 73 | } 74 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/switch/switch.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, ViewEncapsulation } from '@angular/core'; 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; 3 | 4 | @Component({ 5 | selector: 'nwb-switch', 6 | templateUrl: './switch.component.html', 7 | styleUrls: ['./switch.component.scss'], 8 | host: { 9 | class: 'nwb-switch', 10 | }, 11 | encapsulation: ViewEncapsulation.None, 12 | providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: NwbSwitchComponent, multi: true }], 13 | }) 14 | export class NwbSwitchComponent implements ControlValueAccessor { 15 | @Input() 16 | extraClasses= ''; 17 | @Input() 18 | disabled = false; 19 | @Input() 20 | checked = true; 21 | 22 | private _onChanged: Function; 23 | private _onTouched: Function; 24 | private currentValue: any = null; 25 | 26 | private _id = null; 27 | 28 | writeValue(obj: any): void { 29 | this._setValue(obj); 30 | } 31 | 32 | registerOnChange(fn: any): void { 33 | this._onChanged = fn; 34 | } 35 | 36 | registerOnTouched(fn: any): void { 37 | this._onTouched = fn; 38 | } 39 | 40 | setDisabledState(isDisabled: boolean) { 41 | this.disabled = isDisabled; 42 | } 43 | 44 | change() { 45 | this._setValue(this.checked); 46 | } 47 | 48 | private _setValue(value: boolean) { 49 | if (typeof value !== 'boolean') { 50 | return; 51 | } 52 | 53 | const init = this.currentValue === null; 54 | 55 | this.currentValue = value; 56 | 57 | if (this.checked !== this.currentValue) { 58 | this.checked = this.currentValue === true; 59 | } 60 | 61 | if (init) { 62 | return; 63 | } 64 | 65 | if (typeof this._onChanged === 'function') { 66 | this._onChanged(this.currentValue); 67 | } 68 | } 69 | 70 | getId() { 71 | if (!this._id) { 72 | this._id = 'search-' + Math.random().toString().replace('.', '-'); 73 | } 74 | return this._id; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/app/features/dialog/dialog-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Dialog 5 |

6 |
7 |
8 |
9 |

Simple Dialog with custom handler function on ok (yes) button

10 | 11 |
12 |
13 |
14 |
15 |
16 |

17 | Dialog with component 18 |

19 |
20 |
21 |
22 | 23 |

Your name is: {{fakeComponentValue}}

24 |
25 |
26 |
27 |
28 |
29 |

30 | Dialog with component and spinner with backdrop disabled 31 |

32 |
33 |
34 |
35 | 36 |

Your name is: {{fakeComponent2Value}}

37 |
38 |
39 |
40 |
41 |
42 |

43 | Dialog with template 44 |

45 |
46 |
47 |
48 | 49 |
50 | 51 | 52 | 58 | 59 | 60 | 61 |
62 |
63 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dropdown/option.component.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, EventEmitter, Input, Output } from '@angular/core'; 2 | 3 | /** 4 | * @name Option 5 | * @description 6 | * `nwb-option` is a child component of `nwb-dropdown`. Similar to the native option element, `nwb-option` can take a value and a selected property. 7 | * 8 | */ 9 | @Directive({ 10 | selector: 'nwb-option' 11 | }) 12 | export class NwbOptionComponent { 13 | _selected: boolean = false; 14 | _disabled: boolean = false; 15 | _divider: boolean = false; 16 | _value: any; 17 | 18 | /** 19 | * @input {boolean} If true, the user cannot interact with this element. 20 | */ 21 | @Input() 22 | get disabled(): boolean { 23 | return this._disabled; 24 | } 25 | 26 | set disabled(val: boolean) { 27 | this._disabled = val; 28 | } 29 | 30 | /** 31 | * @input {boolean} If true, the element is selected. 32 | */ 33 | @Input() 34 | get selected(): boolean { 35 | return this._selected; 36 | } 37 | 38 | set selected(val: boolean) { 39 | this._selected = val; 40 | } 41 | 42 | /** 43 | * @input {any} The value of the option. 44 | */ 45 | @Input() 46 | get value() { 47 | if (this._value !== 'undefined') { 48 | return this._value; 49 | } 50 | return this.text; 51 | } 52 | 53 | set value(val: any) { 54 | this._value = val; 55 | } 56 | 57 | /** 58 | * @input {boolean} If true, the option element will be a divider. 59 | */ 60 | @Input() 61 | get divider(): boolean { 62 | return this._divider; 63 | } 64 | 65 | set divider(val: boolean) { 66 | this._divider = val; 67 | } 68 | 69 | /** 70 | * @output {any} Event to evaluate when option is selected. 71 | */ 72 | @Output() 73 | nwbSelect: EventEmitter = new EventEmitter(); 74 | 75 | constructor(private _elementRef: ElementRef) {} 76 | 77 | /** 78 | * @hidden 79 | */ 80 | get text() { 81 | return this._elementRef.nativeElement.innerHTML; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 40 |
41 |
42 | 43 |
44 |
45 |
46 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/paginator/paginator.component.html: -------------------------------------------------------------------------------- 1 | 62 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/modal-search/modal-search.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-modal-search { 2 | .modal-content { 3 | position: fixed; 4 | top: 10%; 5 | } 6 | 7 | .modal-card-body { 8 | overflow: hidden; 9 | } 10 | 11 | .modal-card-body { 12 | padding-bottom: 0; 13 | &.has-no-header { 14 | border-top-left-radius: 6px; 15 | border-top-right-radius: 6px; 16 | } 17 | &.has-no-footer { 18 | border-bottom-left-radius: 6px; 19 | border-bottom-right-radius: 6px; 20 | padding-bottom: 20px; 21 | } 22 | } 23 | 24 | input { 25 | font-size: 2em; 26 | } 27 | 28 | .control.has-icons-left .input { 29 | padding-left: 2em; 30 | } 31 | .icon { 32 | height: 100% !important; 33 | 34 | &.is-left { 35 | left: 0; 36 | padding: 20px 12px; 37 | display: inline-block; 38 | border-right: 1px dashed #ddd; 39 | width: 3.25em; 40 | } 41 | } 42 | .fa-search { 43 | font-size: 2em; 44 | } 45 | 46 | .nwb-modal-search-found-rows { 47 | max-height: 300px; 48 | overflow: scroll; 49 | 50 | margin-top: 20px; 51 | padding-bottom: 20px; 52 | 53 | .is-parent { 54 | font-size: 1.2em; 55 | font-weight: bold; 56 | } 57 | 58 | .is-child { 59 | padding-left: 25px; 60 | } 61 | 62 | .nwb-modal-search-row { 63 | display: block; 64 | color: black; 65 | 66 | .nwb-modal-search-row-content { 67 | padding-left: 1em; 68 | height: 26px; 69 | } 70 | } 71 | 72 | .nwb-modal-search-row:focus { 73 | outline: none; 74 | } 75 | 76 | .nwb-modal-search-row.selected { 77 | background-color: #239de3; 78 | border-radius: 5px; 79 | color: white; 80 | } 81 | .nwb-modal-search-row.not-selectable { 82 | cursor: default; 83 | } 84 | } 85 | 86 | @media screen and (max-width: 769px) { 87 | .modal-content, 88 | .modal-card { 89 | margin: 0; 90 | } 91 | } 92 | } 93 | 94 | nwb-spinner { 95 | margin-top: 20px; 96 | } 97 | -------------------------------------------------------------------------------- /src/app/features/sort/sort-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Sort } from 'projects/ng-wizi-bulma/src/public_api'; 3 | 4 | export interface Dessert { 5 | calories: number; 6 | carbs: number; 7 | fat: number; 8 | name: string; 9 | protein: number; 10 | } 11 | 12 | @Component({ 13 | providers: [], 14 | templateUrl: './sort-demo.html', 15 | styleUrls: ['./sort-demo.scss'] 16 | }) 17 | export class SortDemo { 18 | desserts: Dessert[] = [ 19 | { name: 'Frozen yogurt', calories: 159, fat: 6, carbs: 24, protein: 4 }, 20 | { 21 | name: 'Ice cream sandwich', 22 | calories: 237, 23 | fat: 9, 24 | carbs: 37, 25 | protein: 4 26 | }, 27 | { name: 'Eclair', calories: 262, fat: 16, carbs: 24, protein: 6 }, 28 | { name: 'Cupcake', calories: 305, fat: 4, carbs: 67, protein: 4 }, 29 | { name: 'Gingerbread', calories: 356, fat: 16, carbs: 49, protein: 4 } 30 | ]; 31 | 32 | sortedData: Dessert[]; 33 | 34 | startSort: Sort = { 35 | active: 'name', 36 | direction: 'desc' 37 | }; 38 | 39 | constructor() { 40 | this.sortedData = this.desserts.slice(); 41 | 42 | this.sortData(this.startSort); 43 | } 44 | 45 | sortData(sort: Sort) { 46 | const data = this.desserts.slice(); 47 | if (!sort.active || sort.direction === '') { 48 | this.sortedData = data; 49 | return; 50 | } 51 | 52 | this.sortedData = data.sort((a, b) => { 53 | const isAsc = sort.direction === 'asc'; 54 | switch (sort.active) { 55 | case 'name': 56 | return compare(a.name, b.name, isAsc); 57 | case 'calories': 58 | return compare(a.calories, b.calories, isAsc); 59 | case 'fat': 60 | return compare(a.fat, b.fat, isAsc); 61 | case 'carbs': 62 | return compare(a.carbs, b.carbs, isAsc); 63 | case 'protein': 64 | return compare(a.protein, b.protein, isAsc); 65 | default: 66 | return 0; 67 | } 68 | }); 69 | } 70 | } 71 | 72 | function compare(a, b, isAsc) { 73 | return (a < b ? -1 : 1) * (isAsc ? 1 : -1); 74 | } 75 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/snackbar/snackbar.component.ts: -------------------------------------------------------------------------------- 1 | import { Observable, Subject } from 'rxjs'; 2 | import { NwbSnackbarConfig } from './snackbar.service'; 3 | import { Component, OnInit, ViewEncapsulation } from '@angular/core'; 4 | import { animate, AnimationEvent, state, style, transition, trigger } from '@angular/animations'; 5 | 6 | @Component({ 7 | selector: 'nwb-snack-bar', 8 | templateUrl: './snackbar.component.html', 9 | host: { 10 | class: 'nwb-snack-bar' 11 | }, 12 | encapsulation: ViewEncapsulation.None, 13 | animations: [ 14 | trigger('state', [ 15 | state( 16 | 'void', 17 | style({ 18 | bottom: '-100px' 19 | }) 20 | ), 21 | state( 22 | 'inactive', 23 | style({ 24 | bottom: '-100px' 25 | }) 26 | ), 27 | state( 28 | 'active', 29 | style({ 30 | bottom: '0px' 31 | }) 32 | ), 33 | transition('void => active', animate(300)), 34 | transition('active => inactive', animate(300)) 35 | ]) 36 | ] 37 | }) 38 | export class NwbSnackbarComponent implements OnInit { 39 | config: NwbSnackbarConfig; 40 | 41 | /** Subject for notifying the user that the dialog has finished closing. */ 42 | private _afterClosed: Subject = new Subject(); 43 | 44 | open = false; 45 | 46 | private manualClose = false; 47 | 48 | private timer: any; 49 | 50 | ngOnInit() { 51 | this.open = true; 52 | if (this.config.duration > 0) { 53 | this.timer = setTimeout(() => this.dismiss(false), this.config.duration); 54 | } 55 | } 56 | 57 | dismiss(manualClose: boolean) { 58 | this.open = false; 59 | 60 | this.manualClose = manualClose; 61 | } 62 | 63 | animationDone(event: AnimationEvent) { 64 | if (event.fromState === 'active' && event.toState === 'inactive') { 65 | this._afterClosed.next(this.manualClose); 66 | this._afterClosed.complete(); 67 | } 68 | } 69 | 70 | /** 71 | * Gets an observable that is notified when the dialog is finished closing. 72 | */ 73 | afterClosed(): Observable { 74 | return this._afterClosed.asObservable(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/services/filter-routing/model.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from 'rxjs'; 2 | 3 | export class NwbFilterGroup { 4 | valuesChange$ = new Subject(); 5 | 6 | private group = new Map(); 7 | 8 | constructor(public name: string, group: { [key: string]: any }) { 9 | Object.keys(group).forEach(key => { 10 | const value = group[key]; 11 | 12 | const filter = new NwbFilter(key, value, value); 13 | 14 | this.group.set(key, filter); 15 | }); 16 | } 17 | 18 | set(key, value) { 19 | if (this._valueChange(key, value)) { 20 | this.emitChange(); 21 | } 22 | } 23 | 24 | get(key) { 25 | if (!this.group.has(key)) { 26 | throw new Error(`FilterGroup: They key ${key} doesn't exist`); 27 | } 28 | 29 | return this.group.get(key).value; 30 | } 31 | 32 | setValues(values: { [key: string]: any }) { 33 | let valueHasChanged = false; 34 | Object.keys(values).forEach(key => { 35 | if (this._valueChange(key, values[key])) { 36 | valueHasChanged = true; 37 | } 38 | }); 39 | 40 | if (valueHasChanged) { 41 | this.emitChange(); 42 | } 43 | } 44 | 45 | private _valueChange(key, value) { 46 | if (!this.group.has(key)) { 47 | throw new Error(`FilterGroup: They key ${key} doesn't exist`); 48 | } 49 | 50 | if (typeof value === 'string') { 51 | value = value.trim(); 52 | } 53 | 54 | if (this.group.get(key).value != value) { 55 | this.group.get(key).value = value; 56 | return true; 57 | } 58 | return false; 59 | } 60 | 61 | private emitChange() { 62 | const filters: NwbFilter[] = []; 63 | this.group.forEach(filter => filters.push(filter)); 64 | 65 | this.valuesChange$.next(filters); 66 | } 67 | 68 | getFilters() { 69 | const filters: NwbFilter[] = []; 70 | this.group.forEach(filter => filters.push(filter)); 71 | 72 | return filters; 73 | } 74 | } 75 | 76 | export class NwbFilter { 77 | constructor(public key: string, public defaultValue: any, public value: any) {} 78 | 79 | isDefaultValue() { 80 | return this.defaultValue === this.value; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/dom/dom.service.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ApplicationRef, 3 | ComponentFactoryResolver, 4 | ComponentRef, 5 | EmbeddedViewRef, 6 | Injectable, 7 | Injector, 8 | Optional, 9 | SkipSelf 10 | } from '@angular/core'; 11 | 12 | import { OverlayContainer } from '../overlay/overlay-container'; 13 | import { PortalInjector } from '../portal/portal-injector'; 14 | 15 | @Injectable() 16 | export class DomService { 17 | constructor( 18 | private componentFactoryResolver: ComponentFactoryResolver, 19 | private appRef: ApplicationRef, 20 | private injector: Injector, 21 | private overlayContainer: OverlayContainer 22 | ) {} 23 | 24 | attachComponentPortal(component: ComponentType, injector?: PortalInjector): ComponentRef { 25 | const componentRef: ComponentRef = this.componentFactoryResolver 26 | .resolveComponentFactory(component) 27 | .create(injector ? injector : this.injector); 28 | 29 | this.appRef.attachView(componentRef.hostView); 30 | 31 | this.overlayContainer.getContainerElement().appendChild(this._getComponentRootNode(componentRef)); 32 | 33 | return componentRef; 34 | } 35 | 36 | /** Gets the root HTMLElement for an instantiated component. */ 37 | private _getComponentRootNode(componentRef: ComponentRef): HTMLElement { 38 | return (componentRef.hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement; 39 | } 40 | } 41 | 42 | export function DOM_SERVICE_PROVIDER_FACTORY( 43 | parentContainer: DomService, 44 | componentFactoryResolver: ComponentFactoryResolver, 45 | appRef: ApplicationRef, 46 | injector: Injector, 47 | overlayContainer: OverlayContainer 48 | ) { 49 | return parentContainer || new DomService(componentFactoryResolver, appRef, injector, overlayContainer); 50 | } 51 | 52 | export const DOM_SERVICE_PROVIDER = { 53 | // If there is already an DomService available, use that. Otherwise, provide a new one. 54 | provide: DomService, 55 | deps: [[new Optional(), new SkipSelf(), DomService], ComponentFactoryResolver, ApplicationRef, Injector, OverlayContainer], 56 | useFactory: DOM_SERVICE_PROVIDER_FACTORY 57 | }; 58 | 59 | export interface ComponentType { 60 | new (...args: any[]): T; 61 | } 62 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/modal-search/modal-search.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Injector } from '@angular/core'; 2 | import { DomService } from '../shared/dom/dom.service'; 3 | import { PortalInjector } from '../shared/portal/portal-injector'; 4 | import { extendObject } from '../shared/util/object-extend'; 5 | import { NwbModalSearchComponent } from './modal-search.component'; 6 | import { Observable } from 'rxjs'; 7 | 8 | @Injectable() 9 | export class NwbModalSearchService { 10 | constructor(private domService: DomService, private injector: Injector) {} 11 | 12 | create(config: NwbModalSearchConfig): NwbModalSearchComponent { 13 | const componentRef = this.getComponentRef(config); 14 | 15 | return componentRef.instance; 16 | } 17 | 18 | private getComponentRef(config: NwbModalSearchConfig) { 19 | const injectionTokens = new WeakMap(); 20 | 21 | injectionTokens.set(NwbModalSearchComponent, NwbModalSearchComponent); 22 | 23 | let injector = new PortalInjector(this.injector, injectionTokens); 24 | 25 | const componentRef = this.domService.attachComponentPortal(NwbModalSearchComponent, injector); 26 | 27 | componentRef.instance.config = extendObject(new NwbModalSearchConfig(), config); 28 | 29 | return componentRef; 30 | } 31 | } 32 | 33 | export class NwbModalSearchConfig { 34 | hasHeader? = false; 35 | hasFooter? = false; 36 | 37 | /** keys combination to open the modal **/ 38 | keyCodes?: { 39 | specialKey: 'cmd' | 'ctrl' | 'alt' | 'shift' | 'windows' | null; 40 | key: string; 41 | }[] = [ 42 | { 43 | specialKey: 'cmd', 44 | key: 'k' 45 | }, 46 | { 47 | specialKey: 'ctrl', 48 | key: 'k' 49 | } 50 | ]; 51 | 52 | /** basic string array with all the values to search to **/ 53 | records?: NwbFoundRow[]; 54 | 55 | /** Custom method to filter the results you want to display **/ 56 | customSearchFn?: (value: string) => NwbFoundRow[] | Observable; 57 | 58 | /** search input place holder **/ 59 | inputPlaceholder? = 'Jump to...'; 60 | 61 | /** extra classes to add **/ 62 | extraClasses? = ''; 63 | } 64 | 65 | export interface NwbFoundRow { 66 | text: string; 67 | isSelectable?: boolean; 68 | data?: any; 69 | children?: NwbFoundRow[]; 70 | } 71 | -------------------------------------------------------------------------------- /src/app/features/progress-bar/progress-bar-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Progress Bar 5 |

6 |
7 |
8 |
9 |

Progress bar configuration

10 |
11 | 12 |
13 | 17 | 21 | 25 | 29 |
30 |
31 |
32 | 33 |
34 | 38 | 42 | 46 |
47 |
48 | 49 |
50 | 51 |
52 | 53 |
54 |
55 | 56 | 57 | 58 | 63 | 64 |
65 |
66 |
67 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/progress-bar/progress-bar.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Porf of Angular Mateiral's Progress Bar 4 | * 5 | * @license 6 | * Copyright Google Inc. All Rights Reserved. 7 | * 8 | * Use of this source code is governed by an MIT-style license that can be 9 | * found in the LICENSE file at https://angular.io/license 10 | */ 11 | 12 | import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core'; 13 | 14 | /** 15 | * component. 16 | */ 17 | @Component({ 18 | selector: 'nwb-progress-bar', 19 | host: { 20 | role: 'progressbar', 21 | 'aria-valuemin': '0', 22 | 'aria-valuemax': '100', 23 | '[attr.aria-valuenow]': 'value', 24 | '[attr.mode]': 'mode', 25 | '[class.is-primary]': 'color == "primary"', 26 | '[class.is-info]': 'color == "info"', 27 | '[class.is-warning]': 'color == "warning"', 28 | '[class.is-danger]': 'color == "danger"', 29 | class: 'nwb-progress-bar' 30 | }, 31 | templateUrl: './progress-bar.component.html', 32 | changeDetection: ChangeDetectionStrategy.OnPush, 33 | encapsulation: ViewEncapsulation.None 34 | }) 35 | export class NwbProgressBarComponent { 36 | /** Color of the progress bar. */ 37 | @Input() 38 | color: 'primary' | 'info' | 'warning' | 'danger' = 'primary'; 39 | 40 | private _value: number = 0; 41 | 42 | /** Value of the progressbar. Defaults to zero. Mirrored to aria-valuenow. */ 43 | @Input() 44 | get value() { 45 | return this._value; 46 | } 47 | 48 | set value(v: number) { 49 | this._value = clamp(v || 0); 50 | } 51 | 52 | /** 53 | * Mode of the progress bar. 54 | * 55 | * Input must be one of these values: determinate, indeterminate, buffer, query, defaults to 56 | * 'determinate'. 57 | * Mirrored to mode attribute. 58 | */ 59 | @Input() 60 | mode: 'determinate' | 'indeterminate' | 'query' = 'determinate'; 61 | 62 | /** Gets the current transform value for the progress bar's primary indicator. */ 63 | _primaryTransform() { 64 | let scale = this.value / 100; 65 | return { transform: `scaleX(${scale})` }; 66 | } 67 | } 68 | 69 | /** Clamps a value to be between two numbers, by default 0 and 100. */ 70 | function clamp(v: number, min = 0, max = 100) { 71 | return Math.max(min, Math.min(max, v)); 72 | } 73 | -------------------------------------------------------------------------------- /src/app/features/alert/alert-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NwbAlertConfig, NwbAlertService } from 'projects/ng-wizi-bulma/src/public_api'; 3 | 4 | @Component({ 5 | providers: [], 6 | templateUrl: './alert-demo.html' 7 | }) 8 | export class AlertDemo { 9 | constructor(private nwbAlert: NwbAlertService) {} 10 | 11 | sample1 = ` 12 | const position = '{your position}'; 13 | const color = '{your color}'; 14 | const alertConfig: NwbAlertConfig = { 15 | message: 'My alert message with bold', 16 | duration: 1000, 17 | position: position, 18 | color: color 19 | }; 20 | 21 | this.nwbAlert.open(alertConfig) 22 | .afterClosed() 23 | .subscribe(() => console.log('alertClose')); 24 | `; 25 | 26 | sample2 = ` 27 | const position = '{your position}'; 28 | const color = '{your color}'; 29 | const alertConfig: NwbAlertConfig = { 30 | message: 'My alert message with bold', 31 | duration: 1000, 32 | position: position, 33 | color: color, 34 | extraClasses: 'is-inverted' 35 | }; 36 | 37 | this.nwbAlert.open(alertConfig) 38 | .afterClosed() 39 | .subscribe(() => console.log('alertClose')); 40 | `; 41 | 42 | sample3 = ` 43 | const position = '{your position}'; 44 | const color = '{your color}'; 45 | const alertConfig: NwbAlertConfig = { 46 | message: 'My alert message with bold', 47 | duration: 1000, 48 | position: position, 49 | color: color, 50 | icon: 'fa fa-warning fa-2x' 51 | }; 52 | 53 | this.nwbAlert.open(alertConfig) 54 | .afterClosed() 55 | .subscribe(() => console.log('alertClose')); 56 | `; 57 | 58 | openAlert(position, color, extraClasses = '', icon = '') { 59 | console.log('openAlert'); 60 | 61 | const alertConfig: NwbAlertConfig = { 62 | message: 'My alert message with bold', 63 | duration: 1000, 64 | position: position, 65 | color: color 66 | }; 67 | if (extraClasses !== '') { 68 | alertConfig.extraClasses = extraClasses; 69 | } 70 | if (icon !== '') { 71 | alertConfig.icon = icon; 72 | } 73 | 74 | this.nwbAlert 75 | .open(alertConfig) 76 | .afterClosed() 77 | .subscribe(() => console.log('alertClose')); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NG Wizi Bulma 2 | 3 | [![npm](https://img.shields.io/npm/v/@wizishop/ng-wizi-bulma.svg)](https://www.npmjs.com/package/@wizishop/ng-wizi-bulma) 4 | [![npm](https://img.shields.io/npm/dm/@wizishop/ng-wizi-bulma.svg)](https://www.npmjs.com/package/@wizishop/ng-wizi-bulma) 5 | 6 | [Bulma](http://bulma.io/) components for Angular 15+ 7 | 8 | The library uses [ng-packagr](https://github.com/dherges/ng-packagr) to transpile into the Angular Package Format 9 | 10 | ## Demo 11 | 12 | Try out the [demo](https://ng-wizi-bulma.firebaseapp.com/) 13 | 14 | ## Install 15 | 16 | Run: 17 | 18 | ```sh 19 | npm i -S @wizishop/ng-wizi-bulma bulma bulma-extensions @angular/cdk 20 | ``` 21 | 22 | Import bulma (and needed extensions) scss into your main scss file: 23 | 24 | ```scss 25 | @import 'node_modules/bulma/bulma.sass'; 26 | @import 'node_modules/bulma-extensions/bulma-switch/src/sass/index'; 27 | @import 'node_modules/bulma-extensions/bulma-tooltip/src/sass/index'; 28 | @import 'node_modules/bulma-extensions/bulma-calendar/src/sass/index'; 29 | ``` 30 | 31 | After Bulma, import ng-wizi-bulma scss into your main scss file allowing you to custom all variable from bulma: 32 | 33 | ```scss 34 | @import 'node_modules/@wizishop/ng-wizi-bulma/ng-wizi-bulma'; 35 | ``` 36 | 37 | Load the Fontawesome icon font in your index.html. 38 | 39 | ```html 40 | 41 | ``` 42 | 43 | Import the required modules `BrowserAnimationsModule` and `FormsModule` into your app module, then 44 | import either all Nwb modules with `NwbAllModule` or only the module you want to use in your application for example `NwbDialogModule 45 | 46 | ```ts 47 | import {ApplicationRef, NgModule} from '@angular/core'; 48 | import {BrowserModule} from '@angular/platform-browser'; 49 | import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 50 | import {HttpModule} from '@angular/http'; 51 | import {FormsModule} from '@angular/forms'; 52 | 53 | import {NwbAllModule} from '@wizishop/ng-wizi-bulma'; 54 | 55 | @NgModule({ 56 | imports: [ 57 | BrowserModule, 58 | FormsModule, 59 | HttpModule, 60 | BrowserAnimationsModule, 61 | NwbAllModule, 62 | ], 63 | declarations: [], 64 | providers: [], 65 | entryComponents: [], 66 | }) 67 | export class AppModule { 68 | 69 | } 70 | ``` 71 | 72 | ## How to use it 73 | 74 | If you want to see how components work, just see the demo file : `src/demo-app/demo-app/demo-app.ts` 75 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/dialog/dialog.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Injector, TemplateRef } from '@angular/core'; 2 | import { NwbDialogComponent } from './dialog.component'; 3 | import { DomService } from '../shared/dom/dom.service'; 4 | import { PortalInjector } from '../shared/portal/portal-injector'; 5 | import { extendObject } from '../shared/util/object-extend'; 6 | 7 | @Injectable() 8 | export class NwbDialogService { 9 | constructor(private domService: DomService, private injector: Injector) {} 10 | 11 | open(config: NwbDialogConfig): NwbDialogComponent { 12 | const componentRef = this.getComponentRef(config); 13 | 14 | return componentRef.instance; 15 | } 16 | 17 | openFromComponent(componentOrTemplateRef: ComponentType | TemplateRef, config: NwbDialogConfig): NwbDialogComponent { 18 | const componentRef = this.getComponentRef(config); 19 | 20 | componentRef.instance._setComponent(componentOrTemplateRef); 21 | 22 | return componentRef.instance as NwbDialogComponent; 23 | } 24 | 25 | private getComponentRef(config: NwbDialogConfig) { 26 | const injectionTokens = new WeakMap(); 27 | 28 | injectionTokens.set(NwbDialogComponent, NwbDialogComponent); 29 | 30 | let injector = new PortalInjector(this.injector, injectionTokens); 31 | 32 | const componentRef = this.domService.attachComponentPortal(NwbDialogComponent, injector); 33 | 34 | componentRef.instance.config = extendObject(new NwbDialogConfig(), config); 35 | 36 | componentRef.instance.afterClosed().subscribe(() => { 37 | componentRef.destroy(); 38 | }); 39 | 40 | return componentRef; 41 | } 42 | } 43 | 44 | export class NwbDialogConfig { 45 | /** Dialog's content */ 46 | message?: string; 47 | 48 | /** Dialog's title */ 49 | title: string; 50 | 51 | /** Text of the ok button. If none the button won't be displayed */ 52 | okButtonText?: string = ''; 53 | 54 | /** Text of the cancel button. If none the button won't be displayed */ 55 | cancelButtonText?: string = ''; 56 | 57 | /** Width of the dialog. */ 58 | width?: string = ''; 59 | 60 | /** Whether the dialog has a backdrop. */ 61 | hasBackdrop?: boolean = true; 62 | 63 | /** Custom method to call when ok button is clicked */ 64 | okHandler?: Function = null; 65 | 66 | /** Custom method to call when cancel button is clicked */ 67 | cancelHandler?: Function = null; 68 | 69 | /** Display the spinner inside the dialog **/ 70 | loading?: boolean = false; 71 | } 72 | 73 | export interface ComponentType { 74 | new (...args: any[]): T; 75 | } 76 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/directives/debounce/debounce.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; 3 | import { Subscription, fromEvent } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | @Directive({ 7 | selector: '[nwbDebounce]', 8 | providers: [ 9 | { 10 | provide: NG_VALUE_ACCESSOR, 11 | useExisting: NwbDebounceDirective, 12 | multi: true 13 | } 14 | ] 15 | }) 16 | export class NwbDebounceDirective implements OnInit, ControlValueAccessor, OnDestroy { 17 | @Input() 18 | nwbDebounceDelay = 700; 19 | @Output() 20 | nwbDebounceChange: EventEmitter = new EventEmitter(); 21 | 22 | private _onChanged: Function; 23 | private _onTouched: Function; 24 | 25 | private _inputValue: any; 26 | 27 | private _modelValue: any; 28 | 29 | private _timerId; 30 | 31 | private _eventStreamKeyUp: Subscription; 32 | private _eventStreamChange: Subscription; 33 | 34 | constructor(private elementRef: ElementRef) {} 35 | 36 | writeValue(value: any): void { 37 | if (this._timerId) { 38 | clearTimeout(this._timerId); 39 | } 40 | this._inputValue = value; 41 | 42 | if (this.elementRef.nativeElement.value !== value) { 43 | this.elementRef.nativeElement.value = value; 44 | } 45 | } 46 | 47 | registerOnChange(fn: any): void { 48 | this._onChanged = fn; 49 | } 50 | 51 | registerOnTouched(fn: any): void { 52 | this._onTouched = fn; 53 | } 54 | 55 | ngOnInit(): void { 56 | this._inputValue = this.elementRef.nativeElement.value; 57 | 58 | const eventStreamKeyUp = fromEvent(this.elementRef.nativeElement, 'keyup').pipe(map(() => this.elementRef.nativeElement.value)); 59 | 60 | this._eventStreamKeyUp = eventStreamKeyUp.subscribe((input: any) => this.valueChange(input)); 61 | 62 | const eventStreamChange = fromEvent(this.elementRef.nativeElement, 'change').pipe(map(() => this.elementRef.nativeElement.value)); 63 | 64 | this._eventStreamChange = eventStreamChange.subscribe((input: any) => this.valueChange(input)); 65 | } 66 | 67 | ngOnDestroy() { 68 | this._eventStreamKeyUp.unsubscribe(); 69 | this._eventStreamChange.unsubscribe(); 70 | } 71 | 72 | private valueChange(value: any) { 73 | if (this._timerId) { 74 | clearTimeout(this._timerId); 75 | } 76 | this._timerId = setTimeout(() => { 77 | if (this._inputValue !== value) { 78 | this._inputValue = value; 79 | this.nwbDebounceChange.emit(value); 80 | 81 | if (this._modelValue !== this._inputValue) { 82 | this._modelValue = this._inputValue; 83 | if (typeof this._onChanged === 'function') { 84 | this._onChanged(this._inputValue); 85 | } 86 | } 87 | } 88 | }, this.nwbDebounceDelay); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/tabs/tabs.component.ts: -------------------------------------------------------------------------------- 1 | import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, OnInit, Output, QueryList } from '@angular/core'; 2 | import { NwbTabComponent } from './tab.component'; 3 | 4 | @Component({ 5 | selector: 'nwb-tabs', 6 | template: ` 7 |
16 | 26 |
27 | 28 | `, 29 | }) 30 | export class NwbTabsComponent implements OnInit, AfterContentInit { 31 | /** IE [box]="true" **/ 32 | @Input() 33 | box: boolean; 34 | 35 | /** IE: [alignment]="'center|left|right'" **/ 36 | @Input() 37 | alignment: string; 38 | 39 | /** IE: [size]="'small|medium|large'" **/ 40 | @Input() 41 | size: 'small' | 'medium' | 'large'; 42 | 43 | /** IE: [toggle]="true" **/ 44 | @Input() 45 | toggle: boolean; 46 | 47 | /** IE: [rounded]="true" **/ 48 | @Input() 49 | rounded: boolean; 50 | 51 | /** IE [fullwidth]="true" **/ 52 | @Input() 53 | fullwidth: boolean; 54 | 55 | /** IE: [(selectedIndex)]="active" (optional, will equal first tab by default) **/ 56 | _selectedIndex = 0; 57 | @Input() 58 | set selectedIndex(selectedIndex: number) { 59 | this.select(selectedIndex); 60 | } 61 | 62 | get selectedIndex() { 63 | return this._selectedIndex; 64 | } 65 | 66 | @Output() 67 | selectedIndexChange: EventEmitter = new EventEmitter(); 68 | 69 | @ContentChildren(NwbTabComponent) 70 | tabList: QueryList; 71 | 72 | constructor() {} 73 | 74 | ngOnInit() { 75 | if (this.rounded) { 76 | this.toggle = true; 77 | } 78 | } 79 | 80 | select(index: number) { 81 | if (this._selectedIndex === index) { 82 | return; 83 | } 84 | 85 | this._selectedIndex = index; 86 | 87 | if (this.tabList) { 88 | this.tabList.forEach((tab: NwbTabComponent) => { 89 | tab.setSelected(tab.index === this.selectedIndex); 90 | }); 91 | 92 | this.selectedIndexChange.emit(this.selectedIndex); 93 | } 94 | } 95 | 96 | ngAfterContentInit() { 97 | this.tabList.forEach((tab: NwbTabComponent, index) => { 98 | tab.index = index; 99 | tab.setSelected(tab.index === this.selectedIndex); 100 | }); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/app/features/alert/alert-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Alert 5 |

6 |
7 |
8 |
9 |

Color : is-success is-warning is-link is-info is-dark

10 |

Position : is-top is-left is-right is-left

11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
30 |

With extraClasses options, you can invert color Example : extraClasses = 'is-inverted' :

31 | 32 | 33 |
34 |
35 | 36 |
37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 | 45 |
46 |
47 |

With icon Example : icon = 'fa fa-warning fa-2x' :

48 | 49 | 50 | 51 |
52 |
53 |
54 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** 38 | * If the application will be indexed by Google Search, the following is required. 39 | * Googlebot uses a renderer based on Chrome 41. 40 | * https://developers.google.com/search/docs/guides/rendering 41 | **/ 42 | // import 'core-js/es6/array'; 43 | 44 | /** IE10 and IE11 requires the following for the Reflect API. */ 45 | // import 'core-js/es6/reflect'; 46 | 47 | /** 48 | * By default, zone.js will patch all possible macroTask and DomEvents 49 | * user can disable parts of macroTask/DomEvents patch by setting following flags 50 | */ 51 | 52 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 53 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 54 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 55 | 56 | /* 57 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 58 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 59 | */ 60 | // (window as any).__Zone_enable_cross_context_check = true; 61 | 62 | /*************************************************************************************************** 63 | * Zone JS is required by default for Angular itself. 64 | */ 65 | import 'zone.js'; // Included with Angular CLI. 66 | 67 | /*************************************************************************************************** 68 | * APPLICATION IMPORTS 69 | */ 70 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/alert/alert.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-alert { 2 | .alert { 3 | z-index: 999999; 4 | position: fixed; 5 | color: $white; 6 | background-color: $primary; 7 | border: 1px solid transparent; 8 | border-radius: 3px; 9 | padding: 15px 20px; 10 | transition: all 200ms; 11 | opacity: 0; 12 | margin: 10px auto; 13 | width: 400px; 14 | box-shadow: 0 0 20px rgba(50, 50, 50, 0.1); 15 | font-size: 14px; 16 | 17 | &.is-left { 18 | left: -100px; 19 | margin: 10px; 20 | top: 100px; 21 | } 22 | 23 | &.is-right { 24 | right: -100px; 25 | margin: 10px; 26 | top: 100px; 27 | } 28 | 29 | &.is-top { 30 | top: -100px; 31 | left: 0; 32 | right: 0; 33 | } 34 | 35 | &.is-bottom { 36 | bottom: -100px; 37 | left: 0; 38 | right: 0; 39 | } 40 | 41 | &.is-active { 42 | opacity: 0.9; 43 | 44 | &.is-left { 45 | left: 0; 46 | } 47 | 48 | &.is-right { 49 | right: 0; 50 | } 51 | 52 | &.is-top { 53 | top: 0; 54 | } 55 | 56 | &.is-bottom { 57 | bottom: 0; 58 | } 59 | } 60 | 61 | p { 62 | display: inline-block; 63 | } 64 | 65 | span { 66 | vertical-align: middle; 67 | margin: 0 10px 0 0; 68 | } 69 | } 70 | 71 | .alert.is-primary { 72 | background-color: $primary; 73 | 74 | &.is-inverted { 75 | background-color: $white; 76 | border: 1px solid $primary; 77 | color: $primary; 78 | } 79 | } 80 | 81 | .alert.is-success { 82 | background-color: $success; 83 | 84 | &.is-inverted { 85 | background-color: $white; 86 | border: 1px solid $primary; 87 | color: $primary; 88 | } 89 | } 90 | 91 | .alert.is-danger { 92 | background-color: $danger; 93 | 94 | &.is-inverted { 95 | background-color: $white; 96 | border: 1px solid $danger; 97 | color: $danger; 98 | } 99 | } 100 | 101 | .alert.is-warning { 102 | background-color: $warning; 103 | color: rgba(0, 0, 0, 0.7); 104 | 105 | &.is-inverted { 106 | background-color: $dark; 107 | border: 1px solid $dark; 108 | color: $warning; 109 | } 110 | } 111 | 112 | .alert.is-info { 113 | background-color: $info; 114 | 115 | &.is-inverted { 116 | background-color: $white; 117 | border: 1px solid $info; 118 | color: $info; 119 | } 120 | } 121 | 122 | .alert.is-dark { 123 | background-color: $dark; 124 | 125 | &.is-inverted { 126 | background-color: $white; 127 | border: 1px solid $dark; 128 | color: $dark; 129 | } 130 | } 131 | 132 | .alert.is-link { 133 | background-color: $link; 134 | 135 | &.is-inverted { 136 | background-color: $white; 137 | border: 1px solid $link; 138 | color: $link; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/app/features/dropdown/dropdown-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Dropdown menu 5 |

6 |
7 |
8 |

A dropdown is composed of nwb-dropdown and nwb-option elements.

9 |
10 |

11 | Specific dropdown items can be disabled via the disabled property. You can also separate items by creating an item 12 | with the divider property set to true. 13 |

14 | 15 | 16 | 17 | NES 18 | Nintendo64 19 | Disabled value 20 | Sega Genesis 21 | Sega Saturn 22 | keyboard SNES 23 | 24 | null value 25 | true value 26 | 27 |

Selected value: {{gaming}}

28 |
29 |
30 |
31 | 32 |
33 |
34 |

35 | Dropdown menu with change handler method 36 |

37 |
38 |
39 |

40 | You can specify a custom change handler in the config input. The following example will change only if user selects 41 | Nintendo64 (n64) or Sega Genesis (genesis) 42 |

43 | 44 | 45 | NES 46 | Nintendo64 47 | Disabled value 48 | Sega Genesis 49 | Sega Saturn 50 | SNES 51 | 52 | null value 53 | true value 54 | 55 |

Selected value: {{gaming2}}

56 | 57 | 60 |
{{dopdown2Config|json}}
61 |
62 |
63 |
64 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { AlertDemo } from './features/alert/alert-demo'; 4 | import { AnimatedCardDemo } from './features/animated-card/animated-card-demo'; 5 | import { DatePickerDemo } from './features/date-picker/date-picker-demo'; 6 | import { DebounceDemo } from './features/debounce/debounce-demo'; 7 | import { DialogDemo } from './features/dialog/dialog-demo'; 8 | import { DropdownDemo } from './features/dropdown/dropdown-demo'; 9 | import { EditInPlaceDemo } from './features/edit-in-place/edit-in-place-demo'; 10 | import { Home } from './features/home/home'; 11 | import { ModalSearchDemo } from './features/modal-search/modal-search-demo'; 12 | import { PaginatorDemo } from './features/paginator/paginator-demo'; 13 | import { ProgressBarDemo } from './features/progress-bar/progress-bar-demo'; 14 | import { SnackbarDemo } from './features/snackbar/snackbar-demo'; 15 | import { SortDemo } from './features/sort/sort-demo'; 16 | import { SpinnerDemo } from './features/spinner/spinner-demo'; 17 | import { SwitchDemo } from './features/switch/switch-demo'; 18 | import { TableDemo } from './features/table/table-demo'; 19 | import { TabsDemo } from './features/tabs/tabs-demo.component'; 20 | import { TooltipDemo } from './features/tooltip/tooltip-demo'; 21 | 22 | const appRoutes: Routes = [ 23 | { 24 | path: '', 25 | component: Home, 26 | }, 27 | { 28 | path: 'dialog', 29 | component: DialogDemo, 30 | }, 31 | { 32 | path: 'snackbar', 33 | component: SnackbarDemo, 34 | }, 35 | { 36 | path: 'alert', 37 | component: AlertDemo, 38 | }, 39 | { 40 | path: 'animated-card', 41 | component: AnimatedCardDemo, 42 | }, 43 | { 44 | path: 'paginator', 45 | component: PaginatorDemo, 46 | }, 47 | { 48 | path: 'spinner', 49 | component: SpinnerDemo, 50 | }, 51 | { 52 | path: 'dropdown', 53 | component: DropdownDemo, 54 | }, 55 | { 56 | path: 'progress-bar', 57 | component: ProgressBarDemo, 58 | }, 59 | { 60 | path: 'debounce', 61 | component: DebounceDemo, 62 | }, 63 | { 64 | path: 'modal-search', 65 | component: ModalSearchDemo, 66 | }, 67 | { 68 | path: 'tabs', 69 | component: TabsDemo, 70 | }, 71 | { 72 | path: 'tabs/:basicTabIndex', 73 | component: TabsDemo, 74 | }, 75 | { 76 | path: 'switch', 77 | component: SwitchDemo, 78 | }, 79 | { 80 | path: 'tooltip', 81 | component: TooltipDemo, 82 | }, 83 | { 84 | path: 'table', 85 | component: TableDemo, 86 | }, 87 | { 88 | path: 'edit-in-place', 89 | component: EditInPlaceDemo, 90 | }, 91 | { 92 | path: 'sort', 93 | component: SortDemo, 94 | }, 95 | { 96 | path: 'date-picker', 97 | component: DatePickerDemo, 98 | }, 99 | { 100 | path: '**', 101 | component: Home, 102 | }, 103 | ]; 104 | 105 | @NgModule({ 106 | imports: [RouterModule.forRoot(appRoutes, {})], 107 | exports: [RouterModule], 108 | providers: [], 109 | }) 110 | export class AppRoutingModule {} 111 | -------------------------------------------------------------------------------- /src/app/features/dialog/dialog-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NwbDialogConfig, NwbDialogService } from 'projects/ng-wizi-bulma/src/public_api'; 3 | import { FakeDialogDemoComponent } from './fake-dialog-demo.component'; 4 | import { User } from './edit-user-dialog-demo.component'; 5 | 6 | @Component({ 7 | providers: [], 8 | templateUrl: './dialog-demo.html' 9 | }) 10 | export class DialogDemo { 11 | dialogConfig: NwbDialogConfig = { 12 | title: 'Logout', 13 | message: 'Do you want to logout?', 14 | okButtonText: 'Yes', 15 | cancelButtonText: 'No', 16 | loading: true 17 | }; 18 | dialogFromComponentConfig: NwbDialogConfig = { 19 | title: 'From component', 20 | okButtonText: 'Yes', 21 | cancelButtonText: 'No' 22 | }; 23 | 24 | dialogFromComponentConfigWithSpinner: NwbDialogConfig = { 25 | title: 'From component with spinner', 26 | okButtonText: 'Yes', 27 | cancelButtonText: 'No', 28 | width: '900px', 29 | loading: true, 30 | hasBackdrop: false 31 | }; 32 | 33 | fakeComponentValue = ''; 34 | fakeComponent2Value = ''; 35 | 36 | userId: number = null; 37 | 38 | constructor(private nwbDialog: NwbDialogService) {} 39 | 40 | openDialog() { 41 | let dialog = this.nwbDialog.open(this.dialogConfig); 42 | 43 | dialog.ready.subscribe(() => { 44 | console.log('openDialog is ready'); 45 | setTimeout(() => { 46 | console.log('openDialog is loaded'); 47 | dialog.hideSpinner(); 48 | }, 700); 49 | }); 50 | 51 | dialog.config.okHandler = () => { 52 | dialog.disableButtonsAndMakeOkButtonLoading(); 53 | 54 | setTimeout(() => { 55 | dialog.enableButtonsAndMakeOkButtonNotLoading(); 56 | dialog.dismiss(true); 57 | }, 700); 58 | }; 59 | 60 | dialog.afterClosed().subscribe(fromOkButton => console.log('dialogClose, fromOkButton', fromOkButton)); 61 | } 62 | 63 | openDialogFromComponent() { 64 | const dialog = this.nwbDialog.openFromComponent(FakeDialogDemoComponent, this.dialogFromComponentConfig); 65 | 66 | dialog.componentInstance.myInput.nativeElement.value = 'Random text'; 67 | 68 | dialog.afterClosed().subscribe(fromOkButton => { 69 | if (fromOkButton) { 70 | this.fakeComponentValue = dialog.componentInstance.myInput.nativeElement.value; 71 | } 72 | }); 73 | } 74 | 75 | openDialogFromComponentWithSpinner() { 76 | const dialog = this.nwbDialog.openFromComponent(FakeDialogDemoComponent, this.dialogFromComponentConfigWithSpinner); 77 | 78 | dialog.ready.subscribe(() => { 79 | console.log('openDialogFromComponentWithSpinner is ready'); 80 | dialog.componentInstance.loading.subscribe(() => { 81 | console.log('FakeDialogDemoComponent is loaded'); 82 | dialog.hideSpinner(); 83 | }); 84 | }); 85 | 86 | dialog.componentInstance.myInput.nativeElement.value = 'Random text'; 87 | 88 | dialog.afterClosed().subscribe(fromOkButton => { 89 | if (fromOkButton) { 90 | this.fakeComponentValue = dialog.componentInstance.myInput.nativeElement.value; 91 | } 92 | }); 93 | } 94 | 95 | openDialogFromTemplate() { 96 | this.userId = 42; 97 | } 98 | 99 | userChange(user: User) { 100 | console.log('user has changed', user); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wizishop/ng-wizi-bulma", 3 | "version": "18.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng build ng-wizi-bulma && npm run block-scss && concurrently \"npm run watch-scss\" \"ng serve\"", 8 | "build:lib": "ng build ng-wizi-bulma --configuration production && npm run block-scss && cp README.md dist/@wizishop/ng-wizi-bulma", 9 | "build:demo": "ng build ng-wizi-bulma-demo --configuration production", 10 | "build": "rm -rf dist && npm run build:lib && npm run build:demo", 11 | "test": "ng test", 12 | "lint": "ng lint", 13 | "deploy": "npm run build && firebase deploy", 14 | "publish:npm": "rm -rf dist && npm run build:lib && cd dist/@wizishop/ng-wizi-bulma && npm publish --access public && cd ../../../", 15 | "publish:npm:next": "rm -rf dist && npm run build:lib && cd dist/@wizishop/ng-wizi-bulma && npm publish --access public --tag next && cd ../../../", 16 | "publish": "npm run deploy && npm run publish:npm", 17 | "precommit": "pretty-quick --staged", 18 | "prepack": "npm run build:lib", 19 | "watch-scss": "nodemon --watch './projects/ng-wizi-bulma/src/**/*.scss' -e scss -d 1 -x \"npm run block-scss\" ", 20 | "block-scss": "node ./scripts/scss-bundle.js", 21 | "ng:update": "ng update @angular/cli @angular/core @angular/cdk @angular-eslint/schematics prettier husky --allow-dirty --force" 22 | }, 23 | "private": true, 24 | "dependencies": { 25 | "@angular/animations": "18.2.11", 26 | "@angular/cdk": "^18.2.13", 27 | "@angular/common": "18.2.11", 28 | "@angular/compiler": "18.2.11", 29 | "@angular/core": "^18.2.11", 30 | "@angular/forms": "18.2.11", 31 | "@angular/platform-browser": "18.2.11", 32 | "@angular/platform-browser-dynamic": "18.2.11", 33 | "@angular/router": "18.2.11", 34 | "bulma": "^0.9.4", 35 | "bulma-calendar": "git+https://github.com/WiziShop/bulma-calendar.git", 36 | "bulma-extensions": "^6.2.7", 37 | "bundle-scss": "^1.5.1", 38 | "colors": "^1.4.0", 39 | "rxjs": "^7.4.0", 40 | "tslib": "^2.3.1", 41 | "zone.js": "^0.14.10" 42 | }, 43 | "devDependencies": { 44 | "@angular-devkit/build-angular": "^18.2.11", 45 | "@angular-devkit/schematics": "^18.2.11", 46 | "@angular-eslint/builder": "^18.4.0", 47 | "@angular-eslint/eslint-plugin": "^18.4.0", 48 | "@angular-eslint/eslint-plugin-template": "^18.4.0", 49 | "@angular-eslint/schematics": "^18.4.0", 50 | "@angular-eslint/template-parser": "^18.4.0", 51 | "@angular/cli": "^18.2.11", 52 | "@angular/compiler-cli": "18.2.11", 53 | "@angular/language-service": "18.2.11", 54 | "@types/jasmine": "^4.3.0", 55 | "@types/jasminewd2": "^2.0.8", 56 | "@types/node": "^18.11.10", 57 | "@typescript-eslint/eslint-plugin": "^7.2.0", 58 | "@typescript-eslint/parser": "^7.2.0", 59 | "concurrently": "^9.1.0", 60 | "eslint": "^8.57.0", 61 | "husky": "^9.1.6", 62 | "jasmine-core": "^4.5.0", 63 | "jasmine-spec-reporter": "^7.0.0", 64 | "karma": "^6.4.1", 65 | "karma-chrome-launcher": "^3.1.1", 66 | "karma-coverage-istanbul-reporter": "^3.0.3", 67 | "karma-jasmine": "^5.1.0", 68 | "karma-jasmine-html-reporter": "^2.0.0", 69 | "ng-packagr": "^18.2.1", 70 | "nodemon": "^3.1.7", 71 | "prettier": "^3.3.3", 72 | "pretty-quick": "^4.0.0", 73 | "protractor": "~7.0.0", 74 | "ts-node": "^10.9.1", 75 | "typescript": "^5.5.4" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/app/features/table/table-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Table 5 |

6 |
7 |
8 |
9 |

This table uses the table 10 | component 11 | from angular CDK

12 |

13 | It's also using our NwbFilterRoutingBuilder service which allow you to mix data table's filters 14 | with angular router. 15 | Go ahead play with the filters (sort, query, page) and refresh the page. 16 |

17 | 18 |
19 |

20 | 29 |

30 |
31 | 32 | 33 |
34 | 35 | 36 |
38 | 39 |
40 | GitHub's API rate limit has been reached. It will be reset in one minute. 41 |
42 |
43 | 44 |
45 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 72 | 73 | 74 | 75 | 76 | 77 |
#{{row.number}}Title{{row.title}}State{{row.state}} 70 | Created 71 | {{row.created_at | date}}
78 |
79 | 80 | 85 |
86 |
87 |
88 | 89 | 90 |
91 | -------------------------------------------------------------------------------- /src/app/features/tabs/tabs-demo.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Basic combine with router

5 | 6 | 7 | 8 |

Selected index: {{ tabBasicIndex }}

9 | 10 | 11 |

Your Pictures are here!

12 | 13 |

Your Music is here!

14 | 15 |

Your Videos are here!

16 |

Your Documents are here!

17 |
18 |
19 |
20 | 21 |
22 |
23 |

Small | Toggle

24 | 25 |

Your Pictures are here!

26 |

Your Music is here!

27 |

Your Videos are here!

28 |

Your Documents are here!

29 |
30 |
31 |
32 | 33 |
34 |
35 |

Large | Rounded

36 | 37 |

Your Pictures are here!

38 |

Your Music is here!

39 |

Your Videos are here!

40 |

Your Documents are here!

41 |
42 |
43 |
44 | 45 |
46 |
47 |

Fullwidth | Boxed

48 | 49 |

Your Pictures are here!

50 |

Your Music is here!

51 |

Your Videos are here!

52 |

Your Documents are here!

53 |
54 |
55 |
56 | 57 |
58 |
59 |

Alignment

60 | 61 |

Your Pictures are here!

62 |

Your Music is here!

63 |

Your Videos are here!

64 |

Your Documents are here!

65 |
66 |
67 |
68 | 69 |
70 |
71 |

Icons

72 | 73 |

Your Pictures are here!

74 |

Your Music is here!

75 |

Your Videos are here!

76 |

Your Documents are here!

77 |
78 |
79 |
80 | -------------------------------------------------------------------------------- /src/app/features/edit-in-place/edit-in-place-demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Edit In Place Input 5 |

6 |
7 |
8 |
9 | 10 |

11 | I am a 12 | 13 |

14 |

Entered value: {{developer}}

15 |
16 |
17 |
18 |
19 | 20 |
21 |
22 |

23 | Edit In Place Input 24 |

25 |
26 |
27 |
28 | 29 |

30 | I am a 31 | 32 |

33 |

Allowed values: developer, devops

34 |
35 |
36 |
37 |
38 | 39 |
40 |
41 |

42 | Edit In Place Input with auto select 43 |

44 |
45 |
46 |
47 | 48 |

49 | I am a 50 | 55 |

56 |

Entered value: {{developer}}

57 |
58 |
59 |
60 |
61 | 62 |
63 |
64 |

65 | Edit In Place Input With Currency 66 |

67 |
68 |
69 |
70 | 71 |

72 | Enter a number value to format: 73 | 79 |

80 |

81 | Choose another currency or percentage 82 | 91 | 92 | 101 | 102 |

103 |

Number value: {{number}}

104 |

Output formatted string: {{formattedString}}

105 |
106 |
107 |
108 |
109 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/sort/sort-animation.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google LLC All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | import { animate, AnimationTriggerMetadata, keyframes, state, style, transition, trigger } from '@angular/animations'; 9 | 10 | export class AnimationCurves { 11 | static STANDARD_CURVE = 'cubic-bezier(0.4,0.0,0.2,1)'; 12 | } 13 | 14 | /** @docs-private */ 15 | export class AnimationDurations { 16 | static ENTERING = '225ms'; 17 | } 18 | 19 | const SORT_ANIMATION_TRANSITION = AnimationDurations.ENTERING + ' ' + AnimationCurves.STANDARD_CURVE; 20 | 21 | /** Animations used by MatSort. */ 22 | export const nwbSortAnimations: { 23 | readonly arrowDirection: AnimationTriggerMetadata; 24 | readonly arrowOpacity: AnimationTriggerMetadata; 25 | readonly arrowPosition: AnimationTriggerMetadata; 26 | } = { 27 | /** Animation that rotates the left pointer of the indicator based on the sorting direction. */ 28 | arrowDirection: trigger('arrowDirection', [ 29 | state('active-asc, asc', style({ transform: 'rotate(0deg)' })), 30 | state('active-desc, desc', style({ transform: 'rotate(-180deg)' })), 31 | transition('active-asc <=> active-desc', animate(SORT_ANIMATION_TRANSITION)) 32 | ]), 33 | 34 | /** Animation that controls the arrow opacity. */ 35 | arrowOpacity: trigger('arrowOpacity', [ 36 | state('desc-to-active, asc-to-active, active', style({ opacity: 1 })), 37 | state('desc-to-hint, asc-to-hint, hint', style({ opacity: 0.54 })), 38 | state('hint-to-desc, active-to-desc, desc, hint-to-asc, active-to-asc, asc, void', style({ opacity: 0 })), 39 | // Transition between all states except for immediate transitions 40 | transition('* => asc, * => desc, * => active, * => hint, * => void', animate('0ms')), 41 | transition('* <=> *', animate(SORT_ANIMATION_TRANSITION)) 42 | ]), 43 | 44 | /** 45 | * Animation for the translation of the arrow as a whole. States are separated into two 46 | * groups: ones with animations and others that are immediate. Immediate states are asc, desc, 47 | * peek, and active. The other states define a specific animation (source-to-destination) 48 | * and are determined as a function of their prev user-perceived state and what the next state 49 | * should be. 50 | */ 51 | arrowPosition: trigger('arrowPosition', [ 52 | // Hidden Above => Hint Center 53 | transition( 54 | '* => desc-to-hint, * => desc-to-active', 55 | animate(SORT_ANIMATION_TRANSITION, keyframes([style({ transform: 'translateY(-25%)' }), style({ transform: 'translateY(0)' })])) 56 | ), 57 | // Hint Center => Hidden Below 58 | transition( 59 | '* => hint-to-desc, * => active-to-desc', 60 | animate(SORT_ANIMATION_TRANSITION, keyframes([style({ transform: 'translateY(0)' }), style({ transform: 'translateY(25%)' })])) 61 | ), 62 | // Hidden Below => Hint Center 63 | transition( 64 | '* => asc-to-hint, * => asc-to-active', 65 | animate(SORT_ANIMATION_TRANSITION, keyframes([style({ transform: 'translateY(25%)' }), style({ transform: 'translateY(0)' })])) 66 | ), 67 | // Hint Center => Hidden Above 68 | transition( 69 | '* => hint-to-asc, * => active-to-asc', 70 | animate(SORT_ANIMATION_TRANSITION, keyframes([style({ transform: 'translateY(0)' }), style({ transform: 'translateY(-25%)' })])) 71 | ), 72 | state('desc-to-hint, asc-to-hint, hint, desc-to-active, asc-to-active, active', style({ transform: 'translateY(0)' })), 73 | state('hint-to-desc, active-to-desc, desc', style({ transform: 'translateY(-25%)' })), 74 | state('hint-to-asc, active-to-asc, asc', style({ transform: 'translateY(25%)' })) 75 | ]) 76 | }; 77 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 4 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 5 | import { CdkTableModule } from '@angular/cdk/table'; 6 | 7 | import { DialogDemo } from './features/dialog/dialog-demo'; 8 | import { FakeDialogDemoComponent } from './features/dialog/fake-dialog-demo.component'; 9 | import { SnackbarDemo } from './features/snackbar/snackbar-demo'; 10 | import { PaginatorDemo } from './features/paginator/paginator-demo'; 11 | import { SpinnerDemo } from './features/spinner/spinner-demo'; 12 | import { TabsDemo } from './features/tabs/tabs-demo.component'; 13 | import { DropdownDemo } from './features/dropdown/dropdown-demo'; 14 | import { ProgressBarDemo } from './features/progress-bar/progress-bar-demo'; 15 | import { Home } from './features/home/home'; 16 | import { DebounceDemo } from './features/debounce/debounce-demo'; 17 | import { EditUserDialogDemoComponent } from './features/dialog/edit-user-dialog-demo.component'; 18 | import { ModalSearchDemo } from './features/modal-search/modal-search-demo'; 19 | import { AppComponent } from './app.component'; 20 | import { AppRoutingModule } from './app-routing.module'; 21 | 22 | import { SwitchDemo } from './features/switch/switch-demo'; 23 | import { DocPreviewComponent } from './doc-preview/doc-preview.component'; 24 | import { AlertDemo } from './features/alert/alert-demo'; 25 | import { TooltipDemo } from './features/tooltip/tooltip-demo'; 26 | import { AnimatedCardDemo } from './features/animated-card/animated-card-demo'; 27 | import { TableDemo } from './features/table/table-demo'; 28 | import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; 29 | import { SortDemo } from './features/sort/sort-demo'; 30 | import { EditInPlaceDemo } from './features/edit-in-place/edit-in-place-demo'; 31 | import { DatePickerDemo } from './features/date-picker/date-picker-demo'; 32 | 33 | import { 34 | NwbAlertModule, 35 | NwbAnimatedCardModule, 36 | NwbCommonModule, 37 | NwbDatePickerModule, 38 | NwbDialogModule, 39 | NwbDropdownModule, 40 | NwbEditInPlaceModule, 41 | NwbModalSearchModule, 42 | NwbPaginatorModule, 43 | NwbProgressBarModule, 44 | NwbSnackbarModule, 45 | NwbSortModule, 46 | NwbSwitchModule, 47 | NwbTabsModule, 48 | } from 'projects/ng-wizi-bulma/src/public_api'; 49 | 50 | @NgModule({ 51 | declarations: [ 52 | AppComponent, 53 | DocPreviewComponent, 54 | DialogDemo, 55 | FakeDialogDemoComponent, 56 | SnackbarDemo, 57 | PaginatorDemo, 58 | SpinnerDemo, 59 | TabsDemo, 60 | DropdownDemo, 61 | ProgressBarDemo, 62 | Home, 63 | DebounceDemo, 64 | EditUserDialogDemoComponent, 65 | ModalSearchDemo, 66 | SwitchDemo, 67 | AlertDemo, 68 | AnimatedCardDemo, 69 | TooltipDemo, 70 | TableDemo, 71 | SortDemo, 72 | EditInPlaceDemo, 73 | DatePickerDemo, 74 | ], 75 | bootstrap: [AppComponent], 76 | imports: [ 77 | BrowserModule, 78 | BrowserAnimationsModule, 79 | FormsModule, 80 | ReactiveFormsModule, 81 | AppRoutingModule, 82 | CdkTableModule, 83 | NwbCommonModule, 84 | NwbAlertModule, 85 | NwbAnimatedCardModule, 86 | NwbDialogModule, 87 | NwbDropdownModule, 88 | NwbModalSearchModule, 89 | NwbPaginatorModule, 90 | NwbProgressBarModule, 91 | NwbSnackbarModule, 92 | NwbSortModule, 93 | NwbSwitchModule, 94 | NwbTabsModule, 95 | NwbEditInPlaceModule, 96 | NwbDatePickerModule, 97 | ], 98 | providers: [provideHttpClient(withInterceptorsFromDi())], 99 | }) 100 | export class AppModule {} 101 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/date-picker/date-picker-input-base.directive.ts: -------------------------------------------------------------------------------- 1 | /** Directive used to connect an input to a MatDatepicker. */ 2 | import { Directive, ElementRef, EventEmitter, Input, OnDestroy } from '@angular/core'; 3 | import { ControlValueAccessor } from '@angular/forms'; 4 | import { NwbDatePickerComponent, NwbDatePickerEvent } from './date-picker.component'; 5 | import { Subscription } from 'rxjs'; 6 | 7 | @Directive() 8 | export abstract class NwbDatePickerInputBaseDirective implements ControlValueAccessor, OnDestroy { 9 | protected _onChanged: Function; 10 | protected _onTouched: Function; 11 | 12 | protected _datepicker: NwbDatePickerComponent; 13 | 14 | private _datepickerSubscription = Subscription.EMPTY; 15 | 16 | /** Emits when the value changes (either due to user input or programmatic change). */ 17 | _valueChange = new EventEmitter(); 18 | 19 | protected constructor(public elementRef: ElementRef) {} 20 | 21 | /** The value of the input. */ 22 | @Input() 23 | get value(): string { 24 | return this._value; 25 | } 26 | 27 | set value(value: string) { 28 | const oldDate = this.value; 29 | this._value = value; 30 | 31 | this.elementRef.nativeElement.value = value; 32 | 33 | if (!!oldDate && oldDate !== value) { 34 | this._valueChange.emit(value); 35 | } 36 | } 37 | 38 | @Input() 39 | nwbDateType: 'date' | 'datetime' = 'date'; 40 | 41 | set dateType(type: 'date' | 'datetime') { 42 | this.nwbDateType = type; 43 | } 44 | 45 | get dateType() { 46 | return this.nwbDateType; 47 | } 48 | 49 | private _value: string; 50 | 51 | protected registerInput(datePickerComponent: NwbDatePickerComponent, inputType: 'startDate' | 'endDate') { 52 | if (!(datePickerComponent instanceof NwbDatePickerComponent)) { 53 | return; 54 | } 55 | 56 | const type = this.elementRef.nativeElement.getAttribute('type'); 57 | if (type !== 'text') { 58 | console.warn( 59 | `nwb-date-picker deprecated warning. The use of an input type "date" or "datetime-local" is now deprecated due to the lack of timezone. Use an input type "text" and set the attribute "nwbDateType" instead.` 60 | ); 61 | 62 | this.dateType = type === 'date' ? 'date' : 'datetime'; 63 | 64 | this.elementRef.nativeElement.setAttribute('type', 'text'); 65 | } 66 | 67 | this._datepicker = datePickerComponent; 68 | this._datepicker._registerInput(this, inputType); 69 | this._datepickerSubscription.unsubscribe(); 70 | 71 | this._datepickerSubscription = this._datepicker.change.subscribe((value: NwbDatePickerEvent) => { 72 | let dateStr; 73 | if (inputType === 'startDate') { 74 | dateStr = value.startDate.toISOString(); 75 | } else { 76 | dateStr = value.endDate.toISOString(); 77 | } 78 | 79 | this.elementRef.nativeElement.value = dateStr; 80 | this._value = dateStr; 81 | 82 | if (this._onChanged) { 83 | this._onChanged(dateStr); 84 | } 85 | }); 86 | } 87 | 88 | getDate() { 89 | if (!this._value) { 90 | return new Date(); 91 | } 92 | 93 | const date = new Date(this._value); 94 | const finalDate = new Date(); 95 | 96 | finalDate.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); 97 | finalDate.setHours(date.getHours(), date.getMinutes(), 0, 0); 98 | if (this.dateType === 'date') { 99 | finalDate.setHours(0, 0, 0, 0); 100 | } 101 | 102 | return finalDate; 103 | } 104 | 105 | writeValue(value: string): void { 106 | this.value = value; 107 | } 108 | 109 | registerOnChange(fn: (value: any) => void): void { 110 | this._onChanged = fn; 111 | } 112 | 113 | registerOnTouched(fn: () => void): void { 114 | this._onTouched = fn; 115 | } 116 | 117 | ngOnDestroy() { 118 | this._datepickerSubscription.unsubscribe(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/app/services/modal-search.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { NwbFoundRow, NwbModalSearchComponent, NwbModalSearchService } from 'projects/ng-wizi-bulma/src/public_api'; 3 | import { Router } from '@angular/router'; 4 | import { Observable } from 'rxjs'; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class ModalSearchService { 10 | private records1: NwbFoundRow[] = [ 11 | { 12 | text: 'First Components Group', 13 | isSelectable: false, 14 | children: [ 15 | { 16 | text: 'Debounce', 17 | data: './debounce' 18 | }, 19 | { 20 | text: 'Dialog', 21 | data: './dialog' 22 | }, 23 | { 24 | text: 'Dropdown', 25 | data: './dropdown' 26 | } 27 | ] 28 | } 29 | ]; 30 | 31 | private records2: NwbFoundRow[] = [ 32 | { 33 | text: 'Second Components Group', 34 | isSelectable: false, 35 | children: [ 36 | { 37 | text: 'Modal Search', 38 | data: './modal-search' 39 | }, 40 | { 41 | text: 'Progress Bar', 42 | data: './progress-bar' 43 | }, 44 | { 45 | text: 'Paginator', 46 | data: './paginator' 47 | }, 48 | { 49 | text: 'Snackbar', 50 | data: './snackbar' 51 | }, 52 | { 53 | text: 'Spinner', 54 | data: './spinner' 55 | } 56 | ] 57 | }, 58 | { 59 | text: 'Tabs', 60 | data: './tabs' 61 | }, 62 | { 63 | text: 'Switch', 64 | data: './switch' 65 | }, 66 | { 67 | text: 'Tooltip', 68 | data: './tooltip' 69 | }, 70 | { 71 | text: 'Sort Header', 72 | data: './sort' 73 | } 74 | ]; 75 | 76 | modalSearch: NwbModalSearchComponent; 77 | 78 | constructor(private router: Router, private modalSearchService: NwbModalSearchService) { 79 | this.modalSearch = this.modalSearchService.create({ 80 | records: this.records1.concat(this.records2), 81 | keyCodes: [ 82 | { 83 | specialKey: 'cmd', 84 | key: 'k' 85 | }, 86 | { 87 | specialKey: 'ctrl', 88 | key: 'e' 89 | } 90 | ], 91 | customSearchFn: (value: string) => this.searchFromRecords(value), 92 | inputPlaceholder: 'Navigate to...', 93 | hasFooter: true, 94 | extraClasses: 'extra-class' 95 | }); 96 | 97 | this.modalSearch.selectedValue$.subscribe((value: NwbFoundRow) => { 98 | this.router.navigate([value.data]); 99 | }); 100 | 101 | this.modalSearch.afterViewInit$.subscribe(() => { 102 | this.modalSearch.footer.nativeElement.innerHTML = ` 103 |
104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | to navigate 112 |
113 |
114 | enter to select 115 |
116 |
117 | esc to dismiss 118 |
119 |
120 | `; 121 | }); 122 | } 123 | 124 | searchFromRecords(searchValue: string): Observable { 125 | return Observable.create((observer: any) => { 126 | const foundRows1 = this.modalSearch.searchAllWordsInFoundRows(searchValue, this.records1); 127 | 128 | const foundRows2 = this.modalSearch.searchAllWordsInFoundRows(searchValue, this.records2); 129 | 130 | setTimeout(() => { 131 | observer.next(foundRows1.concat(foundRows2)); 132 | observer.complete(); 133 | }, 500); 134 | }); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/shared/services/filter-routing/filter-routing-group.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { ActivatedRoute, Params, Router } from '@angular/router'; 3 | import { NwbFilter, NwbFilterGroup } from './model'; 4 | 5 | const FILTER_GROUP_PARAM_PREFIX = 'fg_'; 6 | 7 | @Injectable() 8 | export class NwbFilterRoutingBuilder { 9 | private groupCounter = 0; 10 | 11 | private filterGroups = new Map(); 12 | 13 | constructor(private router: Router, private route: ActivatedRoute) { 14 | this.route.queryParams.subscribe(params => { 15 | this.queryParamsChange(params); 16 | }); 17 | } 18 | 19 | private queryParamsChange(params: Params) { 20 | const groupChanges = new Map(); 21 | 22 | Object.keys(params).forEach(key => { 23 | const parsedKeys = this.getParsedKey(key); 24 | 25 | const values = groupChanges.has(parsedKeys.filterGroupName) ? groupChanges.get(parsedKeys.filterGroupName) : {}; 26 | 27 | values[parsedKeys.filterKey] = params[key]; 28 | 29 | groupChanges.set(parsedKeys.filterGroupName, values); 30 | }); 31 | 32 | this.filterGroups.forEach(filterGroup => { 33 | const defaultValues = {}; 34 | 35 | filterGroup.getFilters().forEach(filter => { 36 | defaultValues[filter.key] = filter.defaultValue; 37 | }); 38 | 39 | const newValues = groupChanges.has(filterGroup.name) ? groupChanges.get(filterGroup.name) : {}; 40 | 41 | filterGroup.setValues(Object.assign(defaultValues, newValues)); 42 | }); 43 | } 44 | 45 | group(group: { [key: string]: any }, groupName?: string) { 46 | if (!groupName) { 47 | groupName = `${FILTER_GROUP_PARAM_PREFIX}${this.groupCounter++}`; 48 | } 49 | const filterGroup = new NwbFilterGroup(groupName, group); 50 | 51 | this.filterGroups.set(filterGroup.name, filterGroup); 52 | 53 | filterGroup.valuesChange$.subscribe(filters => { 54 | this.updateRouting(filterGroup.name, filters); 55 | }); 56 | 57 | // Check values from query parameters 58 | this.route.queryParams 59 | .subscribe(params => { 60 | this.queryParamsChange(params); 61 | }) 62 | .unsubscribe(); 63 | 64 | return filterGroup; 65 | } 66 | 67 | private addFilterGroupNameToQueryParamKey(filterGroupName: string, key: string) { 68 | return filterGroupName + ':' + key; 69 | } 70 | 71 | private getParsedKey(encodedKey: string) { 72 | const value = encodedKey.split(':'); 73 | const filterGroupName = value[0]; 74 | const filterKey = value[1]; 75 | 76 | return { filterGroupName, filterKey }; 77 | } 78 | 79 | private updateRouting(filterGroupName: string, filters: NwbFilter[]) { 80 | this.route.queryParamMap 81 | .subscribe(paramsMap => { 82 | const params = {}; 83 | paramsMap.keys.forEach(key => { 84 | params[key] = paramsMap.get(key); 85 | }); 86 | const queryParams = Object.assign({}, params); 87 | 88 | filters.forEach(filter => { 89 | const paramKey = this.addFilterGroupNameToQueryParamKey(filterGroupName, filter.key); 90 | 91 | if (!filter.isDefaultValue()) { 92 | let value = filter.value; 93 | 94 | if (value instanceof Date) { 95 | value = value.toISOString(); 96 | } 97 | 98 | queryParams[paramKey] = value; 99 | } else { 100 | if (queryParams.hasOwnProperty(paramKey)) { 101 | delete queryParams[paramKey]; 102 | } 103 | } 104 | }); 105 | 106 | this.router.navigate([], { 107 | queryParams: queryParams, 108 | relativeTo: this.route 109 | }); 110 | }) 111 | .unsubscribe(); 112 | } 113 | 114 | remove(filterGroup: NwbFilterGroup) { 115 | if (this.filterGroups.has(filterGroup.name)) { 116 | this.filterGroups.delete(filterGroup.name); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/app/features/table/table-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ViewChild } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { Observable, of } from 'rxjs'; 4 | import { catchError, map } from 'rxjs/operators'; 5 | import { 6 | NwbFilter, 7 | NwbFilterGroup, 8 | NwbFilterRoutingBuilder, 9 | NwbPageEvent, 10 | NwbPaginatorComponent, 11 | NwbSort, 12 | Sort 13 | } from 'projects/ng-wizi-bulma/src/public_api'; 14 | 15 | @Component({ 16 | providers: [], 17 | templateUrl: './table-demo.html', 18 | styleUrls: ['./table-demo.scss'] 19 | }) 20 | export class TableDemo implements OnInit { 21 | displayedColumns: string[] = ['created', 'state', 'number', 'title']; 22 | exampleDatabase: ExampleHttpDao | null; 23 | data: GithubIssue[] = []; 24 | 25 | @ViewChild(NwbPaginatorComponent, { static: true }) 26 | paginator; 27 | @ViewChild(NwbSort, { static: true }) 28 | sort; 29 | 30 | resultsLength = 0; 31 | isLoadingResults = false; 32 | isRateLimitReached = false; 33 | 34 | sortActive = 'title'; 35 | sortStart = 'asc'; 36 | 37 | dataTableFilters = { 38 | sort: this.sortActive, 39 | order: this.sortStart, 40 | pageIndex: 0, 41 | q: 'repo:angular/angular' 42 | }; 43 | 44 | filterGroup: NwbFilterGroup; 45 | 46 | constructor(private http: HttpClient, private filterRoutingBuilder: NwbFilterRoutingBuilder) {} 47 | 48 | ngOnInit() { 49 | this.exampleDatabase = new ExampleHttpDao(this.http); 50 | 51 | this.filterGroup = this.filterRoutingBuilder.group(this.dataTableFilters, 'datatable'); 52 | 53 | this.filterGroup.valuesChange$.subscribe(filters => { 54 | this.updateFilters(filters); 55 | 56 | this.fetchData(); 57 | }); 58 | 59 | this.updateFilters(this.filterGroup.getFilters()); 60 | 61 | this.fetchData(); 62 | 63 | // If the user changes the sort order, reset back to the first page. 64 | this.sort.sortChange.subscribe((sort: Sort) => { 65 | this.filterGroup.setValues({ 66 | pageIndex: 0, 67 | sort: sort.active, 68 | order: sort.direction 69 | }); 70 | }); 71 | 72 | this.paginator.page.subscribe((page: NwbPageEvent) => { 73 | this.filterGroup.set('pageIndex', page.pageIndex); 74 | }); 75 | } 76 | 77 | private updateFilters(filters: NwbFilter[]) { 78 | filters.forEach(filter => { 79 | this.dataTableFilters[filter.key] = filter.value; 80 | }); 81 | } 82 | 83 | private fetchData() { 84 | this.isLoadingResults = true; 85 | this.exampleDatabase!.getRepoIssues( 86 | this.dataTableFilters.q, 87 | this.dataTableFilters.sort, 88 | this.dataTableFilters.order, 89 | this.dataTableFilters.pageIndex 90 | ) 91 | .pipe( 92 | map(data => { 93 | // Flip flag to show that loading has finished. 94 | this.isLoadingResults = false; 95 | this.isRateLimitReached = false; 96 | this.resultsLength = data.total_count; 97 | 98 | return data.items; 99 | }), 100 | catchError(() => { 101 | this.isLoadingResults = false; 102 | // Catch if the GitHub API has reached its rate limit. Return empty data. 103 | this.isRateLimitReached = true; 104 | return of([]); 105 | }) 106 | ) 107 | .subscribe(data => (this.data = data)); 108 | } 109 | } 110 | 111 | export interface GithubApi { 112 | items: GithubIssue[]; 113 | total_count: number; 114 | } 115 | 116 | export interface GithubIssue { 117 | created_at: string; 118 | number: string; 119 | state: string; 120 | title: string; 121 | } 122 | 123 | /** An example database that the data source uses to retrieve data for the table. */ 124 | export class ExampleHttpDao { 125 | constructor(private http: HttpClient) {} 126 | 127 | getRepoIssues(q: string, sort: string, order: string, page: number): Observable { 128 | const href = 'https://api.github.com/search/issues'; 129 | const requestUrl = `${href}?q=${q}&sort=${sort}&order=${order}&page=${+page + 1}`; 130 | 131 | return this.http.get(requestUrl); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/app/features/dropdown/dropdown-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NwbDialogService, NwbDropdownConfig } from 'projects/ng-wizi-bulma/src/public_api'; 3 | import { Observable } from 'rxjs'; 4 | 5 | @Component({ 6 | providers: [], 7 | templateUrl: './dropdown-demo.html' 8 | }) 9 | export class DropdownDemo { 10 | gaming = 'nes'; 11 | gaming2 = 'genesis'; 12 | 13 | sample1 = ` 14 | NES 15 | Nintendo64 16 | Disabled value 17 | Sega Genesis 18 | Sega Saturn 19 | keyboard SNES 20 | 21 | null value 22 | true value 23 | 24 |

Selected value: {{gaming}}

25 | 26 | gaming = 'nes'; 27 | 28 | modelChange(event: any) { 29 | console.log('modelChange', event); 30 | } 31 | 32 | nesHasBeenSelected(event: any) { 33 | console.log('nesHasBeenSelected', event); 34 | }`; 35 | 36 | sample2 = ` 38 | NES 39 | Nintendo64 40 | Disabled value 41 | Sega Genesis 42 | Sega Saturn 43 | SNES 44 | 45 | null value 46 | true value 47 | 48 |

Selected value: {{gaming2}}

49 | 51 | 55 |
{{dopdown2Config|json}}
56 | 57 | gaming2 = 'genesis'; 58 | 59 | dopdown2Config: NwbDropdownConfig = { 60 | data: 20, 61 | handler: (value: any, data: number) => { 62 | return this.changeHandler(value, data); 63 | } 64 | }; 65 | 66 | changeHandler(value: any, data: number) { 67 | return Observable.create((observer: any) => { 68 | setTimeout(() => { 69 | if (value === 'n64' || value === 'genesis') { 70 | console.log('value has changed to', value, 'with data = ', data); 71 | observer.next(true); 72 | } else { 73 | this.dialog.open({ 74 | title: 'Not changed', 75 | message: \`Value: \${value} is not allowed\` 76 | }); 77 | observer.next(false); 78 | } 79 | observer.complete(); 80 | }, 700); 81 | }); 82 | }`; 83 | 84 | dopdown2Config: NwbDropdownConfig = { 85 | data: 20, 86 | handler: (value: any, data: number) => { 87 | return this.changeHandler(value, data); 88 | } 89 | }; 90 | 91 | constructor(private dialog: NwbDialogService) {} 92 | 93 | modelChange(event: any) { 94 | console.log('modelChange', event); 95 | } 96 | 97 | nesHasBeenSelected(event: any) { 98 | console.log('nesHasBeenSelected', event); 99 | } 100 | 101 | changeHandler(value: any, data: number) { 102 | return Observable.create((observer: any) => { 103 | setTimeout(() => { 104 | if (value === 'n64' || value === 'genesis') { 105 | console.log('value has changed to', value, 'with data = ', data); 106 | observer.next(true); 107 | } else { 108 | this.dialog.open({ 109 | title: 'Not changed', 110 | message: `Value: ${value} is not allowed` 111 | }); 112 | observer.next(false); 113 | } 114 | observer.complete(); 115 | }, 700); 116 | }); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /projects/ng-wizi-bulma/src/lib/edit-in-place/edit-in-place.component.scss: -------------------------------------------------------------------------------- 1 | .nwb-wrapper { 2 | display: inline-block; 3 | position: relative; 4 | width: auto; 5 | min-width: 12px; 6 | min-height: 1.4em; 7 | cursor: pointer; 8 | 9 | input { 10 | font-size: inherit; 11 | transition: width 50ms; 12 | position: absolute; 13 | top: 0; 14 | left: -5px; 15 | width: calc(100% + 16px) !important; 16 | height: calc(100% + 14px) !important; 17 | padding: 5px; 18 | z-index: 1; 19 | margin: 0; 20 | outline: none !important; 21 | border: 1px solid #a8a8a8; 22 | background: inherit; 23 | transform: translateY(-17%); 24 | background-color: #fff; 25 | 26 | &.nwb-editable { 27 | text-decoration: none; 28 | color: inherit; 29 | border: none; 30 | cursor: pointer; 31 | height: 26px; 32 | } 33 | 34 | &.nwb-editing { 35 | color: #a8a8a8; 36 | } 37 | } 38 | 39 | span.nwb-loader { 40 | &.nwb-is-loading { 41 | z-index: 2; 42 | opacity: 1; 43 | position: absolute; 44 | top: -7px; 45 | left: -7px; 46 | width: calc(100% + 16px) !important; 47 | height: calc(100% + 14px) !important; 48 | min-width: 12px; 49 | min-height: 1em; 50 | margin: 0; 51 | background-size: auto 70%; 52 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30px' height='30px' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid' class='lds-ellipsis' style='background: none;'%3E%3C!--circle(cx='16',cy='50',r='10')--%3E%3Ccircle cx='84' cy='50' r='0' fill='%236c6c6c'%3E%3Canimate attributeName='r' values='10;0;0;0;0' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='0s'/%3E%3Canimate attributeName='cx' values='84;84;84;84;84' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='0s'/%3E%3C/circle%3E%3Ccircle cx='28.6338' cy='50' r='10' fill='%236c6c6c'%3E%3Canimate attributeName='r' values='0;10;10;10;0' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='-1s'/%3E%3Canimate attributeName='cx' values='16;16;50;84;84' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='-1s'/%3E%3C/circle%3E%3Ccircle cx='16' cy='50' r='3.71582' fill='%236c6c6c'%3E%3Canimate attributeName='r' values='0;10;10;10;0' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='-0.5s'/%3E%3Canimate attributeName='cx' values='16;16;50;84;84' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='-0.5s'/%3E%3C/circle%3E%3Ccircle cx='84' cy='50' r='6.28418' fill='%236c6c6c'%3E%3Canimate attributeName='r' values='0;10;10;10;0' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='0s'/%3E%3Canimate attributeName='cx' values='16;16;50;84;84' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='0s'/%3E%3C/circle%3E%3Ccircle cx='62.6338' cy='50' r='10' fill='%236c6c6c'%3E%3Canimate attributeName='r' values='0;0;10;10;10' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='0s'/%3E%3Canimate attributeName='cx' values='16;16;16;50;84' keyTimes='0;0.25;0.5;0.75;1' keySplines='0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1' calcMode='spline' dur='2s' repeatCount='indefinite' begin='0s'/%3E%3C/circle%3E%3C/svg%3E"); 53 | background-repeat: no-repeat; 54 | background-position: center center; 55 | } 56 | } 57 | span { 58 | color: inherit; 59 | &:not(.nwb-loader) { 60 | display: inline-block; 61 | min-width: 12px; 62 | } 63 | &.nwb-editing { 64 | visibility: hidden; 65 | } 66 | 67 | &.nwb-is-loading { 68 | text-shadow: 0 0 0.5em rgba(0, 0, 0, 0.6); 69 | color: rgba(0, 0, 0, 0.4); 70 | opacity: 0.25; 71 | } 72 | } 73 | } 74 | 75 | .nwb-wrapper--editable::after { 76 | position: absolute; 77 | content: ''; 78 | border-bottom: dashed 1px $primary; 79 | width: 100%; 80 | bottom: 0; 81 | left: 0; 82 | } 83 | -------------------------------------------------------------------------------- /src/app/features/edit-in-place/edit-in-place-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NwbDialogService } from 'projects/ng-wizi-bulma/src/public_api'; 3 | import { timer } from 'rxjs'; 4 | import { NwbEditInPlaceConfig } from '../../../../projects/ng-wizi-bulma/src/lib/edit-in-place'; 5 | import { map } from 'rxjs/operators'; 6 | 7 | @Component({ 8 | providers: [], 9 | templateUrl: './edit-in-place-demo.html' 10 | }) 11 | export class EditInPlaceDemo { 12 | docPreview1 = ` 13 | 16 | 17 | 18 | modelChange(event: any) { 19 | console.log('modelChange', event); 20 | } 21 | `; 22 | 23 | docPreview2 = ` 24 | 27 | 28 | 29 | editInPlaceConfig: NwbEditInPlaceConfig = { 30 | data: 20, 31 | handler: (value: any, data: number) => { 32 | return this.changeHandler(value, data); 33 | } 34 | }; 35 | 36 | changeHandler(value: any, data: number) { 37 | return timer(700).pipe( 38 | map(() => { 39 | if (value === 'developer' || value === 'devops') { 40 | console.log('value has changed to', value, 'with data = ', data); 41 | return true; 42 | } 43 | 44 | this.dialog.open({ 45 | title: 'Not changed', 46 | message: \`Value: \${value} is not allowed\` 47 | }); 48 | return false; 49 | }) 50 | ); 51 | } 52 | `; 53 | 54 | docPreview3 = ` 55 | editInPlaceConfig2: NwbEditInPlaceConfig = { 56 | selectTextUponClick: true 57 | }; 58 | 59 | 63 | 64 | 65 | 66 | modelChange(event: any) { 67 | console.log('modelChange', event); 68 | } 69 | `; 70 | 71 | docPreview4 = ` 72 | number = 12.5; 73 | formattedString: string; 74 | 75 | editInPlaceConfig3: NwbEditInPlaceConfig = { 76 | currency: '$', 77 | separator: ',', 78 | selectTextUponClick: true 79 | }; 80 | 81 | 86 | 87 | modelChange(event: any) { 88 | console.log('modelChange', event); 89 | } 90 | 91 | //CustomChange is optional 92 | getFormattedString(event: string) { 93 | this.formattedString = event; 94 | console.log(event); 95 | } 96 | 97 | 100 | 101 | 102 | 105 | 106 | 107 | changeConfig() { 108 | this.editInPlaceConfig3 = Object.assign({}, this.editInPlaceConfig3); 109 | } 110 | `; 111 | 112 | developer = 'developer'; 113 | devops = 'devops'; 114 | number = 12.5; 115 | formattedString: string; 116 | 117 | editInPlaceConfig: NwbEditInPlaceConfig = { 118 | data: 20, 119 | handler: (value: any, data: number) => { 120 | return this.changeHandler(value, data); 121 | } 122 | }; 123 | 124 | editInPlaceConfig2: NwbEditInPlaceConfig = { 125 | selectTextUponClick: true 126 | }; 127 | 128 | editInPlaceConfig3: NwbEditInPlaceConfig = { 129 | currency: '$', 130 | separator: ',', 131 | selectTextUponClick: true 132 | }; 133 | 134 | constructor(private dialog: NwbDialogService) {} 135 | 136 | changeHandler(value: any, data: number) { 137 | return timer(700).pipe( 138 | map(() => { 139 | if (value === 'developer' || value === 'devops') { 140 | console.log('value has changed to', value, 'with data = ', data); 141 | return true; 142 | } 143 | 144 | this.dialog.open({ 145 | title: 'Not changed', 146 | message: `Value: ${value} is not allowed` 147 | }); 148 | return false; 149 | }) 150 | ); 151 | } 152 | 153 | modelChange(event: any) { 154 | console.log('VALEUR RECUE : ' + event); 155 | console.log('TYPE RECU : ' + typeof event); 156 | } 157 | 158 | // CustomChange is optional 159 | getFormattedString(event: string) { 160 | this.formattedString = event; 161 | } 162 | 163 | changeConfig() { 164 | this.editInPlaceConfig3 = Object.assign({}, this.editInPlaceConfig3); 165 | } 166 | } 167 | --------------------------------------------------------------------------------