waibu-bootstrap 1.0.1
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/LICENSE +21 -0
- package/README.md +23 -0
- package/bajo/.alias +1 -0
- package/bajo/config.json +6 -0
- package/bajo/hook/waibu-mpa.bootstrap@after-build-page.js +5 -0
- package/bajoI18N/resource/id.json +2 -0
- package/package.json +33 -0
- package/waibuMpa/theme/component/factory/_lib.js +140 -0
- package/waibuMpa/theme/component/factory/a.js +12 -0
- package/waibuMpa/theme/component/factory/accordion-item.js +34 -0
- package/waibuMpa/theme/component/factory/accordion.js +24 -0
- package/waibuMpa/theme/component/factory/alert.js +33 -0
- package/waibuMpa/theme/component/factory/app-launcher-trigger.js +37 -0
- package/waibuMpa/theme/component/factory/app-launcher.js +55 -0
- package/waibuMpa/theme/component/factory/badge.js +24 -0
- package/waibuMpa/theme/component/factory/blockquote.js +22 -0
- package/waibuMpa/theme/component/factory/breadcrumb-item.js +27 -0
- package/waibuMpa/theme/component/factory/breadcrumb.js +64 -0
- package/waibuMpa/theme/component/factory/btn-back-to-top.js +40 -0
- package/waibuMpa/theme/component/factory/btn-close.js +18 -0
- package/waibuMpa/theme/component/factory/btn-group.js +25 -0
- package/waibuMpa/theme/component/factory/btn-toolbar.js +13 -0
- package/waibuMpa/theme/component/factory/btn.js +40 -0
- package/waibuMpa/theme/component/factory/card-body.js +13 -0
- package/waibuMpa/theme/component/factory/card-footer.js +17 -0
- package/waibuMpa/theme/component/factory/card-group.js +13 -0
- package/waibuMpa/theme/component/factory/card-header.js +27 -0
- package/waibuMpa/theme/component/factory/card-link.js +14 -0
- package/waibuMpa/theme/component/factory/card-subtitle.js +13 -0
- package/waibuMpa/theme/component/factory/card-text.js +15 -0
- package/waibuMpa/theme/component/factory/card-title.js +13 -0
- package/waibuMpa/theme/component/factory/card.js +23 -0
- package/waibuMpa/theme/component/factory/carousel-item.js +25 -0
- package/waibuMpa/theme/component/factory/carousel.js +53 -0
- package/waibuMpa/theme/component/factory/collapse-item.js +14 -0
- package/waibuMpa/theme/component/factory/collapse.js +58 -0
- package/waibuMpa/theme/component/factory/container.js +22 -0
- package/waibuMpa/theme/component/factory/drawer-toolbar.js +6 -0
- package/waibuMpa/theme/component/factory/drawer.js +59 -0
- package/waibuMpa/theme/component/factory/dropdown-item.js +34 -0
- package/waibuMpa/theme/component/factory/dropdown.js +121 -0
- package/waibuMpa/theme/component/factory/fieldset.js +39 -0
- package/waibuMpa/theme/component/factory/figcaption.js +13 -0
- package/waibuMpa/theme/component/factory/figure.js +20 -0
- package/waibuMpa/theme/component/factory/form-check-toggle.js +33 -0
- package/waibuMpa/theme/component/factory/form-check.js +56 -0
- package/waibuMpa/theme/component/factory/form-color.js +12 -0
- package/waibuMpa/theme/component/factory/form-date.js +26 -0
- package/waibuMpa/theme/component/factory/form-datetime.js +83 -0
- package/waibuMpa/theme/component/factory/form-file.js +17 -0
- package/waibuMpa/theme/component/factory/form-input-addon.js +10 -0
- package/waibuMpa/theme/component/factory/form-input.js +132 -0
- package/waibuMpa/theme/component/factory/form-password.js +13 -0
- package/waibuMpa/theme/component/factory/form-plaintext.js +14 -0
- package/waibuMpa/theme/component/factory/form-radio-toggle.js +13 -0
- package/waibuMpa/theme/component/factory/form-radio.js +12 -0
- package/waibuMpa/theme/component/factory/form-range.js +14 -0
- package/waibuMpa/theme/component/factory/form-select-country.js +25 -0
- package/waibuMpa/theme/component/factory/form-select-ext.js +53 -0
- package/waibuMpa/theme/component/factory/form-select.js +34 -0
- package/waibuMpa/theme/component/factory/form-switch.js +18 -0
- package/waibuMpa/theme/component/factory/form-textarea.js +12 -0
- package/waibuMpa/theme/component/factory/form-time.js +22 -0
- package/waibuMpa/theme/component/factory/form.js +46 -0
- package/waibuMpa/theme/component/factory/grid-col.js +44 -0
- package/waibuMpa/theme/component/factory/grid-row.js +21 -0
- package/waibuMpa/theme/component/factory/heading.js +20 -0
- package/waibuMpa/theme/component/factory/img.js +20 -0
- package/waibuMpa/theme/component/factory/lead.js +15 -0
- package/waibuMpa/theme/component/factory/list-item.js +38 -0
- package/waibuMpa/theme/component/factory/list.js +62 -0
- package/waibuMpa/theme/component/factory/masonry.js +34 -0
- package/waibuMpa/theme/component/factory/modal-body.js +13 -0
- package/waibuMpa/theme/component/factory/modal-footer.js +13 -0
- package/waibuMpa/theme/component/factory/modal-header.js +13 -0
- package/waibuMpa/theme/component/factory/modal.js +60 -0
- package/waibuMpa/theme/component/factory/nav-divider.js +24 -0
- package/waibuMpa/theme/component/factory/nav-dropdown-darkmode.js +24 -0
- package/waibuMpa/theme/component/factory/nav-dropdown-language.js +26 -0
- package/waibuMpa/theme/component/factory/nav-dropdown-setting.js +84 -0
- package/waibuMpa/theme/component/factory/nav-dropdown-user.js +36 -0
- package/waibuMpa/theme/component/factory/nav-item-signout.js +26 -0
- package/waibuMpa/theme/component/factory/nav-item.js +55 -0
- package/waibuMpa/theme/component/factory/nav-toggle-fullscreen.js +47 -0
- package/waibuMpa/theme/component/factory/nav.js +30 -0
- package/waibuMpa/theme/component/factory/navbar-brand.js +16 -0
- package/waibuMpa/theme/component/factory/navbar-text.js +13 -0
- package/waibuMpa/theme/component/factory/navbar.js +65 -0
- package/waibuMpa/theme/component/factory/pagination-item.js +21 -0
- package/waibuMpa/theme/component/factory/pagination.js +22 -0
- package/waibuMpa/theme/component/factory/progress-stack.js +26 -0
- package/waibuMpa/theme/component/factory/progress.js +37 -0
- package/waibuMpa/theme/component/factory/scrollspy.js +25 -0
- package/waibuMpa/theme/component/factory/sidebar.js +74 -0
- package/waibuMpa/theme/component/factory/spinner.js +17 -0
- package/waibuMpa/theme/component/factory/table.js +40 -0
- package/waibuMpa/theme/component/factory/tbody.js +14 -0
- package/waibuMpa/theme/component/factory/td.js +15 -0
- package/waibuMpa/theme/component/factory/tfoot.js +14 -0
- package/waibuMpa/theme/component/factory/th.js +15 -0
- package/waibuMpa/theme/component/factory/thead.js +14 -0
- package/waibuMpa/theme/component/factory/toast-stack.js +15 -0
- package/waibuMpa/theme/component/factory/toast.js +33 -0
- package/waibuMpa/theme/component/factory/tr.js +15 -0
- package/waibuMpa/theme/component/method/after-build-tag/_lib.js +50 -0
- package/waibuMpa/theme/component/method/after-build-tag/active.js +7 -0
- package/waibuMpa/theme/component/method/after-build-tag/background.js +25 -0
- package/waibuMpa/theme/component/method/after-build-tag/border.js +26 -0
- package/waibuMpa/theme/component/method/after-build-tag/dim.js +23 -0
- package/waibuMpa/theme/component/method/after-build-tag/disabled.js +6 -0
- package/waibuMpa/theme/component/method/after-build-tag/display.js +34 -0
- package/waibuMpa/theme/component/method/after-build-tag/flex.js +69 -0
- package/waibuMpa/theme/component/method/after-build-tag/font.js +19 -0
- package/waibuMpa/theme/component/method/after-build-tag/gutter.js +23 -0
- package/waibuMpa/theme/component/method/after-build-tag/label.js +6 -0
- package/waibuMpa/theme/component/method/after-build-tag/link.js +24 -0
- package/waibuMpa/theme/component/method/after-build-tag/margin-padding.js +15 -0
- package/waibuMpa/theme/component/method/after-build-tag/popover.js +14 -0
- package/waibuMpa/theme/component/method/after-build-tag/position.js +52 -0
- package/waibuMpa/theme/component/method/after-build-tag/rounded.js +25 -0
- package/waibuMpa/theme/component/method/after-build-tag/text.js +32 -0
- package/waibuMpa/theme/component/method/after-build-tag/tooltip.js +14 -0
- package/waibuMpa/theme/component/method/after-build-tag.js +113 -0
- package/waibuMpa/theme.js +24 -0
- package/waibuStatic/asset/css/wbs.css +12 -0
- package/waibuStatic/asset/js/wbs.js +200 -0
- package/waibuStatic/virtual.json +7 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ardhi Lukianto
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# waibu-bootstrap
|
|
2
|
+
|
|
3
|
+
Plugin name: **waibuBootstrap**, alias: **wbs**
|
|
4
|
+
|
|
5
|
+
 
|
|
6
|
+
|
|
7
|
+
> <br />**Attention**: I do NOT accept any pull request at the moment, thanks!<br /><br />
|
|
8
|
+
|
|
9
|
+
Bootstrap support for [Waibu MPA](https://github.com/ardhi/waibu-mpa)
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
Goto your ```<bajo-base-dir>``` and type:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
$ npm install waibu-bootstrap
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Now open your ```<bajo-data-dir>/config/.plugins``` and put ```waibu-bootstrap``` in it.
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
|
|
23
|
+
[MIT](LICENSE)
|
package/bajo/.alias
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
wbs
|
package/bajo/config.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "waibu-bootstrap",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Bootstrap suport for Waibu Framework",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/ardhi/waibu-bootstrap.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"bootstrap",
|
|
16
|
+
"waibu",
|
|
17
|
+
"web",
|
|
18
|
+
"webserver",
|
|
19
|
+
"bajo",
|
|
20
|
+
"framework",
|
|
21
|
+
"fastify",
|
|
22
|
+
"modular"
|
|
23
|
+
],
|
|
24
|
+
"author": "Ardhi Lukianto <ardhi@lukianto.com>",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/ardhi/waibu-bootstrap/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/ardhi/waibu-bootstrap#readme",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"bootstrap": "^5.3.3"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { sizes } from '../method/after-build-tag/_lib.js'
|
|
2
|
+
|
|
3
|
+
function getInputAttr (group, formControl = true, ro) {
|
|
4
|
+
const { omit, get, isPlainObject, isArray, isString, has } = this.plugin.app.bajo.lib._
|
|
5
|
+
const { escape } = this.plugin.app.waibu
|
|
6
|
+
if (formControl) group._.class.push('form-control')
|
|
7
|
+
const attr = omit(group._, ['hint', 'label', 'wrapper'])
|
|
8
|
+
if (has(attr, 'name') && !attr.value && this.component.locals.form) {
|
|
9
|
+
attr.dataType = attr.dataType ?? 'auto'
|
|
10
|
+
const val = get(this, `locals.form.${attr.name}`)
|
|
11
|
+
if (isPlainObject(val) || isArray(val)) attr.dataValue = escape(JSON.stringify(val))
|
|
12
|
+
else if (isString(val)) attr.dataValue = escape(val)
|
|
13
|
+
else attr.dataValue = val
|
|
14
|
+
if (ro) {
|
|
15
|
+
if (attr.dataType === 'boolean') attr.value = this.component.req.t(val ? 'Yes' : 'No')
|
|
16
|
+
else if (has(attr, 'name') === 'lat') attr.value = escape(this.component.req.format(val, attr.dataType, { latitude: true }))
|
|
17
|
+
else if (has(attr, 'name') === 'lng') attr.value = escape(this.component.req.format(val, attr.dataType, { longitude: true }))
|
|
18
|
+
else attr.value = escape(this.component.req.format(val, attr.dataType))
|
|
19
|
+
} else attr.value = attr.dataValue
|
|
20
|
+
}
|
|
21
|
+
if (sizes.includes(attr.size) && formControl) attr.class.push(`form-control-${attr.size}`)
|
|
22
|
+
return omit(attr, ['size', 'col'])
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function buildFormHint (group, tag, cls) {
|
|
26
|
+
if (!group.hint.id && group._.id) group.hint.id = group._.id + '-hint'
|
|
27
|
+
group.hint.class.push(cls ?? 'form-text')
|
|
28
|
+
return await this.component.render({ tag: tag ?? 'div', attr: group.hint, html: group._.hint })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function buildFormLabel (group, tag, cls) {
|
|
32
|
+
const { omit } = this.plugin.app.bajo.lib._
|
|
33
|
+
group.label.for = group._.id
|
|
34
|
+
if (!group.label.floating) group.label.class.push(cls ?? 'form-label')
|
|
35
|
+
group.label = omit(group.label, ['floating'])
|
|
36
|
+
return await this.component.render({ tag: tag ?? 'label', attr: group.label, html: group._.label })
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function buildFormInput (group, params) {
|
|
40
|
+
const attr = getInputAttr.call(this, group)
|
|
41
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function buildFormCheck (group, params) {
|
|
45
|
+
const { has, get } = this.plugin.app.bajo.lib._
|
|
46
|
+
const attr = getInputAttr.call(this, group, false)
|
|
47
|
+
attr.type = 'checkbox'
|
|
48
|
+
attr.class.push('form-check-input')
|
|
49
|
+
if (has(attr, 'name') && !attr.value) attr.value = 'true'
|
|
50
|
+
if (has(attr, 'name') && !has(attr, 'checked') && attr.value === get(this, `locals.form.${attr.name}`)) attr.checked = true
|
|
51
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function buildFormSwitch (group, params) {
|
|
55
|
+
const { has, get } = this.plugin.app.bajo.lib._
|
|
56
|
+
const attr = getInputAttr.call(this, group, false)
|
|
57
|
+
attr.type = 'checkbox'
|
|
58
|
+
attr.class.push('form-check-input')
|
|
59
|
+
attr.role = 'switch'
|
|
60
|
+
if (has(attr, 'name') && !attr.value) attr.value = 'true'
|
|
61
|
+
if (has(attr, 'name') && !has(attr, 'checked') && attr.value === get(this, `locals.form.${attr.name}`)) attr.checked = true
|
|
62
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function buildFormRadio (group, params) {
|
|
66
|
+
const attr = getInputAttr.call(this, group, false)
|
|
67
|
+
attr.type = 'radio'
|
|
68
|
+
attr.class.push('form-check-input')
|
|
69
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function buildFormCheckToggle (group, params) {
|
|
73
|
+
const attr = getInputAttr.call(this, group, false)
|
|
74
|
+
attr.type = 'checkbox'
|
|
75
|
+
attr.autocomplete = 'off'
|
|
76
|
+
attr.class.push('btn-check')
|
|
77
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function buildFormRadioToggle (group, params) {
|
|
81
|
+
const attr = getInputAttr.call(this, group, false)
|
|
82
|
+
attr.type = 'radio'
|
|
83
|
+
attr.autocomplete = 'off'
|
|
84
|
+
attr.class.push('btn-check')
|
|
85
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function buildFormPlaintext (group, params) {
|
|
89
|
+
const attr = getInputAttr.call(this, group, false, true)
|
|
90
|
+
attr.class.push('form-control-plaintext')
|
|
91
|
+
attr.readonly = ''
|
|
92
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function buildFormColor (group, params) {
|
|
96
|
+
const attr = getInputAttr.call(this, group)
|
|
97
|
+
attr.class.push('form-control-color')
|
|
98
|
+
attr.type = 'color'
|
|
99
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function buildFormFile (group, params) {
|
|
103
|
+
const attr = getInputAttr.call(this, group)
|
|
104
|
+
attr.type = 'file'
|
|
105
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function buildFormTextarea (group, params) {
|
|
109
|
+
const attr = getInputAttr.call(this, group)
|
|
110
|
+
params.html = attr.value
|
|
111
|
+
delete attr.value
|
|
112
|
+
return await this.component.render({ tag: 'textarea', attr, html: params.html })
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function buildFormSelect (group, params) {
|
|
116
|
+
const { omit, trim } = this.plugin.app.bajo.lib._
|
|
117
|
+
const { $ } = this.component
|
|
118
|
+
let attr = getInputAttr.call(this, group, false)
|
|
119
|
+
attr.value = attr.value + ''
|
|
120
|
+
attr.class.push('form-select')
|
|
121
|
+
let html = params.html
|
|
122
|
+
if (sizes.includes(attr.size)) attr.class.push(`form-select-${attr.size}`)
|
|
123
|
+
if (attr.options) html = this._buildOptions({ attr, html: '' })
|
|
124
|
+
else {
|
|
125
|
+
const items = []
|
|
126
|
+
$(`<div>${trim(html ?? '')}</div>`).find('option').each(function () {
|
|
127
|
+
items.push(trim($(this).prop('outerHTML')))
|
|
128
|
+
})
|
|
129
|
+
html = items.join('\n')
|
|
130
|
+
}
|
|
131
|
+
attr = omit(attr, ['size', 'type', 'options', 'value'])
|
|
132
|
+
return await this.component.render({ tag: 'select', attr, html })
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function buildFormRange (group, params) {
|
|
136
|
+
const attr = getInputAttr.call(this, group, false)
|
|
137
|
+
attr.type = 'range'
|
|
138
|
+
attr.class.push('form-range')
|
|
139
|
+
return await this.component.render({ tag: 'input', attr, selfClosing: true })
|
|
140
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
async function a () {
|
|
2
|
+
return class A extends this.baseFactory {
|
|
3
|
+
constructor (options) {
|
|
4
|
+
super(options)
|
|
5
|
+
this.component.normalizeAttr(this.params, { tag: 'a' })
|
|
6
|
+
if (!this.params.attr.href) this.params.attr.href = '#'
|
|
7
|
+
if (this.params.html.includes('<i class="')) this.params.attr.class.push('icon-link')
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default a
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const cls = 'accordion-item'
|
|
2
|
+
|
|
3
|
+
async function accordionItem () {
|
|
4
|
+
return class AccordionItem extends this.baseFactory {
|
|
5
|
+
constructor (options) {
|
|
6
|
+
super(options)
|
|
7
|
+
this.selector = '.' + cls
|
|
8
|
+
this.component.normalizeAttr(this.params, { tag: 'div', cls, autoId: true })
|
|
9
|
+
this.params.attr.body = this.params.attr.body ?? true
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async build () {
|
|
13
|
+
const { omit, without } = this.plugin.app.bajo.lib._
|
|
14
|
+
const { groupAttrs } = this.plugin.app.waibuMpa
|
|
15
|
+
const group = groupAttrs(this.params.attr, ['body'])
|
|
16
|
+
if (!group.body.noPadding) group.body.class.push('accordion-body')
|
|
17
|
+
const clsList = without(this.params.attr.class, cls)
|
|
18
|
+
const header = ['<h2 class="accordion-header">',
|
|
19
|
+
`<button class="${this.params.attr.narrowHeader ? 'px-3 py-2 ' : ''}accordion-button${this.params.attr.showOnStart ? '' : ' collapsed'}"`,
|
|
20
|
+
`type="button" data-bs-toggle="collapse" data-bs-target="#${this.params.attr.id}"`,
|
|
21
|
+
`aria-expanded="${this.params.attr.showOnStart}"`,
|
|
22
|
+
'x-data',
|
|
23
|
+
`@click="$dispatch('accordion-item', { id: $el.closest('.accordion').id, cls: '${clsList.join(' ')}' })"`,
|
|
24
|
+
`aria-controls="${this.params.attr.id}">${this.params.attr.header}</button></h2>`]
|
|
25
|
+
const body = await this.component.buildTag({ tag: 'div', attr: group.body, html: this.params.html })
|
|
26
|
+
const details = [`<div id="${this.params.attr.id}" class="accordion-collapse collapse${this.params.attr.showOnStart ? ' show' : ''}">`,
|
|
27
|
+
body, '</div']
|
|
28
|
+
this.params.html = `${header.join(' ')}\n${details.join(' ')}`
|
|
29
|
+
this.params.attr = omit(this.params.attr, ['id', 'noPadding', 'narrowHeader', 'bodyClass'])
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default accordionItem
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const cls = 'accordion'
|
|
2
|
+
|
|
3
|
+
async function accordion () {
|
|
4
|
+
return class Accordion extends this.baseFactory {
|
|
5
|
+
constructor (options) {
|
|
6
|
+
super(options)
|
|
7
|
+
this.selector = '.' + cls
|
|
8
|
+
this.component.normalizeAttr(this.params, { tag: 'div', cls, autoId: true })
|
|
9
|
+
if (this.params.attr.noBorder) this.params.attr.class.push('accordion-flush')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async build () {
|
|
13
|
+
const { $ } = this.component
|
|
14
|
+
if (!this.params.attr.alwaysOpen) {
|
|
15
|
+
const me = this
|
|
16
|
+
this.params.html = $(`<div>${this.params.html}</div>`).children().each(function () {
|
|
17
|
+
$(this).find('.accordion-collapse').prop('data-bs-parent', '#' + me.params.attr.id)
|
|
18
|
+
}).parent().html()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default accordion
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { colors, parseVariant } from '../method/after-build-tag/_lib.js'
|
|
2
|
+
|
|
3
|
+
const cls = 'alert'
|
|
4
|
+
|
|
5
|
+
async function alert () {
|
|
6
|
+
return class Alert extends this.baseFactory {
|
|
7
|
+
constructor (options) {
|
|
8
|
+
super(options)
|
|
9
|
+
const { without } = this.plugin.app.bajo.lib._
|
|
10
|
+
this.selector = '.' + cls
|
|
11
|
+
const myColors = without(colors, 'link')
|
|
12
|
+
this.component.normalizeAttr(this.params, { cls, tag: 'div', role: 'alert' })
|
|
13
|
+
if (this.params.attr.color) this.params.attr.class.push(parseVariant.call(this, { cls, value: this.params.attr.color, values: myColors, prepend: true }))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async build () {
|
|
17
|
+
const { isEmpty } = this.plugin.app.bajo.lib._
|
|
18
|
+
const { $ } = this.component
|
|
19
|
+
const html = $(`<div>${this.params.html}</div>`).children().each(function () {
|
|
20
|
+
if (this.name === 'a') $(this).addClass('alert-link')
|
|
21
|
+
if (['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(this.name)) $(this).addClass('alert-heading')
|
|
22
|
+
}).parent().html()
|
|
23
|
+
if (!isEmpty(html)) this.params.html = html
|
|
24
|
+
if (this.params.attr.dismiss) {
|
|
25
|
+
this.params.attr.class.push('alert-dismissible', 'fade', 'show')
|
|
26
|
+
const attr = { 'data-bs-dismiss': 'alert' }
|
|
27
|
+
this.params.html += await this.component.buildTag({ tag: 'btnClose', attr })
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default alert
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
async function appLauncherTrigger () {
|
|
2
|
+
return class AppLauncherTrigger extends this.baseFactory {
|
|
3
|
+
constructor (options) {
|
|
4
|
+
super(options)
|
|
5
|
+
const { isString } = this.plugin.app.bajo.lib._
|
|
6
|
+
this.params.attr.color = this.params.attr.color ?? 'color:body-emphasis'
|
|
7
|
+
this.params.attr.text = this.params.attr.text ?? 'decoration:none'
|
|
8
|
+
this.params.attr.display = 'type:block'
|
|
9
|
+
this.params.attr.flex = 'justify-content:center align-items:center'
|
|
10
|
+
this.params.attr.href = this.params.attr.href ?? '#'
|
|
11
|
+
if (isString(this.params.attr.open)) {
|
|
12
|
+
const [id, type = 'modal'] = this.params.attr.open.split(':')
|
|
13
|
+
this.params.attr['data-bs-target'] = `#${id}`
|
|
14
|
+
this.params.attr['data-bs-toggle'] = type === 'drawer' ? 'offcanvas' : type
|
|
15
|
+
this.params.attr['aria-controls'] = id
|
|
16
|
+
}
|
|
17
|
+
this.params.attr.padding = this.params.attr.padding ?? 'all-1'
|
|
18
|
+
this.params.attr.imgDimWidth = this.params.attr.imgDimWidth ?? 48
|
|
19
|
+
this.params.attr.imgDimHeight = this.params.attr.imgDimHeight ?? 48
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async build () {
|
|
23
|
+
const { fastGlob } = this.plugin.app.bajo.lib
|
|
24
|
+
const { get, omit, merge } = this.plugin.app.bajo.lib._
|
|
25
|
+
let logo = 'waibu'
|
|
26
|
+
const files = await fastGlob(`${this.plugin.app.main.dir.pkg}/bajo/logo.*`)
|
|
27
|
+
if (files.length > 0) logo = 'main'
|
|
28
|
+
this.params.tag = 'a'
|
|
29
|
+
const logoStyle = get(this, `plugin.app.${logo}.config.waibu.logoStyle`)
|
|
30
|
+
if (logoStyle) this.params.attr.style = merge({}, logoStyle, this.params.attr.style)
|
|
31
|
+
this.params.html = await this.component.buildSentence(`<c:img width="${this.params.attr.imgDimWidth}" height="${this.params.attr.imgDimHeight}" src="waibuMpa:/logo/${logo}" />`)
|
|
32
|
+
this.params.attr = omit(this.params.attr, ['imgDimHeight', 'imgDimWidth'])
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default appLauncherTrigger
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
async function appLauncher () {
|
|
2
|
+
return class AppLauncher extends this.baseFactory {
|
|
3
|
+
constructor (options) {
|
|
4
|
+
super(options)
|
|
5
|
+
const { generateId } = this.plugin.app.bajo
|
|
6
|
+
this.params.noTag = true
|
|
7
|
+
this.params.attr.id = this.params.attr.id ?? generateId('alpha')
|
|
8
|
+
this.params.attr.type = this.params.attr.type ?? 'drawer'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async build () {
|
|
12
|
+
const { groupAttrs, attrToArray } = this.plugin.app.waibuMpa
|
|
13
|
+
const group = groupAttrs(this.params.attr, ['trigger'])
|
|
14
|
+
let launcher = `<c:drawer id="${this.params.attr.id}" t:title="Modules" no-padding>\n`
|
|
15
|
+
launcher += '<c:div padding="start-3 bottom-3 end-3">'
|
|
16
|
+
if (this.params.attr.type === 'modal') launcher = `<c:modal id="${this.params.attr.id}" t:title="Modules" centered>\n`
|
|
17
|
+
const toolbar = attrToArray(this.params.attr.toolbar)
|
|
18
|
+
if (toolbar.length > 0) {
|
|
19
|
+
launcher += '<c:navbar>\n<c:nav tag="ul" dim="width:100" flex="justify-content:end">\n'
|
|
20
|
+
for (const t of toolbar) {
|
|
21
|
+
if (t === 'user') launcher += '<c:nav-dropdown-user />\n'
|
|
22
|
+
if (t === '-') launcher += '<c:nav-divider />\n'
|
|
23
|
+
if (t === 'fullscreen') launcher += '<c:nav-toggle-fullscreen />\n'
|
|
24
|
+
if (t === 'darkmode') launcher += '<c:nav-dropdown-darkmode dropdown-menu="end" />\n'
|
|
25
|
+
if (t === 'language') launcher += '<c:nav-dropdown-language dropdown-menu="end" />\n'
|
|
26
|
+
}
|
|
27
|
+
launcher += '</c:nav></c:navbar>\n'
|
|
28
|
+
}
|
|
29
|
+
launcher += '<c:grid-row gutter="1">\n'
|
|
30
|
+
for (const m of (this.component.locals.menu.homes ?? [])) {
|
|
31
|
+
launcher += `
|
|
32
|
+
<c:grid-col col="4" text="align:center">
|
|
33
|
+
<c:a href="${m.href}" display="type:block" border rounded padding="all-2" text="decoration:none">
|
|
34
|
+
<c:img src="waibuMpa:/logo/${m.ns}" height="60" fluid/>
|
|
35
|
+
<c:div margin="top-2">${m.title}</c:div>
|
|
36
|
+
</c:a>
|
|
37
|
+
</c:grid-col>
|
|
38
|
+
`
|
|
39
|
+
}
|
|
40
|
+
launcher += '</c:grid-row>\n'
|
|
41
|
+
if (this.params.attr.type === 'modal') launcher += '</c:modal>'
|
|
42
|
+
else launcher += '</c:div></c:drawer>'
|
|
43
|
+
let trigger = ''
|
|
44
|
+
if (group.trigger) {
|
|
45
|
+
this.params.attr = group._
|
|
46
|
+
group.trigger.open = `${this.params.attr.id}:drawer`
|
|
47
|
+
trigger = await this.component.buildTag({ tag: 'appLauncherTrigger', attr: group.trigger })
|
|
48
|
+
}
|
|
49
|
+
launcher = `${trigger} ${launcher}`
|
|
50
|
+
this.params.html = await this.component.buildSentence(launcher)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default appLauncher
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const cls = 'badge'
|
|
2
|
+
|
|
3
|
+
async function badge () {
|
|
4
|
+
return class Badge extends this.baseFactory {
|
|
5
|
+
constructor (options) {
|
|
6
|
+
super(options)
|
|
7
|
+
this.selector = '.' + cls
|
|
8
|
+
this.component.normalizeAttr(this.params, { tag: 'span' })
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async build () {
|
|
12
|
+
const { isString, omit } = this.plugin.app.bajo.lib._
|
|
13
|
+
if (isString(this.params.attr.alt)) this.params.html += `<span class="visually-hidden">${this.params.attr.alt}</span>`
|
|
14
|
+
if (this.params.attr.dot) {
|
|
15
|
+
this.params.attr.class.push('p-2')
|
|
16
|
+
this.params.html = ''
|
|
17
|
+
} else this.params.attr.class.push(cls)
|
|
18
|
+
|
|
19
|
+
this.params.attr = omit(this.params.attr, ['alt', 'dot'])
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default badge
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const cls = 'blockquote'
|
|
2
|
+
|
|
3
|
+
async function blockquote () {
|
|
4
|
+
return class Blockquote extends this.baseFactory {
|
|
5
|
+
constructor (options) {
|
|
6
|
+
super(options)
|
|
7
|
+
this.selector = '.' + cls
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async build () {
|
|
11
|
+
const { isString } = this.plugin.app.bajo.lib._
|
|
12
|
+
this.component.normalizeAttr(this.params, { cls })
|
|
13
|
+
if (isString(this.params.attr.attribution)) {
|
|
14
|
+
this.params.prepend = '<figure>'
|
|
15
|
+
this.params.append = `<figcaption class="blockquote-footer">${this.params.attr.attribution}</figcaption></figure>`
|
|
16
|
+
delete this.params.attr.attribution
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default blockquote
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const cls = 'breadcrumb-item'
|
|
2
|
+
|
|
3
|
+
async function breadcrumbItem () {
|
|
4
|
+
return class BreadcrumbItem extends this.baseFactory {
|
|
5
|
+
constructor (options) {
|
|
6
|
+
super(options)
|
|
7
|
+
this.selector = '.' + cls
|
|
8
|
+
this.component.normalizeAttr(this.params, { tag: 'li', cls })
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async build () {
|
|
12
|
+
const { omit } = this.plugin.app.bajo.lib._
|
|
13
|
+
const { attrToArray } = this.plugin.app.waibuMpa
|
|
14
|
+
if (this.params.attr.href) {
|
|
15
|
+
if (this.params.attr.hrefRebuild) {
|
|
16
|
+
this.params.attr.hrefRebuild = attrToArray(this.params.attr.hrefRebuild)
|
|
17
|
+
const [path, ...exclude] = this.params.attr.hrefRebuild
|
|
18
|
+
this.params.attr.href = this.component.buildUrl({ exclude, base: path })
|
|
19
|
+
}
|
|
20
|
+
this.params.html = `<a href="${this.params.attr.href}">${this.params.html}</a>`
|
|
21
|
+
}
|
|
22
|
+
this.params.attr = omit(this.params.attr, ['href', 'hrefRebuild'])
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default breadcrumbItem
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const cls = 'breadcrumb'
|
|
2
|
+
|
|
3
|
+
function bcHandler (href, source, opts = {}) {
|
|
4
|
+
const { last } = this.plugin.app.bajo.lib._
|
|
5
|
+
const { titleize } = this.plugin.app.bajo
|
|
6
|
+
const parts = href.split('/')
|
|
7
|
+
const content = titleize(last(parts))
|
|
8
|
+
if (href === source) return { content }
|
|
9
|
+
return { content, href, hrefRebuild: opts.hrefRebuild }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function generateItems (breadcrumb) {
|
|
13
|
+
const html = []
|
|
14
|
+
for (const b of breadcrumb) {
|
|
15
|
+
let href = ''
|
|
16
|
+
if (b.href) {
|
|
17
|
+
href = 'href="' + b.href + '"'
|
|
18
|
+
if (b.hrefRebuild) {
|
|
19
|
+
href += ' href-rebuild="' + b.hrefRebuild.join(' ') + '"'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const icon = b.icon ? (' icon="' + b.icon + '"') : ''
|
|
23
|
+
const title = b.href && b.hrefRebuild && !this.component.locals._meta.this.params.model ? this.component.locals.page.title : b.content
|
|
24
|
+
const content = b.content ? (' t:content="' + title + '"') : ''
|
|
25
|
+
const active = b.href ? ' active' : ''
|
|
26
|
+
html.push(`<c:breadcrumb-item ${icon} ${href} ${content} ${active} />`)
|
|
27
|
+
}
|
|
28
|
+
return await this.component.buildSentence(html.join('\n'))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function breadcrumb () {
|
|
32
|
+
return class Breadcrumb extends this.baseFactory {
|
|
33
|
+
constructor (options) {
|
|
34
|
+
super(options)
|
|
35
|
+
this.selector = '.' + cls
|
|
36
|
+
this.component.normalizeAttr(this.params, { tag: 'ol', cls })
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async build () {
|
|
40
|
+
const { isString, omit } = this.plugin.app.bajo.lib._
|
|
41
|
+
const { routePath } = this.plugin.app.waibu
|
|
42
|
+
const { urlToBreadcrumb, attrToArray } = this.plugin.app.waibuMpa
|
|
43
|
+
let divider = ''
|
|
44
|
+
if (this.params.attr.noDivider) divider = ' style="--bs-breadcrumb-divider: \'\';"'
|
|
45
|
+
else if (isString(this.params.attr.divider)) divider = ` style="--bs-breadcrumb-divider: '${this.params.attr.divider}';"`
|
|
46
|
+
this.params.prepend = `<nav aria-label="breadcrumb"${divider}>`
|
|
47
|
+
this.params.append = '</nav>'
|
|
48
|
+
if (this.params.attr.autoFill && this.component.locals.breadcrumb) {
|
|
49
|
+
this.params.html = await generateItems.call(this, this.component.locals.breadcrumb)
|
|
50
|
+
} else if (this.params.attr.autoDetect) {
|
|
51
|
+
const url = isString(this.params.attr.autoDetect) ? this.params.attr.autoDetect : this.component.locals._meta.url
|
|
52
|
+
const handlerOpts = {}
|
|
53
|
+
if (this.params.attr.hrefRebuild === true) this.params.attr.hrefRebuild = 'list id mode'
|
|
54
|
+
if (isString(this.params.attr.hrefRebuild)) handlerOpts.hrefRebuild = attrToArray(this.params.attr.hrefRebuild)
|
|
55
|
+
const breadcrumb = urlToBreadcrumb(routePath(url), { handler: bcHandler, handlerScope: this, handlerOpts })
|
|
56
|
+
if (!this.params.attr.noHome) breadcrumb.unshift({ icon: 'house', href: '/' })
|
|
57
|
+
this.params.html = await generateItems.call(this, breadcrumb)
|
|
58
|
+
}
|
|
59
|
+
this.params.attr = omit(this.params.attr, ['divider', 'autoFill', 'autoDetect', 'autoDetectHome', 'hrefRebuild'])
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default breadcrumb
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
async function btnBackToTop () {
|
|
2
|
+
return class BtnBackToTop extends this.baseFactory {
|
|
3
|
+
constructor (options) {
|
|
4
|
+
super(options)
|
|
5
|
+
this.params.noTag = true
|
|
6
|
+
this.params.attr.icon = this.params.attr.icon ?? 'arrowUp'
|
|
7
|
+
this.params.attr.color = this.params.attr.color ?? 'primary'
|
|
8
|
+
this.params.attr.revealAt = this.params.attr.revealAt ?? '20'
|
|
9
|
+
this.params.attr.style = {
|
|
10
|
+
position: 'fixed',
|
|
11
|
+
bottom: '20px',
|
|
12
|
+
right: '20px',
|
|
13
|
+
display: 'none'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async build () {
|
|
18
|
+
this.params.attr['x-data'] = `{
|
|
19
|
+
scroll () {
|
|
20
|
+
if (document.body.scrollTop > ${this.params.attr.revealAt} || document.documentElement.scrollTop > ${this.params.attr.revealAt}) {
|
|
21
|
+
this.$refs.btn.style.display = 'block'
|
|
22
|
+
} else {
|
|
23
|
+
this.$refs.btn.style.display = 'none'
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
toTop () {
|
|
27
|
+
document.body.scrollTop = 0
|
|
28
|
+
document.documentElement.scrollTop = 0
|
|
29
|
+
}
|
|
30
|
+
}`
|
|
31
|
+
this.params.attr['@scroll.window'] = 'scroll()'
|
|
32
|
+
this.params.attr['x-ref'] = 'btn'
|
|
33
|
+
this.params.attr['@click'] = 'toTop()'
|
|
34
|
+
delete this.params.attr.revealAt
|
|
35
|
+
this.params.html = await this.component.buildTag({ tag: 'btn', attr: this.params.attr })
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default btnBackToTop
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const cls = 'btn-close'
|
|
2
|
+
|
|
3
|
+
async function btnClose () {
|
|
4
|
+
return class BtnClose extends this.baseFactory {
|
|
5
|
+
constructor (options) {
|
|
6
|
+
super(options)
|
|
7
|
+
this.selector = '.' + cls
|
|
8
|
+
this.component.normalizeAttr(this.params, { tag: 'button', cls, type: 'button', ariaLabel: this.component.req.t('Close') })
|
|
9
|
+
const { isString } = this.plugin.app.bajo.lib._
|
|
10
|
+
if (this.params.attr.close) this.params.attr.dataBsDismiss = isString(this.params.attr.close) ? this.params.attr.close : 'modal'
|
|
11
|
+
if (this.params.attr.disabled) this.params.attr.class.push('disabled')
|
|
12
|
+
this.params.html = ''
|
|
13
|
+
delete this.params.attr.disabled
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default btnClose
|