├── .gitignore ├── .npmignore ├── .travis.yml ├── .yo-rc.json ├── README.MD ├── bs-config.json ├── gulpfile.js ├── package.json ├── playground ├── index.html ├── index.ts ├── systemjs-angular-loader.js ├── systemjs.config.js └── tsconfig.json ├── src ├── index.ts ├── package.json ├── slick.component.ts ├── tsconfig.es5.json └── tsconfig.spec.json ├── tools └── gulp │ └── inline-resources.js ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Node 2 | node_modules/* 3 | npm-debug.log 4 | 5 | # TypeScript 6 | src/*.js 7 | src/*.map 8 | src/*.d.ts 9 | 10 | # JetBrains 11 | .idea 12 | .project 13 | .settings 14 | .idea/* 15 | *.iml 16 | 17 | # VS Code 18 | .vscode/* 19 | 20 | # Windows 21 | Thumbs.db 22 | Desktop.ini 23 | 24 | # Mac 25 | .DS_Store 26 | **/.DS_Store 27 | 28 | # Ngc generated files 29 | **/*.ngfactory.ts 30 | 31 | # Build files 32 | dist/* 33 | 34 | # Playground tmp files 35 | .playground 36 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Node 2 | node_modules/* 3 | npm-debug.log 4 | docs/* 5 | # DO NOT IGNORE TYPESCRIPT FILES FOR NPM 6 | # TypeScript 7 | # *.js 8 | # *.map 9 | # *.d.ts 10 | 11 | # JetBrains 12 | .idea 13 | .project 14 | .settings 15 | .idea/* 16 | *.iml 17 | 18 | # VS Code 19 | .vscode/* 20 | 21 | # Windows 22 | Thumbs.db 23 | Desktop.ini 24 | 25 | # Mac 26 | .DS_Store 27 | **/.DS_Store 28 | 29 | # Ngc generated files 30 | **/*.ngfactory.ts 31 | 32 | # Library files 33 | src/* 34 | build/* 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - '4.2.1' 5 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-angular2-library": { 3 | "promptValues": { 4 | "gitRepositoryUrl": "https://github.com/devmark/ngx-slick" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # ngx-slick 2 | 3 | Support angular 6+, Slick 1.8.1 4 | 5 | [Example](https://embed.plnkr.co/fblxzfPneL66950A4VDM/) 6 | 7 | ## Installation 8 | 9 | To install this library, run: 10 | 11 | ```bash 12 | $ npm install ngx-slick --save 13 | ``` 14 | 15 | ## Consuming your library 16 | 17 | Once you have published your library to npm, you can import your library in any Angular application by running: 18 | 19 | ```bash 20 | $ npm install ngx-slick 21 | ``` 22 | 23 | and then from your Angular `AppModule`: 24 | 25 | ```typescript 26 | import { BrowserModule } from '@angular/platform-browser'; 27 | import { NgModule } from '@angular/core'; 28 | 29 | import { AppComponent } from './app.component'; 30 | 31 | // Import your library 32 | import { SlickModule } from 'ngx-slick'; 33 | 34 | @NgModule({ 35 | declarations: [ 36 | AppComponent 37 | ], 38 | imports: [ 39 | BrowserModule, 40 | 41 | // Specify your library as an import 42 | SlickModule.forRoot() 43 | ], 44 | providers: [], 45 | bootstrap: [AppComponent] 46 | }) 47 | export class AppModule { } 48 | ``` 49 | 50 | - Include jquery and slick css/js in your application : 51 | ``` 52 | 53 | 54 | 55 | 56 | 57 | ``` 58 | 59 | Once your library is imported, you can use its components, directives and pipes in your Angular application: 60 | ```html 61 | 62 | 63 |
64 | 65 |
66 |
67 | 68 | 69 | 70 | 71 | 72 | ``` 73 | 74 | ```javascript 75 | slides = [ 76 | {img: "http://placehold.it/350x150/000000"}, 77 | {img: "http://placehold.it/350x150/111111"}, 78 | {img: "http://placehold.it/350x150/333333"}, 79 | {img: "http://placehold.it/350x150/666666"} 80 | ]; 81 | slideConfig = {"slidesToShow": 4, "slidesToScroll": 4}; 82 | 83 | addSlide() { 84 | this.slides.push({img: "http://placehold.it/350x150/777777"}) 85 | } 86 | 87 | removeSlide() { 88 | this.slides.length = this.slides.length - 1; 89 | } 90 | 91 | afterChange(e) { 92 | console.log('afterChange'); 93 | } 94 | ``` 95 | 96 | 97 | ## Development 98 | 99 | To generate all `*.js`, `*.d.ts` and `*.metadata.json` files: 100 | 101 | ```bash 102 | $ npm run build 103 | ``` 104 | 105 | To lint all `*.ts` files: 106 | 107 | ```bash 108 | $ npm run lint 109 | ``` 110 | 111 | ## License 112 | 113 | MIT © [Mark](mailto:hc.devmark@gmail.com) -------------------------------------------------------------------------------- /bs-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "baseDir": "src", 4 | "routes": { 5 | "/": "playground", 6 | "/node_modules/": "node_modules", 7 | "/dist/": "dist", 8 | "/.playground": ".playground" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var gulp = require('gulp'), 3 | path = require('path'), 4 | ngc = require('@angular/compiler-cli/src/main').main, 5 | rollup = require('gulp-rollup'), 6 | rename = require('gulp-rename'), 7 | fs = require('fs-extra'), 8 | runSequence = require('run-sequence'), 9 | inlineResources = require('./tools/gulp/inline-resources'); 10 | 11 | const rootFolder = path.join(__dirname); 12 | const srcFolder = path.join(rootFolder, 'src'); 13 | const tmpFolder = path.join(rootFolder, '.tmp'); 14 | const buildFolder = path.join(rootFolder, 'build'); 15 | const distFolder = path.join(rootFolder, 'dist'); 16 | 17 | /** 18 | * 1. Delete /dist folder 19 | */ 20 | gulp.task('clean:dist', function () { 21 | 22 | // Delete contents but not dist folder to avoid broken npm links 23 | // when dist directory is removed while npm link references it. 24 | return fs.emptyDirSync(distFolder); 25 | }); 26 | 27 | /** 28 | * 2. Clone the /src folder into /.tmp. If an npm link inside /src has been made, 29 | * then it's likely that a node_modules folder exists. Ignore this folder 30 | * when copying to /.tmp. 31 | */ 32 | gulp.task('copy:source', function () { 33 | return gulp.src([`${srcFolder}/**/*`, `!${srcFolder}/node_modules`]) 34 | .pipe(gulp.dest(tmpFolder)); 35 | }); 36 | 37 | /** 38 | * 3. Inline template (.html) and style (.css) files into the the component .ts files. 39 | * We do this on the /.tmp folder to avoid editing the original /src files 40 | */ 41 | gulp.task('inline-resources', function () { 42 | return Promise.resolve() 43 | .then(() => inlineResources(tmpFolder)); 44 | }); 45 | 46 | 47 | /** 48 | * 4. Run the Angular compiler, ngc, on the /.tmp folder. This will output all 49 | * compiled modules to the /build folder. 50 | * 51 | * As of Angular 5, ngc accepts an array and no longer returns a promise. 52 | */ 53 | gulp.task('ngc', function () { 54 | ngc(['--project', `${tmpFolder}/tsconfig.es5.json`]); 55 | return Promise.resolve() 56 | }); 57 | 58 | /** 59 | * 5. Run rollup inside the /build folder to generate our Flat ES module and place the 60 | * generated file into the /dist folder 61 | */ 62 | gulp.task('rollup:fesm', function () { 63 | return gulp.src(`${buildFolder}/**/*.js`) 64 | // transform the files here. 65 | .pipe(rollup({ 66 | 67 | // Bundle's entry point 68 | // See "input" in https://rollupjs.org/#core-functionality 69 | input: `${buildFolder}/index.js`, 70 | 71 | // Allow mixing of hypothetical and actual files. "Actual" files can be files 72 | // accessed by Rollup or produced by plugins further down the chain. 73 | // This prevents errors like: 'path/file' does not exist in the hypothetical file system 74 | // when subdirectories are used in the `src` directory. 75 | allowRealFiles: true, 76 | 77 | // A list of IDs of modules that should remain external to the bundle 78 | // See "external" in https://rollupjs.org/#core-functionality 79 | external: [ 80 | '@angular/core', 81 | '@angular/common' 82 | ], 83 | 84 | output: { 85 | // Format of generated bundle 86 | // See "format" in https://rollupjs.org/#core-functionality 87 | format: 'es' 88 | } 89 | })) 90 | .pipe(gulp.dest(distFolder)); 91 | }); 92 | 93 | /** 94 | * 6. Run rollup inside the /build folder to generate our UMD module and place the 95 | * generated file into the /dist folder 96 | */ 97 | gulp.task('rollup:umd', function () { 98 | return gulp.src(`${buildFolder}/**/*.js`) 99 | // transform the files here. 100 | .pipe(rollup({ 101 | 102 | // Bundle's entry point 103 | // See "input" in https://rollupjs.org/#core-functionality 104 | input: `${buildFolder}/index.js`, 105 | 106 | // Allow mixing of hypothetical and actual files. "Actual" files can be files 107 | // accessed by Rollup or produced by plugins further down the chain. 108 | // This prevents errors like: 'path/file' does not exist in the hypothetical file system 109 | // when subdirectories are used in the `src` directory. 110 | allowRealFiles: true, 111 | 112 | // A list of IDs of modules that should remain external to the bundle 113 | // See "external" in https://rollupjs.org/#core-functionality 114 | external: [ 115 | '@angular/core', 116 | '@angular/common' 117 | ], 118 | 119 | output: { 120 | // The name to use for the module for UMD/IIFE bundles 121 | // (required for bundles with exports) 122 | // See "name" in https://rollupjs.org/#core-functionality 123 | name: 'ngx-slick', 124 | 125 | // See "globals" in https://rollupjs.org/#core-functionality 126 | globals: { 127 | typescript: 'ts' 128 | }, 129 | 130 | // Format of generated bundle 131 | // See "format" in https://rollupjs.org/#core-functionality 132 | format: 'umd', 133 | 134 | // Export mode to use 135 | // See "exports" in https://rollupjs.org/#danger-zone 136 | exports: 'named' 137 | } 138 | 139 | })) 140 | .pipe(rename('ngx-slick.umd.js')) 141 | .pipe(gulp.dest(distFolder)); 142 | }); 143 | 144 | /** 145 | * 7. Copy all the files from /build to /dist, except .js files. We ignore all .js from /build 146 | * because with don't need individual modules anymore, just the Flat ES module generated 147 | * on step 5. 148 | */ 149 | gulp.task('copy:build', function () { 150 | return gulp.src([`${buildFolder}/**/*`, `!${buildFolder}/**/*.js`]) 151 | .pipe(gulp.dest(distFolder)); 152 | }); 153 | 154 | /** 155 | * 8. Copy package.json from /src to /dist 156 | */ 157 | gulp.task('copy:manifest', function () { 158 | return gulp.src([`${srcFolder}/package.json`]) 159 | .pipe(gulp.dest(distFolder)); 160 | }); 161 | 162 | /** 163 | * 9. Copy README.md from / to /dist 164 | */ 165 | gulp.task('copy:readme', function () { 166 | return gulp.src([path.join(rootFolder, 'README.MD')]) 167 | .pipe(gulp.dest(distFolder)); 168 | }); 169 | 170 | /** 171 | * 10. Delete /.tmp folder 172 | */ 173 | gulp.task('clean:tmp', function () { 174 | return deleteFolder(tmpFolder); 175 | }); 176 | 177 | /** 178 | * 11. Delete /build folder 179 | */ 180 | gulp.task('clean:build', function () { 181 | return deleteFolder(buildFolder); 182 | }); 183 | 184 | gulp.task('compile', function () { 185 | runSequence( 186 | 'clean:dist', 187 | 'copy:source', 188 | 'inline-resources', 189 | 'ngc', 190 | 'rollup:fesm', 191 | 'rollup:umd', 192 | 'copy:build', 193 | 'copy:manifest', 194 | 'copy:readme', 195 | 'clean:build', 196 | 'clean:tmp', 197 | function (err) { 198 | if (err) { 199 | console.log('ERROR:', err.message); 200 | deleteFolder(distFolder); 201 | deleteFolder(tmpFolder); 202 | deleteFolder(buildFolder); 203 | } else { 204 | console.log('Compilation finished succesfully'); 205 | } 206 | }); 207 | }); 208 | 209 | /** 210 | * Watch for any change in the /src folder and compile files 211 | */ 212 | gulp.task('watch', function () { 213 | gulp.watch(`${srcFolder}/**/*`, ['compile']); 214 | }); 215 | 216 | gulp.task('clean', function (callback) { 217 | runSequence('clean:dist', 'clean:tmp', 'clean:build', callback); 218 | }); 219 | 220 | gulp.task('build', function (callback) { 221 | runSequence('clean', 'compile', callback); 222 | }); 223 | 224 | gulp.task('build:watch', function (callback) { 225 | runSequence('build', 'watch', callback); 226 | }); 227 | 228 | gulp.task('default', ['build:watch']); 229 | 230 | /** 231 | * Deletes the specified folder 232 | */ 233 | function deleteFolder(folder) { 234 | return fs.removeSync(folder); 235 | } 236 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-slick", 3 | "version": "0.2.1", 4 | "scripts": { 5 | "build": "gulp build", 6 | "build:watch": "gulp", 7 | "docs": "npm run docs:build", 8 | "docs:build": "compodoc -p tsconfig.json -n ngx-slick -d docs --hideGenerator", 9 | "docs:serve": "npm run docs:build -- -s", 10 | "docs:watch": "npm run docs:build -- -s -w", 11 | "lint": "tslint --type-check --project tsconfig.json src/**/*.ts", 12 | "lite": "lite-server", 13 | "playground:build": "tsc -p playground -w", 14 | "playground": "concurrently \"npm run build:watch\" \"npm run playground:build\" \"npm run lite\"", 15 | "test": "tsc && karma start" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/devmark/ngx-slick" 20 | }, 21 | "author": { 22 | "name": "Mark", 23 | "email": "hc.devmark@gmail.com" 24 | }, 25 | "keywords": [ 26 | "angular" 27 | ], 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/devmark/ngx-slick/issues" 31 | }, 32 | "devDependencies": { 33 | "@angular/common": "^6.0.7", 34 | "@angular/compiler": "^6.0.7", 35 | "@angular/compiler-cli": "^6.0.7", 36 | "@angular/core": "^6.0.7", 37 | "@angular/forms": "^6.0.7", 38 | "@angular/platform-browser": "^6.0.7", 39 | "@angular/platform-browser-dynamic": "^6.0.7", 40 | "@compodoc/compodoc": "^1.0.0-beta.10", 41 | "@types/jasmine": "2.5.53", 42 | "@types/node": "~6.0.60", 43 | "angular-in-memory-web-api": "^0.3.2", 44 | "codelyzer": "~3.2.0", 45 | "concurrently": "^3.4.0", 46 | "core-js": "^2.4.1", 47 | "fs-extra": "^5.0.0", 48 | "gulp": "^3.9.1", 49 | "gulp-rename": "^1.2.2", 50 | "gulp-rollup": "^2.16.2", 51 | "jasmine-core": "~2.6.2", 52 | "jasmine-spec-reporter": "~4.1.0", 53 | "karma": "~1.7.0", 54 | "karma-chrome-launcher": "~2.1.1", 55 | "karma-cli": "~1.0.1", 56 | "karma-coverage-istanbul-reporter": "^1.2.1", 57 | "karma-jasmine": "~1.1.0", 58 | "karma-jasmine-html-reporter": "^0.2.2", 59 | "lite-server": "^2.3.0", 60 | "node-sass": "^4.5.2", 61 | "node-sass-tilde-importer": "^1.0.0", 62 | "node-watch": "^0.5.2", 63 | "protractor": "~5.1.2", 64 | "rollup": "^0.62.0", 65 | "run-sequence": "^1.2.2", 66 | "rxjs": "~6.2.1", 67 | "systemjs": "^0.20.12", 68 | "ts-node": "~3.2.0", 69 | "tslint": "~5.7.0", 70 | "typescript": "~2.7.2", 71 | "zone.js": "^0.8.26" 72 | }, 73 | "engines": { 74 | "node": ">=6.0.0" 75 | }, 76 | "dependencies": { 77 | "@types/slick-carousel": "^1.6.32", 78 | "slick-carousel": "^1.8.1" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ngx-slick Playground 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Loading AppComponent content here ... 29 | 30 | 31 | -------------------------------------------------------------------------------- /playground/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This is only for local test 3 | */ 4 | import {BrowserModule} from '@angular/platform-browser'; 5 | import {NgModule} from '@angular/core'; 6 | import {Component} from '@angular/core'; 7 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 8 | 9 | import {SlickModule} from 'ngx-slick'; 10 | 11 | @Component({ 12 | selector: 'app', 13 | template: ` 14 | 15 |
16 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | ` 25 | }) 26 | class AppComponent { 27 | slides = [ 28 | {img: 'http://placehold.it/350x150/000000'}, 29 | {img: 'http://placehold.it/350x150/111111'}, 30 | {img: 'http://placehold.it/350x150/333333'}, 31 | {img: 'http://placehold.it/350x150/666666'} 32 | ]; 33 | slideConfig = { 34 | dots: true, 35 | speed: 300, 36 | slidesToShow: 2, 37 | slidesToScroll: 2 38 | }; 39 | 40 | addSlide() { 41 | this.slides.push({img: 'http://placehold.it/350x150/777777'}); 42 | } 43 | 44 | removeSlide() { 45 | this.slides.length = this.slides.length - 1; 46 | } 47 | 48 | slickInit(e) { 49 | console.log('slick initialized'); 50 | } 51 | afterChange(e) { 52 | console.log('afterChange'); 53 | } 54 | } 55 | 56 | @NgModule({ 57 | bootstrap: [AppComponent], 58 | declarations: [AppComponent], 59 | imports: [BrowserModule, SlickModule] 60 | }) 61 | class AppModule { 62 | } 63 | 64 | platformBrowserDynamic().bootstrapModule(AppModule); 65 | -------------------------------------------------------------------------------- /playground/systemjs-angular-loader.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*)/gm; 4 | var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g; 5 | var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g; 6 | 7 | module.exports.translate = function (load){ 8 | if (load.source.indexOf('moduleId') !== -1) { 9 | return load; 10 | } 11 | 12 | // eslint-disable-next-line 13 | var url = document.createElement('a'); 14 | url.href = load.address; 15 | 16 | var basePathParts = url.pathname.split('/'); 17 | 18 | basePathParts.pop(); 19 | var basePath = basePathParts.join('/'); 20 | 21 | // eslint-disable-next-line 22 | var baseHref = document.createElement('a'); 23 | baseHref.href = this.baseURL; 24 | baseHref = baseHref.pathname; 25 | 26 | if (!baseHref.startsWith('/base/')) { // it is not karma 27 | basePath = basePath.replace(baseHref, ''); 28 | } 29 | 30 | load.source = load.source 31 | .replace(templateUrlRegex, function (match, quote, sourceUrl){ 32 | var resolvedUrl = sourceUrl; 33 | 34 | if (sourceUrl.startsWith('.')) { 35 | resolvedUrl = basePath + sourceUrl.substr(1); 36 | } 37 | 38 | return 'templateUrl: "' + resolvedUrl + '"'; 39 | }) 40 | .replace(stylesRegex, function (match, relativeUrls) { 41 | var urls = []; 42 | 43 | while ((match = stringRegex.exec(relativeUrls)) !== null) { 44 | if (match[2].startsWith('.')) { 45 | urls.push('"' + basePath + match[2].substr(1) + '"'); 46 | } else { 47 | urls.push('"' + match[2] + '"'); 48 | } 49 | } 50 | 51 | return 'styleUrls: [' + urls.join(', ') + ']'; 52 | }); 53 | 54 | return load; 55 | }; 56 | -------------------------------------------------------------------------------- /playground/systemjs.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * System configuration for Angular samples 4 | * Adjust as necessary for your application needs. 5 | */ 6 | (function () { 7 | System.config({ 8 | paths: { 9 | // paths serve as alias 10 | 'npm:': '../node_modules/' 11 | }, 12 | // map tells the System loader where to look for things 13 | map: { 14 | // our app is within the app folder 15 | app: 'app', 16 | 17 | // angular bundles 18 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 19 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 20 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 21 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 22 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 23 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 24 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 25 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 26 | 27 | // other libraries 28 | rxjs: 'npm:rxjs', 29 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js', 30 | 'ngx-slick': '../dist' 31 | }, 32 | // packages tells the System loader how to load when no filename and/or no extension 33 | packages: { 34 | '.': { 35 | defaultExtension: 'js' 36 | }, 37 | app: { 38 | defaultExtension: 'js', 39 | meta: { 40 | './*.js': { 41 | loader: 'systemjs-angular-loader.js' 42 | } 43 | } 44 | }, 45 | rxjs: { defaultExtension: 'js', main: "index.js" }, 46 | "rxjs-compat": {defaultExtension: 'js', main: "index.js"}, 47 | "rxjs/operators": {"main": "index.js", "defaultExtension": "js"}, 48 | "rxjs/internal-compatibility": {"main": "index.js", "defaultExtension": "js"}, 49 | "rxjs/testing": {"main": "index.js", "defaultExtension": "js"}, 50 | 'rxjs/ajax': {main: 'index.js', defaultExtension: 'js'}, 51 | 'rxjs/webSocket': {main: 'index.js', defaultExtension: 'js'}, 52 | 'ngx-slick': { 53 | main: 'ngx-slick.umd.js', 54 | defaultExtension: 'js' 55 | } 56 | } 57 | }); 58 | })(this); 59 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "../.playground", 4 | "target": "es5", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "lib": [ "es2015", "dom" ], 11 | "noImplicitAny": true, 12 | "suppressImplicitAnyIndexErrors": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import {NgModule, ModuleWithProviders} from '@angular/core'; 2 | import {CommonModule} from '@angular/common'; 3 | import {SlickComponent, SlickItemDirective} from './slick.component'; 4 | 5 | export * from './slick.component'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule 10 | ], 11 | declarations: [ 12 | SlickComponent, 13 | SlickItemDirective, 14 | ], 15 | exports: [ 16 | SlickComponent, 17 | SlickItemDirective, 18 | ] 19 | }) 20 | export class SlickModule { 21 | static forRoot(): ModuleWithProviders { 22 | return { 23 | ngModule: SlickModule, 24 | }; 25 | } 26 | } 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-slick", 3 | "version": "0.2.1", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/devmark/ngx-slick" 7 | }, 8 | "author": { 9 | "name": "Mark", 10 | "email": "hc.devmark@gmail.com" 11 | }, 12 | "keywords": [ 13 | "angular" 14 | ], 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/devmark/ngx-slick/issues" 18 | }, 19 | "main": "ngx-slick.umd.js", 20 | "module": "ngx-slick.js", 21 | "jsnext:main": "ngx-slick.js", 22 | "typings": "ngx-slick.d.ts", 23 | "peerDependencies": { 24 | "@angular/core": "^6.0.0", 25 | "@angular/common": "^6.0.0", 26 | "@angular/forms": "^6.0.0", 27 | "rxjs": "^6.0.0", 28 | "zone.js": "^0.8.4" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/slick.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, Input, Output, EventEmitter, NgZone, forwardRef, AfterViewInit, 3 | OnDestroy, Directive, ElementRef, Host 4 | } from '@angular/core'; 5 | import {NG_VALUE_ACCESSOR} from '@angular/forms'; 6 | 7 | declare const jQuery: any; 8 | 9 | /** 10 | * Slick component 11 | */ 12 | @Component({ 13 | selector: 'ngx-slick', 14 | exportAs: 'slick-modal', 15 | providers: [ 16 | { 17 | provide: NG_VALUE_ACCESSOR, 18 | useExisting: forwardRef(() => SlickComponent), 19 | multi: true 20 | } 21 | ], 22 | template: '', 23 | }) 24 | export class SlickComponent implements AfterViewInit, OnDestroy { 25 | 26 | @Input() config: any; 27 | @Output() afterChange: EventEmitter = new EventEmitter(); 28 | @Output() beforeChange: EventEmitter = new EventEmitter(); 29 | @Output() breakpoint: EventEmitter = new EventEmitter(); 30 | @Output() destroy: EventEmitter = new EventEmitter(); 31 | @Output() init: EventEmitter = new EventEmitter(); 32 | public slides: any = []; 33 | public $instance: any; 34 | private initialized: Boolean = false; 35 | 36 | /** 37 | * Constructor 38 | */ 39 | constructor(private el: ElementRef, private zone: NgZone) { 40 | 41 | } 42 | 43 | /** 44 | * On component destroy 45 | */ 46 | ngOnDestroy() { 47 | this.unslick(); 48 | } 49 | 50 | /** 51 | * On component view init 52 | */ 53 | ngAfterViewInit() { 54 | } 55 | 56 | /** 57 | * init slick 58 | */ 59 | initSlick() { 60 | const self = this; 61 | 62 | this.zone.runOutsideAngular(() => { 63 | jQuery(this.el.nativeElement)[0].innerHTML = ''; 64 | this.$instance = jQuery(this.el.nativeElement); 65 | this.$instance.on('init', (event, slick) => { 66 | this.zone.run(() => { 67 | this.init.emit({event, slick}); 68 | }); 69 | }); 70 | 71 | this.$instance.slick(this.config); 72 | this.initialized = true; 73 | 74 | this.$instance.on('afterChange', (event, slick, currentSlide) => { 75 | self.zone.run(() => { 76 | self.afterChange.emit({event, slick, currentSlide}); 77 | }); 78 | }); 79 | 80 | this.$instance.on('beforeChange', (event, slick, currentSlide, nextSlide) => { 81 | self.zone.run(() => { 82 | self.beforeChange.emit({event, slick, currentSlide, nextSlide}); 83 | }); 84 | }); 85 | 86 | this.$instance.on('breakpoint', (event, slick, breakpoint) => { 87 | self.zone.run(() => { 88 | self.breakpoint.emit({event, slick, breakpoint}); 89 | }); 90 | }); 91 | 92 | this.$instance.on('destroy', (event, slick) => { 93 | self.zone.run(() => { 94 | self.destroy.emit({event, slick}); 95 | }); 96 | }); 97 | }); 98 | } 99 | 100 | addSlide(slickItem: SlickItemDirective) { 101 | if (!this.initialized) { 102 | this.initSlick(); 103 | } 104 | this.slides.push(slickItem); 105 | 106 | this.zone.run(() => { 107 | this.$instance.slick('slickAdd', slickItem.el.nativeElement); 108 | }); 109 | } 110 | 111 | removeSlide(slickItem: SlickItemDirective) { 112 | const idx = this.slides.indexOf(slickItem); 113 | 114 | this.zone.run(() => { 115 | this.$instance.slick('slickRemove', idx); 116 | }); 117 | 118 | this.slides = this.slides.filter(s => s !== slickItem); 119 | } 120 | 121 | /** 122 | * Slick Method 123 | */ 124 | public slickGoTo(index: number) { 125 | this.zone.run(() => { 126 | this.$instance.slick('slickGoTo', index); 127 | }); 128 | } 129 | 130 | public slickNext() { 131 | this.zone.run(() => { 132 | this.$instance.slick('slickNext'); 133 | }); 134 | } 135 | 136 | 137 | public slickPrev() { 138 | this.zone.run(() => { 139 | this.$instance.slick('slickPrev'); 140 | }); 141 | } 142 | 143 | public slickPause() { 144 | this.zone.run(() => { 145 | this.$instance.slick('slickPause'); 146 | }); 147 | } 148 | 149 | public slickPlay() { 150 | this.zone.run(() => { 151 | this.$instance.slick('slickPlay'); 152 | }); 153 | } 154 | 155 | public unslick() { 156 | if (this.$instance) { 157 | this.zone.run(() => { 158 | this.$instance.slick('unslick'); 159 | }); 160 | } 161 | this.initialized = false; 162 | } 163 | 164 | } 165 | 166 | @Directive({ 167 | selector: '[ngxSlickItem]', 168 | }) 169 | export class SlickItemDirective implements AfterViewInit, OnDestroy { 170 | constructor(public el: ElementRef, @Host() private carousel: SlickComponent) { 171 | } 172 | 173 | ngAfterViewInit() { 174 | this.carousel.addSlide(this); 175 | } 176 | 177 | ngOnDestroy() { 178 | this.carousel.removeSlide(this); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/tsconfig.es5.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "module": "es2015", 5 | "target": "es5", 6 | "baseUrl": ".", 7 | "stripInternal": true, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "moduleResolution": "node", 11 | "outDir": "../build", 12 | "rootDir": ".", 13 | "lib": [ 14 | "es2015", 15 | "dom" 16 | ], 17 | "skipLibCheck": true, 18 | "types": [] 19 | }, 20 | "angularCompilerOptions": { 21 | "annotateForClosureCompiler": true, 22 | "strictMetadataEmit": true, 23 | "skipTemplateCodegen": true, 24 | "flatModuleOutFile": "ngx-slick.js", 25 | "flatModuleId": "ngx-slick" 26 | }, 27 | "files": [ 28 | "./index.ts" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.es5.json", 3 | "compilerOptions": { 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "outDir": "../out-tsc/spec", 7 | "module": "commonjs", 8 | "target": "es6", 9 | "baseUrl": "", 10 | "types": [ 11 | "jest", 12 | "node" 13 | ] 14 | }, 15 | "files": [ 16 | "**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tools/gulp/inline-resources.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // https://github.com/filipesilva/angular-quickstart-lib/blob/master/inline-resources.js 3 | 'use strict'; 4 | 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | const glob = require('glob'); 8 | const sass = require('node-sass'); 9 | const tildeImporter = require('node-sass-tilde-importer'); 10 | 11 | /** 12 | * Simple Promiseify function that takes a Node API and return a version that supports promises. 13 | * We use promises instead of synchronized functions to make the process less I/O bound and 14 | * faster. It also simplifies the code. 15 | */ 16 | function promiseify(fn) { 17 | return function () { 18 | const args = [].slice.call(arguments, 0); 19 | return new Promise((resolve, reject) => { 20 | fn.apply(this, args.concat([function (err, value) { 21 | if (err) { 22 | reject(err); 23 | } else { 24 | resolve(value); 25 | } 26 | }])); 27 | }); 28 | }; 29 | } 30 | 31 | const readFile = promiseify(fs.readFile); 32 | const writeFile = promiseify(fs.writeFile); 33 | 34 | /** 35 | * Inline resources in a tsc/ngc compilation. 36 | * @param projectPath {string} Path to the project. 37 | */ 38 | function inlineResources(projectPath) { 39 | 40 | // Match only TypeScript files in projectPath. 41 | const files = glob.sync('**/*.ts', {cwd: projectPath}); 42 | 43 | // For each file, inline the templates and styles under it and write the new file. 44 | return Promise.all(files.map(filePath => { 45 | const fullFilePath = path.join(projectPath, filePath); 46 | return readFile(fullFilePath, 'utf-8') 47 | .then(content => inlineResourcesFromString(content, url => { 48 | // Resolve the template url. 49 | return path.join(path.dirname(fullFilePath), url); 50 | })) 51 | .then(content => writeFile(fullFilePath, content)) 52 | .catch(err => { 53 | console.error('An error occured: ', err); 54 | }); 55 | })); 56 | } 57 | 58 | /** 59 | * Inline resources from a string content. 60 | * @param content {string} The source file's content. 61 | * @param urlResolver {Function} A resolver that takes a URL and return a path. 62 | * @returns {string} The content with resources inlined. 63 | */ 64 | function inlineResourcesFromString(content, urlResolver) { 65 | // Curry through the inlining functions. 66 | return [ 67 | inlineTemplate, 68 | inlineStyle, 69 | removeModuleId 70 | ].reduce((content, fn) => fn(content, urlResolver), content); 71 | } 72 | 73 | /** 74 | * Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and 75 | * replace with `template: ...` (with the content of the file included). 76 | * @param content {string} The source file's content. 77 | * @param urlResolver {Function} A resolver that takes a URL and return a path. 78 | * @return {string} The content with all templates inlined. 79 | */ 80 | function inlineTemplate(content, urlResolver) { 81 | return content.replace(/templateUrl:\s*(['"])([^\1]+?\.html)\1/g, function (fullMatch, quote, templateUrl) { 82 | const templateFile = urlResolver(templateUrl); 83 | const templateContent = fs.readFileSync(templateFile, 'utf-8'); 84 | const shortenedTemplate = templateContent 85 | .replace(/([\n\r]\s*)+/gm, ' ') 86 | .replace(/"/g, '\\"'); 87 | return `template: "${shortenedTemplate}"`; 88 | }); 89 | } 90 | 91 | 92 | /** 93 | * Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and 94 | * replace with `styles: [...]` (with the content of the file included). 95 | * @param urlResolver {Function} A resolver that takes a URL and return a path. 96 | * @param content {string} The source file's content. 97 | * @return {string} The content with all styles inlined. 98 | */ 99 | function inlineStyle(content, urlResolver) { 100 | return content.replace(/styleUrls\s*:\s*(\[[\s\S]*?\])/gm, function (m, styleUrls) { 101 | const urls = eval(styleUrls); 102 | return 'styles: [' 103 | + urls.map(styleUrl => { 104 | const styleFile = urlResolver(styleUrl); 105 | const originContent = fs.readFileSync(styleFile, 'utf-8'); 106 | const styleContent = styleFile.endsWith('.scss') ? buildSass(originContent, styleFile) : originContent; 107 | const shortenedStyle = styleContent 108 | .replace(/([\n\r]\s*)+/gm, ' ') 109 | .replace(/"/g, '\\"'); 110 | return `"${shortenedStyle}"`; 111 | }) 112 | .join(',\n') 113 | + ']'; 114 | }); 115 | } 116 | 117 | /** 118 | * build sass content to css 119 | * @param content {string} the css content 120 | * @param sourceFile {string} the scss file sourceFile 121 | * @return {string} the generated css, empty string if error occured 122 | */ 123 | function buildSass(content, sourceFile) { 124 | try { 125 | const result = sass.renderSync({ 126 | data: content, 127 | file: sourceFile, 128 | importer: tildeImporter 129 | }); 130 | return result.css.toString() 131 | } catch (e) { 132 | console.error('\x1b[41m'); 133 | console.error('at ' + sourceFile + ':' + e.line + ":" + e.column); 134 | console.error(e.formatted); 135 | console.error('\x1b[0m'); 136 | return ""; 137 | } 138 | } 139 | 140 | /** 141 | * Remove every mention of `moduleId: module.id`. 142 | * @param content {string} The source file's content. 143 | * @returns {string} The content with all moduleId: mentions removed. 144 | */ 145 | function removeModuleId(content) { 146 | return content.replace(/\s*moduleId:\s*module\.id\s*,?\s*/gm, ''); 147 | } 148 | 149 | module.exports = inlineResources; 150 | module.exports.inlineResourcesFromString = inlineResourcesFromString; 151 | 152 | // Run inlineResources if module is being called directly from the CLI with arguments. 153 | if (require.main === module && process.argv.length > 2) { 154 | console.log('Inlining resources from project:', process.argv[2]); 155 | return inlineResources(process.argv[2]); 156 | } 157 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./src", 4 | "experimentalDecorators": true, 5 | "moduleResolution": "node", 6 | "rootDir": "./src", 7 | "lib": [ 8 | "es2015", 9 | "dom" 10 | ], 11 | "skipLibCheck": true, 12 | "types": [] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "class-name": true, 7 | "comment-format": [ 8 | true, 9 | "check-space" 10 | ], 11 | "curly": true, 12 | "eofline": true, 13 | "forin": true, 14 | "indent": [ 15 | true, 16 | "spaces" 17 | ], 18 | "label-position": true, 19 | "max-line-length": [ 20 | true, 21 | 140 22 | ], 23 | "member-access": false, 24 | "member-ordering": [ 25 | true, 26 | "static-before-instance", 27 | "variables-before-functions" 28 | ], 29 | "no-arg": true, 30 | "no-bitwise": true, 31 | "no-console": [ 32 | true, 33 | "debug", 34 | "info", 35 | "time", 36 | "timeEnd", 37 | "trace" 38 | ], 39 | "no-construct": true, 40 | "no-debugger": true, 41 | "no-duplicate-variable": true, 42 | "no-empty": false, 43 | "no-eval": true, 44 | "no-inferrable-types": true, 45 | "no-shadowed-variable": true, 46 | "no-string-literal": false, 47 | "no-switch-case-fall-through": true, 48 | "no-trailing-whitespace": true, 49 | "no-unused-expression": true, 50 | "no-unused-variable": true, 51 | "no-use-before-declare": true, 52 | "no-var-keyword": true, 53 | "object-literal-sort-keys": false, 54 | "one-line": [ 55 | true, 56 | "check-open-brace", 57 | "check-catch", 58 | "check-else", 59 | "check-whitespace" 60 | ], 61 | "quotemark": [ 62 | true, 63 | "single" 64 | ], 65 | "radix": true, 66 | "semicolon": [ 67 | true, 68 | "always" 69 | ], 70 | "triple-equals": [ 71 | true, 72 | "allow-null-check" 73 | ], 74 | "typedef-whitespace": [ 75 | true, 76 | { 77 | "call-signature": "nospace", 78 | "index-signature": "nospace", 79 | "parameter": "nospace", 80 | "property-declaration": "nospace", 81 | "variable-declaration": "nospace" 82 | } 83 | ], 84 | "variable-name": false, 85 | "whitespace": [ 86 | true, 87 | "check-branch", 88 | "check-decl", 89 | "check-operator", 90 | "check-separator", 91 | "check-type" 92 | ], 93 | "directive-selector": [true, "attribute", "", "camelCase"], 94 | "component-selector": [true, "element", "", "kebab-case"], 95 | "use-input-property-decorator": true, 96 | "use-output-property-decorator": true, 97 | "use-host-property-decorator": true, 98 | "no-input-rename": true, 99 | "no-output-rename": true, 100 | "use-life-cycle-interface": true, 101 | "use-pipe-transform-interface": true, 102 | "component-class-suffix": true, 103 | "directive-class-suffix": true 104 | } 105 | } 106 | --------------------------------------------------------------------------------