stalefish 8.0.0 → 8.0.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.
@@ -1,46 +1,5 @@
1
- import { html, Component, LRU } from 'halfcab'
2
- import * as deepDiff from 'deep-object-diff'
3
- import clone from 'fast-clone'
1
+ import { html } from 'halfcab'
4
2
 
5
- let cache = new LRU(300)
6
-
7
- class Button extends Component {
8
- createElement (args) {
9
- this.args = clone(args)
10
- this.action = args.action
11
- let { width, minWidth, height, text, colour, disabled } = args
12
-
13
- return html`
14
- <button style="${disabled ? 'opacity: 0.3;' : ''}font-family: inherit; line-height: inherit; cursor: ${disabled ? 'not-allowed' : 'pointer'}; background-color: ${colour}; ${minWidth ? `min-width: ${minWidth};` : ''} border-radius: 3px; margin: 30px 10px; width: ${width}; height: ${height}; border: none; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); font-size: 17px; color: white;" ${disabled ? 'disabled' : ''} onclick=${e => this.action(e)}>${text}</button>
15
- `
16
- }
17
-
18
- update (args) {
19
- let diff = deepDiff.diff(this.args, args)
20
- Object.keys(diff).forEach(key => {
21
- if (typeof diff[key] === 'function') {
22
- this[key] = args[key]
23
- }
24
- })
25
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
26
- }
27
- }
28
-
29
- function button (args) {
30
- let instance
31
- if (args.uniqueKey) {
32
- let found = cache.get(args.uniqueKey)
33
- if (found) {
34
- instance = found
35
- } else {
36
- instance = new Button()
37
- cache.set(args.uniqueKey, instance)
38
- }
39
- return instance.render(args)
40
- } else {
41
- instance = new Button()
42
- return instance.createElement(args)
43
- }
44
- }
45
-
46
- export default args => button(args)
3
+ export default ({ width, minWidth, height, text, colour, disabled }) => html`
4
+ <button style="${disabled ? 'opacity: 0.3;' : ''}font-family: inherit; line-height: inherit; cursor: ${disabled ? 'not-allowed' : 'pointer'}; background-color: ${colour}; ${minWidth ? `min-width: ${minWidth};` : ''} border-radius: 3px; margin: 30px 10px; width: ${width}; height: ${height}; border: none; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); font-size: 17px; color: white;" ?disabled=${disabled} onclick=${e => this.action(e)}>${text}</button>
5
+ `
@@ -1,8 +1,4 @@
1
- import { html, css, formField, fieldIsTouched, Component, LRU } from 'halfcab'
2
- import * as deepDiff from 'deep-object-diff'
3
- import clone from 'fast-clone'
4
-
5
- let cache = new LRU(300)
1
+ import { html, css, formField, fieldIsTouched } from 'halfcab'
6
2
 
7
3
  let styles = css`
8
4
  .checkbox {
@@ -33,52 +29,21 @@ let styles = css`
33
29
  }
34
30
  `
35
31
 
36
- class Checkbox extends Component {
37
- createElement (args) {
38
- this.args = clone(args)
39
- this.onchange = args.onchange
40
- let { wrapperStyle, holdingPen, label, property, required, indeterminate, disabled, darkBackground } = args
41
-
42
- let checkboxEl = html`<input data-gramm="false" ${disabled ? { disabled } : ''} style="${disabled ? 'cursor: not-allowed;' : ''}" class="${styles.checkbox} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" value="${holdingPen[property] === true ? 'true' : null}" ${holdingPen[property] === true ? { checked: 'checked' } : ''} onchange=${e => {
43
- formField(holdingPen, property)(e)
44
- this.onchange && this.onchange(e)
45
- }} type="checkbox" ${required ? { required: 'required' } : ''} />`
46
-
47
- checkboxEl.indeterminate = indeterminate || false
32
+ export default ({ wrapperStyle, holdingPen, label, property, required, indeterminate, disabled, darkBackground, onchange }) => {
33
+ let checkboxEl = html`<input data-gramm="false" ${disabled ? { disabled } : ''} style="${disabled ? 'cursor: not-allowed;' : ''}" class="${styles.checkbox} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" value="${holdingPen[property] === true ? 'true' : null}" ?checked=${holdingPen[property] === true} onchange=${e => {
34
+ formField(holdingPen, property)(e)
35
+ onchange && onchange(e)
36
+ }} type="checkbox" ${required ? { required: 'required' } : ''} />`
48
37
 
49
- return html`
50
- <label style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}text-align: left; width: 100%; display: inline-block; vertical-align: bottom;" ${wrapperStyle ? { 'class': wrapperStyle } : ''}>
51
- <span class="${styles.label}" style="background-color: rgba(255,255,255,${darkBackground ? 1 : 0.8});">${label}${required ? ' *' : ''}${checkboxEl}</span>
52
- </label>
53
- `
54
- }
38
+ checkboxEl.indeterminate = indeterminate || false
55
39
 
56
- update (args) {
57
- let diff = deepDiff.diff(this.args, args)
58
- Object.keys(diff).forEach(key => {
59
- if (typeof diff[key] === 'function') {
60
- this[key] = args[key]
61
- }
62
- })
63
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
64
- }
65
- }
40
+ const wrapperClassName = wrapperStyle
41
+ ? (typeof wrapperStyle === 'string' ? wrapperStyle : (wrapperStyle.toString ? wrapperStyle.toString() : ''))
42
+ : ''
66
43
 
67
- function checkbox (args) {
68
- let instance
69
- if (args.uniqueKey) {
70
- let found = cache.get(args.uniqueKey)
71
- if (found) {
72
- instance = found
73
- } else {
74
- instance = new Checkbox()
75
- cache.set(args.uniqueKey, instance)
76
- }
77
- return instance.render(args)
78
- } else {
79
- instance = new Checkbox()
80
- return instance.createElement(args)
81
- }
44
+ return html`
45
+ <label style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}text-align: left; width: 100%; display: inline-block; vertical-align: bottom;" class="${wrapperClassName}">
46
+ <span class="${styles.label}" style="background-color: rgba(255,255,255,${darkBackground ? 1 : 0.8});">${label}${required ? ' *' : ''}${checkboxEl}</span>
47
+ </label>
48
+ `
82
49
  }
83
-
84
- export default args => checkbox(args)
@@ -1,11 +1,7 @@
1
- import { html, css, formField, fieldIsTouched, Component, LRU } from 'halfcab'
1
+ import { html, css, formField, fieldIsTouched } from 'halfcab'
2
2
  import flatpickr from 'flatpickr'
3
3
  import calendarIcon from './icons/calendarIcon.mjs'
4
4
  import timeIcon from './icons/timeIcon.mjs'
5
- import clone from 'fast-clone'
6
- import * as deepDiff from 'deep-object-diff'
7
-
8
- let cache = new LRU(300)
9
5
 
10
6
  let styles = css`
11
7
  .textfield {
@@ -108,15 +104,8 @@ function detectTouchscreen () {
108
104
  return result
109
105
  }
110
106
 
111
- class DateTimePicker extends Component {
112
- createElement (args) {
113
- this.args = clone(args)
114
- this.onchange = args.onchange
115
- this.oninput = args.oninput
116
-
117
- let { wrapperStyle = null, holdingPen, label, placeholder, property, required, pattern, permanentTopPlaceholder = true, permanentTopLabel = false, flatpickrConfig = {}, timeOnly = false, disabled, disableClear = false } = args
118
-
119
- let el = html`
107
+ export default ({ wrapperStyle = null, holdingPen, label, placeholder, property, required, pattern, permanentTopPlaceholder = true, permanentTopLabel = false, flatpickrConfig = {}, timeOnly = false, disabled, disableClear = false, onchange, oninput }) => {
108
+ let el = html`
120
109
  <div ${wrapperStyle ? { 'class': wrapperStyle } : ''} style="min-height: 55px; display: inline-block; width: calc(100% - 10px); margin: 40px 5px 5px 5px;">
121
110
  <div style="display: inline-block; width: 100%; text-align: left; position: relative; padding: 0;">
122
111
  <div class="${styles.icon}">${timeOnly ? timeIcon({ colour: '#ccc' }) : calendarIcon({ colour: '#ccc' })}</div>
@@ -128,7 +117,7 @@ class DateTimePicker extends Component {
128
117
  e.target.parentNode.parentNode._flatpickr.close()
129
118
  return false
130
119
  }}>clear</div>` : ''}
131
- <input data-gramm="false" ${disabled ? { disabled } : ''} style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}" class="${styles.textfield} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" ${required ? { required: 'required' } : ''} onfocus=${e => {
120
+ <input data-gramm="false" ?disabled=${disabled} style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}" class="${styles.textfield} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" ${required ? { required: 'required' } : ''} onfocus=${e => {
132
121
  e.target.parentNode.parentNode._flatpickr && e.target.parentNode.parentNode._flatpickr.set('onValueUpdate', (fpDate, dateString) => {
133
122
  let fauxE = {
134
123
  currentTarget: {
@@ -139,58 +128,28 @@ class DateTimePicker extends Component {
139
128
  }
140
129
  }
141
130
  formField(holdingPen, property)(fauxE)
142
- this.onchange && this.onchange(fauxE)
131
+ onchange && onchange(fauxE)
143
132
  })
144
- }} onchange=${e => { change({ e, holdingPen, property, label: styles.label }); this.onchange && this.onchange(e) }} oninput=${e => { e.target.defaultValue = ''; this.oninput && this.oninput(e) }} placeholder="${placeholder || ''}${required ? ' *' : ''}" type="${detectTouchscreen() ? timeOnly ? 'time' : 'date' : 'text'}" ${pattern ? { pattern } : ''} value="${holdingPen[property] || ''}" data-input />
133
+ }} onchange=${e => { change({ e, holdingPen, property, label: styles.label }); onchange && onchange(e) }} oninput=${e => { e.target.defaultValue = ''; oninput && oninput(e) }} placeholder="${placeholder || ''}${required ? ' *' : ''}" type="${detectTouchscreen() ? timeOnly ? 'time' : 'date' : 'text'}" ${pattern ? { pattern } : ''} value="${holdingPen[property] || ''}" data-input />
145
134
  </div>
146
135
  </div>
147
136
  `
148
137
 
149
- this.flatpickr = flatpickr(el, Object.assign(flatpickrConfig, {
150
- wrap: true,
151
- onValueUpdate: (fpDate, dateString) => {
152
- let fauxE = {
153
- currentTarget: {
154
- validity: {
155
- valid: true
156
- },
157
- value: dateString
158
- }
138
+ this.flatpickr = flatpickr(el, Object.assign(flatpickrConfig, {
139
+ wrap: true,
140
+ onValueUpdate: (fpDate, dateString) => {
141
+ let fauxE = {
142
+ currentTarget: {
143
+ validity: {
144
+ valid: true
145
+ },
146
+ value: dateString
159
147
  }
160
- formField(holdingPen, property)(fauxE)
161
- this.onchange && this.onchange(fauxE)
162
- }
163
- }, timeOnly ? { noCalendar: true, enableTime: true } : null))
164
-
165
- return el
166
- }
167
-
168
- update (args) {
169
- let diff = deepDiff.diff(this.args, args)
170
- Object.keys(diff).forEach(key => {
171
- if (typeof diff[key] === 'function') {
172
- this[key] = args[key]
173
148
  }
174
- })
175
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
176
- }
177
- }
178
-
179
- function dateTimePicker (args) {
180
- let instance
181
- if (args.uniqueKey) {
182
- let found = cache.get(args.uniqueKey)
183
- if (found) {
184
- instance = found
185
- } else {
186
- instance = new DateTimePicker()
187
- cache.set(args.uniqueKey, instance)
149
+ formField(holdingPen, property)(fauxE)
150
+ onchange && onchange(fauxE)
188
151
  }
189
- return instance.render(args)
190
- } else {
191
- instance = new DateTimePicker()
192
- return instance.createElement(args)
193
- }
194
- }
152
+ }, timeOnly ? { noCalendar: true, enableTime: true } : null))
195
153
 
196
- export default args => dateTimePicker(args)
154
+ return el
155
+ }
@@ -1,8 +1,4 @@
1
- import { html, css, Component, LRU } from 'halfcab'
2
- import * as deepDiff from 'deep-object-diff'
3
- import clone from 'fast-clone'
4
-
5
- let cache = new LRU(300)
1
+ import { html, css } from 'halfcab'
6
2
 
7
3
  let styles = css`
8
4
 
@@ -38,45 +34,13 @@ let styles = css`
38
34
  }
39
35
  `
40
36
 
41
- class Dropdown extends Component {
42
- createElement (args) {
43
- this.args = clone(args)
44
- // TODO - for menu items where the action changes, we need to use this.item.action
45
- let { menuItems, visible, side, width, margin, backgroundColour } = args
46
-
47
- return html`
48
- <div tabindex="-1" class="${styles.dropdown}" style="position: relative; z-index: 100000; ${!visible ? 'display: none;' : ''}${side === 'right' ? 'float: right;' : ''}">
49
- <div class="${styles.dropdownContent}" style="background-color: ${backgroundColour || '#f9f9f9'}; ${side === 'right' ? 'right: 0;' : ''} width: ${width || '160px'};${margin ? `margin: ${margin};` : ''}">
50
- ${menuItems.filter(item => !item.visibleUnder || (item.visibleUnder && typeof window !== 'undefined' && window.innerWidth <= parseInt(item.visibleUnder)))
37
+ export default ({ menuItems, visible, side, width, margin, backgroundColour }) => html`
38
+ <div tabindex="-1" class="${styles.dropdown}" style="position: relative; z-index: 100000; ${!visible ? 'display: none;' : ''}${side === 'right' ? 'float: right;' : ''}">
39
+ <div class="${styles.dropdownContent}" style="background-color: ${backgroundColour || '#f9f9f9'}; ${side === 'right' ? 'right: 0;' : ''} width: ${width || '160px'};${margin ? `margin: ${margin};` : ''}">
40
+ ${menuItems.filter(item => !item.visibleUnder || (item.visibleUnder && typeof window !== 'undefined' && window.innerWidth <= parseInt(item.visibleUnder)))
51
41
  .map(item => html`
52
- ${item.separator ? html`<hr class="${styles.separator}">` : item.disabled === true ? html`<div style="opacity: 0.3; pointer-events: none;">${item.text}</div>` : html`<div style="cursor: pointer;" onclick=${item.action}>${item.text}</div>`}
53
- `)}
54
- </div>
55
- </div>
56
- `
57
- }
58
-
59
- update (args) {
60
- let diff = deepDiff.diff(this.args, args)
61
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
62
- }
63
- }
64
-
65
- function dropdown (args) {
66
- let instance
67
- if (args.uniqueKey) {
68
- let found = cache.get(args.uniqueKey)
69
- if (found) {
70
- instance = found
71
- } else {
72
- instance = new Dropdown()
73
- cache.set(args.uniqueKey, instance)
74
- }
75
- return instance.render(args)
76
- } else {
77
- instance = new Dropdown()
78
- return instance.createElement(args)
79
- }
80
- }
81
-
82
- export default args => dropdown(args)
42
+ ${item.separator ? html`<hr class="${styles.separator}">` : item.disabled === true ? html`<div style="opacity: 0.3; pointer-events: none;">${item.text}</div>` : html`<div style="cursor: pointer;" onclick=${item.action}>${item.text}</div>`}
43
+ `)}
44
+ </div>
45
+ </div>
46
+ `
@@ -1,4 +1,4 @@
1
- import { html, css, Component } from 'halfcab'
1
+ import { html, css } from 'halfcab'
2
2
 
3
3
  let styles = css`
4
4
  .progress {
@@ -63,16 +63,6 @@ let styles = css`
63
63
  right: -8%; } }
64
64
  `
65
65
 
66
- class Loader extends Component {
67
- createElement ({ on }) {
68
- this.on = on
69
- return on === true ? html`<div class="${styles.progress} indeterminate"></div>` : html`<div></div>`
70
- }
71
-
72
- update ({ on }) {
73
- return on !== this.on
74
- }
66
+ export default ({ on }) => {
67
+ return on === true ? html`<div class="${styles.progress} indeterminate"></div>` : html`<div></div>`
75
68
  }
76
-
77
- let loader = new Loader()
78
- export default args => loader.render(args)
@@ -1,13 +1,9 @@
1
- import { html, css, Component, LRU } from 'halfcab'
1
+ import { html, css } from 'halfcab'
2
2
  import close from './icons/close.mjs'
3
3
  import up from './icons/up.mjs'
4
4
  import down from './icons/down.mjs'
5
5
  import moreVertical from './icons/moreVertical.mjs'
6
6
  import dropdown from './dropdown.mjs'
7
- import * as deepDiff from 'deep-object-diff'
8
- import clone from 'fast-clone'
9
-
10
- let cache = new LRU(2000)
11
7
 
12
8
  let styles = css`
13
9
  .panel h3 {
@@ -37,28 +33,15 @@ let styles = css`
37
33
  }
38
34
  `
39
35
 
40
- class Panel extends Component {
41
- createElement (args) {
42
- this.args = clone(args)
43
- this.headerAction = args.headerAction
44
- this.dragStartAction = args.dragStartAction
45
- this.dragOverAction = args.dragOverAction
46
- this.dragEndAction = args.dragEndAction
47
- this.dragLeaveAction = args.dragLeaveAction
48
- this.draggable = args.draggable
49
- this.collapseToggleAction = args.collapseToggleAction
50
- this.closeAction = args.closeAction
51
-
52
- let { chevronStyle = null, on = true, content, heading = '', collapsed = false, thinBorder = false, light = false, optionsMenu, tooltipHeading = false } = args
53
-
54
- return on ? html`<div ondragover=${e => {
55
- if (this.dragOverAction) {
56
- e.preventDefault()
57
- e.dataTransfer.dropEffect = 'move'
58
- }
59
- }} class="${styles.panel}" style='box-sizing: border-box; position: relative; top: 0; left: 0; text-align: left; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); border: solid ${thinBorder ? '3px' : '5px'} ${light ? '#DDD' : '#4371AD'}; background-color: #FBFBFB;'>
60
- <div title="${tooltipHeading && collapsed ? heading : ''}" style="position: relative;" ondragleave="${e => this.dragLeaveAction && this.dragLeaveAction(e)}" ondragend="${e => this.dragEndAction && this.dragEndAction(e)}" ondragover="${e => this.dragOverAction && this.dragOverAction(e)}" ondragstart="${e => this.dragStartAction && this.dragStartAction(e)}" draggable="${this.draggable ? 'true' : ''}" >
61
- ${heading ? html`<div class="${styles.header}" onclick=${e => this.headerAction && this.headerAction(e)}>
36
+ export default ({ chevronStyle = null, on = true, content, heading = '', collapsed = false, thinBorder = false, light = false, optionsMenu, tooltipHeading = false, headerAction, dragStartAction, dragOverAction, dragEndAction, dragLeaveAction, draggable, collapseToggleAction, closeAction }) => {
37
+ return on ? html`<div ondragover=${e => {
38
+ if (dragOverAction) {
39
+ e.preventDefault()
40
+ e.dataTransfer.dropEffect = 'move'
41
+ }
42
+ }} class="${styles.panel}" style='box-sizing: border-box; position: relative; top: 0; left: 0; text-align: left; box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); border: solid ${thinBorder ? '3px' : '5px'} ${light ? '#DDD' : '#4371AD'}; background-color: #FBFBFB;'>
43
+ <div title="${tooltipHeading && collapsed ? heading : ''}" style="position: relative;" ondragleave="${e => dragLeaveAction && dragLeaveAction(e)}" ondragend="${e => dragEndAction && dragEndAction(e)}" ondragover="${e => dragOverAction && dragOverAction(e)}" ondragstart="${e => dragStartAction && dragStartAction(e)}" draggable="${draggable ? 'true' : ''}" >
44
+ ${heading ? html`<div class="${styles.header}" onclick=${e => headerAction && headerAction(e)}>
62
45
  <h3 style="margin: 12px; max-width: calc(100% - ${optionsMenu ? '70' : '50'}px); color: ${light ? '#555;' : '#22487e'} ${collapsed ? 'text-overflow: ellipsis; white-space: nowrap; overflow: hidden;' : ''}">${heading}</h3>
63
46
 
64
47
  ${optionsMenu ? html`<div style="position: absolute; right: 45px; top: 13px;">
@@ -76,40 +59,10 @@ ${dropdown({
76
59
  </div>` : ''}
77
60
  </div>` : ''}
78
61
  </div>
79
- ${this.closeAction && !this.collapseToggleAction ? html`<div style="position: absolute; width: 20px; height: 20px; right: 5px; top: 5px; cursor: pointer;" onclick=${this.closeAction}><div style="display: flex; justify-content: center; align-items: center;">${close({ colour: '#22487e' })}</div></div>` : ''}
62
+ ${closeAction && !collapseToggleAction ? html`<div style="position: absolute; width: 20px; height: 20px; right: 5px; top: 5px; cursor: pointer;" onclick=${closeAction}><div style="display: flex; justify-content: center; align-items: center;">${close({ colour: '#22487e' })}</div></div>` : ''}
80
63
 
81
- ${this.collapseToggleAction ? html`<div ${chevronStyle ? { 'class': chevronStyle } : ''} style="position: absolute; width: 50px; height: 50px; right: 0; margin-top: -3px; top: 5px; cursor: pointer;" onclick=${this.collapseToggleAction}><div style="display: flex; justify-content: center; align-items: center;">${collapsed ? down({ colour: light ? '#999' : '#22487e', width: '40px', height: '50px' }) : up({ colour: light ? '#999' : '#22487e', width: '40px', height: '40px' })}</div></div>` : ''}
64
+ ${collapseToggleAction ? html`<div ${chevronStyle ? { 'class': chevronStyle } : ''} style="position: absolute; width: 50px; height: 50px; right: 0; margin-top: -3px; top: 5px; cursor: pointer;" onclick=${collapseToggleAction}><div style="display: flex; justify-content: center; align-items: center;">${collapsed ? down({ colour: light ? '#999' : '#22487e', width: '40px', height: '50px' }) : up({ colour: light ? '#999' : '#22487e', width: '40px', height: '40px' })}</div></div>` : ''}
82
65
 
83
66
  ${collapsed === false ? typeof content === 'function' ? content() : content : ''}
84
67
  </div>` : ''
85
- }
86
-
87
- update (args) {
88
- let diff = deepDiff.diff(this.args, args)
89
- Object.keys(diff).forEach(key => {
90
- if (typeof diff[key] === 'function' && key !== 'content') {
91
- this[key] = args[key]
92
- }
93
- })
94
- return !!Object.keys(diff).find(key => key !== 'optionsMenu' && typeof diff[key] !== 'function')
95
- }
96
68
  }
97
-
98
- function panel (args) {
99
- let instance
100
- if (args.uniqueKey) {
101
- let found = cache.get(args.uniqueKey)
102
- if (found) {
103
- instance = found
104
- } else {
105
- instance = new Panel()
106
- cache.set(args.uniqueKey, instance)
107
- }
108
- return instance.render(args)
109
- } else {
110
- instance = new Panel()
111
- return instance.createElement(args)
112
- }
113
- }
114
-
115
- export default args => panel(args)
@@ -1,9 +1,5 @@
1
- import { html, css, formField, fieldIsTouched, Component, LRU } from 'halfcab'
1
+ import { html, css, formField, fieldIsTouched } from 'halfcab'
2
2
  import solidDown from './icons/solidDown.mjs'
3
- import * as deepDiff from 'deep-object-diff'
4
- import clone from 'fast-clone'
5
-
6
- let cache = new LRU(300)
7
3
 
8
4
  let styles = css`
9
5
  .selectBox {
@@ -66,29 +62,21 @@ let styles = css`
66
62
  }
67
63
  `
68
64
 
69
- class Selectbox extends Component {
70
- createElement (args) {
71
- this.args = clone(args)
72
- this.onchange = args.onchange
73
- this.oninput = args.oninput
74
-
75
- let { wrapperStyle = null, holdingPen, label, property, options, required, disabled } = args
76
-
77
- let currentOption = options.find(option => {
78
- if (typeof option === 'object') {
79
- return option.value === holdingPen[property]
80
- } else {
81
- return option === holdingPen[property]
82
- }
83
- })
84
- this.currentOption = currentOption
65
+ export default ({ wrapperStyle = null, holdingPen, label, property, options, required, disabled, onchange, oninput }) => {
66
+ let currentOption = options.find(option => {
67
+ if (typeof option === 'object') {
68
+ return option.value === holdingPen[property]
69
+ } else {
70
+ return option === holdingPen[property]
71
+ }
72
+ })
85
73
 
86
- return html`
74
+ return html`
87
75
  <label style="text-align: left; position: relative; display: inline-block; width: 100%;" ${wrapperStyle ? { 'class': wrapperStyle } : ''}>
88
76
  <div class="${styles.down}">${solidDown({ colour: '#ccc' })}</div>
89
77
  <span class="${styles.label}">${label}${required ? ' *' : ''}</span>
90
- <select ${disabled ? { disabled } : ''} style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}background-color: ${typeof currentOption === 'object' && currentOption.colour ? `#${currentOption.colour}` : 'white'}" class="${styles.selectBox} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" oninput=${e => { formField(holdingPen, property)(e); this.oninput && this.oninput(e) }} onchange=${e => { formField(holdingPen, property)(e); this.onchange && this.onchange(e) }} onblur=${formField(holdingPen, property)}>
91
- <option value="${required ? 'Select an option' : ''}" ${!holdingPen[property] ? { selected: 'true' } : ''} ${required ? { disabled: 'disabled' } : ''}>${required ? 'Select an option' : ''}</option>
78
+ <select ${disabled ? { disabled } : ''} style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}background-color: ${typeof currentOption === 'object' && currentOption.colour ? `#${currentOption.colour}` : 'white'}" class="${styles.selectBox} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" oninput=${e => { formField(holdingPen, property)(e); oninput && oninput(e) }} onchange=${e => { formField(holdingPen, property)(e); onchange && onchange(e) }} onblur=${formField(holdingPen, property)}>
79
+ <option value="${required ? 'Select an option' : ''}" ?selected=${!holdingPen[property]} ?disabled=${required} : ''}>${required ? 'Select an option' : ''}</option>
92
80
  ${options.map(option => {
93
81
  let optionValue
94
82
  let optionName
@@ -98,39 +86,9 @@ class Selectbox extends Component {
98
86
  } else {
99
87
  optionValue = option
100
88
  }
101
- return html`<option value="${optionValue}" ${holdingPen[property] == optionValue ? { selected: 'true' } : ''}>${optionName || optionValue}</option>` // eslint-disable-line
89
+ return html`<option value="${optionValue}" ?selected=${holdingPen[property] == optionValue}>${optionName || optionValue}</option>` // eslint-disable-line
102
90
  })}
103
91
  </select>
104
92
  </label>
105
93
  `
106
- }
107
-
108
- update (args) {
109
- let diff = deepDiff.diff(this.args, args)
110
- Object.keys(diff).forEach(key => {
111
- if (typeof diff[key] === 'function') {
112
- this[key] = args[key]
113
- }
114
- })
115
- return this.currentOption !== args.currentOption || !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
116
- }
117
94
  }
118
-
119
- function selectbox (args) {
120
- let instance
121
- if (args.uniqueKey) {
122
- let found = cache.get(args.uniqueKey)
123
- if (found) {
124
- instance = found
125
- } else {
126
- instance = new Selectbox()
127
- cache.set(args.uniqueKey, instance)
128
- }
129
- return instance.render(args)
130
- } else {
131
- instance = new Selectbox()
132
- return instance.createElement(args)
133
- }
134
- }
135
-
136
- export default args => selectbox(args)
@@ -1,8 +1,4 @@
1
- import { html, css, Component, LRU } from 'halfcab'
2
- import * as deepDiff from 'deep-object-diff'
3
- import clone from 'fast-clone'
4
-
5
- let cache = new LRU(100)
1
+ import { html, css } from 'halfcab'
6
2
 
7
3
  let styles = css`
8
4
  .table {
@@ -46,46 +42,15 @@ let _data = [
46
42
  ['C1-R2', () => 'C2-R2', () => 'C3-R2']
47
43
  ]
48
44
 
49
- class Table extends Component {
50
- createElement (args) {
51
- this.args = clone(args)
52
- let { columns = _columns, data = _data } = args
53
-
54
- return html`
55
- <table class="${styles.table}">
56
- <thead class="${styles.thRow}">
57
- <tr>
58
- ${columns.map(column => html`<th class="${styles.th} ${column.style || ''}" scope="col" ${column.action ? { onclick: column.action } : ''}>${column.title}${column.icon ? column.icon : ''}</th>`)}
59
- </tr>
60
- </thead>
61
- <tbody>
62
- ${data.map(row => html`<tr class="${styles.tr}">${row.map(column => html`<td class="${column.style || ''}" style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap; max-width: 0; direction: rtl;">${typeof column.content === 'function' ? column.content() : column.content}</td>`)}</tr>`)}
63
- </tbody>
64
- </table>
65
- `
66
- }
67
-
68
- update (args) {
69
- let diff = deepDiff.diff(this.args, args)
70
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
71
- }
72
- }
73
-
74
- function table (args) {
75
- let instance
76
- if (args.uniqueKey) {
77
- let found = cache.get(args.uniqueKey)
78
- if (found) {
79
- instance = found
80
- } else {
81
- instance = new Table()
82
- cache.set(args.uniqueKey, instance)
83
- }
84
- return instance.render(args)
85
- } else {
86
- instance = new Table()
87
- return instance.createElement(args)
88
- }
89
- }
90
-
91
- export default args => table(args)
45
+ export default ({ columns = _columns, data = _data }) => html`
46
+ <table class="${styles.table}">
47
+ <thead class="${styles.thRow}">
48
+ <tr>
49
+ ${columns.map(column => html`<th class="${styles.th} ${column.style || ''}" scope="col" ${column.action ? { onclick: column.action } : ''}>${column.title}${column.icon ? column.icon : ''}</th>`)}
50
+ </tr>
51
+ </thead>
52
+ <tbody>
53
+ ${data.map(row => html`<tr class="${styles.tr}">${row.map(column => html`<td class="${column.style || ''}" style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap; max-width: 0; direction: rtl;">${typeof column.content === 'function' ? column.content() : column.content}</td>`)}</tr>`)}
54
+ </tbody>
55
+ </table>
56
+ `
@@ -1,8 +1,4 @@
1
- import { html, css, formField, fieldIsTouched, Component, LRU } from 'halfcab'
2
- import * as deepDiff from 'deep-object-diff'
3
- import clone from 'fast-clone'
4
-
5
- let cache = new LRU(300)
1
+ import { html, css, formField, fieldIsTouched } from 'halfcab'
6
2
 
7
3
  let styles = css`
8
4
  .textarea {
@@ -59,51 +55,14 @@ function change ({ e, holdingPen, property, label }) {
59
55
  return ff
60
56
  }
61
57
 
62
- class Textarea extends Component {
63
- createElement (args) {
64
- this.args = clone(args)
65
- this.onchange = args.onchange
66
- this.oninput = args.oninput
67
-
68
- let { holdingPen, label, placeholder, property, required, pattern, onkeyup, autofocus, permanentTopPlaceholder = false, permanentTopLabel = false, disabled, darkBackground } = args
69
-
70
- let input = html`<textarea data-gramm="false" style="${this.height ? `height: ${this.height}` : ''}" class="${styles.textarea} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" onkeyup=${e => onkeyup && onkeyup(e)} ${required ? { required: 'required' } : ''} onchange=${e => { change({ e, holdingPen, property, label: styles.label }); this.onchange && this.onchange(e) }} oninput=${e => { this.height = window.getComputedStyle(this.element.querySelector('textarea')).height; change({ e, holdingPen, property, label: styles.label }); this.oninput && this.oninput(e) }} onblur=${formField(holdingPen, property)} placeholder="${placeholder || ''}${required ? ' *' : ''}" ${pattern ? { pattern } : ''}>${holdingPen[property] || ''}</textarea>`
71
-
72
- if (autofocus) {
73
- input.autofocus = true
74
- }
75
-
76
- return html`
77
- <label ${disabled ? { disabled } : ''} style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}width: 100%; text-align: left; display: inline-block;"><span class="${styles.label}" style="opacity: ${holdingPen[property] === 0 || holdingPen[property] || (permanentTopPlaceholder || permanentTopLabel) ? 1 : 0}; font-size: 16px; font-weight: normal; color: #999; margin-left: 5px; padding: 9px; background-color: rgba(255,255,255,${darkBackground ? 1 : 0.8}); ">${label}${required ? ' *' : ''}</span>${input}</label>
78
- `
79
- }
58
+ export default ({ holdingPen, label, placeholder, property, required, pattern, onkeyup, autofocus, permanentTopPlaceholder = false, permanentTopLabel = false, disabled, darkBackground, onchange, height, oninput, element }) => {
59
+ let input = html`<textarea data-gramm="false" style="${height ? `height: ${height}` : ''}" class="${styles.textarea} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''}" onkeyup=${e => onkeyup && onkeyup(e)} ${required ? { required: 'required' } : ''} onchange=${e => { change({ e, holdingPen, property, label: styles.label }); onchange && onchange(e) }} oninput=${e => { height = window.getComputedStyle(element.querySelector('textarea')).height; change({ e, holdingPen, property, label: styles.label }); oninput && oninput(e) }} onblur=${formField(holdingPen, property)} placeholder="${placeholder || ''}${required ? ' *' : ''}" ${pattern ? { pattern } : ''}>${holdingPen[property] || ''}</textarea>`
80
60
 
81
- update (args) {
82
- let diff = deepDiff.diff(this.args, args)
83
- Object.keys(diff).forEach(key => {
84
- if (typeof diff[key] === 'function') {
85
- this[key] = args[key]
86
- }
87
- })
88
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
61
+ if (autofocus) {
62
+ input.autofocus = true
89
63
  }
90
- }
91
64
 
92
- function textarea (args) {
93
- let instance
94
- if (args.uniqueKey) {
95
- let found = cache.get(args.uniqueKey)
96
- if (found) {
97
- instance = found
98
- } else {
99
- instance = new Textarea()
100
- cache.set(args.uniqueKey, instance)
101
- }
102
- return instance.render(args)
103
- } else {
104
- instance = new Textarea()
105
- return instance.createElement(args)
106
- }
65
+ return html`
66
+ <label ${disabled ? { disabled } : ''} style="${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}width: 100%; text-align: left; display: inline-block;"><span class="${styles.label}" style="opacity: ${holdingPen[property] === 0 || holdingPen[property] || (permanentTopPlaceholder || permanentTopLabel) ? 1 : 0}; font-size: 16px; font-weight: normal; color: #999; margin-left: 5px; padding: 9px; background-color: rgba(255,255,255,${darkBackground ? 1 : 0.8}); ">${label}${required ? ' *' : ''}</span>${input}</label>
67
+ `
107
68
  }
108
-
109
- export default args => textarea(args)
@@ -1,9 +1,4 @@
1
- import { html, css, formField, fieldIsTouched, Component, LRU } from 'halfcab'
2
- import * as deepDiff from 'deep-object-diff'
3
- import clone from 'fast-clone'
4
-
5
- let cache = new LRU(300)
6
-
1
+ import { html, css, formField, fieldIsTouched } from 'halfcab'
7
2
  // language=CSS
8
3
  let styles = css`
9
4
  .textfield {
@@ -98,58 +93,20 @@ function determineStep (type) {
98
93
  return '1'
99
94
  }
100
95
 
101
- class Textfield extends Component {
102
- createElement (args) {
103
- this.args = clone(args)
104
- this.onkeyup = args.onkeyup
105
- this.oninput = args.oninput
106
- this.onchange = args.onchange
107
-
108
- let { highlightBorder = false, wrapperStyle = null, holdingPen, label, placeholder, property, required, pattern, type, autofocus, valueContext, permanentTopPlaceholder = false, permanentTopLabel = false, disabled, maxCharacters, maxNumber, minNumber, darkBackground } = args
109
-
110
- let input = html`<input data-gramm="false" ${disabled ? { disabled } : ''} ${maxNumber ? { max: maxNumber } : ''} ${minNumber ? { min: minNumber } : ''} ${maxCharacters ? { maxlength: maxCharacters } : ''} style="${type === 'color' ? 'height: 50px; padding: 2px 3px;' : ''}${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}" class="${styles.textfield} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''} ${highlightBorder ? styles.highlight : ''}" value="${holdingPen[property] !== undefined && holdingPen[property] !== null ? holdingPen[property] : ''}" onkeyup=${e => this.onkeyup && this.onkeyup(e)} ${required ? { required: 'required' } : ''} onchange=${e => { change({ e, holdingPen, property, label: styles.label }); this.onchange && this.onchange(e) }} oninput=${e => { change({ e, holdingPen, property, label: styles.label }); this.oninput && this.oninput(e) }} onblur=${formField(holdingPen, property)} placeholder="${placeholder || ''}${required ? ' *' : ''}" type="${determineType(type)}" ${pattern ? { pattern } : ''} ${type.toLowerCase() === 'number' ? { step: determineStep(type) } : ''} />`
96
+ export default ({ highlightBorder = false, wrapperStyle = null, holdingPen, label, placeholder, property, required, pattern, type, autofocus, valueContext, permanentTopPlaceholder = false, permanentTopLabel = false, disabled, maxCharacters, maxNumber, minNumber, darkBackground, onkeyup, oninput, onchange }) => {
97
+ let input = html`<input data-gramm="false" ${disabled ? { disabled } : ''} ${maxNumber ? { max: maxNumber } : ''} ${minNumber ? { min: minNumber } : ''} ${maxCharacters ? { maxlength: maxCharacters } : ''} style="${type === 'color' ? 'height: 50px; padding: 2px 3px;' : ''}${disabled ? 'cursor: not-allowed; opacity: 0.3;' : ''}" class="${styles.textfield} ${fieldIsTouched(holdingPen, property) === true ? styles.touched : ''} ${highlightBorder ? styles.highlight : ''}" value="${holdingPen[property] !== undefined && holdingPen[property] !== null ? holdingPen[property] : ''}" onkeyup=${e => onkeyup && onkeyup(e)} ${required ? { required: 'required' } : ''} onchange=${e => { change({ e, holdingPen, property, label: styles.label }); onchange && onchange(e) }} oninput=${e => { change({ e, holdingPen, property, label: styles.label }); oninput && oninput(e) }} onblur=${formField(holdingPen, property)} placeholder="${placeholder || ''}${required ? ' *' : ''}" type="${determineType(type)}" ${pattern ? { pattern } : ''} ${type.toLowerCase() === 'number' ? { step: determineStep(type) } : ''} />`
111
98
 
112
- if (autofocus) {
113
- input.autofocus = true
114
- }
115
-
116
- return html`
117
- <div ${wrapperStyle ? { 'class': wrapperStyle } : ''} style="display: inline-block; width: calc(100% - 10px); margin: ${label ? '40' : '5'}px 5px 5px 5px;">
118
- <label style="width: 100%; text-align: left; position: relative; padding: 0;">
119
- ${valueContext ? html`<div class="${styles.valueContext}">${valueContext}</div>` : ''}
120
- ${label ? html`<span class="${styles.label}" style="opacity: ${holdingPen[property] === 0 || holdingPen[property] || (permanentTopPlaceholder || permanentTopLabel) ? 1 : 0}; font-size: 16px; font-weight: normal; color: #999; margin-left: 5px; padding: 9px; background-color: rgba(255,255,255,${darkBackground ? 1 : 0.8}); ">${label}${required ? ' *' : ''}</span>` : ''}
121
- ${input}
122
- </label>
123
- </div>
124
- `
99
+ if (autofocus) {
100
+ input.autofocus = true
125
101
  }
126
102
 
127
- update (args) {
128
- let diff = deepDiff.diff(this.args, args)
129
- Object.keys(diff).forEach(key => {
130
- if (typeof diff[key] === 'function') {
131
- this[key] = args[key]
132
- }
133
- })
134
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
135
- }
103
+ return html`
104
+ <div ${wrapperStyle ? { 'class': wrapperStyle } : ''} style="display: inline-block; width: calc(100% - 10px); margin: ${label ? '40' : '5'}px 5px 5px 5px;">
105
+ <label style="width: 100%; text-align: left; position: relative; padding: 0;">
106
+ ${valueContext ? html`<div class="${styles.valueContext}">${valueContext}</div>` : ''}
107
+ ${label ? html`<span class="${styles.label}" style="opacity: ${holdingPen[property] === 0 || holdingPen[property] || (permanentTopPlaceholder || permanentTopLabel) ? 1 : 0}; font-size: 16px; font-weight: normal; color: #999; margin-left: 5px; padding: 9px; background-color: rgba(255,255,255,${darkBackground ? 1 : 0.8}); ">${label}${required ? ' *' : ''}</span>` : ''}
108
+ ${input}
109
+ </label>
110
+ </div>
111
+ `
136
112
  }
137
-
138
- function textfield (args) {
139
- let instance
140
- if (args.uniqueKey) {
141
- let found = cache.get(args.uniqueKey)
142
- if (found) {
143
- instance = found
144
- } else {
145
- instance = new Textfield()
146
- cache.set(args.uniqueKey, instance)
147
- }
148
- return instance.render(args)
149
- } else {
150
- instance = new Textfield()
151
- return instance.createElement(args)
152
- }
153
- }
154
-
155
- export default args => textfield(args)
@@ -1,7 +1,5 @@
1
- import { html, css, geb, Component } from 'halfcab'
1
+ import { html, css, geb } from 'halfcab'
2
2
  import close from './icons/close.mjs'
3
- import * as deepDiff from 'deep-object-diff'
4
- import clone from 'fast-clone'
5
3
 
6
4
  let styles = css`
7
5
  .toast{
@@ -31,11 +29,8 @@ let styles = css`
31
29
  }
32
30
  `
33
31
 
34
- class Toast extends Component {
35
- createElement (args) {
36
- this.args = clone(args)
37
- let { on, message, colour, multiline, closeAction } = args
38
- return html`
32
+ export default ({ on, message, colour, multiline, closeAction }) => {
33
+ return html`
39
34
  <div class="${styles.toastContainer}" onclick=${() => geb.broadcast('errorDismissed')} style="${on ? 'bottom: 0px;' : `bottom: -${multiline ? '100' : '50'}px; opacity: 0; `}${multiline ? 'height: 100px;' : ''}">
40
35
  <div class="${styles.toast}" style="background-color: ${colour || 'red'};">
41
36
  <div style="width: 100%; margin-left: 20px">${message}</div>
@@ -43,13 +38,4 @@ class Toast extends Component {
43
38
  </div>
44
39
  </div>
45
40
  `
46
- }
47
-
48
- update (args) {
49
- let diff = deepDiff.diff(this.args, args)
50
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
51
- }
52
41
  }
53
-
54
- let toast = new Toast()
55
- export default args => toast.render(args)
@@ -1,6 +1,4 @@
1
- import { html, css, Component } from 'halfcab'
2
- import clone from 'fast-clone'
3
- import * as deepDiff from 'deep-object-diff'
1
+ import { html, css } from 'halfcab'
4
2
 
5
3
  let styles = css`
6
4
  .toolbar {
@@ -17,24 +15,10 @@ let styles = css`
17
15
  }
18
16
  `
19
17
 
20
- class Toolbar extends Component {
21
- createElement (args) {
22
- this.args = clone(args)
23
- let { content } = args
24
- return html`
25
- <div class="${styles.toolbar}">
18
+ export default ({ content }) => html`
19
+ <div class="${styles.toolbar}">
26
20
  <div style="display: flex; justify-content: space-between; align-items: center; width: 100%;">
27
- ${typeof content === 'function' ? content() : content}
21
+ ${typeof content === 'function' ? content() : content}
28
22
  </div>
29
- </div>
30
- `
31
- }
32
-
33
- update (args) {
34
- let diff = deepDiff.diff(this.args, args)
35
- return !!Object.keys(diff).find(key => typeof diff[key] !== 'function')
36
- }
37
- }
38
-
39
- let toolbar = new Toolbar()
40
- export default args => toolbar.render(args)
23
+ </div>
24
+ `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stalefish",
3
- "version": "8.0.0",
3
+ "version": "8.0.2",
4
4
  "description": "Simple function based component library for halfcab tagged template literals",
5
5
  "main": "index.mjs",
6
6
  "module": "index.mjs",
@@ -8,7 +8,7 @@
8
8
  "scripts": {
9
9
  "test": "npm run test:lint",
10
10
  "test:lint": "standard \"**/*.mjs\"",
11
- "npm-publish": "npm publish -tag beta",
11
+ "npm-publish": "npm publish --tag beta",
12
12
  "versionbump:fix": "npm version patch --no-git-tag-version",
13
13
  "versionbump:feature": "npm version minor --no-git-tag-version",
14
14
  "versionbump:breakingchanges": "npm version major --no-git-tag-version"
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "homepage": "https://github.com/lorengreenfield/stalefish#readme",
32
32
  "devDependencies": {
33
- "halfcab": "^13.0.5",
33
+ "halfcab": "^15.0.3",
34
34
  "standard": "^12.0.1"
35
35
  },
36
36
  "dependencies": {