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.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/bajo/.alias +1 -0
  4. package/bajo/config.json +6 -0
  5. package/bajo/hook/waibu-mpa.bootstrap@after-build-page.js +5 -0
  6. package/bajoI18N/resource/id.json +2 -0
  7. package/package.json +33 -0
  8. package/waibuMpa/theme/component/factory/_lib.js +140 -0
  9. package/waibuMpa/theme/component/factory/a.js +12 -0
  10. package/waibuMpa/theme/component/factory/accordion-item.js +34 -0
  11. package/waibuMpa/theme/component/factory/accordion.js +24 -0
  12. package/waibuMpa/theme/component/factory/alert.js +33 -0
  13. package/waibuMpa/theme/component/factory/app-launcher-trigger.js +37 -0
  14. package/waibuMpa/theme/component/factory/app-launcher.js +55 -0
  15. package/waibuMpa/theme/component/factory/badge.js +24 -0
  16. package/waibuMpa/theme/component/factory/blockquote.js +22 -0
  17. package/waibuMpa/theme/component/factory/breadcrumb-item.js +27 -0
  18. package/waibuMpa/theme/component/factory/breadcrumb.js +64 -0
  19. package/waibuMpa/theme/component/factory/btn-back-to-top.js +40 -0
  20. package/waibuMpa/theme/component/factory/btn-close.js +18 -0
  21. package/waibuMpa/theme/component/factory/btn-group.js +25 -0
  22. package/waibuMpa/theme/component/factory/btn-toolbar.js +13 -0
  23. package/waibuMpa/theme/component/factory/btn.js +40 -0
  24. package/waibuMpa/theme/component/factory/card-body.js +13 -0
  25. package/waibuMpa/theme/component/factory/card-footer.js +17 -0
  26. package/waibuMpa/theme/component/factory/card-group.js +13 -0
  27. package/waibuMpa/theme/component/factory/card-header.js +27 -0
  28. package/waibuMpa/theme/component/factory/card-link.js +14 -0
  29. package/waibuMpa/theme/component/factory/card-subtitle.js +13 -0
  30. package/waibuMpa/theme/component/factory/card-text.js +15 -0
  31. package/waibuMpa/theme/component/factory/card-title.js +13 -0
  32. package/waibuMpa/theme/component/factory/card.js +23 -0
  33. package/waibuMpa/theme/component/factory/carousel-item.js +25 -0
  34. package/waibuMpa/theme/component/factory/carousel.js +53 -0
  35. package/waibuMpa/theme/component/factory/collapse-item.js +14 -0
  36. package/waibuMpa/theme/component/factory/collapse.js +58 -0
  37. package/waibuMpa/theme/component/factory/container.js +22 -0
  38. package/waibuMpa/theme/component/factory/drawer-toolbar.js +6 -0
  39. package/waibuMpa/theme/component/factory/drawer.js +59 -0
  40. package/waibuMpa/theme/component/factory/dropdown-item.js +34 -0
  41. package/waibuMpa/theme/component/factory/dropdown.js +121 -0
  42. package/waibuMpa/theme/component/factory/fieldset.js +39 -0
  43. package/waibuMpa/theme/component/factory/figcaption.js +13 -0
  44. package/waibuMpa/theme/component/factory/figure.js +20 -0
  45. package/waibuMpa/theme/component/factory/form-check-toggle.js +33 -0
  46. package/waibuMpa/theme/component/factory/form-check.js +56 -0
  47. package/waibuMpa/theme/component/factory/form-color.js +12 -0
  48. package/waibuMpa/theme/component/factory/form-date.js +26 -0
  49. package/waibuMpa/theme/component/factory/form-datetime.js +83 -0
  50. package/waibuMpa/theme/component/factory/form-file.js +17 -0
  51. package/waibuMpa/theme/component/factory/form-input-addon.js +10 -0
  52. package/waibuMpa/theme/component/factory/form-input.js +132 -0
  53. package/waibuMpa/theme/component/factory/form-password.js +13 -0
  54. package/waibuMpa/theme/component/factory/form-plaintext.js +14 -0
  55. package/waibuMpa/theme/component/factory/form-radio-toggle.js +13 -0
  56. package/waibuMpa/theme/component/factory/form-radio.js +12 -0
  57. package/waibuMpa/theme/component/factory/form-range.js +14 -0
  58. package/waibuMpa/theme/component/factory/form-select-country.js +25 -0
  59. package/waibuMpa/theme/component/factory/form-select-ext.js +53 -0
  60. package/waibuMpa/theme/component/factory/form-select.js +34 -0
  61. package/waibuMpa/theme/component/factory/form-switch.js +18 -0
  62. package/waibuMpa/theme/component/factory/form-textarea.js +12 -0
  63. package/waibuMpa/theme/component/factory/form-time.js +22 -0
  64. package/waibuMpa/theme/component/factory/form.js +46 -0
  65. package/waibuMpa/theme/component/factory/grid-col.js +44 -0
  66. package/waibuMpa/theme/component/factory/grid-row.js +21 -0
  67. package/waibuMpa/theme/component/factory/heading.js +20 -0
  68. package/waibuMpa/theme/component/factory/img.js +20 -0
  69. package/waibuMpa/theme/component/factory/lead.js +15 -0
  70. package/waibuMpa/theme/component/factory/list-item.js +38 -0
  71. package/waibuMpa/theme/component/factory/list.js +62 -0
  72. package/waibuMpa/theme/component/factory/masonry.js +34 -0
  73. package/waibuMpa/theme/component/factory/modal-body.js +13 -0
  74. package/waibuMpa/theme/component/factory/modal-footer.js +13 -0
  75. package/waibuMpa/theme/component/factory/modal-header.js +13 -0
  76. package/waibuMpa/theme/component/factory/modal.js +60 -0
  77. package/waibuMpa/theme/component/factory/nav-divider.js +24 -0
  78. package/waibuMpa/theme/component/factory/nav-dropdown-darkmode.js +24 -0
  79. package/waibuMpa/theme/component/factory/nav-dropdown-language.js +26 -0
  80. package/waibuMpa/theme/component/factory/nav-dropdown-setting.js +84 -0
  81. package/waibuMpa/theme/component/factory/nav-dropdown-user.js +36 -0
  82. package/waibuMpa/theme/component/factory/nav-item-signout.js +26 -0
  83. package/waibuMpa/theme/component/factory/nav-item.js +55 -0
  84. package/waibuMpa/theme/component/factory/nav-toggle-fullscreen.js +47 -0
  85. package/waibuMpa/theme/component/factory/nav.js +30 -0
  86. package/waibuMpa/theme/component/factory/navbar-brand.js +16 -0
  87. package/waibuMpa/theme/component/factory/navbar-text.js +13 -0
  88. package/waibuMpa/theme/component/factory/navbar.js +65 -0
  89. package/waibuMpa/theme/component/factory/pagination-item.js +21 -0
  90. package/waibuMpa/theme/component/factory/pagination.js +22 -0
  91. package/waibuMpa/theme/component/factory/progress-stack.js +26 -0
  92. package/waibuMpa/theme/component/factory/progress.js +37 -0
  93. package/waibuMpa/theme/component/factory/scrollspy.js +25 -0
  94. package/waibuMpa/theme/component/factory/sidebar.js +74 -0
  95. package/waibuMpa/theme/component/factory/spinner.js +17 -0
  96. package/waibuMpa/theme/component/factory/table.js +40 -0
  97. package/waibuMpa/theme/component/factory/tbody.js +14 -0
  98. package/waibuMpa/theme/component/factory/td.js +15 -0
  99. package/waibuMpa/theme/component/factory/tfoot.js +14 -0
  100. package/waibuMpa/theme/component/factory/th.js +15 -0
  101. package/waibuMpa/theme/component/factory/thead.js +14 -0
  102. package/waibuMpa/theme/component/factory/toast-stack.js +15 -0
  103. package/waibuMpa/theme/component/factory/toast.js +33 -0
  104. package/waibuMpa/theme/component/factory/tr.js +15 -0
  105. package/waibuMpa/theme/component/method/after-build-tag/_lib.js +50 -0
  106. package/waibuMpa/theme/component/method/after-build-tag/active.js +7 -0
  107. package/waibuMpa/theme/component/method/after-build-tag/background.js +25 -0
  108. package/waibuMpa/theme/component/method/after-build-tag/border.js +26 -0
  109. package/waibuMpa/theme/component/method/after-build-tag/dim.js +23 -0
  110. package/waibuMpa/theme/component/method/after-build-tag/disabled.js +6 -0
  111. package/waibuMpa/theme/component/method/after-build-tag/display.js +34 -0
  112. package/waibuMpa/theme/component/method/after-build-tag/flex.js +69 -0
  113. package/waibuMpa/theme/component/method/after-build-tag/font.js +19 -0
  114. package/waibuMpa/theme/component/method/after-build-tag/gutter.js +23 -0
  115. package/waibuMpa/theme/component/method/after-build-tag/label.js +6 -0
  116. package/waibuMpa/theme/component/method/after-build-tag/link.js +24 -0
  117. package/waibuMpa/theme/component/method/after-build-tag/margin-padding.js +15 -0
  118. package/waibuMpa/theme/component/method/after-build-tag/popover.js +14 -0
  119. package/waibuMpa/theme/component/method/after-build-tag/position.js +52 -0
  120. package/waibuMpa/theme/component/method/after-build-tag/rounded.js +25 -0
  121. package/waibuMpa/theme/component/method/after-build-tag/text.js +32 -0
  122. package/waibuMpa/theme/component/method/after-build-tag/tooltip.js +14 -0
  123. package/waibuMpa/theme/component/method/after-build-tag.js +113 -0
  124. package/waibuMpa/theme.js +24 -0
  125. package/waibuStatic/asset/css/wbs.css +12 -0
  126. package/waibuStatic/asset/js/wbs.js +200 -0
  127. 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
+ ![GitHub package.json version](https://img.shields.io/github/package-json/v/ardhi/waibu-bootstrap) ![NPM Version](https://img.shields.io/npm/v/waibu-bootstrap)
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
@@ -0,0 +1,6 @@
1
+ {
2
+ "waibu": {
3
+ "prefix": "bootstrap"
4
+ },
5
+ "dependencies": ["waibu-mpa", "waibu-extra"]
6
+ }
@@ -0,0 +1,5 @@
1
+ async function waibuMpaBootstrapAfterBuildPage ({ $, req }) {
2
+ if (req.darkMode) $('html').attr('data-bs-theme', 'dark')
3
+ }
4
+
5
+ export default waibuMpaBootstrapAfterBuildPage
@@ -0,0 +1,2 @@
1
+ {
2
+ }
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