foundation-apps
Advanced tools
Comparing version 1.0.2 to 1.0.3
{ | ||
"name": "foundation-apps", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"main": [ | ||
"scss/foundation.scss", | ||
"js/angular/app.js" | ||
"dist/css/foundation-apps.css", | ||
"dist/js/foundation-apps.js" | ||
], | ||
@@ -13,5 +13,4 @@ "dependencies": { | ||
"angular": "~1.3.4", | ||
"ui-router": "~0.2.12", | ||
"angular-ui-router": "~0.2.12", | ||
"angular-animate": "~1.3.4", | ||
"angular-touch": "~1.3.7", | ||
"hammerjs": "~2.0.4" | ||
@@ -18,0 +17,0 @@ }, |
@@ -0,1 +1,57 @@ | ||
# Version 1.0.3 | ||
*February 16, 2015* | ||
### General | ||
- The Bower and npm packages now include a `dist` folder, which contains compiled CSS and JavaScript files, in minified and unminified flavors. | ||
- The Sass is now fully compatible with libsass. It's been tested in node-sass 1.2.3. Eventually our documentation and template stack will be compiled with node-sass instead of Ruby Sass, but we'll continue to test both. | ||
### Breaking Changes | ||
These Sass variables changed. If you're updating an existing project, you'll need to update your `_settings.scss` file manually. | ||
- **Added:** `$badge-diameter: 1.5rem` | ||
- **Renamed:** `$badge-font-color` is now `$badge-color` | ||
- **Removed:** `$badge-padding` | ||
- **Removed:** `$badge-radius` | ||
The old variables are still in the codebase but aren't being used. They'll be permanently removed in version 1.1. | ||
### Template Changes | ||
The Gulpfile used in the [template stack](https://github.com/zurb/foundation-apps-template) now uses the `gulp-load-plugins` library to streamline use of plugins. **If you have an existing project, you don't need to change anything to upgrade.** | ||
### New Features | ||
- **Stacking notifications.** (#388) Dynamically-called notifications will now stack when you call more than one. | ||
- **Responsive Iconic icons.** (#408) Iconic icons are now fluid by default, which means they will adjust their geometry based on the width of the parent container. | ||
- **Staggered animations.** (#394) When using our motion classes in conjunction with the `ng-repeat`, you can now add a stagger class to make items animate in sequence. Add the class `.stagger`, `.short-stagger`, or `.long-stagger` to an element to enable the stagger effect. | ||
- #376: Added `.info` and `.dark` coloring classes to buttons. | ||
- #436: The items in a menu bar can be aligned with `.align-right`, `.align-center`, `.align-justify`, or `.align-spaced`. These classes mimic the behavior of the grid alignment classes. | ||
- Notifications can now be assigned a timeout by adding the `autoclose` attribute. The value of `autoclose` is the number of milliseconds to wait before closing. | ||
- The speed of all animations has been increased slightly. The default felt just a *little* too slow. | ||
### Bug Fixes | ||
**CSS:** | ||
- #194: Fixed modals not scrolling when they overflow their parent. | ||
- #412: `<button>` and `<input>` elements can be used as prefix/postfix elements in forms now, in addition to `<a>`. | ||
- #417: Added padding to `<select>` elements to prevent the text from overlapping with the arrow. | ||
- #435: Fixed a misnamed parameter in the `grid-block()` mixin. | ||
- #438: Fixed display issues with `<select>` elements in Firefox. | ||
- #453: Fixed block list checkboxes being misaligned. | ||
- Fixed the `.dialog` class and sizing classes of modals not working. | ||
- The CSS for badges was refactored so they're sized with width and height instead of padding. | ||
- The pointer cursor is now used when hovering over any anchor (`<a>`) or any element with the `ui-sref` attribute. | ||
**JavaScript:** | ||
- #363: Fixed `zf-close` not working when placed outside of a component. | ||
- #420: Fixed panel/block animations triggering even though the element is in block mode. | ||
- #427: Fixed the `pin-at` directive not passing its value to Tether. | ||
- #448: Fixed invalid `$scope.params` property on the DefaultController controller. | ||
- If a component is closed or opened while a transition is in progress, the transition will reverse. | ||
# Version 1.0.2 | ||
@@ -2,0 +58,0 @@ |
@@ -7,2 +7,3 @@ (function() { | ||
'ngAnimate', | ||
'ngSVGAttributes', | ||
@@ -24,13 +25,20 @@ //foundation | ||
$locationProvider.html5Mode({ | ||
enabled:false, | ||
enabled:true, | ||
requireBase: false | ||
}); | ||
$locationProvider.hashPrefix('!'); | ||
} | ||
run.$inject = ['$rootScope', '$location', '$compile']; | ||
function run() { | ||
function run($rootScope, $location, $compile) { | ||
FastClick.attach(document.body); | ||
if ($location.$$html5) { | ||
$rootScope.$on('$zfIconicInjected', function(event, injectedElem) { | ||
var angElem = angular.element(injectedElem); | ||
$compile(angElem.contents())(angElem.scope()); | ||
}); | ||
} | ||
} | ||
})(); |
@@ -10,3 +10,2 @@ (function() { | ||
zfAccordionController.$inject = ['$scope']; | ||
@@ -13,0 +12,0 @@ |
@@ -9,4 +9,26 @@ (function() { | ||
.directive('zfAsButton', zfAsButton) | ||
.service('FoundationActionSheet', FoundationActionSheet) | ||
; | ||
FoundationActionSheet.$inject = ['FoundationApi']; | ||
function FoundationActionSheet(foundationApi) { | ||
var service = {}; | ||
service.activate = activate; | ||
service.deactivate = deactivate; | ||
return service; | ||
//target should be element ID | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
//target should be element ID | ||
function deactivate(target) { | ||
foundationApi.publish(target, 'hide'); | ||
} | ||
} | ||
zfActionSheetController.$inject = ['$scope', 'FoundationApi']; | ||
@@ -18,2 +40,3 @@ | ||
var container = controller.container = $scope.container; | ||
var body = angular.element(document.body); | ||
@@ -30,11 +53,31 @@ controller.registerContent = function(scope) { | ||
controller.toggle = function() { | ||
content.toggle(); | ||
container.toggle(); | ||
controller.toggle = toggle; | ||
controller.hide = hide; | ||
content.$apply(); | ||
container.$apply(); | ||
controller.registerListener = function() { | ||
document.body.addEventListener('click', listenerLogic); | ||
}; | ||
controller.hide = function() { | ||
controller.deregisterListener = function() { | ||
document.body.removeEventListener('click', listenerLogic); | ||
} | ||
function listenerLogic(e) { | ||
var el = e.target; | ||
var insideActionSheet = false; | ||
do { | ||
if(el.classList && el.classList.contains('action-sheet-container')) { | ||
insideActionSheet = true; | ||
break; | ||
} | ||
} while ((el = el.parentNode)); | ||
if(!insideActionSheet) { | ||
hide(); | ||
} | ||
} | ||
function hide() { | ||
content.hide(); | ||
@@ -45,3 +88,11 @@ container.hide(); | ||
container.$apply(); | ||
}; | ||
} | ||
function toggle() { | ||
content.toggle(); | ||
container.toggle(); | ||
content.$apply(); | ||
container.$apply(); | ||
} | ||
} | ||
@@ -130,2 +181,9 @@ | ||
scope.active = !scope.active; | ||
if(scope.active) { | ||
controller.registerListener(); | ||
} else { | ||
controller.deregisterListener(); | ||
} | ||
return; | ||
@@ -136,2 +194,3 @@ }; | ||
scope.active = false; | ||
controller.deregisterListener(); | ||
return; | ||
@@ -138,0 +197,0 @@ }; |
@@ -24,19 +24,25 @@ (function() { | ||
function link(scope, element, attrs) { | ||
var parentElement= false; | ||
var tempElement = element.parent(); | ||
//find parent modal | ||
while(parentElement === false) { | ||
if(tempElement[0].nodeName == 'BODY') { | ||
parentElement = ''; | ||
} | ||
var targetId = ''; | ||
if (attrs.zfClose) { | ||
targetId = attrs.zfClose; | ||
} else { | ||
var parentElement= false; | ||
var tempElement = element.parent(); | ||
//find parent modal | ||
while(parentElement === false) { | ||
if(tempElement[0].nodeName == 'BODY') { | ||
parentElement = ''; | ||
} | ||
if(typeof tempElement.attr('zf-closable') !== 'undefined' && tempElement.attr('zf-closable') !== false) { | ||
parentElement = tempElement; | ||
if(typeof tempElement.attr('zf-closable') !== 'undefined' && tempElement.attr('zf-closable') !== false) { | ||
parentElement = tempElement; | ||
} | ||
tempElement = tempElement.parent(); | ||
} | ||
tempElement = tempElement.parent(); | ||
targetId = parentElement.attr('id'); | ||
} | ||
element.on('click', function(e) { | ||
foundationApi.publish(parentElement.attr('id'), 'close'); | ||
foundationApi.publish(targetId, 'close'); | ||
e.preventDefault(); | ||
@@ -159,14 +165,5 @@ }); | ||
element.on('click', function(e) { | ||
var animatedElements = document.querySelectorAll('.ng-enter-active'); | ||
// if there are any currently animated elements on the page | ||
// SIDENOTE: there is probably a more elegant way of doing this | ||
if (animatedElements.length !== 0) { | ||
e.preventDefault(); // do nothing | ||
} | ||
// else do the toggle thang | ||
else { | ||
foundationApi.closeActiveElements({exclude: attrs.zfHardToggle}); | ||
foundationApi.publish(attrs.zfHardToggle, 'toggle'); | ||
e.preventDefault(); | ||
} | ||
foundationApi.closeActiveElements({exclude: attrs.zfHardToggle}); | ||
foundationApi.publish(attrs.zfHardToggle, 'toggle'); | ||
e.preventDefault(); | ||
}); | ||
@@ -173,0 +170,0 @@ } |
@@ -24,11 +24,18 @@ (function() { | ||
zfIconic.$inject = ['Iconic'] | ||
zfIconic.$inject = ['Iconic', 'FoundationApi', '$compile', '$location'] | ||
function zfIconic(iconic) { | ||
function zfIconic(iconic, foundationApi, $compile, $location) { | ||
var directive = { | ||
restrict: 'A', | ||
template: '<img ng-transclude>', | ||
transclude: true, | ||
replace: true, | ||
scope: { | ||
dynSrc: '=?' | ||
dynSrc: '=?', | ||
dynIcon: '=?', | ||
size: '@?', | ||
icon: '@', | ||
iconDir: '@?' | ||
}, | ||
link: link | ||
compile: compile | ||
}; | ||
@@ -38,14 +45,114 @@ | ||
function link(scope, element, attrs, controller) { | ||
var ico = iconic.getAccess(); | ||
if(scope.dynSrc) { | ||
attrs.$set('data-src', scope.dynSrc); | ||
} else { | ||
// To support expressions on data-src | ||
attrs.$set('data-src', attrs.src); | ||
function compile() { | ||
var contents, assetPath; | ||
return { | ||
pre: preLink, | ||
post: postLink | ||
}; | ||
function preLink(scope, element, attrs, ctrl, transclude) { | ||
if (scope.iconDir) { | ||
// make sure ends with / | ||
assetPath = scope.iconDir; | ||
if (assetPath.charAt(assetPath.length - 1) !== '/') { | ||
assetPath += '/'; | ||
} | ||
} else { | ||
// default path | ||
assetPath = 'assets/img/iconic/'; | ||
} | ||
if(scope.dynSrc) { | ||
attrs.$set('data-src', scope.dynSrc); | ||
} else if(scope.dynIcon) { | ||
attrs.$set('data-src', assetPath + scope.dynIcon + '.svg'); | ||
} else { | ||
if (scope.icon) { | ||
attrs.$set('data-src', assetPath + scope.icon + '.svg'); | ||
} else { | ||
// To support expressions on data-src | ||
attrs.$set('data-src', attrs.src); | ||
} | ||
} | ||
// check if size already added as class | ||
if (!element.hasClass('iconic-sm') && | ||
!element.hasClass('iconic-md') && | ||
!element.hasClass('iconic-lg')) { | ||
var iconicClass; | ||
switch (scope.size) { | ||
case 'small': | ||
iconicClass = 'iconic-sm' | ||
break; | ||
case 'medium': | ||
iconicClass = 'iconic-md' | ||
break; | ||
case 'large': | ||
iconicClass = 'iconic-lg' | ||
break; | ||
default: | ||
iconicClass = 'iconic-fluid' | ||
} | ||
element.addClass(iconicClass); | ||
} | ||
// save contents of un-inject html, to use for dynamic re-injection | ||
contents = element[0].outerHTML; | ||
} | ||
ico.inject(element[0]); | ||
function postLink(scope, element, attrs) { | ||
var svgElement, ico = iconic.getAccess(); | ||
injectSvg(element[0]); | ||
foundationApi.subscribe('resize', function() { | ||
// only run update on current element | ||
ico.update(element[0]); | ||
}); | ||
// handle dynamic updating of src | ||
if(scope.dynSrc) { | ||
scope.$watch('dynSrc', function(newVal, oldVal) { | ||
if (newVal && newVal != oldVal) { | ||
reinjectSvg(scope.dynSrc); | ||
} | ||
}); | ||
} | ||
// handle dynamic updating of icon | ||
if (scope.dynIcon) { | ||
scope.$watch('dynIcon', function(newVal, oldVal) { | ||
if (newVal && newVal != oldVal) { | ||
reinjectSvg(assetPath + scope.dynIcon + '.svg'); | ||
} | ||
}); | ||
} | ||
function reinjectSvg(newSrc) { | ||
if (svgElement) { | ||
// set html | ||
svgElement.empty(); | ||
svgElement.append(angular.element(contents)); | ||
// set new source | ||
svgElement.attr('data-src', newSrc); | ||
// reinject | ||
injectSvg(svgElement[0]); | ||
} | ||
} | ||
function injectSvg(element) { | ||
ico.inject(element, { | ||
each: function(injectedElem) { | ||
// compile injected svg | ||
var angElem = angular.element(injectedElem); | ||
svgElement = $compile(angElem)(angElem.scope()); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
})(); | ||
})(); |
(function() { | ||
'use strict'; | ||
angular.module('foundation.interchange', ['foundation.core']) | ||
angular.module('foundation.interchange', ['foundation.core', 'foundation.mediaquery']) | ||
.directive('zfInterchange', zfInterchange) | ||
; | ||
zfInterchange.$inject = ['FoundationApi', '$compile', '$http', '$templateCache', '$animate']; | ||
zfInterchange.$inject = [ '$compile', '$http', '$templateCache', 'FoundationApi', 'FoundationMQ']; | ||
function zfInterchange(foundationApi, $compile, $http, $templateCache) { | ||
function zfInterchange($compile, $http, $templateCache, foundationApi, foundationMQ) { | ||
@@ -28,17 +28,4 @@ var directive = { | ||
var namedQueries = { | ||
'default' : 'only screen', | ||
landscape : 'only screen and (orientation: landscape)', | ||
portrait : 'only screen and (orientation: portrait)', | ||
retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),' + | ||
'only screen and (min--moz-device-pixel-ratio: 2),' + | ||
'only screen and (-o-min-device-pixel-ratio: 2/1),' + | ||
'only screen and (min-device-pixel-ratio: 2),' + | ||
'only screen and (min-resolution: 192dpi),' + | ||
'only screen and (min-resolution: 2dppx)' | ||
}; | ||
var globalQueries = foundationMQ.getMediaQueries(); | ||
var globalQueries = foundationApi.getSettings().mediaQueries; | ||
namedQueries = angular.extend(namedQueries, globalQueries); | ||
//setup | ||
@@ -51,3 +38,3 @@ foundationApi.subscribe('resize', function(msg) { | ||
var ruleMatches = matched(); | ||
var ruleMatches = foundationMQ.match(scenarios); | ||
var scenario = ruleMatches.length === 0 ? null : scenarios[ruleMatches[0].ind]; | ||
@@ -96,49 +83,9 @@ | ||
function matched() { | ||
var count = scenarios.length; | ||
var matches = []; | ||
function collectInformation(el) { | ||
var data = foundationMQ.collectScenariosFromElement(el); | ||
if (count > 0) { | ||
while (count--) { | ||
var mq; | ||
var rule = scenarios[count].media; | ||
if (namedQueries[rule]) { | ||
mq = matchMedia(namedQueries[rule]); | ||
} else { | ||
mq = matchMedia(rule); | ||
} | ||
if (mq.matches) { | ||
matches.push({ ind: count}); | ||
} | ||
} | ||
} | ||
return matches; | ||
scenarios = data.scenarios; | ||
innerTemplates = data.templates; | ||
} | ||
function collectInformation(parentElement) { | ||
scenarios = []; | ||
innerTemplates = []; | ||
var elements = parentElement.children(); | ||
var i = 0; | ||
angular.forEach(elements, function(el) { | ||
var elem = angular.element(el); | ||
//if no source or no html, capture element itself | ||
if (!elem.attr('src') || !elem.attr('src').match(/.html$/)) { | ||
innerTemplates[i] = elem; | ||
scenarios[i] = { media: elem.attr('media'), templ: i }; | ||
} else { | ||
scenarios[i] = { media: elem.attr('media'), src: elem.attr('src') }; | ||
} | ||
i++; | ||
}); | ||
} | ||
function checkScenario(scenario) { | ||
@@ -145,0 +92,0 @@ return !current || current !== scenario; |
@@ -5,4 +5,33 @@ (function() { | ||
angular.module('foundation.modal', ['foundation.core']) | ||
.directive('zfModal', modalDirective); | ||
.directive('zfModal', modalDirective) | ||
.factory('ModalFactory', ModalFactory) | ||
; | ||
FoundationModal.$inject = ['FoundationApi', 'ModalFactory']; | ||
function FoundationModal(foundationApi, ModalFactory) { | ||
var service = {}; | ||
service.activate = activate; | ||
service.deactivate = deactivate; | ||
service.newModal = newModal; | ||
return service; | ||
//target should be element ID | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
//target should be element ID | ||
function deactivate(target) { | ||
foundationApi.publish(target, 'hide'); | ||
} | ||
//new modal has to be controlled via the new instance | ||
function newModal(config) { | ||
return new ModalFactory(config); | ||
} | ||
} | ||
modalDirective.$inject = ['FoundationApi']; | ||
@@ -29,3 +58,3 @@ | ||
post: postLink | ||
} | ||
}; | ||
@@ -39,5 +68,5 @@ function preLink(scope, iElement, iAttrs, controller) { | ||
scope.active = false; | ||
scope.overlay = attrs.overlay === 'true' || attrs.overlayClose === 'true' ? true : false; | ||
scope.overlayClose = attrs.overlayClose === 'true' ? true : false; | ||
scope.active = scope.active || false; | ||
scope.overlay = attrs.overlay === 'false' ? false : true; | ||
scope.overlayClose = attrs.overlayClose === 'false' ? false : true; | ||
@@ -49,17 +78,2 @@ var animationIn = attrs.animationIn || 'fadeIn'; | ||
//setup | ||
foundationApi.subscribe(attrs.id, function(msg) { | ||
if(msg === 'show' || msg === 'open') { | ||
scope.show(); | ||
} else if (msg === 'close' || msg === 'hide') { | ||
scope.hide(); | ||
} else if (msg === 'toggle') { | ||
scope.toggle(); | ||
} | ||
scope.$apply(); | ||
return; | ||
}); | ||
scope.hideOverlay = function() { | ||
@@ -80,2 +94,4 @@ if(scope.overlayClose) { | ||
animate(); | ||
dialog.tabIndex = -1; | ||
dialog[0].focus(); | ||
return; | ||
@@ -90,2 +106,21 @@ }; | ||
init(); | ||
//setup | ||
foundationApi.subscribe(attrs.id, function(msg) { | ||
if(msg === 'show' || msg === 'open') { | ||
scope.show(); | ||
} else if (msg === 'close' || msg === 'hide') { | ||
scope.hide(); | ||
} else if (msg === 'toggle') { | ||
scope.toggle(); | ||
} | ||
if (!scope.$root.$$phase) { | ||
scope.$apply(); | ||
} | ||
return; | ||
}); | ||
function animate() { | ||
@@ -100,2 +135,8 @@ //animate both overlay and dialog | ||
} | ||
function init() { | ||
if(scope.active) { | ||
scope.show(); | ||
} | ||
} | ||
} | ||
@@ -105,2 +146,120 @@ } | ||
ModalFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', 'FoundationApi']; | ||
function ModalFactory($http, $templateCache, $rootScope, $compile, $timeout, foundationApi) { | ||
return modalFactory; | ||
function modalFactory(config) { | ||
var self = this, //for prototype functions | ||
container = angular.element(config.container || document.body), | ||
id = config.id || foundationApi.generateUuid(), | ||
attached = false, | ||
destroyed = false, | ||
html, | ||
element, | ||
scope | ||
; | ||
var props = [ | ||
'animationIn', | ||
'animationOut', | ||
'overlay', | ||
'overlayClose' | ||
]; | ||
if(config.templateUrl) { | ||
//get template | ||
$http.get(config.templateUrl, { | ||
cache: $templateCache | ||
}).then(function (response) { | ||
html = response.data; | ||
assembleDirective(); | ||
}); | ||
} else if(config.template) { | ||
//use provided template | ||
html = config.template; | ||
assembleDirective(); | ||
} | ||
self.activate = activate; | ||
self.deactivate = deactivate; | ||
self.toggle = toggle; | ||
self.destroy = destroy; | ||
return { | ||
activate: activate, | ||
deactivate: deactivate, | ||
toggle: toggle, | ||
destroy: destroy | ||
}; | ||
function checkStatus() { | ||
if(destroyed) { | ||
throw "Error: Modal was destroyed. Delete the object and create a new ModalFactory instance." | ||
} | ||
} | ||
function activate() { | ||
checkStatus(); | ||
$timeout(function() { | ||
init(true); | ||
foundationApi.publish(id, 'show'); | ||
}, 0, false); | ||
} | ||
function deactivate() { | ||
checkStatus(); | ||
$timeout(function() { | ||
init(false); | ||
foundationApi.publish(id, 'hide'); | ||
}, 0, false); | ||
} | ||
function toggle() { | ||
checkStatus(); | ||
$timeout(function() { | ||
init(true); | ||
foundationApi.publish(id, 'toggle'); | ||
}, 0, false); | ||
} | ||
function init(state) { | ||
if(!attached && html.length > 0) { | ||
var modalEl = container.append(element); | ||
scope.active = state; | ||
$compile(element)(scope); | ||
attached = true; | ||
} | ||
} | ||
function assembleDirective() { | ||
html = '<zf-modal id="' + id + '">' + html + '</zf-modal>'; | ||
element = angular.element(html); | ||
scope = $rootScope.$new(); | ||
for(var prop in props) { | ||
if(config[prop]) { | ||
element.attr(prop, config[prop]); | ||
} | ||
} | ||
} | ||
function destroy() { | ||
self.deactivate(); | ||
setTimeout(function() { | ||
scope.$destroy(); | ||
element.remove(); | ||
destroyed = true; | ||
}, 3000); | ||
} | ||
} | ||
} | ||
})(); |
@@ -10,4 +10,36 @@ (function() { | ||
.directive('zfNotify', zfNotify) | ||
.factory('NotificationFactory', NotificationFactory) | ||
.service('FoundationNotification', FoundationNotification) | ||
; | ||
FoundationNotification.$inject = ['FoundationApi', 'NotificationFactory']; | ||
function FoundationNotification(foundationApi, NotificationFactory) { | ||
var service = {}; | ||
service.activate = activate; | ||
service.deactivate = deactivate; | ||
return service; | ||
//target should be element ID | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
//target should be element ID | ||
function deactivate(target) { | ||
foundationApi.publish(target, 'hide'); | ||
} | ||
function toggle(target) { | ||
foundationApi.publish(target, 'toggle'); | ||
} | ||
function createNotificationSet(config) { | ||
return new NotificationFactory(config); | ||
} | ||
} | ||
ZfNotificationController.$inject = ['$scope', 'FoundationApi']; | ||
@@ -17,3 +49,3 @@ | ||
var controller = this; | ||
controller.notifications = $scope.notifications = []; | ||
controller.notifications = $scope.notifications = $scope.notifications || []; | ||
@@ -49,3 +81,6 @@ controller.addNotification = function(info) { | ||
controller: 'ZfNotificationController', | ||
scope: true, | ||
replace: true, | ||
scope: { | ||
position: '@' | ||
}, | ||
link: link | ||
@@ -57,8 +92,13 @@ }; | ||
function link(scope, element, attrs, controller) { | ||
scope.position = scope.position ? scope.position.split(' ').join('-') : 'top-right'; | ||
foundationApi.subscribe(attrs.id, function(msg) { | ||
if(msg === 'clearall') { | ||
controller.clearAll(); | ||
} else { | ||
} | ||
else { | ||
controller.addNotification(msg); | ||
scope.$apply(); | ||
if (!scope.$root.$$phase) { | ||
scope.$apply(); | ||
} | ||
} | ||
@@ -84,4 +124,4 @@ }); | ||
notifId: '=', | ||
position: '=?', | ||
color: '=?' | ||
color: '=?', | ||
autoclose: '=?' | ||
}, | ||
@@ -106,5 +146,6 @@ compile: compile | ||
scope.active = false; | ||
scope.position = scope.position ? scope.position.split(' ').join('-') : 'top-right'; | ||
var animationIn = attrs.animationIn || 'fadeIn'; | ||
var animationIn = attrs.animationIn || 'fadeIn'; | ||
var animationOut = attrs.animationOut || 'fadeOut'; | ||
var hammerElem; | ||
//due to dynamic insertion of DOM, we need to wait for it to show up and get working! | ||
@@ -116,3 +157,3 @@ setTimeout(function() { | ||
scope.remove = function() { | ||
scope.hide = function() { | ||
scope.active = false; | ||
@@ -124,2 +165,26 @@ foundationApi.animate(element, scope.active, animationIn, animationOut); | ||
}; | ||
// close if autoclose | ||
if (scope.autoclose && scope.active) { | ||
setTimeout(function() { | ||
scope.hide(); | ||
}, parseInt(scope.autoclose)); | ||
}; | ||
// close on swipe | ||
if (Hammer) { | ||
hammerElem = new Hammer(element[0]); | ||
// set the options for swipe (to make them a bit more forgiving in detection) | ||
hammerElem.get('swipe').set({ | ||
direction: Hammer.DIRECTION_ALL, | ||
threshold: 5, // this is how far the swipe has to travel | ||
velocity: 0.5 // and this is how fast the swipe must travel | ||
}); | ||
} | ||
hammerElem.on('swipe', function() { | ||
if (scope.active) { | ||
scope.hide(); | ||
} | ||
}); | ||
} | ||
@@ -134,3 +199,3 @@ } | ||
restrict: 'EA', | ||
templateUrl: 'components/notification/notification.html', | ||
templateUrl: 'components/notification/notification-static.html', | ||
replace: true, | ||
@@ -142,4 +207,4 @@ transclude: true, | ||
image: '@?', | ||
position: '@?', | ||
color: '@?' | ||
color: '@?', | ||
autoclose: '@?' | ||
}, | ||
@@ -164,16 +229,30 @@ compile: compile | ||
function postLink(scope, element, attrs, controller) { | ||
scope.position = scope.position ? scope.position.split(' ').join('-') : 'top-right'; | ||
scope.position = attrs.position ? attrs.position.split(' ').join('-') : 'top-right'; | ||
var animationIn = attrs.animationIn || 'fadeIn'; | ||
var animationOut = attrs.animationOut || 'fadeOut'; | ||
//setup | ||
foundationApi.subscribe(attrs.id, function(msg) { | ||
if(msg === 'show' || msg === 'open') { | ||
if(msg == 'show' || msg == 'open') { | ||
scope.show(); | ||
} else if (msg === 'close' || msg === 'hide') { | ||
// close if autoclose | ||
if (scope.autoclose) { | ||
setTimeout(function() { | ||
scope.hide(); | ||
}, parseInt(scope.autoclose)); | ||
}; | ||
} else if (msg == 'close' || msg == 'hide') { | ||
scope.hide(); | ||
} else if (msg === 'toggle') { | ||
} else if (msg == 'toggle') { | ||
scope.toggle(); | ||
// close if autoclose | ||
if (scope.autoclose) { | ||
setTimeout(function() { | ||
scope.toggle(); | ||
}, parseInt(scope.autoclose)); | ||
}; | ||
} | ||
foundationApi.animate(element, scope.active, animationIn, animationOut); | ||
scope.$apply(); | ||
@@ -190,7 +269,2 @@ | ||
scope.remove = function() { | ||
scope.hide(); | ||
foundationApi.animate(element, scope.active, animationIn, animationOut); | ||
}; | ||
scope.show = function() { | ||
@@ -207,2 +281,3 @@ scope.active = true; | ||
}; | ||
} | ||
@@ -220,5 +295,5 @@ } | ||
content: '@?', | ||
position: '@?', | ||
color: '@?', | ||
image: '@?' | ||
image: '@?', | ||
autoclose: '@?' | ||
}, | ||
@@ -235,5 +310,5 @@ link: link | ||
content: scope.content, | ||
position: scope.position, | ||
color: scope.color, | ||
image: scope.image | ||
image: scope.image, | ||
autoclose: scope.autoclose | ||
}); | ||
@@ -245,2 +320,91 @@ e.preventDefault(); | ||
NotificationFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', 'FoundationApi']; | ||
function NotificationFactory($http, $templateCache, $rootScope, $compile, $timeout, foundationApi) { | ||
return notificationFactory; | ||
function notificationFactory(config) { | ||
var self = this, //for prototype functions | ||
container = angular.element(config.container || document.body), | ||
id = config.id || foundationApi.generateUuid(), | ||
attached = false, | ||
destroyed = false, | ||
html, | ||
element, | ||
scope | ||
; | ||
var props = [ | ||
'position' | ||
]; | ||
assembleDirective(); | ||
self.addNotification = addNotification; | ||
self.clearAll = clearAll; | ||
self.destroy = destroy; | ||
return { | ||
addNotification: addNotification, | ||
clearAll: clearAll, | ||
destroy: destroy | ||
}; | ||
function checkStatus() { | ||
if(destroyed) { | ||
throw "Error: Notification Set was destroyed. Delete the object and create a new NotificationFactory instance." | ||
} | ||
} | ||
function addNotification(notification) { | ||
checkStatus(); | ||
$timeout(function() { | ||
init(true, notification); | ||
foundationApi.publish(id, notification); | ||
}, 0, false); | ||
} | ||
function clearAll() { | ||
checkStatus(); | ||
$timeout(function() { | ||
foundationApi.publish(id, 'clearall'); | ||
}, 0, false); | ||
} | ||
function init(state, notification) { | ||
if(!attached && html.length > 0) { | ||
var modalEl = container.append(element); | ||
scope.notifications = [ notification ]; | ||
$compile(element)(scope); | ||
attached = true; | ||
} | ||
} | ||
function assembleDirective() { | ||
html = '<zf-notification-set id="' + id + '"></zf-notification-set>'; | ||
element = angular.element(html); | ||
scope = $rootScope.$new(); | ||
for(var prop in props) { | ||
if(config[prop]) { | ||
element.attr(prop, config[prop]); | ||
} | ||
} | ||
} | ||
function destroy() { | ||
self.clearAll(); | ||
setTimeout(function() { | ||
scope.$destroy(); | ||
element.remove(); | ||
destroyed = true; | ||
}, 3000); | ||
} | ||
} | ||
} | ||
})(); |
@@ -6,4 +6,30 @@ (function() { | ||
.directive('zfOffcanvas', zfOffcanvas) | ||
.service('FoundationOffcanvas', FoundationOffcanvas) | ||
; | ||
FoundationOffcanvas.$inject = ['FoundationApi']; | ||
function FoundationOffcanvas(foundationApi) { | ||
var service = {}; | ||
service.activate = activate; | ||
service.deactivate = deactivate; | ||
return service; | ||
//target should be element ID | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
//target should be element ID | ||
function deactivate(target) { | ||
foundationApi.publish(target, 'hide'); | ||
} | ||
function toggle(target) { | ||
foundationApi.publish(target, 'toggle'); | ||
} | ||
} | ||
zfOffcanvas.$inject = ['FoundationApi']; | ||
@@ -10,0 +36,0 @@ |
@@ -6,4 +6,26 @@ (function() { | ||
.directive('zfPanel', zfPanel) | ||
.service('FoundationPanel', FoundationPanel) | ||
; | ||
FoundationPanel.$inject = ['FoundationApi']; | ||
function FoundationPanel(foundationApi) { | ||
var service = {}; | ||
service.activate = activate; | ||
service.deactivate = deactivate; | ||
return service; | ||
//target should be element ID | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
//target should be element ID | ||
function deactivate(target) { | ||
foundationApi.publish(target, 'hide'); | ||
} | ||
} | ||
zfPanel.$inject = ['FoundationApi']; | ||
@@ -70,4 +92,2 @@ | ||
foundationApi.animate(element, scope.active, animationIn, animationOut); | ||
scope.$apply(); | ||
@@ -79,3 +99,7 @@ | ||
scope.hide = function() { | ||
scope.active = false; | ||
if(scope.active){ | ||
scope.active = false; | ||
foundationApi.animate(element, scope.active, animationIn, animationOut); | ||
} | ||
return; | ||
@@ -85,3 +109,7 @@ }; | ||
scope.show = function() { | ||
scope.active = true; | ||
if(!scope.active){ | ||
scope.active = true; | ||
foundationApi.animate(element, scope.active, animationIn, animationOut); | ||
} | ||
return; | ||
@@ -92,2 +120,4 @@ }; | ||
scope.active = !scope.active; | ||
foundationApi.animate(element, scope.active, animationIn, animationOut); | ||
return; | ||
@@ -94,0 +124,0 @@ }; |
@@ -7,4 +7,30 @@ (function() { | ||
.directive('zfPopupToggle', zfPopupToggle) | ||
.service('FoundationPopup', FoundationPopup) | ||
; | ||
FoundationPopup.$inject = ['FoundationApi']; | ||
function FoundationPopup(foundationApi) { | ||
var service = {}; | ||
service.activate = activate; | ||
service.deactivate = deactivate; | ||
return service; | ||
//target should be element ID | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
//target should be element ID | ||
function deactivate(target) { | ||
foundationApi.publish(target, 'hide'); | ||
} | ||
function toggle(target, popupTarget) { | ||
foundationApi.publish(target, ['toggle', popupTarget]); | ||
} | ||
} | ||
zfPopup.$inject = ['FoundationApi']; | ||
@@ -21,2 +47,3 @@ | ||
pinAt: '@?', | ||
target: '@?' | ||
}, | ||
@@ -43,2 +70,3 @@ compile: compile | ||
var attachment = scope.pinTo || 'top center'; | ||
var targetAttachment = scope.pinAt || 'bottom center'; | ||
var tetherInit = false; | ||
@@ -65,3 +93,3 @@ var tether = {}; | ||
scope.active = false; | ||
tetherElement(newTarget); | ||
tetherElement(); | ||
tether.disable(); | ||
@@ -103,2 +131,3 @@ return; | ||
attachment: attachment, | ||
targetAttachment: targetAttachment, | ||
enable: false | ||
@@ -105,0 +134,0 @@ }); |
@@ -13,4 +13,21 @@ (function() { | ||
.directive('zfTabContentCustom', zfTabContentCustom) | ||
.service('FoundationTabs', FoundationTabs) | ||
; | ||
FoundationTabs.$inject = ['FoundationApi']; | ||
function FoundationTabs(foundationApi) { | ||
var service = {}; | ||
service.activate = activate; | ||
return service; | ||
//target should be element ID | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
} | ||
ZfTabsController.$inject = ['$scope', 'FoundationApi']; | ||
@@ -17,0 +34,0 @@ |
@@ -8,2 +8,3 @@ (function() { | ||
'foundation.core', | ||
'foundation.mediaquery', | ||
'foundation.accordion', | ||
@@ -10,0 +11,0 @@ 'foundation.actionsheet', |
(function() { | ||
'use strict'; | ||
angular.module('foundation.core', []) | ||
.run(mqInitRun) | ||
.factory('FoundationMQInit', FoundationMQInit) | ||
.factory('mqHelpers', mqHelpers) | ||
angular.module('foundation.core', [ | ||
'foundation.core.animation' | ||
]) | ||
.service('FoundationApi', FoundationApi) | ||
.filter('prepareRoute', prepareRoute) | ||
.service('FoundationAdapter', FoundationAdapter) | ||
.factory('Utils', Utils) | ||
; | ||
mqInitRun.$inject = ['FoundationMQInit']; | ||
FoundationApi.$inject = ['FoundationAnimation']; | ||
function mqInitRun(mqInit) { | ||
mqInit.init(); | ||
} | ||
FoundationMQInit.$inject = ['mqHelpers', 'FoundationApi', 'Utils']; | ||
function FoundationMQInit(helpers, foundationApi, u){ | ||
var factory = {}; | ||
factory.init = init; | ||
return factory; | ||
function init() { | ||
var mediaQueries; | ||
var extractedMedia; | ||
var mediaObject; | ||
helpers.headerHelper(['foundation-mq']); | ||
extractedMedia = helpers.getStyle('.foundation-mq', 'font-family'); | ||
mediaQueries = helpers.parseStyleToObject((extractedMedia)); | ||
for(var key in mediaQueries) { | ||
mediaQueries[key] = 'only screen and (min-width: ' + mediaQueries[key].replace('rem', 'em') + ')'; | ||
} | ||
foundationApi.modifySettings({ | ||
mediaQueries: mediaQueries | ||
}); | ||
window.addEventListener('resize', u.throttle(function() { | ||
foundationApi.publish('resize', 'window resized'); | ||
}, 50)); | ||
} | ||
} | ||
function mqHelpers() { | ||
var factory = {}; | ||
factory.headerHelper = headerHelper; | ||
factory.getStyle = getStyle; | ||
factory.parseStyleToObject = parseStyleToObject; | ||
return factory; | ||
function headerHelper(classArray) { | ||
var i = classArray.length; | ||
var head = angular.element(document.querySelectorAll('head')); | ||
while(i--) { | ||
head.append('<meta class="' + classArray[i] + '" />'); | ||
} | ||
return; | ||
} | ||
function getStyle(selector, styleName) { | ||
var elem = document.querySelectorAll(selector)[0]; | ||
var style = window.getComputedStyle(elem, null); | ||
return style.getPropertyValue('font-family'); | ||
} | ||
// https://github.com/sindresorhus/query-string | ||
function parseStyleToObject(str) { | ||
var styleObject = {}; | ||
if (typeof str !== 'string') { | ||
return styleObject; | ||
} | ||
str = str.trim().slice(1, -1); // browsers re-quote string style values | ||
if (!str) { | ||
return styleObject; | ||
} | ||
styleObject = str.split('&').reduce(function(ret, param) { | ||
var parts = param.replace(/\+/g, ' ').split('='); | ||
var key = parts[0]; | ||
var val = parts[1]; | ||
key = decodeURIComponent(key); | ||
// missing `=` should be `null`: | ||
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters | ||
val = val === undefined ? null : decodeURIComponent(val); | ||
if (!ret.hasOwnProperty(key)) { | ||
ret[key] = val; | ||
} else if (Array.isArray(ret[key])) { | ||
ret[key].push(val); | ||
} else { | ||
ret[key] = [ret[key], val]; | ||
} | ||
return ret; | ||
}, {}); | ||
return styleObject; | ||
} | ||
} | ||
function FoundationApi() { | ||
function FoundationApi(FoundationAnimation) { | ||
var listeners = []; | ||
var settings = {}; | ||
var uniqueIds = []; | ||
var animations = []; | ||
var service = {}; | ||
@@ -132,3 +25,3 @@ | ||
service.generateUuid = generateUuid; | ||
service.toggleAnimation = toggleAnimation; | ||
service.toggleAnimate = toggleAnimate; | ||
service.closeActiveElements = closeActiveElements; | ||
@@ -184,9 +77,4 @@ service.animate = animate; | ||
function toggleAnimation(element, futureState) { | ||
var activeClass = 'is-active'; | ||
if(futureState) { | ||
element.addClass(activeClass); | ||
} else { | ||
element.removeClass(activeClass); | ||
} | ||
function toggleAnimate(element, futureState) { | ||
FoundationAnimation.toggleAnimate(element, futureState); | ||
} | ||
@@ -208,112 +96,30 @@ | ||
function animate(element, futureState, animationIn, animationOut) { | ||
var initClasses = ['ng-enter', 'ng-leave']; | ||
var activeClasses = ['ng-enter-active', 'ng-leave-active']; | ||
var activeGenericClass = 'is-active'; | ||
var events = ['webkitAnimationEnd', 'mozAnimationEnd', 'MSAnimationEnd', 'oanimationend', 'animationend', | ||
'webkitTransitionEnd', 'otransitionend', 'transitionend']; | ||
var timedOut = true; | ||
var self = this; | ||
self.cancelAnimation = cancelAnimation; | ||
FoundationAnimation.animate(element, futureState, animationIn, animationOut); | ||
} | ||
} | ||
animateElement(futureState ? animationIn : animationOut, futureState); | ||
FoundationAdapter.$inject = ['FoundationApi']; | ||
function cancelAnimation() { | ||
deregisterElement(element); | ||
element.off(events.join(' ')); //kill all animation event handlers | ||
timedOut = false; | ||
}; | ||
function FoundationAdapter(foundationApi) { | ||
function registerElement(el) { | ||
var elObj = { | ||
el: el, | ||
animation: self | ||
}; | ||
var service = {}; | ||
//kill in progress animations | ||
var inProgress = animations.filter(function(obj) { | ||
return obj.el === el; | ||
}); | ||
service.activate = activate; | ||
service.deactivate = deactivate; | ||
if(inProgress.length > 0) { | ||
inProgress[0].animation.cancelAnimation(); | ||
} | ||
return service; | ||
animations.push(elObj); | ||
} | ||
function activate(target) { | ||
foundationApi.publish(target, 'show'); | ||
} | ||
function deregisterElement(el) { | ||
var index; | ||
var currentAnimation = animations.filter(function(obj, ind) { | ||
if(obj.el === el) { | ||
index = ind; | ||
} | ||
}); | ||
if(index >= 0) { | ||
animations.splice(index, 1); | ||
} | ||
} | ||
function reflow() { | ||
return element[0].offsetWidth; | ||
} | ||
function reset() { | ||
element[0].style.transitionDuration = 0; | ||
element.removeClass(initClasses.join(' ') + ' ' + activeClasses.join(' ') + ' ' + animationIn + ' ' + animationOut); | ||
} | ||
function animateElement(animationClass, activation) { | ||
var initClass = activation ? initClasses[0] : initClasses[1]; | ||
var activeClass = activation ? activeClasses[0] : activeClasses[1]; | ||
var finishAnimation = function() { | ||
deregisterElement(element); | ||
reset(); //reset all classes | ||
element.removeClass(!activation ? activeGenericClass : ''); //if not active, remove active class | ||
reflow(); | ||
timedOut = false; | ||
}; | ||
//stop animation | ||
registerElement(element); | ||
reset(); | ||
element.addClass(animationClass); | ||
element.addClass(initClass); | ||
element.addClass(activeGenericClass); | ||
//force a "tick" | ||
reflow(); | ||
//activate | ||
element[0].style.transitionDuration = ''; | ||
element.addClass(activeClass); | ||
element.one(events.join(' '), function() { | ||
finishAnimation(); | ||
}); | ||
setTimeout(function() { | ||
if(timedOut) { | ||
finishAnimation(); | ||
} | ||
}, 3000); | ||
} | ||
function deactivate(target) { | ||
foundationApi.publish(target, 'hide'); | ||
} | ||
} | ||
function prepareRoute() { | ||
return prepare; | ||
function prepare(input) { | ||
return 'route-' + input.replace(/\./, '-').toLowerCase(); | ||
} | ||
} | ||
function Utils() { | ||
var utils = {}; | ||
utils.prepareRoute = prepareRouteUtil; | ||
utils.throttle = throttleUtil; | ||
@@ -323,6 +129,2 @@ | ||
function prepareRouteUtil(input) { | ||
return 'route-' + input.replace(/\./, '-').toLowerCase(); | ||
} | ||
function throttleUtil(func, delay) { | ||
@@ -340,3 +142,3 @@ var timer = null; | ||
} | ||
} | ||
}; | ||
} | ||
@@ -343,0 +145,0 @@ } |
@@ -47,5 +47,5 @@ (function() { | ||
controller: getController(page), | ||
data: { vars: page }, | ||
data: getData(page), | ||
}; | ||
$stateProvider.state(page.name, state); | ||
@@ -59,3 +59,3 @@ } | ||
parent: page.parent || '', | ||
data: { vars: page }, | ||
data: getData(page), | ||
views: { | ||
@@ -65,3 +65,3 @@ '': buildState(page.path, page) | ||
}; | ||
angular.forEach(page.children, function(sub) { | ||
@@ -76,3 +76,17 @@ state.views[sub.name + '@' + page.name] = buildState(sub.path, page); | ||
this.$get = angular.noop; | ||
function getData(page) { | ||
var data = { vars: {} }; | ||
if (page.data) { | ||
if (typeof page.data.vars === "object") { | ||
data.vars = page.data.vars; | ||
} | ||
delete page.data.vars; | ||
angular.extend(data, page.data); | ||
} | ||
delete page.data; | ||
angular.extend(data.vars, page); | ||
return data; | ||
} | ||
function buildState(path, state) { | ||
@@ -99,3 +113,3 @@ return { | ||
function DefaultController($scope, $stateParams, $state) { | ||
var params = []; | ||
var params = {}; | ||
angular.forEach($stateParams, function(value, key) { | ||
@@ -102,0 +116,0 @@ params[key] = value; |
{ | ||
"name": "foundation-apps", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "A responsive, Angular-powered framework for web apps from ZURB.", | ||
@@ -33,6 +33,10 @@ "scripts": { | ||
"gulp-connect": "^2.0.6", | ||
"gulp-filter": "^2.0.0", | ||
"gulp-highlight": "0.0.3", | ||
"gulp-karma": "0.0.4", | ||
"gulp-load-plugins": "^0.8.0", | ||
"gulp-markdown": "^1.0.0", | ||
"gulp-prompt": "^0.1.1", | ||
"gulp-minify-css": "^0.3.11", | ||
"gulp-prompt": "^0.1.2", | ||
"gulp-rename": "^1.2.0", | ||
"gulp-rsync": "^0.0.4", | ||
@@ -42,3 +46,2 @@ "gulp-ruby-sass": "1.0.0-alpha", | ||
"gulp-uglify": "^1.0.1", | ||
"gulp-minify-css": "^0.3.11", | ||
"gulp-util": "^3.0.1", | ||
@@ -52,5 +55,5 @@ "highlight.js": "~7.5.0", | ||
"run-sequence": "^1.0.1", | ||
"through2": "^0.6.2", | ||
"settings-parser": "zurb/foundation-settings-parser" | ||
"settings-parser": "zurb/foundation-settings-parser", | ||
"through2": "^0.6.2" | ||
} | ||
} |
@@ -43,3 +43,3 @@ # Foundation for Apps | ||
This will aseemble the templates, static assets, Sass, and JavaScript. You can view the test server at this URL: | ||
This will assemble the templates, static assets, Sass, and JavaScript. You can view the test server at this URL: | ||
``` | ||
@@ -46,0 +46,0 @@ http://localhost:8080 |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
673774
102
10912
28
2
10
4