diff --git a/.editorconfig b/.editorconfig index 8565360..644dd12 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,18 +1,45 @@ -# This file is for unifying the coding style for different editors and IDEs -# editorconfig.org +# This project uses EditorConfig for setting code formatting options: http://EditorConfig.org root = true +# Default settings for all files [*] -end_of_line = lf charset = utf-8 +end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true +indent_style = tab +indent_size = tab +tab_width = 4 +max_line_length = 120 -# Tabs in JS unless otherwise specified -[**.js] +spaces_around_operators = true +spaces_around_brackets = none +curly_bracket_next_line = true +indent_brace_style = Allman +continuation_indent_size = 4 + +[*.{css,less}] +curly_bracket_next_line = false +continuation_indent_size = 0 + +# Formats likely to be pasted into an REPL on a terminal should not use tabs to avoid triggering tab-completion. +[*.{sh,bash,sql,psql,pgsql}] +indent_style = space +indent_size = 4 + +[*.yml] indent_style = space indent_size = 2 -[*.md] -trim_trailing_whitespace = false \ No newline at end of file +[*.{js,json}] +indent_style = space +indent_size = 4 + +# Special overrides for automatically-generated files +[package.json] +indent_size = 2 + +# For some formats, trailing whitespace is significant; don't strip it. +[*.{md,diff,patch}] +trim_trailing_whitespace = false diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b81057..88f0671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# [3.0.0](https://github.com/morgul/ui-bootstrap4/compare/3.0.0-beta.4...3.0.0) (2017-12-11) + + + # [3.0.0-beta.4](https://github.com/morgul/ui-bootstrap4/compare/2.5.0...3.0.0-beta.4) (2017-12-10) diff --git a/Gruntfile.js b/Gruntfile.js index 8006026..76a12f3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,496 +1,561 @@ -var marked = require('marked'); -var fs = require('fs'); -var _ = require('lodash'); +const marked = require('marked'); +const fs = require('fs'); +const _ = require('lodash'); module.exports = function(grunt) { - require('load-grunt-tasks')(grunt); + require('load-grunt-tasks')(grunt); - // Project configuration. - grunt.util.linefeed = '\n'; + // Project configuration. + grunt.util.linefeed = '\n'; - grunt.initConfig({ - ngversion: '1.6.1', - bsversion: '4.0.0-beta.2', - modules: [],//to be filled in by build task - pkg: grunt.file.readJSON('package.json'), - dist: 'dist', - filename: 'ui-bootstrap', - filenamecustom: '<%= filename %>-custom', - meta: { - modules: 'angular.module("ui.bootstrap", [<%= srcModules %>]);', - tplmodules: 'angular.module("ui.bootstrap.tpls", [<%= tplModules %>]);', - all: 'angular.module("ui.bootstrap", ["ui.bootstrap.tpls", <%= srcModules %>]);', - cssInclude: '', - cssFileBanner: '/* Include this file in your html if you are using the CSP mode. */\n\n', - cssFileDest: '<%= dist %>/<%= filename %>-<%= pkg.version %>-csp.css', - banner: [ - '/*', - ' * <%= pkg.name %>', - ' * <%= pkg.homepage %>\n', - ' * Version: <%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>', - ' * License: <%= pkg.license %>', - ' */' - ].join('\n') - }, - delta: { - docs: { - files: ['misc/demo/index.html'], - tasks: ['after-test'] - }, - html: { - files: ['template/**/*.html'], - tasks: ['html2js', 'karma:watch:run'] - }, - js: { - files: ['src/**/*.js', '!src/**/index.js'], - tasks: ['karma:watch:run'] - } - }, - concat: { - dist: { - options: { - banner: '<%= meta.banner %><%= meta.modules %>\n', - footer: '<%= meta.cssInclude %>' + grunt.initConfig({ + ngversion: '1.6.1', + bsversion: '4.0.0-beta.2', + modules: [],//to be filled in by build task + pkg: grunt.file.readJSON('package.json'), + dist: 'dist', + filename: 'ui-bootstrap', + filenamecustom: '<%= filename %>-custom', + meta: { + modules: 'angular.module("ui.bootstrap", [<%= srcModules %>]);', + tplmodules: 'angular.module("ui.bootstrap.tpls", [<%= tplModules %>]);', + all: 'angular.module("ui.bootstrap", ["ui.bootstrap.tpls", <%= srcModules %>]);', + cssInclude: '', + cssFileBanner: '/* Include this file in your html if you are using the CSP mode. */\n\n', + cssFileDest: '<%= dist %>/<%= filename %>-<%= pkg.version %>-csp.css', + banner: [ + '/*', + ' * <%= pkg.name %>', + ' * <%= pkg.homepage %>\n', + ' * Version: <%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>', + ' * License: <%= pkg.license %>', + ' */' + ].join('\n') }, - src: [], //src filled in by build task - dest: '<%= dist %>/<%= filename %>-<%= pkg.version %>.js' - }, - dist_tpls: { - options: { - banner: '<%= meta.banner %><%= meta.all %>\n<%= meta.tplmodules %>\n', - footer: '<%= meta.cssInclude %>' + delta: { + docs: { + files: ['misc/demo/index.html'], + tasks: ['after-test'] + }, + html: { + files: ['template/**/*.html'], + tasks: ['html2js', 'karma:watch:run'] + }, + js: { + files: ['src/**/*.js', '!src/**/index.js'], + tasks: ['karma:watch:run'] + } }, - src: [], //src filled in by build task - dest: '<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.js' - } - }, - copy: { - demohtml: { - options: { - //process html files with gruntfile config - processContent: grunt.template.process + concat: { + dist: { + options: { + banner: '<%= meta.banner %><%= meta.modules %>\n', + footer: '<%= meta.cssInclude %>' + }, + src: [], //src filled in by build task + dest: '<%= dist %>/<%= filename %>-<%= pkg.version %>.js' + }, + dist_tpls: { + options: { + banner: '<%= meta.banner %><%= meta.all %>\n<%= meta.tplmodules %>\n', + footer: '<%= meta.cssInclude %>' + }, + src: [], //src filled in by build task + dest: '<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.js' + } }, - files: [ - { - expand: true, - src: ['**/*.html'], - cwd: 'misc/demo/', - dest: 'dist/' - }, - { - expand: true, - src: ['svg-icon.css'], - cwd: 'src/', - dest: 'dist/' - } - ] - }, - demoassets: { - files: [{ - expand: true, - //Don't re-copy html files, we process those - src: ['**/**/*', '!**/*.html'], - cwd: 'misc/demo', - dest: 'dist/' - }] - }, - docs: { - files:[{ - expand: true, - src: ['**/*', '*/*'], - cwd: 'dist/', - dest: 'docs/' - }] - } - }, - uglify: { - options: { - banner: '<%= meta.banner %>' - }, - dist:{ - src:['<%= concat.dist.dest %>'], - dest:'<%= dist %>/<%= filename %>-<%= pkg.version %>.min.js' - }, - dist_tpls:{ - src:['<%= concat.dist_tpls.dest %>'], - dest:'<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.min.js' - } - }, - html2js: { - dist: { - options: { - module: null, // no bundle module for all the html2js templates - base: '.', - rename: function(moduleName) { - return `uib/${moduleName}`; - } + copy: { + demohtml: { + options: { + //process html files with gruntfile config + processContent: grunt.template.process + }, + files: [ + { + expand: true, + src: ['**/*.html'], + cwd: 'misc/demo/', + dest: 'dist/' + }, + { + expand: true, + src: ['svg-icon.css'], + cwd: 'src/', + dest: 'dist/' + } + ] + }, + demoassets: { + files: [ + { + expand: true, + //Don't re-copy html files, we process those + src: ['**/**/*', '!**/*.html'], + cwd: 'misc/demo', + dest: 'dist/' + } + ] + }, + docs: { + files: [ + { + expand: true, + src: ['**/*', '*/*'], + cwd: 'dist/', + dest: 'docs/' + } + ] + } }, - files: [{ - expand: true, - src: ['template/**/*.html'], - ext: '.html.js' - }] - } - }, - eslint: { - files: ['Gruntfile.js','src/**/*.js'] - }, - karma: { - options: { - configFile: 'karma.conf.js' - }, - watch: { - background: true - }, - continuous: { - singleRun: true - }, - jenkins: { - singleRun: true, - autoWatch: false, - colors: false, - reporters: ['dots', 'junit'], - browsers: ['Chrome', 'ChromeCanary', 'Firefox', 'Opera', '/Users/jenkins/bin/safari.sh'] - }, - travis: { - singleRun: true, - autoWatch: false, - reporters: ['dots'], - browsers: ['Firefox'] - }, - coverage: { - preprocessors: { - 'src/*/*.js': 'coverage' + uglify: { + options: { + banner: '<%= meta.banner %>' + }, + dist: { + src: ['<%= concat.dist.dest %>'], + dest: '<%= dist %>/<%= filename %>-<%= pkg.version %>.min.js' + }, + dist_tpls: { + src: ['<%= concat.dist_tpls.dest %>'], + dest: '<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.min.js' + } }, - reporters: ['progress', 'coverage'] - } - }, - conventionalChangelog: { - options: { - changelogOpts: { - preset: 'angular' + html2js: { + dist: { + options: { + module: null, // no bundle module for all the html2js templates + base: '.', + rename: function(moduleName) { + return `uib/${moduleName}`; + } + }, + files: [ + { + expand: true, + src: ['template/**/*.html'], + ext: '.html.js' + } + ] + } }, - templateFile: 'misc/changelog.tpl.md' - }, - release: { - src: 'CHANGELOG.md' - } - }, - shell: { - //We use %version% and evaluate it at run-time, because <%= pkg.version %> - //is only evaluated once - 'release-prepare': [ - 'grunt before-test after-test', - 'grunt version', //remove "-SNAPSHOT" - 'grunt conventionalChangelog' - ], - 'release-complete': [ - 'git commit CHANGELOG.md package.json -m "chore(release): v%version%"', - 'git tag %version%' - ], - 'release-start': [ - 'grunt version:minor:"SNAPSHOT"', - 'git commit package.json -m "chore(release): Starting v%version%"' - ] - }, - 'ddescribe-iit': { - files: [ - 'src/**/*.spec.js' - ] - } - }); - - //register before and after test tasks so we've don't have to change cli - //options on the google's CI server - grunt.registerTask('before-test', [/*'ddescribe-iit',*/ 'eslint', 'html2js']); - grunt.registerTask('after-test', ['build', 'copy']); - - //Rename our watch task to 'delta', then make actual 'watch' - //task build things, then start test server - grunt.renameTask('watch', 'delta'); - grunt.registerTask('watch', ['before-test', 'after-test', 'karma:watch', 'delta']); - - // Default task. - grunt.registerTask('default', ['before-test', 'test', 'after-test']); - - // Build docs - grunt.registerTask('docs', ['before-test', 'after-test', 'copy:docs']); - - //Common ui.bootstrap module containing all modules for src and templates - //findModule: Adds a given module to config - var foundModules = {}; - function findModule(name) { - if (foundModules[name]) { return; } - foundModules[name] = true; - - function breakup(text, separator) { - return text.replace(/[A-Z]/g, function (match) { - return separator + match; - }); - } - function ucwords(text) { - return text.replace(/^([a-z])|\s+([a-z])/g, function ($1) { - return $1.toUpperCase(); - }); - } - function enquote(str) { - return `"${str}"`; - } - function enquoteUibDir(str) { - return enquote(`uib/${str}`); - } - - var module = { - name: name, - moduleName: enquote(`ui.bootstrap.${name}`), - displayName: ucwords(breakup(name, ' ')), - srcFiles: grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`]), - cssFiles: grunt.file.expand(`src/${name}/*.css`), - tplFiles: grunt.file.expand(`template/${name}/*.html`), - tpljsFiles: grunt.file.expand(`template/${name}/*.html.js`), - tplModules: grunt.file.expand(`template/${name}/*.html`).map(enquoteUibDir), - dependencies: dependenciesForModule(name), - docs: { - md: grunt.file.expand(`src/${name}/docs/*.md`) - .map(grunt.file.read).map((str) => marked(str)).join('\n'), - js: grunt.file.expand(`src/${name}/docs/*.js`) - .map(grunt.file.read).join('\n'), - html: grunt.file.expand(`src/${name}/docs/*.html`) - .map(grunt.file.read).join('\n') - } - }; - - var styles = { - css: [], - js: [] - }; - module.cssFiles.forEach(processCSS.bind(null, module.name, styles, true)); - if (styles.css.length) { - module.css = styles.css.join('\n'); - module.cssJs = styles.js.join('\n'); - } - - module.dependencies.forEach(findModule); - grunt.config('modules', grunt.config('modules').concat(module)); - } - - function dependenciesForModule(name) { - var deps = []; - grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`]) - .map(grunt.file.read) - .forEach(function(contents) { - //Strategy: find where module is declared, - //and from there get everything inside the [] and split them by comma - var moduleDeclIndex = contents.indexOf('angular.module('); - var depArrayStart = contents.indexOf('[', moduleDeclIndex); - var depArrayEnd = contents.indexOf(']', depArrayStart); - var dependencies = contents.substring(depArrayStart + 1, depArrayEnd); - dependencies.split(',').forEach(function(dep) { - if (dep.indexOf('ui.bootstrap.') > -1) { - var depName = dep.trim().replace('ui.bootstrap.','').replace(/['"]/g,''); - if (deps.indexOf(depName) < 0) { - deps.push(depName); - //Get dependencies for this new dependency - deps = deps.concat(dependenciesForModule(depName)); - } + eslint: { + files: ['Gruntfile.js', 'src/**/*.js'] + }, + karma: { + options: { + configFile: 'karma.conf.js' + }, + watch: { + background: true + }, + continuous: { + singleRun: true + }, + jenkins: { + singleRun: true, + autoWatch: false, + colors: false, + reporters: ['dots', 'junit'], + browsers: ['Chrome', 'ChromeCanary', 'Firefox', 'Opera', '/Users/jenkins/bin/safari.sh'] + }, + travis: { + singleRun: true, + autoWatch: false, + reporters: ['dots'], + browsers: ['Firefox'] + }, + coverage: { + preprocessors: { + 'src/*/*.js': 'coverage' + }, + reporters: ['progress', 'coverage'] + } + }, + conventionalChangelog: { + options: { + changelogOpts: { + preset: 'angular' + }, + templateFile: 'misc/changelog.tpl.md' + }, + release: { + src: 'CHANGELOG.md' + } + }, + shell: { + //We use %version% and evaluate it at run-time, because <%= pkg.version %> + //is only evaluated once + 'release-prepare': [ + 'cp ./dist/ui-bootstrap* docs', + 'git add docs', + ], + 'release-complete': [ + 'git commit -a -m "chore(release): v%version%"', + 'git tag %version%', + 'git push --follow-tags' + ], + 'publish': [ + 'rm -rf dist/*', + 'cp ./docs/ui-bootstrap-%version%.js ./dist/ui-bootstrap.js', + 'cp ./docs/ui-bootstrap-%version%-csp.css ./dist/ui-bootstrap-csp.css', + 'cp ./docs/ui-bootstrap-tpls-%version%.js ./dist/ui-bootstrap-tpls.js', + 'npm publish' + ] + }, + 'ddescribe-iit': { + files: [ + 'src/**/*.spec.js' + ] } - }); }); - return deps; - } - grunt.registerTask('dist', 'Override dist directory', function() { - var dir = this.args[0]; - if (dir) { grunt.config('dist', dir); } - }); + //register before and after test tasks so we've don't have to change cli + //options on the google's CI server + grunt.registerTask('before-test', [/*'ddescribe-iit',*/ 'eslint', 'html2js']); + grunt.registerTask('after-test', ['build', 'copy']); - grunt.registerTask('build', 'Create bootstrap build files', function() { - var _ = grunt.util._; + //Rename our watch task to 'delta', then make actual 'watch' + //task build things, then start test server + grunt.renameTask('watch', 'delta'); + grunt.registerTask('watch', ['before-test', 'after-test', 'karma:watch', 'delta']); - //If arguments define what modules to build, build those. Else, everything - if (this.args.length) { - this.args.forEach(findModule); - grunt.config('filename', grunt.config('filenamecustom')); - } else { - grunt.file.expand({ - filter: 'isDirectory', cwd: '.' - }, 'src/*').forEach((dir) => { - findModule(dir.split('/')[1]); - }); - } + // Default task. + grunt.registerTask('default', ['before-test', 'test', 'after-test']); - var modules = grunt.config('modules'); - grunt.config('srcModules', _.pluck(modules, 'moduleName')); - grunt.config('tplModules', _.pluck(modules, 'tplModules').filter((tpls) => tpls.length > 0)); - grunt.config('demoModules', modules - .filter((module) => module.docs.md && module.docs.js && module.docs.html) - .sort((a, b) => { - if (a.name < b.name) { return -1; } - if (a.name > b.name) { return 1; } - return 0; - }) - ); + // Build docs + grunt.registerTask('docs', ['before-test', 'after-test', 'copy:docs']); - var cssStrings = _.flatten(_.compact(_.pluck(modules, 'css'))); - var cssJsStrings = _.flatten(_.compact(_.pluck(modules, 'cssJs'))); - if (cssStrings.length) { - grunt.config('meta.cssInclude', cssJsStrings.join('\n')); + //Common ui.bootstrap module containing all modules for src and templates + //findModule: Adds a given module to config + const foundModules = {}; - grunt.file.write(grunt.config('meta.cssFileDest'), grunt.config('meta.cssFileBanner') + - cssStrings.join('\n')); + function findModule(name) + { + if(foundModules[name]) + { return; } + foundModules[name] = true; - grunt.log.writeln('File ' + grunt.config('meta.cssFileDest') + ' created'); - } + function breakup(text, separator) + { + return text.replace(/[A-Z]/g, function(match) { + return separator + match; + }); + } - var moduleFileMapping = _.clone(modules, true); - moduleFileMapping.forEach((module) => delete module.docs); + function ucwords(text) + { + return text.replace(/^([a-z])|\s+([a-z])/g, function($1) { + return $1.toUpperCase(); + }); + } - grunt.config('moduleFileMapping', moduleFileMapping); + function enquote(str) + { + return `"${str}"`; + } - var srcFiles = _.pluck(modules, 'srcFiles'); - var tpljsFiles = _.pluck(modules, 'tpljsFiles'); - //Set the concat task to concatenate the given src modules - grunt.config('concat.dist.src', grunt.config('concat.dist.src') - .concat(srcFiles)); - //Set the concat-with-templates task to concat the given src & tpl modules - grunt.config('concat.dist_tpls.src', grunt.config('concat.dist_tpls.src') - .concat(srcFiles).concat(tpljsFiles)); + function enquoteUibDir(str) + { + return enquote(`uib/${str}`); + } - grunt.task.run(['concat', 'uglify', 'makeModuleMappingFile', 'makeRawFilesJs', 'makeVersionsMappingFile']); - }); - - grunt.registerTask('test', 'Run tests on singleRun karma server', function() { - //this task can be executed in 3 different environments: local, Travis-CI and Jenkins-CI - //we need to take settings for each one into account - if (process.env.TRAVIS) { - grunt.task.run('karma:travis'); - } else { - var isToRunJenkinsTask = !!this.args.length; - if (grunt.option('coverage')) { - var karmaOptions = grunt.config.get('karma.options'), - coverageOpts = grunt.config.get('karma.coverage'); - grunt.util._.extend(karmaOptions, coverageOpts); - grunt.config.set('karma.options', karmaOptions); - } - grunt.task.run(this.args.length ? 'karma:jenkins' : 'karma:continuous'); - } - }); - - grunt.registerTask('makeModuleMappingFile', function() { - var _ = grunt.util._; - var moduleMappingJs = 'dist/assets/module-mapping.json'; - var moduleMappings = grunt.config('moduleFileMapping'); - var moduleMappingsMap = _.object(_.pluck(moduleMappings, 'name'), moduleMappings); - var jsContent = JSON.stringify(moduleMappingsMap); - grunt.file.write(moduleMappingJs, jsContent); - grunt.log.writeln('File ' + moduleMappingJs.cyan + ' created.'); - }); - - grunt.registerTask('makeRawFilesJs', function() { - var _ = grunt.util._; - var jsFilename = 'dist/assets/raw-files.json'; - var genRawFilesJs = require('./misc/raw-files-generator'); - - genRawFilesJs(grunt, jsFilename, _.flatten(grunt.config('concat.dist_tpls.src')), - grunt.config('meta.banner'), grunt.config('meta.cssFileBanner')); - }); - - grunt.registerTask('makeVersionsMappingFile', function() { - var done = this.async(); - - var exec = require('child_process').exec; - - var versionsMappingFile = 'dist/versions-mapping.json'; - - exec('git tag --sort -version:refname', function(error, stdout, stderr) { - // Let's remove the oldest 14 versions. - var versions = stdout.split('\n').slice(0, -14); - var jsContent = versions.map(function(version) { - version = version.replace(/^v/, ''); - return { - version: version, - url: `/angular-ui-bootstrap4/versioned-docs/${version}` + const module = { + name: name, + moduleName: enquote(`ui.bootstrap.${name}`), + displayName: ucwords(breakup(name, ' ')), + srcFiles: grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`]), + cssFiles: grunt.file.expand(`src/${name}/*.css`), + tplFiles: grunt.file.expand(`template/${name}/*.html`), + tpljsFiles: grunt.file.expand(`template/${name}/*.html.js`), + tplModules: grunt.file.expand(`template/${name}/*.html`).map(enquoteUibDir), + dependencies: dependenciesForModule(name), + docs: { + md: grunt.file.expand(`src/${name}/docs/*.md`) + .map(grunt.file.read).map((str) => marked(str)).join('\n'), + js: grunt.file.expand(`src/${name}/docs/*.js`) + .map(grunt.file.read).join('\n'), + html: grunt.file.expand(`src/${name}/docs/*.html`) + .map(grunt.file.read).join('\n') + } }; - }); - jsContent = _.sortBy(jsContent, 'version').reverse(); - jsContent.unshift({ - version: 'Current', - url: '/angular-ui-bootstrap4' - }); - grunt.file.write(versionsMappingFile, JSON.stringify(jsContent)); - grunt.log.writeln(`File ${versionsMappingFile.cyan} created.`); - done(); - }); - }); + const styles = { + css: [], + js: [] + }; + module.cssFiles.forEach(processCSS.bind(null, module.name, styles, true)); + if(styles.css.length) + { + module.css = styles.css.join('\n'); + module.cssJs = styles.js.join('\n'); + } - /** - * Logic from AngularJS - * https://github.com/angular/angular.js/blob/36831eccd1da37c089f2141a2c073a6db69f3e1d/lib/grunt/utils.js#L121-L145 - */ - function processCSS(moduleName, state, minify, file) { - var css = fs.readFileSync(file).toString(), - js; - state.css.push(css); - - if (minify) { - css = css - .replace(/\r?\n/g, '') - .replace(/\/\*.*?\*\//g, '') - .replace(/:\s+/g, ':') - .replace(/\s*\{\s*/g, '{') - .replace(/\s*\}\s*/g, '}') - .replace(/\s*\,\s*/g, ',') - .replace(/\s*\;\s*/g, ';'); + module.dependencies.forEach(findModule); + grunt.config('modules', grunt.config('modules').concat(module)); } - //escape for js - css = css - .replace(/\\/g, '\\\\') - .replace(/'/g, "\\'") - .replace(/\r?\n/g, '\\n'); - js = `angular.module('ui.bootstrap.${moduleName}').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uib${_.capitalize(moduleName)}Css && angular.element(document).find('head').prepend(''); angular.$$uib${_.capitalize(moduleName)}Css = true; });`; - state.js.push(js); - return state; - } + function dependenciesForModule(name) + { + let deps = []; + grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`]) + .map(grunt.file.read) + .forEach(function(contents) { + //Strategy: find where module is declared, + //and from there get everything inside the [] and split them by comma + const moduleDeclIndex = contents.indexOf('angular.module('); + const depArrayStart = contents.indexOf('[', moduleDeclIndex); + const depArrayEnd = contents.indexOf(']', depArrayStart); + const dependencies = contents.substring(depArrayStart + 1, depArrayEnd); + dependencies.split(',').forEach(function(dep) { + if(dep.indexOf('ui.bootstrap.') > -1) + { + const depName = dep.trim().replace('ui.bootstrap.', '').replace(/['"]/g, ''); + if(deps.indexOf(depName) < 0) + { + deps.push(depName); + //Get dependencies for this new dependency + deps = deps.concat(dependenciesForModule(depName)); + } + } + }); + }); + return deps; + } - function setVersion(type, suffix) { - var file = 'package.json'; - var VERSION_REGEX = /([\'|\"]version[\'|\"][ ]*:[ ]*[\'|\"])([\d|.]*)(-\w+)*([\'|\"])/; - var contents = grunt.file.read(file); - var version; - contents = contents.replace(VERSION_REGEX, function(match, left, center) { - version = center; - if (type) { - version = require('semver').inc(version, type); - } - //semver.inc strips our suffix if it existed - if (suffix) { - version += '-' + suffix; - } - return left + version + '"'; + grunt.registerTask('dist', 'Override dist directory', function() { + const dir = this.args[0]; + if(dir) + { grunt.config('dist', dir); } }); - grunt.log.ok('Version set to ' + version.cyan); - grunt.file.write(file, contents); - return version; - } - grunt.registerTask('version', 'Set version. If no arguments, it just takes off suffix', function() { - setVersion(this.args[0], this.args[1]); - }); + grunt.registerTask('build', 'Create bootstrap build files', function() { + const _ = grunt.util._; - grunt.registerMultiTask('shell', 'run shell commands', function() { - var self = this; - var sh = require('shelljs'); - self.data.forEach(function(cmd) { - cmd = cmd.replace('%version%', grunt.file.readJSON('package.json').version); - grunt.log.ok(cmd); - var result = sh.exec(cmd,{silent:true}); - if (result.code !== 0) { - grunt.fatal(result.output); - } + //If arguments define what modules to build, build those. Else, everything + if(this.args.length) + { + this.args.forEach(findModule); + grunt.config('filename', grunt.config('filenamecustom')); + } + else + { + grunt.file.expand({ + filter: 'isDirectory', cwd: '.' + }, 'src/*').forEach((dir) => { + findModule(dir.split('/')[1]); + }); + } + + const modules = grunt.config('modules'); + grunt.config('srcModules', _.pluck(modules, 'moduleName')); + grunt.config('tplModules', _.pluck(modules, 'tplModules').filter((tpls) => tpls.length > 0)); + grunt.config('demoModules', modules + .filter((module) => module.docs.md && module.docs.js && module.docs.html) + .sort((a, b) => { + if(a.name < b.name) + { return -1; } + if(a.name > b.name) + { return 1; } + return 0; + }) + ); + + const cssStrings = _.flatten(_.compact(_.pluck(modules, 'css'))); + const cssJsStrings = _.flatten(_.compact(_.pluck(modules, 'cssJs'))); + if(cssStrings.length) + { + grunt.config('meta.cssInclude', cssJsStrings.join('\n')); + + grunt.file.write(grunt.config('meta.cssFileDest'), grunt.config('meta.cssFileBanner') + + cssStrings.join('\n')); + + grunt.log.writeln('File ' + grunt.config('meta.cssFileDest') + ' created'); + } + + const moduleFileMapping = _.clone(modules, true); + moduleFileMapping.forEach((module) => delete module.docs); + + grunt.config('moduleFileMapping', moduleFileMapping); + + const srcFiles = _.pluck(modules, 'srcFiles'); + const tpljsFiles = _.pluck(modules, 'tpljsFiles'); + //Set the concat task to concatenate the given src modules + grunt.config('concat.dist.src', grunt.config('concat.dist.src') + .concat(srcFiles)); + //Set the concat-with-templates task to concat the given src & tpl modules + grunt.config('concat.dist_tpls.src', grunt.config('concat.dist_tpls.src') + .concat(srcFiles).concat(tpljsFiles)); + + grunt.task.run(['concat', 'uglify', 'makeModuleMappingFile', 'makeRawFilesJs', 'makeVersionsMappingFile']); }); - }); - return grunt; + grunt.registerTask('test', 'Run tests on singleRun karma server', function() { + //this task can be executed in 3 different environments: local, Travis-CI and Jenkins-CI + //we need to take settings for each one into account + if(process.env.TRAVIS) + { + grunt.task.run('karma:travis'); + } + else + { + const isToRunJenkinsTask = !!this.args.length; + if(grunt.option('coverage')) + { + const karmaOptions = grunt.config.get('karma.options'), + coverageOpts = grunt.config.get('karma.coverage'); + grunt.util._.extend(karmaOptions, coverageOpts); + grunt.config.set('karma.options', karmaOptions); + } + grunt.task.run(this.args.length ? 'karma:jenkins' : 'karma:continuous'); + } + }); + + grunt.registerTask('makeModuleMappingFile', function() { + const _ = grunt.util._; + const moduleMappingJs = 'dist/assets/module-mapping.json'; + const moduleMappings = grunt.config('moduleFileMapping'); + const moduleMappingsMap = _.object(_.pluck(moduleMappings, 'name'), moduleMappings); + const jsContent = JSON.stringify(moduleMappingsMap); + grunt.file.write(moduleMappingJs, jsContent); + grunt.log.writeln('File ' + moduleMappingJs.cyan + ' created.'); + }); + + grunt.registerTask('makeRawFilesJs', function() { + const _ = grunt.util._; + const jsFilename = 'dist/assets/raw-files.json'; + const genRawFilesJs = require('./misc/raw-files-generator'); + + genRawFilesJs(grunt, jsFilename, _.flatten(grunt.config('concat.dist_tpls.src')), + grunt.config('meta.banner'), grunt.config('meta.cssFileBanner') + ); + }); + + grunt.registerTask('makeVersionsMappingFile', function() { + const done = this.async(); + + const exec = require('child_process').exec; + + const versionsMappingFile = 'dist/versions-mapping.json'; + + exec('git tag --sort -version:refname', function(error, stdout, stderr) { + // Let's remove the oldest 14 versions. + const versions = stdout.split('\n').slice(0, -14); + let jsContent = versions.map(function(version) { + version = version.replace(/^v/, ''); + return { + version: version, + url: `/angular-ui-bootstrap4/versioned-docs/${version}` + }; + }); + jsContent = _.sortBy(jsContent, 'version').reverse(); + jsContent.unshift({ + version: 'Current', + url: '/angular-ui-bootstrap4' + }); + grunt.file.write(versionsMappingFile, JSON.stringify(jsContent)); + grunt.log.writeln(`File ${versionsMappingFile.cyan} created.`); + done(); + }); + + }); + + /** + * Logic from AngularJS + * https://github.com/angular/angular.js/blob/36831eccd1da37c089f2141a2c073a6db69f3e1d/lib/grunt/utils.js#L121-L145 + */ + function processCSS(moduleName, state, minify, file) + { + let css = fs.readFileSync(file).toString(), + js; + state.css.push(css); + + if(minify) + { + css = css + .replace(/\r?\n/g, '') + .replace(/\/\*.*?\*\//g, '') + .replace(/:\s+/g, ':') + .replace(/\s*\{\s*/g, '{') + .replace(/\s*\}\s*/g, '}') + .replace(/\s*\,\s*/g, ',') + .replace(/\s*\;\s*/g, ';'); + } + //escape for js + css = css + .replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(/\r?\n/g, '\\n'); + js = `angular.module('ui.bootstrap.${moduleName}').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uib${_.capitalize( + moduleName)}Css && angular.element(document).find('head').prepend(''); angular.$$uib${_.capitalize( + moduleName)}Css = true; });`; + state.js.push(js); + + return state; + } + + function setVersion(type, suffix) + { + const file = 'package.json'; + const VERSION_REGEX = /([\'|\"]version[\'|\"][ ]*:[ ]*[\'|\"])([\d|.]*)(-\w+)*([\'|\"])/; + let contents = grunt.file.read(file); + let version; + contents = contents.replace(VERSION_REGEX, function(match, left, center) { + version = center; + if(type) + { + version = require('semver').inc(version, type); + } + //semver.inc strips our suffix if it existed + if(suffix) + { + version += '-' + suffix; + } + return left + version + '"'; + }); + grunt.log.ok('Version set to ' + version.cyan); + grunt.file.write(file, contents); + return version; + } + + grunt.registerTask('version', 'Set version. If no arguments, it just takes off suffix', function() { + setVersion(this.args[0], this.args[1]); + }); + + grunt.registerMultiTask('shell', 'run shell commands', function() { + const self = this; + const sh = require('shelljs'); + self.data.forEach(function(cmd) { + cmd = cmd.replace('%version%', grunt.file.readJSON('package.json').version); + grunt.log.ok(cmd); + const result = sh.exec(cmd, { silent: true }); + if(result.code !== 0) + { + grunt.fatal(result.output); + } + }); + }); + + //------------------------------------------------------------------------------------------------------------------ + // New Release System + //------------------------------------------------------------------------------------------------------------------ + + grunt.registerTask('release', function(version) { + // Step 1, we change package.json + const pkg = grunt.config('pkg'); + pkg.version = version; + grunt.file.write('./package.json', JSON.stringify(pkg, null, 2)); + + // Step 2, we queue up additional tasks + grunt.task.run([ + 'conventionalChangelog', + 'build', + 'shell:release-prepare', + 'shell:release-complete', + 'shell:publish' + ]) + }); + + //------------------------------------------------------------------------------------------------------------------ + + return grunt; }; diff --git a/docs/ui-bootstrap-3.0.0-beta.4.js b/docs/ui-bootstrap-3.0.0-beta.4.js index 8ecd51d..3325a8f 100644 --- a/docs/ui-bootstrap-3.0.0-beta.4.js +++ b/docs/ui-bootstrap-3.0.0-beta.4.js @@ -2,7 +2,7 @@ * ui-bootstrap4 * http://morgul.github.io/ui-bootstrap4/ - * Version: 3.0.0-beta.4 - 2017-12-09 + * Version: 3.0.0-beta.4 - 2017-12-11 * License: MIT */angular.module("ui.bootstrap", ["ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.multiMap","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]); angular.module('ui.bootstrap.collapse', []) @@ -2736,8 +2736,6 @@ angular.module('ui.bootstrap.position', []) arrowCss[placement[1]] = borderRadius; - console.log('calc CSS:', arrowCss); - angular.element(arrowElem).css(arrowCss); } }; diff --git a/docs/ui-bootstrap-3.0.0-beta.4.min.js b/docs/ui-bootstrap-3.0.0-beta.4.min.js index 9037955..01dee33 100644 --- a/docs/ui-bootstrap-3.0.0-beta.4.min.js +++ b/docs/ui-bootstrap-3.0.0-beta.4.min.js @@ -2,9 +2,9 @@ * ui-bootstrap4 * http://morgul.github.io/ui-bootstrap4/ - * Version: 3.0.0-beta.4 - 2017-12-09 + * Version: 3.0.0-beta.4 - 2017-12-11 * License: MIT */angular.module("ui.bootstrap",["ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.multiMap","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$q","$parse","$injector",function(a,b,c,d){var e=d.has("$animateCss")?d.get("$animateCss"):null;return{link:function(d,f,g){function h(){r=!!("horizontal"in g),r?(s={width:""},t={width:"0"}):(s={height:""},t={height:"0"}),d.$eval(g.uibCollapse)||f.addClass("show").addClass("collapse").attr("aria-expanded",!0).attr("aria-hidden",!1).css(s)}function i(a){return r?{width:a.scrollWidth+"px"}:{height:a.scrollHeight+"px"}}function j(){f.hasClass("collapse")&&f.hasClass("show")||b.resolve(n(d)).then(function(){f.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),e?e(f,{addClass:"show",easing:"ease",css:{overflow:"hidden"},to:i(f[0])}).start()["finally"](k):a.addClass(f,"show",{css:{overflow:"hidden"},to:i(f[0])}).then(k)},angular.noop)}function k(){f.removeClass("collapsing").addClass("collapse").css(s),o(d)}function l(){return f.hasClass("collapse")||f.hasClass("show")?void b.resolve(p(d)).then(function(){f.css(i(f[0])).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),e?e(f,{removeClass:"show",to:t}).start()["finally"](m):a.removeClass(f,"show",{to:t}).then(m)},angular.noop):m()}function m(){f.css(t),f.removeClass("collapsing").addClass("collapse"),q(d)}var n=c(g.expanding),o=c(g.expanded),p=c(g.collapsing),q=c(g.collapsed),r=!1,s={},t={};h(),d.$watch(g.uibCollapse,function(a){a?l():j()})}}}]),angular.module("ui.bootstrap.tabindex",[]).directive("uibTabindexToggle",function(){return{restrict:"A",link:function(a,b,c){c.$observe("disabled",function(a){c.$set("tabindex",a?-1:null)})}}}),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse","ui.bootstrap.tabindex"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(c){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);b!==-1&&this.groups.splice(b,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion-group.html"},scope:{heading:"@",cardClass:"@?",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){b.addClass("card"),d.addGroup(a),a.openClass=c.openClass||"card-open",a.cardClass=c.cardClass||"card-default",a.$watch("isOpen",function(c){b.toggleClass(a.openClass,!!c),c&&d.closeOthers(a)}),a.toggleOpen=function(b){a.isDisabled||b&&32!==b.which||(a.isOpen=!a.isOpen)};var e="accordiongroup-"+a.$id+"-"+Math.floor(1e4*Math.random());a.headingId=e+"-tab",a.cardId=e+"-card"}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("uibAccordionTransclude",function(){function a(){return"uib-accordion-header,data-uib-accordion-header,x-uib-accordion-header,uib\\:accordion-header,[uib-accordion-header],[data-uib-accordion-header],[x-uib-accordion-header]"}return{require:"^uibAccordionGroup",link:function(b,c,d,e){b.$watch(function(){return e[d.uibAccordionTransclude]},function(b){if(b){var d=angular.element(c[0].querySelector(a()));d.html(""),d.append(b)}})}}}),angular.module("ui.bootstrap.alert",[]).controller("UibAlertController",["$scope","$element","$attrs","$interpolate","$timeout",function(a,b,c,d,e){a.closeable=!!c.close,b.addClass("alert"),c.$set("role","alert"),a.closeable&&b.addClass("alert-dismissible");var f=angular.isDefined(c.dismissOnTimeout)?d(c.dismissOnTimeout)(a.$parent):null;f&&e(function(){a.close()},parseInt(f,10))}]).directive("uibAlert",function(){return{controller:"UibAlertController",controllerAs:"alert",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/alert/alert.html"},transclude:!0,scope:{close:"&"}}}),angular.module("ui.bootstrap.buttons",[]).constant("uibButtonConfig",{activeClass:"active",toggleEvent:"click"}).controller("UibButtonsController",["uibButtonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("uibBtnRadio",["$parse",function(a){return{require:["uibBtnRadio","ngModel"],controller:"UibButtonsController",controllerAs:"buttons",link:function(b,c,d,e){var f=e[0],g=e[1],h=a(d.uibUncheckable);c.find("input").css({display:"none"}),g.$render=function(){c.toggleClass(f.activeClass,angular.equals(g.$modelValue,b.$eval(d.uibBtnRadio)))},c.on(f.toggleEvent,function(){if(!d.disabled){var a=c.hasClass(f.activeClass);a&&!angular.isDefined(d.uncheckable)||b.$apply(function(){g.$setViewValue(a?null:b.$eval(d.uibBtnRadio)),g.$render()})}}),d.uibUncheckable&&b.$watch(h,function(a){d.$set("uncheckable",a?"":void 0)})}}}]).directive("uibBtnCheckbox",function(){return{require:["uibBtnCheckbox","ngModel"],controller:"UibButtonsController",controllerAs:"button",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){return angular.isDefined(b)?a.$eval(b):c}var h=d[0],i=d[1];b.find("input").css({display:"none"}),i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.on(h.toggleEvent,function(){c.disabled||a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("UibCarouselController",["$scope","$element","$interval","$timeout","$animate",function(a,b,c,d,e){function f(a){for(var b=0;b
o.modes.indexOf(o[b]))&&(a.datepickerMode=o[b],a.datepickerOptions.datepickerMode=o[b])}):o[b]=a[b]=i[b]||null}}),a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),a.disabled=angular.isDefined(c.disabled)||!1,angular.isDefined(c.ngDisabled)&&r.push(a.$parent.$watch(c.ngDisabled,function(b){a.disabled=b,o.refreshView()})),a.isActive=function(b){return 0===o.compare(b.date,o.activeDate)&&(a.activeDateId=b.uid,!0)},this.init=function(b){p=b,q=n(p),a.datepickerOptions.initDate?(o.activeDate=l.fromTimezone(a.datepickerOptions.initDate,q.getOption("timezone"))||new Date,a.$watch("datepickerOptions.initDate",function(a){a&&(p.$isEmpty(p.$modelValue)||p.$invalid)&&(o.activeDate=l.fromTimezone(a,q.getOption("timezone")),o.refreshView())})):o.activeDate=new Date;var c=p.$modelValue?new Date(p.$modelValue):new Date;this.activeDate=isNaN(c)?l.fromTimezone(new Date,q.getOption("timezone")):l.fromTimezone(c,q.getOption("timezone")),p.$render=function(){o.render()}},this.render=function(){if(p.$viewValue){var a=new Date(p.$viewValue),b=!isNaN(a);b?this.activeDate=l.fromTimezone(a,q.getOption("timezone")):k||g.error('Datepicker directive: "ng-model" value must be a Date object')}this.refreshView()},this.refreshView=function(){if(this.element){a.selectedDt=null,this._refreshView(),a.activeDt&&(a.activeDateId=a.activeDt.uid);var b=p.$viewValue?new Date(p.$viewValue):null;b=l.fromTimezone(b,q.getOption("timezone")),p.$setValidity("dateDisabled",!b||this.element&&!this.isDisabled(b))}},this.createDateObject=function(b,c){var d=p.$viewValue?new Date(p.$viewValue):null;d=l.fromTimezone(d,q.getOption("timezone"));var e=new Date;e=l.fromTimezone(e,q.getOption("timezone"));var f=this.compare(b,e),g={date:b,label:l.filter(b,c),selected:d&&0===this.compare(b,d),disabled:this.isDisabled(b),past:f<0,current:0===f,future:f>0,customClass:this.customClass(b)||null};return d&&0===this.compare(b,d)&&(a.selectedDt=g),o.activeDate&&0===this.compare(g.date,o.activeDate)&&(a.activeDt=g),g},this.isDisabled=function(b){return a.disabled||this.minDate&&this.compare(b,this.minDate)<0||this.maxDate&&this.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===o.minMode){var c=p.$viewValue?l.fromTimezone(new Date(p.$viewValue),q.getOption("timezone")):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),c=l.toTimezone(c,q.getOption("timezone")),p.$setViewValue(c),p.$render()}else o.activeDate=b,m(o.modes[o.modes.indexOf(a.datepickerMode)-1]),a.$emit("uib:datepicker.mode");a.$broadcast("uib:datepicker.focus")},a.move=function(a){var b=o.activeDate.getFullYear()+a*(o.step.years||0),c=o.activeDate.getMonth()+a*(o.step.months||0);o.activeDate.setFullYear(b,c,1),o.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===o.maxMode&&1===b||a.datepickerMode===o.minMode&&b===-1||(m(o.modes[o.modes.indexOf(a.datepickerMode)+b]),a.$emit("uib:datepicker.mode"))},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var s=function(){o.element[0].focus()};a.$on("uib:datepicker.focus",s),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey&&!a.disabled)if(b.preventDefault(),o.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(o.isDisabled(o.activeDate))return;a.select(o.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(o.handleKeyDown(c,b),o.refreshView()):a.toggleMode("up"===c?1:-1)},b.on("keydown",function(b){a.$apply(function(){a.keydown(b)})}),a.$on("$destroy",function(){for(;r.length;)r.shift()()})}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;f0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;k<42;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;l<7;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;o o.modes.indexOf(o[b]))&&(a.datepickerMode=o[b],a.datepickerOptions.datepickerMode=o[b])}):o[b]=a[b]=i[b]||null}}),a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),a.disabled=angular.isDefined(c.disabled)||!1,angular.isDefined(c.ngDisabled)&&r.push(a.$parent.$watch(c.ngDisabled,function(b){a.disabled=b,o.refreshView()})),a.isActive=function(b){return 0===o.compare(b.date,o.activeDate)&&(a.activeDateId=b.uid,!0)},this.init=function(b){p=b,q=n(p),a.datepickerOptions.initDate?(o.activeDate=l.fromTimezone(a.datepickerOptions.initDate,q.getOption("timezone"))||new Date,a.$watch("datepickerOptions.initDate",function(a){a&&(p.$isEmpty(p.$modelValue)||p.$invalid)&&(o.activeDate=l.fromTimezone(a,q.getOption("timezone")),o.refreshView())})):o.activeDate=new Date;var c=p.$modelValue?new Date(p.$modelValue):new Date;this.activeDate=isNaN(c)?l.fromTimezone(new Date,q.getOption("timezone")):l.fromTimezone(c,q.getOption("timezone")),p.$render=function(){o.render()}},this.render=function(){if(p.$viewValue){var a=new Date(p.$viewValue),b=!isNaN(a);b?this.activeDate=l.fromTimezone(a,q.getOption("timezone")):k||g.error('Datepicker directive: "ng-model" value must be a Date object')}this.refreshView()},this.refreshView=function(){if(this.element){a.selectedDt=null,this._refreshView(),a.activeDt&&(a.activeDateId=a.activeDt.uid);var b=p.$viewValue?new Date(p.$viewValue):null;b=l.fromTimezone(b,q.getOption("timezone")),p.$setValidity("dateDisabled",!b||this.element&&!this.isDisabled(b))}},this.createDateObject=function(b,c){var d=p.$viewValue?new Date(p.$viewValue):null;d=l.fromTimezone(d,q.getOption("timezone"));var e=new Date;e=l.fromTimezone(e,q.getOption("timezone"));var f=this.compare(b,e),g={date:b,label:l.filter(b,c),selected:d&&0===this.compare(b,d),disabled:this.isDisabled(b),past:f<0,current:0===f,future:f>0,customClass:this.customClass(b)||null};return d&&0===this.compare(b,d)&&(a.selectedDt=g),o.activeDate&&0===this.compare(g.date,o.activeDate)&&(a.activeDt=g),g},this.isDisabled=function(b){return a.disabled||this.minDate&&this.compare(b,this.minDate)<0||this.maxDate&&this.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===o.minMode){var c=p.$viewValue?l.fromTimezone(new Date(p.$viewValue),q.getOption("timezone")):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),c=l.toTimezone(c,q.getOption("timezone")),p.$setViewValue(c),p.$render()}else o.activeDate=b,m(o.modes[o.modes.indexOf(a.datepickerMode)-1]),a.$emit("uib:datepicker.mode");a.$broadcast("uib:datepicker.focus")},a.move=function(a){var b=o.activeDate.getFullYear()+a*(o.step.years||0),c=o.activeDate.getMonth()+a*(o.step.months||0);o.activeDate.setFullYear(b,c,1),o.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===o.maxMode&&1===b||a.datepickerMode===o.minMode&&b===-1||(m(o.modes[o.modes.indexOf(a.datepickerMode)+b]),a.$emit("uib:datepicker.mode"))},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var s=function(){o.element[0].focus()};a.$on("uib:datepicker.focus",s),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey&&!a.disabled)if(b.preventDefault(),o.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(o.isDisabled(o.activeDate))return;a.select(o.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(o.handleKeyDown(c,b),o.refreshView()):a.toggleMode("up"===c?1:-1)},b.on("keydown",function(b){a.$apply(function(){a.keydown(b)})}),a.$on("$destroy",function(){for(;r.length;)r.shift()()})}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;f0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;k<42;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;l<7;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;o\n {{heading}}\n
\n\n
\n')}]),angular.module("uib/template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("uib/template/carousel/slide.html",'\n')}]),angular.module("uib/template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/datepicker.html",'\n \n
\n')}]),angular.module("uib/template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n {{::label.abbr}} \n \n \n \n{{ weekNumbers[$index] }} \n \n \n \n \n \n
\n')}]),angular.module("uib/template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n')}]),angular.module("uib/template/datepickerPopup/popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepickerPopup/popup.html",'\n')}]),angular.module("uib/template/modal/window.html",[]).run(["$templateCache",function(a){a.put("uib/template/modal/window.html","\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n')}]),angular.module("uib/template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-match.html",'\n')}]),angular.module("uib/template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-popup.html",'\n')}]),angular.module("ui.bootstrap.carousel").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibCarouselCss&&angular.element(document).find("head").prepend(''),angular.$$uibCarouselCss=!0}),angular.module("ui.bootstrap.datepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerCss&&angular.element(document).find("head").prepend(''),angular.$$uibDatepickerCss=!0}),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend(''),angular.$$uibPositionCss=!0}),angular.module("ui.bootstrap.datepickerPopup").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerpopupCss&&angular.element(document).find("head").prepend(''),angular.$$uibDatepickerpopupCss=!0}),angular.module("ui.bootstrap.tooltip").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTooltipCss&&angular.element(document).find("head").prepend(''),
+},require:["^uibDatepicker","uibDaypicker"],restrict:"A",controller:"UibDaypickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibMonthpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/month.html"},require:["^uibDatepicker","uibMonthpicker"],restrict:"A",controller:"UibMonthpickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibYearpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/year.html"},require:["^uibDatepicker","uibYearpicker"],restrict:"A",controller:"UibYearpickerController",link:function(a,b,c,d){var e=d[0];angular.extend(e,d[1]),e.yearpickerInit(),e.refreshView()}}}),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(a,b){var c,d,e={normal:/(auto|scroll)/,hidden:/(auto|scroll|hidden)/},f={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/},g=/(HTML|BODY)/;return{getRawNode:function(a){return a.nodeName?a:a[0]||a},parseStyle:function(a){return a=parseFloat(a),isFinite(a)?a:0},offsetParent:function(c){function d(a){return"static"===(b.getComputedStyle(a).position||"static")}c=this.getRawNode(c);for(var e=c.offsetParent||a[0].documentElement;e&&e!==a[0].documentElement&&d(e);)e=e.offsetParent;return e||a[0].documentElement},scrollbarWidth:function(e){if(e){if(angular.isUndefined(d)){var f=a.find("body");f.addClass("uib-position-body-scrollbar-measure"),d=b.innerWidth-f[0].clientWidth,d=isFinite(d)?d:0,f.removeClass("uib-position-body-scrollbar-measure")}return d}if(angular.isUndefined(c)){var g=angular.element('');a.find("body").append(g),c=g[0].offsetWidth-g[0].clientWidth,c=isFinite(c)?c:0,g.remove()}return c},scrollbarPadding:function(a){a=this.getRawNode(a);var c=b.getComputedStyle(a),d=this.parseStyle(c.paddingRight),e=this.parseStyle(c.paddingBottom),f=this.scrollParent(a,!1,!0),h=this.scrollbarWidth(g.test(f.tagName));return{scrollbarWidth:h,widthOverflow:f.scrollWidth>f.clientWidth,right:d+h,originalRight:d,heightOverflow:f.scrollHeight>f.clientHeight,bottom:e+h,originalBottom:e}},isScrollable:function(a,c){a=this.getRawNode(a);var d=c?e.hidden:e.normal,f=b.getComputedStyle(a);return d.test(f.overflow+f.overflowY+f.overflowX)},scrollParent:function(c,d,f){c=this.getRawNode(c);var g=d?e.hidden:e.normal,h=a[0].documentElement,i=b.getComputedStyle(c);if(f&&g.test(i.overflow+i.overflowY+i.overflowX))return c;var j="absolute"===i.position,k=c.parentElement||h;if(k===h||"fixed"===i.position)return h;for(;k.parentElement&&k!==h;){var l=b.getComputedStyle(k);if(j&&"static"!==l.position&&(j=!1),!j&&g.test(l.overflow+l.overflowY+l.overflowX))break;k=k.parentElement}return k},position:function(c,d){c=this.getRawNode(c);var e=this.offset(c);if(d){var f=b.getComputedStyle(c);e.top-=this.parseStyle(f.marginTop),e.left-=this.parseStyle(f.marginLeft)}var g=this.offsetParent(c),h={top:0,left:0};return g!==a[0].documentElement&&(h=this.offset(g),h.top+=g.clientTop-g.scrollTop,h.left+=g.clientLeft-g.scrollLeft),{width:Math.round(angular.isNumber(e.width)?e.width:c.offsetWidth),height:Math.round(angular.isNumber(e.height)?e.height:c.offsetHeight),top:Math.round(e.top-h.top),left:Math.round(e.left-h.left)}},offset:function(c){c=this.getRawNode(c);var d=c.getBoundingClientRect();return{width:Math.round(angular.isNumber(d.width)?d.width:c.offsetWidth),height:Math.round(angular.isNumber(d.height)?d.height:c.offsetHeight),top:Math.round(d.top+(b.pageYOffset||a[0].documentElement.scrollTop)),left:Math.round(d.left+(b.pageXOffset||a[0].documentElement.scrollLeft))}},viewportOffset:function(c,d,e){c=this.getRawNode(c),e=e!==!1;var f=c.getBoundingClientRect(),g={top:0,left:0,bottom:0,right:0},h=d?a[0].documentElement:this.scrollParent(c),i=h.getBoundingClientRect();if(g.top=i.top+h.clientTop,g.left=i.left+h.clientLeft,h===a[0].documentElement&&(g.top+=b.pageYOffset,g.left+=b.pageXOffset),g.bottom=g.top+h.clientHeight,g.right=g.left+h.clientWidth,e){var j=b.getComputedStyle(h);g.top+=this.parseStyle(j.paddingTop),g.bottom-=this.parseStyle(j.paddingBottom),g.left+=this.parseStyle(j.paddingLeft),g.right-=this.parseStyle(j.paddingRight)}return{top:Math.round(f.top-g.top),bottom:Math.round(g.bottom-f.bottom),left:Math.round(f.left-g.left),right:Math.round(g.right-f.right)}},parsePlacement:function(a){var b=f.auto.test(a);return b&&(a=a.replace(f.auto,"")),a=a.split("-"),a[0]=a[0]||"top",f.primary.test(a[0])||(a[0]="top"),a[1]=a[1]||"center",f.secondary.test(a[1])||(a[1]="center"),b?a[2]=!0:a[2]=!1,a},positionElements:function(a,c,d,e){a=this.getRawNode(a),c=this.getRawNode(c);var g=angular.isDefined(c.offsetWidth)?c.offsetWidth:c.prop("offsetWidth"),h=angular.isDefined(c.offsetHeight)?c.offsetHeight:c.prop("offsetHeight");d=this.parsePlacement(d);var i=e?this.offset(a):this.position(a),j={top:0,left:0,placement:""};if(d[2]){var k=this.viewportOffset(a,e),l=b.getComputedStyle(c),m={width:g+Math.round(Math.abs(this.parseStyle(l.marginLeft)+this.parseStyle(l.marginRight))),height:h+Math.round(Math.abs(this.parseStyle(l.marginTop)+this.parseStyle(l.marginBottom)))};if(d[0]="top"===d[0]&&m.height>k.top&&m.height<=k.bottom?"bottom":"bottom"===d[0]&&m.height>k.bottom&&m.height<=k.top?"top":"left"===d[0]&&m.width>k.left&&m.width<=k.right?"right":"right"===d[0]&&m.width>k.right&&m.width<=k.left?"left":d[0],d[1]="top"===d[1]&&m.height-i.height>k.bottom&&m.height-i.height<=k.top?"bottom":"bottom"===d[1]&&m.height-i.height>k.top&&m.height-i.height<=k.bottom?"top":"left"===d[1]&&m.width-i.width>k.right&&m.width-i.width<=k.left?"right":"right"===d[1]&&m.width-i.width>k.left&&m.width-i.width<=k.right?"left":d[1],"center"===d[1])if(f.vertical.test(d[0])){var n=i.width/2-g/2;k.left+n<0&&m.width-i.width<=k.right?d[1]="left":k.right+n<0&&m.width-i.width<=k.left&&(d[1]="right")}else{var o=i.height/2-m.height/2;k.top+o<0&&m.height-i.height<=k.bottom?d[1]="top":k.bottom+o<0&&m.height-i.height<=k.top&&(d[1]="bottom")}}switch(d[0]){case"top":j.top=i.top-h;break;case"bottom":j.top=i.top+i.height;break;case"left":j.left=i.left-g;break;case"right":j.left=i.left+i.width}switch(d[1]){case"top":j.top=i.top;break;case"bottom":j.top=i.top+i.height-h;break;case"left":j.left=i.left;break;case"right":j.left=i.left+i.width-g;break;case"center":f.vertical.test(d[0])?j.left=i.left+i.width/2-g/2:j.top=i.top+i.height/2-h/2}return j.top=Math.round(j.top),j.left=Math.round(j.left),j.placement="center"===d[1]?d[0]:d[0]+"-"+d[1],j},adjustTop:function(a,b,c,d){if(a.indexOf("top")!==-1&&c!==d)return{top:b.top-d+"px"}},positionArrow:function(a,c){a=this.getRawNode(a);var d=!0,e=a.querySelector(".tooltip-inner");if(!e){if(!angular.element(a).hasClass("popover"))return;d=!1}var g=a.querySelector(".arrow");if(g){var h={top:"",bottom:"",left:"",right:""};if(c=this.parsePlacement(c),"center"===c[1]){var i=this.offset(g);if(f.vertical.test(c[0])){var j=i.width/2,k=this.offset(a).width/2,l=k-j;h.left=""+l+"px"}else{var m=i.height/2,n=this.offset(a).height/2,o=n-m;h.top=""+o+"px"}}var p="border-"+c[0]+"-width",q=b.getComputedStyle(g)[p],r="border-";r+=f.vertical.test(c[0])?c[0]+"-"+c[1]:c[1]+"-"+c[0],r+="-radius";var s=b.getComputedStyle(d?e:a)[r];switch(c[0]){case"top":h.bottom=d?"0":"-"+q;break;case"bottom":h.top=d?"0":"-"+q;break;case"left":h.right=d?"0":"-"+q;break;case"right":h.left=d?"0":"-"+q}h[c[1]]=s,angular.element(g).css(h)}}}}]),angular.module("ui.bootstrap.datepickerPopup",["ui.bootstrap.datepicker","ui.bootstrap.position"]).value("$datepickerPopupLiteralWarning",!0).constant("uibDatepickerPopupConfig",{altInputFormats:[],appendToBody:!1,clearText:"Clear",closeOnDateSelection:!0,closeText:"Done",currentText:"Today",datepickerPopup:"yyyy-MM-dd",datepickerPopupTemplateUrl:"uib/template/datepickerPopup/popup.html",datepickerTemplateUrl:"uib/template/datepicker/datepicker.html",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},onOpenFocus:!0,showButtonBar:!0,placement:"auto bottom-left"}).controller("UibDatepickerPopupController",["$scope","$element","$attrs","$compile","$log","$parse","$window","$document","$rootScope","$uibPosition","dateFilter","uibDateParser","uibDatepickerPopupConfig","$timeout","uibDatepickerConfig","$datepickerPopupLiteralWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){function q(b){var c=l.parse(b,x,a.date);if(isNaN(c))for(var d=0;d\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n : \n \n \n \n : \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {{heading}}\n
\n\n
\n')}]),angular.module("uib/template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("uib/template/carousel/slide.html",'\n')}]),angular.module("uib/template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/datepicker.html",'\n \n
\n')}]),angular.module("uib/template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n {{::label.abbr}} \n \n \n \n{{ weekNumbers[$index] }} \n \n \n \n \n \n
\n')}]),angular.module("uib/template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n')}]),angular.module("uib/template/datepickerPopup/popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepickerPopup/popup.html",'\n')}]),angular.module("uib/template/modal/window.html",[]).run(["$templateCache",function(a){a.put("uib/template/modal/window.html","\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n')}]),angular.module("uib/template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-match.html",'\n')}]),angular.module("uib/template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-popup.html",'\n')}]),angular.module("ui.bootstrap.carousel").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibCarouselCss&&angular.element(document).find("head").prepend(''),angular.$$uibCarouselCss=!0}),angular.module("ui.bootstrap.datepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerCss&&angular.element(document).find("head").prepend(''),angular.$$uibDatepickerCss=!0}),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend(''),angular.$$uibPositionCss=!0}),angular.module("ui.bootstrap.datepickerPopup").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerpopupCss&&angular.element(document).find("head").prepend(''),angular.$$uibDatepickerpopupCss=!0}),angular.module("ui.bootstrap.tooltip").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTooltipCss&&angular.element(document).find("head").prepend(''),
angular.$$uibTooltipCss=!0}),angular.module("ui.bootstrap.timepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTimepickerCss&&angular.element(document).find("head").prepend(''),angular.$$uibTimepickerCss=!0}),angular.module("ui.bootstrap.typeahead").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTypeaheadCss&&angular.element(document).find("head").prepend(''),angular.$$uibTypeaheadCss=!0});
\ No newline at end of file
diff --git a/package.json b/package.json
index fc1f77b..dac7e3a 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"author": "https://github.com/morgul/ui-bootstrap4/graphs/contributors",
"name": "ui-bootstrap4",
- "version": "3.0.0-beta.4",
+ "version": "3.0.0",
"description": "Native AngularJS (Angular) directives for Bootstrap",
"homepage": "http://morgul.github.io/ui-bootstrap4/",
"keywords": [
@@ -59,4 +59,4 @@
"shelljs": "^0.6.0"
},
"license": "MIT"
-}
+}
\ No newline at end of file
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n : \n \n \n \n : \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n