@stonecrop/beam 0.2.6
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/README.md +16 -0
- package/package.json +51 -0
- package/src/ActionFooter.vue +19 -0
- package/src/BeamModal.vue +15 -0
- package/src/BeamModalOutlet.vue +8 -0
- package/src/Confirm.vue +20 -0
- package/src/ItemCheck.vue +95 -0
- package/src/ItemCount.vue +62 -0
- package/src/ListAnchor.vue +17 -0
- package/src/ListItem.vue +34 -0
- package/src/ListView.vue +47 -0
- package/src/Navbar.vue +25 -0
- package/src/ScanInput.vue +35 -0
- package/src/index.js +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# BEAM UI Components
|
|
2
|
+
|
|
3
|
+
- Navbar
|
|
4
|
+
- Dropdown or drawer menu depending on client
|
|
5
|
+
- ListView
|
|
6
|
+
- List Item
|
|
7
|
+
- ItemCounter
|
|
8
|
+
- Needs count logic and styling, should accept an object, not a string
|
|
9
|
+
- Implement v-model to parent
|
|
10
|
+
- Item Checkbox
|
|
11
|
+
- Implement v-model to parent
|
|
12
|
+
- ListAnchor
|
|
13
|
+
- Dynamic component so its swapable with `nuxt-link` or `router-link`
|
|
14
|
+
- Calculator/Number input
|
|
15
|
+
- Modal helper (sized depending on client)
|
|
16
|
+
- SCSS variables throughout
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stonecrop/beam",
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Tyler Matteson",
|
|
8
|
+
"email": "tyler@agritheory.com"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/agritheory/stonecrop",
|
|
13
|
+
"directory": "beam"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/agritheory/stonecrop/issues"
|
|
17
|
+
},
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": "./dist/beam-ui.es.js",
|
|
21
|
+
"require": "./dist/beam-ui.umd.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/beam-ui.umd.js",
|
|
25
|
+
"module": "./dist/beam-ui.es.js",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist/*",
|
|
28
|
+
"src/*"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"portal-vue": "^3.0.0",
|
|
32
|
+
"vue": "^3.4.23"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@vitejs/plugin-vue": "^5.0.4",
|
|
36
|
+
"cypress": "^12.11.0",
|
|
37
|
+
"vite": "^5.2.9",
|
|
38
|
+
"vue-router": "^4"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=20.11.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"dev": "vite serve dev/ -c dev/vite.config.js -d",
|
|
48
|
+
"build": "vite build dev/ -c dev/vite.config.js -d",
|
|
49
|
+
"serve": "vite preview"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<footer class="beam__actionfooter">
|
|
3
|
+
<span class="footer-action-wrapper">
|
|
4
|
+
<button class="footer-action btn" @click="handleFooterAction">
|
|
5
|
+
<slot />
|
|
6
|
+
</button>
|
|
7
|
+
</span>
|
|
8
|
+
</footer>
|
|
9
|
+
</template>
|
|
10
|
+
<script>
|
|
11
|
+
export default {
|
|
12
|
+
name: 'ActionFooter',
|
|
13
|
+
methods: {
|
|
14
|
+
handleFooterAction() {
|
|
15
|
+
this.$emit('click')
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<portal to="beam__modal_outlet">
|
|
3
|
+
<div class="beam__modal" v-show="showModal">
|
|
4
|
+
<button class="btn" @click="$emit('closemodal')">Close Modal</button>
|
|
5
|
+
<slot @closemodal="$emit('closemodal')" @confirmmodal="$emit('confirmmodal')"></slot>
|
|
6
|
+
</div>
|
|
7
|
+
</portal>
|
|
8
|
+
</template>
|
|
9
|
+
<script>
|
|
10
|
+
export default {
|
|
11
|
+
name: 'BeamModal',
|
|
12
|
+
props: ['showModal'],
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
<style scoped></style>
|
package/src/Confirm.vue
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="beam__modal-confirm">
|
|
3
|
+
<h2>Would you like to continue?</h2>
|
|
4
|
+
<button class="btn" @click="confirmModal">Yes</button>
|
|
5
|
+
<button class="btn" @click="closeModal">No</button>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
<script>
|
|
9
|
+
export default {
|
|
10
|
+
name: 'ConfirmDialog',
|
|
11
|
+
methods: {
|
|
12
|
+
confirmModal() {
|
|
13
|
+
this.$emit('confirmmodal')
|
|
14
|
+
},
|
|
15
|
+
closeModal() {
|
|
16
|
+
this.$emit('closemodal')
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
</script>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<label class="container">
|
|
3
|
+
<input type="checkbox" :checked="value" @input="handleInput" tabindex="-1" />
|
|
4
|
+
<div class="checkmark" tabindex="0"></div>
|
|
5
|
+
</label>
|
|
6
|
+
</template>
|
|
7
|
+
<script>
|
|
8
|
+
export default {
|
|
9
|
+
// make this v-model sensitive from parent
|
|
10
|
+
name: 'ItemCheck',
|
|
11
|
+
props: {
|
|
12
|
+
value: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
required: false,
|
|
15
|
+
default: false,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
data() {
|
|
19
|
+
return {
|
|
20
|
+
checked: this.value,
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
methods: {
|
|
24
|
+
handleInput(e) {
|
|
25
|
+
this.$emit('input', this.checked)
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<style scoped>
|
|
32
|
+
.container {
|
|
33
|
+
display: block;
|
|
34
|
+
position: relative;
|
|
35
|
+
padding-left: 2.5ch;
|
|
36
|
+
margin: 0;
|
|
37
|
+
margin-top: 0.5rem;
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
font-size: 2rem;
|
|
40
|
+
-webkit-user-select: none;
|
|
41
|
+
-moz-user-select: none;
|
|
42
|
+
-ms-user-select: none;
|
|
43
|
+
user-select: none;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* hide default checkbox */
|
|
47
|
+
.container input {
|
|
48
|
+
position: absolute;
|
|
49
|
+
opacity: 0;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
height: 0;
|
|
52
|
+
width: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.checkmark {
|
|
56
|
+
position: absolute;
|
|
57
|
+
top: 0;
|
|
58
|
+
left: 0;
|
|
59
|
+
height: 2rem;
|
|
60
|
+
width: 2rem;
|
|
61
|
+
background-color: #eee;
|
|
62
|
+
outline: 2px solid transparent;
|
|
63
|
+
border: 1px solid var(--highlight);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.container:hover input ~ .checkmark {
|
|
67
|
+
background-color: white;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.container input:checked ~ .checkmark {
|
|
71
|
+
background-color: var(--brand-secondary);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.checkmark:after {
|
|
75
|
+
content: '';
|
|
76
|
+
position: absolute;
|
|
77
|
+
display: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.container input:checked ~ .checkmark:after {
|
|
81
|
+
display: block;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.container .checkmark:after {
|
|
85
|
+
left: 25%;
|
|
86
|
+
top: 50%;
|
|
87
|
+
width: 0.5rem;
|
|
88
|
+
height: 1rem;
|
|
89
|
+
border: solid var(--text-color);
|
|
90
|
+
border-width: 0 3px 3px 0;
|
|
91
|
+
-webkit-transform: rotate(45deg);
|
|
92
|
+
-ms-transform: rotate(45deg);
|
|
93
|
+
transform: rotate(45deg) translate(-50%, -50%);
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="beam__itemcount">
|
|
3
|
+
<span
|
|
4
|
+
:contenteditable="editable"
|
|
5
|
+
:class="{ alert: countColor === false }"
|
|
6
|
+
@input="handleInput($event)"
|
|
7
|
+
@click="handleInput($event)"
|
|
8
|
+
>{{ count }}</span
|
|
9
|
+
>
|
|
10
|
+
<span>/{{ denominator }}</span
|
|
11
|
+
><span v-if="uom"> {{ uom }}</span>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
<script>
|
|
15
|
+
export default {
|
|
16
|
+
name: 'ItemCount',
|
|
17
|
+
props: {
|
|
18
|
+
value: {
|
|
19
|
+
type: Number,
|
|
20
|
+
required: false,
|
|
21
|
+
default: 0,
|
|
22
|
+
},
|
|
23
|
+
denominator: {
|
|
24
|
+
type: Number,
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
uom: {
|
|
28
|
+
type: String,
|
|
29
|
+
required: false,
|
|
30
|
+
default: null,
|
|
31
|
+
},
|
|
32
|
+
editable: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
required: false,
|
|
35
|
+
default: false,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
data() {
|
|
39
|
+
return {
|
|
40
|
+
count: this.value,
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
methods: {
|
|
44
|
+
handleInput(event) {
|
|
45
|
+
event.preventDefault()
|
|
46
|
+
event.stopPropagation()
|
|
47
|
+
this.count = Number(event.target.innerHTML.replace(/[^0-9]/g, ''))
|
|
48
|
+
this.$emit('input', this.count)
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
computed: {
|
|
52
|
+
countColor() {
|
|
53
|
+
return this.count === this.denominator
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
watch: {
|
|
57
|
+
value() {
|
|
58
|
+
this.count = this.value
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
</script>
|
package/src/ListItem.vue
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<li tabindex="0" class="beam__listitem">
|
|
3
|
+
<div class="beam__listtext">
|
|
4
|
+
<label>{{ item.label }}</label>
|
|
5
|
+
<p>{{ item.description }}</p>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<ItemCount
|
|
9
|
+
v-if="item.count"
|
|
10
|
+
v-model="item.count.count"
|
|
11
|
+
:denominator="item.count.of"
|
|
12
|
+
:uom="item.count.uom"
|
|
13
|
+
:editable="true" />
|
|
14
|
+
<ItemCheck v-if="item.hasOwnProperty('checked')" v-model="item.checked" />
|
|
15
|
+
</li>
|
|
16
|
+
</template>
|
|
17
|
+
<script>
|
|
18
|
+
import ItemCount from './ItemCount.vue'
|
|
19
|
+
import ItemCheck from './ItemCheck.vue'
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
name: 'ListItem',
|
|
23
|
+
components: {
|
|
24
|
+
ItemCount,
|
|
25
|
+
ItemCheck,
|
|
26
|
+
},
|
|
27
|
+
props: {
|
|
28
|
+
item: {
|
|
29
|
+
type: Object,
|
|
30
|
+
required: true,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
</script>
|
package/src/ListView.vue
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ul class="beam__listview">
|
|
3
|
+
<li v-for="(item, index) in items" :key="index">
|
|
4
|
+
<template v-if="item.linkComponent">
|
|
5
|
+
<component :is="item.linkComponent" :to="item.route" tabindex="-1">
|
|
6
|
+
<ListItem :item="item"></ListItem>
|
|
7
|
+
</component>
|
|
8
|
+
</template>
|
|
9
|
+
<template v-else>
|
|
10
|
+
<ListItem :item="item"></ListItem>
|
|
11
|
+
</template>
|
|
12
|
+
</li>
|
|
13
|
+
</ul>
|
|
14
|
+
</template>
|
|
15
|
+
<script>
|
|
16
|
+
import ListAnchor from './ListAnchor.vue'
|
|
17
|
+
import ListItem from './ListItem.vue'
|
|
18
|
+
|
|
19
|
+
export default {
|
|
20
|
+
name: 'ListView',
|
|
21
|
+
components: {
|
|
22
|
+
ListItem,
|
|
23
|
+
ListAnchor,
|
|
24
|
+
},
|
|
25
|
+
props: {
|
|
26
|
+
items: {
|
|
27
|
+
type: Array,
|
|
28
|
+
required: true,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
created() {
|
|
32
|
+
window.addEventListener('scroll', this.handleScroll)
|
|
33
|
+
},
|
|
34
|
+
destroyed() {
|
|
35
|
+
window.removeEventListener('scroll', this.handleScroll)
|
|
36
|
+
},
|
|
37
|
+
methods: {
|
|
38
|
+
handleScroll() {
|
|
39
|
+
const scrollHeightDifference = document.documentElement.scrollHeight - window.innerHeight
|
|
40
|
+
const scrollposition = document.documentElement.scrollTop
|
|
41
|
+
if (scrollHeightDifference - scrollposition <= 2) {
|
|
42
|
+
this.$emit('scrollbottom')
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
</script>
|
package/src/Navbar.vue
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<nav class="beam__navbar">
|
|
3
|
+
<slot name="icon">
|
|
4
|
+
<span class="home-icon">⬣</span>
|
|
5
|
+
</slot>
|
|
6
|
+
<slot name="title">
|
|
7
|
+
<h1 class="nav-title">TITLE</h1>
|
|
8
|
+
</slot>
|
|
9
|
+
<div class="navbar-action-wrapper">
|
|
10
|
+
<button class="navbar-action btn" @click="handlePrimaryAction">
|
|
11
|
+
<slot name="navbaraction">Action</slot>
|
|
12
|
+
</button>
|
|
13
|
+
</div>
|
|
14
|
+
</nav>
|
|
15
|
+
</template>
|
|
16
|
+
<script>
|
|
17
|
+
export default {
|
|
18
|
+
name: 'Navbar',
|
|
19
|
+
methods: {
|
|
20
|
+
handlePrimaryAction() {
|
|
21
|
+
this.$emit('click')
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div id="scan_input"></div>
|
|
3
|
+
</template>
|
|
4
|
+
<script>
|
|
5
|
+
export default {
|
|
6
|
+
name: 'ScanInput',
|
|
7
|
+
data() {
|
|
8
|
+
return {
|
|
9
|
+
barcode: '',
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
methods: {
|
|
13
|
+
handleScanInput(event) {
|
|
14
|
+
if (event.target.tagName !== 'INPUT') {
|
|
15
|
+
if (event.key !== 'Enter') {
|
|
16
|
+
this.barcode += `${event.key}`
|
|
17
|
+
} else {
|
|
18
|
+
this.$emit('scaninput', this.barcode)
|
|
19
|
+
this.barcode = ''
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
mounted() {
|
|
25
|
+
document.addEventListener('keypress', event => {
|
|
26
|
+
this.handleScanInput(event)
|
|
27
|
+
})
|
|
28
|
+
},
|
|
29
|
+
destroyed() {
|
|
30
|
+
window.removeEventListener('keypress', event => {
|
|
31
|
+
this.handleScanInput(event)
|
|
32
|
+
})
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
</script>
|
package/src/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import Navbar from './Navbar.vue'
|
|
2
|
+
import ListView from './ListView.vue'
|
|
3
|
+
import ListItem from './ListItem.vue'
|
|
4
|
+
import ListAnchor from './ListAnchor.vue'
|
|
5
|
+
import ItemCount from './ItemCount.vue'
|
|
6
|
+
import ItemCheck from './ItemCheck.vue'
|
|
7
|
+
import ScanInput from './ScanInput.vue'
|
|
8
|
+
import ActionFooter from './ActionFooter.vue'
|
|
9
|
+
import BeamModal from './BeamModal.vue'
|
|
10
|
+
import BeamModalOutlet from './BeamModalOutlet.vue'
|
|
11
|
+
import ConfirmDialog from './Confirm.vue'
|
|
12
|
+
import PortalVue from 'portal-vue'
|
|
13
|
+
|
|
14
|
+
const components = [
|
|
15
|
+
Navbar,
|
|
16
|
+
ListView,
|
|
17
|
+
ListItem,
|
|
18
|
+
ListAnchor,
|
|
19
|
+
ItemCount,
|
|
20
|
+
ItemCheck,
|
|
21
|
+
ScanInput,
|
|
22
|
+
ActionFooter,
|
|
23
|
+
BeamModal,
|
|
24
|
+
ConfirmDialog,
|
|
25
|
+
BeamModalOutlet,
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
const install = function (Vue, opts = {}) {
|
|
29
|
+
Vue.use(PortalVue)
|
|
30
|
+
components.forEach(component => {
|
|
31
|
+
Vue.component(component.name, component)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof window !== 'undefined' && window.Vue) {
|
|
36
|
+
install(window.Vue)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
version: '0.1.0',
|
|
41
|
+
install,
|
|
42
|
+
Navbar,
|
|
43
|
+
ListView,
|
|
44
|
+
ListItem,
|
|
45
|
+
ListAnchor,
|
|
46
|
+
ItemCount,
|
|
47
|
+
ItemCheck,
|
|
48
|
+
ScanInput,
|
|
49
|
+
ActionFooter,
|
|
50
|
+
BeamModal,
|
|
51
|
+
ConfirmDialog,
|
|
52
|
+
BeamModalOutlet,
|
|
53
|
+
}
|