material 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "material",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "A lightweight implementation of Material Design Components - ES6",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -0,0 +1,23 @@
1
+ class EventEmitter {
2
+ constructor () {
3
+ this.events = {}
4
+ }
5
+
6
+ on (event, listener) {
7
+ if (!this.events[event]) {
8
+ this.events[event] = []
9
+ }
10
+ this.events[event].push(listener)
11
+
12
+ return this
13
+ }
14
+
15
+ emit (event, ...args) {
16
+ if (this.events[event]) {
17
+ this.events[event].forEach(listener => listener.apply(this, args))
18
+ }
19
+ return this
20
+ }
21
+ }
22
+
23
+ export default EventEmitter
@@ -56,6 +56,10 @@ class Button {
56
56
  build () {
57
57
  this.root = document.createElement(this.options.tag)
58
58
 
59
+ this.element = this.root
60
+
61
+ // console.log('class', this.options.class)
62
+
59
63
  if (this.options.class !== 'button') {
60
64
  this.root.setAttribute('class', 'button ' + this.options.class)
61
65
  } else {
@@ -1,5 +1,3 @@
1
- 'use strict'
2
-
3
1
  // dialog related modules
4
2
  import emitter from '../module/emitter'
5
3
  import attach from '../module/attach'
@@ -27,7 +25,7 @@ let defaults = {
27
25
  ]
28
26
  ],
29
27
  events: [
30
- ['root.click', 'onClickRoot'],
28
+ ['element.click', 'onClickRoot'],
31
29
  ['surface.click', 'onClick'],
32
30
  ['ui.ok.click', 'ok'],
33
31
  ['ui.cancel.click', 'cancel'],
@@ -62,6 +60,8 @@ class Dialog {
62
60
  this.root = document.createElement('div')
63
61
  this.root.classList.add('dialog')
64
62
 
63
+ this.element = this.root
64
+
65
65
  if (this.options.class !== 'dialog') {
66
66
  this.root.classList.add(this.options.class)
67
67
  }
@@ -149,6 +149,7 @@ class Dialog {
149
149
  }
150
150
 
151
151
  onClickRoot (e) {
152
+ console.log('onClickRoot')
152
153
  e.stopPropagation()
153
154
  if (!this.options.modal) {
154
155
  this.destroy()
@@ -1,9 +1,22 @@
1
- import addClass from './module/addclass'
1
+ // menu related modules
2
+ import emitter from '../module/emitter'
3
+ import attach from '../module/attach'
4
+ import build from '../module/build'
5
+ import display from '../module/display'
6
+
7
+ import Layout from '../layout'
8
+ import Element from '../element'
9
+ import Button from './text'
2
10
 
3
11
  const defaults = {
4
- class: 'text',
5
- tag: 'span',
6
- seprator: ' | '
12
+ class: 'list',
13
+ layout: [
14
+ [Element, 'main', { tag: 'ul' }]
15
+ ],
16
+ item: [Text, { tag: 'li' }],
17
+ events: [
18
+ ['ui.main.click', 'select']
19
+ ]
7
20
  }
8
21
 
9
22
  class List {
@@ -14,40 +27,15 @@ class List {
14
27
  */
15
28
  constructor (options) {
16
29
  this.options = Object.assign({}, defaults, options || {})
17
-
18
- // console.log('options', this.options)
30
+ // implement modules
31
+ Object.assign(this, emitter, build, attach, display)
19
32
 
20
33
  this.build()
21
34
 
22
35
  return this
23
36
  }
24
37
 
25
- /**
26
- * Build Method
27
- * @return {Object} This class instance
28
- */
29
- build () {
30
- this.root = document.createElement(this.options.tag)
31
- addClass(this.root, this.options.class)
32
-
33
- if (this.options.class !== 'text') {
34
- this.root.classList.add('text')
35
- }
36
-
37
- if (this.options.list) {
38
- this.set(this.options.list)
39
- }
40
-
41
- if (this.options.container) {
42
- this.options.container.appendChild(this.root)
43
- }
44
-
45
- return this
46
- }
47
-
48
- set (list) {
49
- var text = ''
50
-
38
+ add (items) {
51
39
  for (var i = 0; i < list.length; i++) {
52
40
  if (i < list.length - 1) {
53
41
  text = text + list[i] + this.options.seprator
@@ -68,6 +56,8 @@ class List {
68
56
  }
69
57
  }
70
58
 
59
+ select()
60
+
71
61
  setText (text) {
72
62
  // console.log('setText', text)
73
63
  this.root.innerHTML = text
@@ -0,0 +1,85 @@
1
+ import EventEmitter from '../component/emitter'
2
+ // menu related modules
3
+ import build from '../module/build'
4
+ import bindEvents from '../module/events'
5
+ import display from '../module/display'
6
+
7
+ import Element from '../element'
8
+ import Button from './button'
9
+
10
+ class Menu extends EventEmitter {
11
+ static defaults = {
12
+ class: 'menu',
13
+ transition: 200,
14
+ modal: false,
15
+ layout: [
16
+ [Element, 'surface', { class: 'surface' },
17
+ [Element, 'list', { tag: 'ul', class: 'items' }]
18
+ ]
19
+ ],
20
+ events: [
21
+ ['element.click', 'close']
22
+ ]
23
+ };
24
+
25
+ constructor (options) {
26
+ super()
27
+
28
+ this.init(options)
29
+ this.build(this.constructor)
30
+ this.bindEvents()
31
+
32
+ this.render(this.options.items)
33
+ }
34
+
35
+ init(options) {
36
+ this.options = Object.assign({}, Menu.defaults, options || {})
37
+ Object.assign(this, build, bindEvents, display)
38
+ }
39
+
40
+ render (items) {
41
+ if (items && Array.isArray(items)) {
42
+ for (var i = 0; i < items.length; i++) {
43
+ this.add(items[i])
44
+ }
45
+ }
46
+
47
+ return this
48
+ }
49
+
50
+ add (obj) {
51
+ if (typeof obj !== 'object') return this;
52
+ let item;
53
+ if (obj.type === 'divider') {
54
+ item = new Element({ tag: 'li', class: 'divider' })
55
+ } else {
56
+ obj.container = this.ui.list
57
+ obj.class = 'item'
58
+ item = new Button(obj).on('click', (ev) => {
59
+ // console.log('select', ev.target.name)
60
+ this.emit('select', ev.target.name)
61
+ })
62
+ }
63
+
64
+ return this
65
+ }
66
+
67
+ position(target) {
68
+ if (!target) return
69
+ var offs = target.getBoundingClientRect()
70
+
71
+ var offsw = this.offset = this.ui.surface.getBoundingClientRect()
72
+
73
+ this.ui.surface.style.top = (offs.top - 4) + 'px'
74
+ this.ui.surface.style.left = offs.left - offsw.width + offs.width + 'px'
75
+
76
+ return this
77
+ }
78
+
79
+ close() {
80
+ // console.log('close')
81
+ this.destroy()
82
+ }
83
+ }
84
+
85
+ export default Menu
@@ -0,0 +1,89 @@
1
+ // base class
2
+ import EventEmitter from '../component/emitter'
3
+ // related modules
4
+ import build from '../module/build'
5
+ import bindEvents from '../module/events'
6
+ import display from '../module/display'
7
+ // ui element
8
+ import Text from './text'
9
+ import Button from './button'
10
+
11
+ class Snackbar extends EventEmitter {
12
+ static defaults = {
13
+ class: 'snackbar',
14
+ transition: 225,
15
+ duration: 4000,
16
+ close: false,
17
+ layout: [
18
+ [Text, 'text', { tag: 'span', class: 'text' }],
19
+ [Button, 'action', { class: 'action', type: 'link' }],
20
+ [Button, 'close', { class: 'close', type: 'action' }]
21
+ ],
22
+ events: [
23
+ ['ui.action.click', 'action'],
24
+ ['ui.close.click', 'destroy']
25
+ ]
26
+ };
27
+
28
+ constructor (options) {
29
+ super()
30
+
31
+ this.init(options)
32
+ this.build(this.constructor)
33
+ this.render()
34
+ this.bindEvents()
35
+ this.show()
36
+
37
+ if (this.options.duration)
38
+ setTimeout(()=>{
39
+ this.destroy()
40
+ }, this.options.duration)
41
+ }
42
+
43
+ init(options) {
44
+ this.options = Object.assign({}, Snackbar.defaults, options || {})
45
+ Object.assign(this, build, bindEvents, display)
46
+
47
+ this.buildSnackbarContainer(this.options.container)
48
+ }
49
+
50
+ buildSnackbarContainer (container = document.body) {
51
+ console.log('buildSnackbarContainer', container)
52
+
53
+ let snackbarContainer = container.querySelector('.snackbars')
54
+
55
+ console.log('snackbarContainer', snackbarContainer)
56
+
57
+ if (!snackbarContainer) {
58
+ this.options.container = document.createElement('div')
59
+ this.options.container.classList.add('snackbars')
60
+ container.appendChild(this.options.container)
61
+ } else {
62
+ this.options.container = snackbarContainer
63
+ }
64
+ }
65
+
66
+ render () {
67
+ this.ui.text.set(this.options.text)
68
+ if (this.options.action) {
69
+ this.ui.action.set(this.options.action)
70
+ this.ui.action.element.classList.add('show')
71
+ }
72
+
73
+ if (this.options.close) this.ui.close.element.classList.add('show')
74
+
75
+ return this
76
+ }
77
+
78
+ action () {
79
+ this.emit('action')
80
+ this.destroy()
81
+ }
82
+
83
+ close() {
84
+ // console.log('close')
85
+ this.destroy()
86
+ }
87
+ }
88
+
89
+ export default Snackbar
@@ -50,7 +50,11 @@ class Text {
50
50
 
51
51
  var label = this.options.label || ''
52
52
 
53
- this.root.innerHTML = label + text
53
+ if (this.options.textFirst) {
54
+ this.root.innerHTML = text + label
55
+ } else {
56
+ this.root.innerHTML = label + text
57
+ }
54
58
 
55
59
  if (this.options.spaceAfter) {
56
60
  this.root.innerHTML = this.root.innerHTML + ' '
package/src/element.js CHANGED
@@ -1,46 +1,21 @@
1
-
2
- /**
3
- * Class Element
4
- * @class
5
- * @since 0.0.1
6
- * @example
7
- * var div = new Element({
8
- * tag: 'div',
9
- * class: 'mydiv',
10
- * })
11
- */
12
-
13
1
  class Element {
14
2
  static isElement () {
15
3
  return true
16
4
  }
17
5
 
18
- /**
19
- * The init method of the Button class
20
- * @param {Object} The element attributes
21
- * @private
22
- * @return {DOMElement} The dom element
23
- */
24
6
  constructor (options) {
25
7
  this.options = Object.assign({}, options || {})
26
8
  // console.log('element options', options)
27
9
  var element = document.createElement(this.options.tag || 'div')
10
+ delete this.options.tag
28
11
 
29
- if (options.html) {
30
- element.innerHTML = this.options.html
31
- }
32
-
33
- if (options.text) {
34
- element.textContent = this.options.text
35
- }
36
-
37
- if (options.id) {
38
- element.setAttribute('id', options.id)
39
- }
12
+ if (options.html) element.innerHTML = this.options.html
13
+ delete this.options.html
40
14
 
41
- delete this.options.tag
15
+ if (options.text) element.textContent = this.options.text
42
16
  delete this.options.text
43
- delete this.options.html
17
+
18
+ if (options.id) element.setAttribute('id', options.id)
44
19
 
45
20
  for (var property in this.options) {
46
21
  if (this.options.hasOwnProperty(property)) {
@@ -0,0 +1,43 @@
1
+ import dataset from './dataset'
2
+ import Layout from '../layout'
3
+
4
+ export default {
5
+ build () {
6
+ this.element = document.createElement(this.options.tag || 'div')
7
+ // for backward compatibility
8
+ this.root = this.element
9
+
10
+ const defaults = this.constructor.defaults || {}
11
+
12
+ this.element.classList.add(defaults.class)
13
+
14
+ if (this.options.class !== defaults.class) {
15
+ this.addClass(this.options.class)
16
+ }
17
+
18
+ if (this.options.data) {
19
+ dataset(this.root, this.options.data)
20
+ }
21
+
22
+ this.container = this.options.container
23
+
24
+ if (this.container) this.appendTo(this.container)
25
+
26
+ if (this.options.layout) {
27
+ this.layout = new Layout(this.options.layout, this.element)
28
+ this.ui = this.layout.component
29
+ }
30
+
31
+ if (this.options.show === true && this.show) this.show()
32
+ },
33
+
34
+ appendTo (container) {
35
+ container.appendChild(this.element)
36
+ },
37
+
38
+ addClass (c) {
39
+ const list = c.split(' ')
40
+ list.forEach(item => this.element.classList.add(item))
41
+ }
42
+
43
+ }
@@ -0,0 +1,12 @@
1
+
2
+ function dataset (element, data) {
3
+ if (data) {
4
+ for (var property in data) {
5
+ if (data.hasOwnProperty(property)) {
6
+ element.dataset[property] = data[property]
7
+ }
8
+ }
9
+ }
10
+ }
11
+
12
+ export default dataset
@@ -0,0 +1,88 @@
1
+
2
+ export default {
3
+ toggle () {
4
+ this.visible ? this.hide() : this.show()
5
+
6
+ this.emit?.('toggle')
7
+ return this
8
+ },
9
+
10
+ show () {
11
+ console.log('show', this.visible)
12
+
13
+ // if (this.options.transition) {
14
+ // this.element.style.display = 'initial'
15
+ // }
16
+
17
+ this.element.getBoundingClientRect()
18
+
19
+ this.element.classList.add('show')
20
+ this.visible = true
21
+
22
+ if (this.underlay) {
23
+ this.underlay.classList.add('show')
24
+ }
25
+
26
+ this.emit?.('show')
27
+ return this
28
+ },
29
+
30
+ hide () {
31
+ console.log('hide')
32
+ // if (this.element.style.display === 'none') return
33
+ // clearTimeout(this.displayTimeout)
34
+ // this._display = getComputedStyle(this.root).display
35
+
36
+ if (!this.root) return
37
+
38
+ this.element.classList.remove('show')
39
+ this.visible = false
40
+
41
+ if (this.underlay) {
42
+ this.underlay.classList.remove('show')
43
+ }
44
+
45
+ // if (this.options.transition) {
46
+ // this.displayTimeout = setTimeout(() => {
47
+ // console.log('display: none', this._display)
48
+ // this.element.style.display = 'none'
49
+ // }, this.options.transition)
50
+ // }
51
+
52
+ this.emit?.('hide')
53
+ return this
54
+ },
55
+
56
+ destroy () {
57
+ // console.log('destroy', this.options.transition, this.root)
58
+ if (this.options.transition && this.root) {
59
+ this.element.classList.remove('show')
60
+
61
+ if (this.underlay) {
62
+ this.underlay.classList.remove('show')
63
+ }
64
+
65
+ setTimeout(() => {
66
+ this.removeChild()
67
+ }, this.options.transition)
68
+ } else {
69
+ this.removeChild()
70
+ }
71
+
72
+ this.emit?.('destroy')
73
+ },
74
+
75
+ removeChild () {
76
+ if (this.root && this.element.parentNode) {
77
+ this.element.parentNode.removeChild(this.root)
78
+ this.root = null
79
+ }
80
+
81
+ if (this.underlay && this.underlay.parentNode) {
82
+ this.underlay.parentNode.removeChild(this.underlay)
83
+ }
84
+
85
+ this.emit?.('remove')
86
+ return this
87
+ }
88
+ }
@@ -0,0 +1,55 @@
1
+ import extract from './extract'
2
+
3
+ export default {
4
+ bindEvents: function (events) {
5
+ console.log('bindEvents', events)
6
+ events = events || this.options.events
7
+ if (!events) return
8
+
9
+ console.log('attach', events, this)
10
+ var instance = this
11
+ events.map((def) => {
12
+ var e = extract.e(instance, def[0])
13
+ var f = extract.f(instance, def[1])
14
+ var option = def[2]
15
+
16
+ var keys = def[1].split('.')
17
+
18
+ keys.pop()
19
+ var bound = this.last(keys.join('.'))
20
+
21
+ if (f && bound && e && e.element && e.element.addEventListener) {
22
+ if (!f) { console.log('error') }
23
+
24
+ if (option) {
25
+ e.element.addEventListener(e.name, f.bind(bound), option)
26
+ } else {
27
+ e.element.addEventListener(e.name, f.bind(bound))
28
+ }
29
+ } else if (e && e.element && e.element.on && f && bound) {
30
+ e.element.on(e.name, f.bind(bound))
31
+ } else {
32
+ // console.log('can\'t attach', def[0])
33
+ }
34
+ })
35
+
36
+ return this
37
+ },
38
+
39
+ last: function (str) {
40
+ // console.log('_path', str)
41
+ if (!str) return this
42
+ else if (!str.match(/\./)) return this[str]
43
+ var last
44
+
45
+ var keys = str.split('.')
46
+ for (var i = 0, l = keys.length; i < l; i++) {
47
+ var key = keys[i]
48
+
49
+ last = last || this
50
+ last = last[key]
51
+ }
52
+
53
+ return last
54
+ }
55
+ }
@@ -0,0 +1,20 @@
1
+ export default function jsonToHTML (obj) {
2
+ // Start an HTML string
3
+ let html = '<div>'
4
+
5
+ // Loop through each property of the object
6
+ for (const [key, value] of Object.entries(obj)) {
7
+ // If the value is an object, call the function recursively
8
+ if (typeof value === 'object' && value !== null) {
9
+ html += `<div class="${key}">${key}${jsonToHTML(value)}</div>`
10
+ } else if (Array.isArray(value)) {
11
+ html += `<div class="${key}">${key}<ul>${value.map(item => `<li>${item}</li>`).join('')}</ul></div>`
12
+ } else {
13
+ html += `<p>${key}: ${value || 'N/A'}</p>`
14
+ }
15
+ }
16
+
17
+ // Close the HTML string
18
+ html += '</div>'
19
+ return html
20
+ }
@@ -0,0 +1,29 @@
1
+ .menu
2
+ //display: none
3
+ &.show
4
+ //display: block
5
+ .surface
6
+ background: rgba(0,0,0,.05)
7
+ .list
8
+ background: white
9
+ .item
10
+ color: rgba(0,0,0,.87)
11
+
12
+ &.floating
13
+ position: fixed
14
+ top: 0
15
+ left: 0
16
+ bottom: 0
17
+ right: 0
18
+ background-color: rgba(0, 0, 0, 0.5)
19
+ display: flex
20
+ align-items: center
21
+ justify-content: center
22
+ overflow: hidden
23
+ opacity: 0
24
+ transition: 0.2s
25
+ .surface
26
+ position: absolute
27
+ background-color: white
28
+
29
+
@@ -0,0 +1,65 @@
1
+ $width: 500px
2
+
3
+ .snackbars
4
+ position: absolute
5
+ z-index: 300
6
+ display: flex
7
+ width: $width
8
+ flex-direction: column
9
+ background-color: rgba(0,0,0,.1)
10
+ bottom: 160px
11
+ width: 100%
12
+ .snackbar
13
+ overflow: hidden
14
+ display: flex
15
+ opacity: 0
16
+ height: 2px
17
+ flex-direction: row
18
+ padding: 0
19
+ margin: 2px
20
+ background-color: #322F35
21
+ border-radius: 4px
22
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2)
23
+ transition: 225ms opacity cubic-bezier(.4,0,.2,1), 225ms height cubic-bezier(.4,0,.2,1), 225ms padding cubic-bezier(.4,0,.2,1)
24
+ &.show
25
+ opacity: 1
26
+ padding: 8px
27
+ height: initial
28
+ transition: 225ms opacity cubic-bezier(.4,0,.2,1), 225ms height cubic-bezier(.4,0,.2,1), 225ms padding cubic-bezier(.4,0,.2,1)
29
+ .text
30
+ line-height: 2em
31
+ padding-left: 8px
32
+ flex: 1
33
+ color: rgba(255,255,255,.87)
34
+ button.action
35
+ flex:none
36
+ display: none
37
+ color: green
38
+ .show
39
+ display: inline-block
40
+ .close
41
+ flex: none
42
+ display: none
43
+ width: 24px
44
+ height: 24px
45
+ min-width: 24px
46
+ background-image: url('../../theme/common/icon/dark/close.svg')
47
+ background-color: transparent
48
+ &:hover, &:active
49
+ background-color: transparent
50
+ &.show
51
+ display: inline-block
52
+
53
+
54
+ @media only screen and (min-width: $desktop_switch)
55
+ .snackbars
56
+ left: 50%
57
+ bottom: 200px
58
+ margin-left: -$width / 2
59
+ width: $width
60
+ transition: 195ms bottom cubic-bezier(0.4, 0, 0.2, 1)
61
+ &.up
62
+ bottom: 500px
63
+ transition: 225ms bottom cubic-bezier(0.4, 0, 0.2, 1)
64
+
65
+
package/src/view/build.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import scrollbar from '../module/scrollbar'
2
- import dataset from './dataset'
2
+ import dataset from '../module/dataset'
3
3
  import Layout from '../layout'
4
4
 
5
5
  export default {
@@ -31,7 +31,7 @@ export default {
31
31
  },
32
32
 
33
33
  hide () {
34
- // console.log('hide', this.root.style.display)
34
+ // console.log('hide')
35
35
  // if (this.root.style.display === 'none') return
36
36
  // clearTimeout(this.displayTimeout)
37
37
  // this._display = getComputedStyle(this.root).display