this.onOverlayClicked()}
+ style={overlayStyles}
+ />
+ );
+ }
+
+ return isVisible ? (
+
+ ) :
;
+ }
+}
+
+SkyLightStateless.displayName = 'SkyLightStateless';
+
+SkyLightStateless.sharedPropTypes = {
+ closeButtonStyle: React.PropTypes.object,
+ dialogStyles: React.PropTypes.object,
+ onCloseClicked: React.PropTypes.func,
+ onOverlayClicked: React.PropTypes.func,
+ overlayStyles: React.PropTypes.object,
+ showOverlay: React.PropTypes.bool,
+ title: React.PropTypes.string,
+ titleStyle: React.PropTypes.object,
+};
+
+SkyLightStateless.propTypes = {
+ ...SkyLightStateless.sharedPropTypes,
+ isVisible: React.PropTypes.bool,
+};
+
+SkyLightStateless.defaultProps = {
+ title: '',
+ showOverlay: true,
+ overlayStyles: styles.overlayStyles,
+ dialogStyles: styles.dialogStyles,
+ closeButtonStyle: styles.closeButtonStyle,
+};
diff --git a/src/styles.js b/src/styles.js
index 2bcffba..ed140bf 100644
--- a/src/styles.js
+++ b/src/styles.js
@@ -1,6 +1,10 @@
+const styles = {
+ overlayStyles: {},
+ dialogStyles: {},
+ title: {
+ marginTop: '0px',
+ },
+ closeButtonStyle: {},
+};
-module.exports = {
- overlayStyles: {},
- dialogStyles: {},
- closeButtonStyle: {}
-};
\ No newline at end of file
+export default styles;
diff --git a/src/utils/assign.js b/src/utils/assign.js
new file mode 100644
index 0000000..3d9fbc6
--- /dev/null
+++ b/src/utils/assign.js
@@ -0,0 +1,18 @@
+export default function (target, ...args) {
+ if (target === null) {
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+
+ const newTarget = target;
+ for (let index = 0; index < args.length; index++) {
+ const source = args[index];
+ if (source !== null) {
+ for (const key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ newTarget[key] = source[key];
+ }
+ }
+ }
+ }
+ return newTarget;
+}
diff --git a/styles-examples/default.css b/styles-examples/default.css
deleted file mode 100644
index d3ad37c..0000000
--- a/styles-examples/default.css
+++ /dev/null
@@ -1,31 +0,0 @@
-.skylight-dialog {
- width: 50%;
- height: 400px;
- position: fixed;
- top: 50%;
- left: 50%;
- margin-top: -200px;
- margin-left: -25%;
- background-color: #fff;
- border-radius: 2px;
- z-index: 100;
- padding: 10px;
- box-shadow: 0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28);
- overflow: auto;
-}
-
-.skylight-dialog--close {
- cursor: pointer;
- float: right;
- font-size: 1.6em;
-}
-
-.skylight-dialog__overlay {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 99;
- background-color: rgba(0,0,0,0.3);
-}
diff --git a/test/assign.spec.js b/test/assign.spec.js
new file mode 100644
index 0000000..98be966
--- /dev/null
+++ b/test/assign.spec.js
@@ -0,0 +1,29 @@
+import assign from '../src/utils/assign';
+import { expect } from 'chai';
+
+describe('Assign function', () => {
+ it('should throw error when target is null', () => {
+ expect(assign.bind(null, null, {})).to.throw(TypeError);
+ });
+
+ it('should accept null source', () => {
+ expect(assign({}, null)).to.deep.equal({});
+ });
+
+ it('should merge ', () => {
+ const first = { a: 1 };
+ const second = {
+ b: {
+ c: 2,
+ },
+ };
+ const expected = {
+ a: 1,
+ b: {
+ c: 2,
+ },
+ };
+
+ expect(assign({}, first, second)).to.deep.equal(expected);
+ });
+});
diff --git a/test/skylight.spec.jsx b/test/skylight.spec.jsx
new file mode 100644
index 0000000..c858d34
--- /dev/null
+++ b/test/skylight.spec.jsx
@@ -0,0 +1,90 @@
+/* eslint-disable no-unused-expressions */
+/* eslint-disable no-return-assign */
+import React from 'react';
+import { expect } from 'chai';
+import Skylight from '../src/skylight';
+import SkylightInteractor from './SkylightInteractor';
+
+describe('The Skylight component', () => {
+ it('will not render initially', () => {
+ const rendered = new SkylightInteractor(
);
+ expect(rendered.isOpen()).to.be.false;
+ });
+
+ it('will render on show()', () => {
+ const rendered = new SkylightInteractor(
);
+ rendered.show();
+ expect(rendered.isOpen()).to.be.true;
+ });
+
+ it('will hide on hide()', () => {
+ const rendered = new SkylightInteractor(
);
+ rendered.show();
+ rendered.hide();
+ expect(rendered.isOpen()).to.be.false;
+ });
+
+ it('will emit beforeOpen and afterOpen events when opening', () => {
+ let beforeTriggered = false;
+ let afterTriggered = false;
+ const onBefore = () => beforeTriggered = true;
+ const onAfter = () => {
+ expect(beforeTriggered).to.be.true;
+ afterTriggered = true;
+ };
+ const rendered = new SkylightInteractor(
+
+ );
+ expect(beforeTriggered).to.be.false;
+ expect(afterTriggered).to.be.false;
+ rendered.show();
+ expect(beforeTriggered).to.be.true;
+ expect(afterTriggered).to.be.true;
+ });
+
+ it('will emit beforeClose and afterClose events when closing', () => {
+ let beforeTriggered = false;
+ let afterTriggered = false;
+ const onBefore = () => beforeTriggered = true;
+ const onAfter = () => {
+ expect(beforeTriggered).to.be.true;
+ afterTriggered = true;
+ };
+ const rendered = new SkylightInteractor(
+
+ );
+ rendered.show();
+ expect(beforeTriggered).to.be.false;
+ expect(afterTriggered).to.be.false;
+ rendered.hide();
+ expect(beforeTriggered).to.be.true;
+ expect(afterTriggered).to.be.true;
+ });
+
+ it('will emit an onOverlayClicked event', () => {
+ let clicked = false;
+ const rendered = new SkylightInteractor(
+
clicked = true} />
+ );
+ rendered.show();
+ rendered.clickOnOverlay();
+ expect(clicked).to.be.true;
+ expect(rendered.isOpen()).to.be.true;
+ });
+
+ it('will close when the overlay is clicked when hideOnOverlayClicked prop is true', () => {
+ const rendered = new SkylightInteractor(
+
+ );
+ rendered.show();
+ rendered.clickOnOverlay();
+ expect(rendered.isOpen()).to.be.false;
+ });
+
+ it('will hide when the close button is clicked', () => {
+ const rendered = new SkylightInteractor();
+ rendered.show();
+ rendered.clickOnClose();
+ expect(rendered.isOpen()).to.be.false;
+ });
+});
diff --git a/test/skylightinteractor.js b/test/skylightinteractor.js
new file mode 100644
index 0000000..93dc102
--- /dev/null
+++ b/test/skylightinteractor.js
@@ -0,0 +1,45 @@
+/* eslint-disable no-unused-expressions */
+/* eslint-disable no-return-assign */
+import {
+ renderIntoDocument,
+ scryRenderedDOMComponentsWithClass,
+ findRenderedDOMComponentWithClass,
+ Simulate,
+} from 'react-addons-test-utils';
+
+/**
+ * A test wrapper for skylight components that performs DOM interaction.
+ */
+export default class SkylightInteractor {
+ constructor(jsx) {
+ this._component = renderIntoDocument(jsx);
+ }
+
+ show() {
+ this._component.show();
+ }
+
+ hide() {
+ this._component.hide();
+ }
+
+ isOverlayVisible() {
+ const found = scryRenderedDOMComponentsWithClass(this._component, 'skylight-overlay');
+ return found.length === 1;
+ }
+
+ clickOnOverlay() {
+ const overlay = findRenderedDOMComponentWithClass(this._component, 'skylight-overlay');
+ Simulate.click(overlay);
+ }
+
+ clickOnClose() {
+ const closeButton = findRenderedDOMComponentWithClass(this._component, 'skylight-close-button');
+ Simulate.click(closeButton);
+ }
+
+ isOpen() {
+ const found = scryRenderedDOMComponentsWithClass(this._component, 'skylight-overlay');
+ return found.length === 1;
+ }
+}
diff --git a/test/skylightstateless.spec.jsx b/test/skylightstateless.spec.jsx
new file mode 100644
index 0000000..f526ace
--- /dev/null
+++ b/test/skylightstateless.spec.jsx
@@ -0,0 +1,55 @@
+/* eslint-disable no-unused-expressions */
+/* eslint-disable no-return-assign */
+import React from 'react';
+import { expect } from 'chai';
+import SkylightStateless from '../src/skylightstateless';
+import SkylightInteractor from './SkylightInteractor';
+
+describe('The SkylightStateless component', () => {
+ it('will not render when it is not visible', () => {
+ const rendered = new SkylightInteractor();
+ expect(rendered.isOpen()).to.be.false;
+ });
+
+ it('will render when it is visible', () => {
+ const rendered = new SkylightInteractor();
+ expect(rendered.isOpen()).to.be.true;
+ });
+
+ it('will not render the overlay when the showOverlay prop is false', () => {
+ const rendered = new SkylightInteractor(
+
+ );
+ expect(rendered.isOverlayVisible()).to.be.false;
+ });
+
+ it('will emit an event when the overlay is clicked', () => {
+ let clicked = false;
+ const rendered = new SkylightInteractor(
+ clicked = true} />
+ );
+ rendered.clickOnOverlay();
+ expect(clicked).to.be.true;
+ });
+
+ it('will emit an event when the close button is clicked', () => {
+ let clicked = false;
+ const rendered = new SkylightInteractor(
+ clicked = true} />
+ );
+ rendered.clickOnClose();
+ expect(clicked).to.be.true;
+ });
+
+ it('will not blow up when no onCloseClicked prop is set', () => {
+ const rendered = new SkylightInteractor();
+ rendered.clickOnClose();
+ // no error thrown
+ });
+
+ it('will not blow up when no onOverlayClicked prop is set', () => {
+ const rendered = new SkylightInteractor();
+ rendered.clickOnOverlay();
+ // no error thrown
+ });
+});