bitwrench 2.0.22 → 2.0.24
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.txt +1 -1
- package/README.md +4 -3
- package/bin/bwmcp.js +3 -0
- package/dist/bitwrench-bccl.cjs.js +1 -1
- package/dist/bitwrench-bccl.cjs.min.js +1 -1
- package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
- package/dist/bitwrench-bccl.esm.js +1 -1
- package/dist/bitwrench-bccl.esm.min.js +1 -1
- package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
- package/dist/bitwrench-bccl.umd.js +1 -1
- package/dist/bitwrench-bccl.umd.min.js +1 -1
- package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
- package/dist/bitwrench-code-edit.cjs.js +1 -1
- package/dist/bitwrench-code-edit.cjs.min.js +1 -1
- package/dist/bitwrench-code-edit.es5.js +1 -1
- package/dist/bitwrench-code-edit.es5.min.js +1 -1
- package/dist/bitwrench-code-edit.esm.js +1 -1
- package/dist/bitwrench-code-edit.esm.min.js +1 -1
- package/dist/bitwrench-code-edit.umd.js +1 -1
- package/dist/bitwrench-code-edit.umd.min.js +1 -1
- package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
- package/dist/bitwrench-debug.js +1 -1
- package/dist/bitwrench-debug.min.js +1 -1
- package/dist/bitwrench-lean.cjs.js +3 -3
- package/dist/bitwrench-lean.cjs.min.js +2 -2
- package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
- package/dist/bitwrench-lean.es5.js +3 -3
- package/dist/bitwrench-lean.es5.min.js +2 -2
- package/dist/bitwrench-lean.es5.min.js.gz +0 -0
- package/dist/bitwrench-lean.esm.js +3 -3
- package/dist/bitwrench-lean.esm.min.js +2 -2
- package/dist/bitwrench-lean.esm.min.js.gz +0 -0
- package/dist/bitwrench-lean.umd.js +3 -3
- package/dist/bitwrench-lean.umd.min.js +2 -2
- package/dist/bitwrench-lean.umd.min.js.gz +0 -0
- package/dist/bitwrench-util-css.cjs.js +1 -1
- package/dist/bitwrench-util-css.cjs.min.js +1 -1
- package/dist/bitwrench-util-css.es5.js +1 -1
- package/dist/bitwrench-util-css.es5.min.js +1 -1
- package/dist/bitwrench-util-css.esm.js +1 -1
- package/dist/bitwrench-util-css.esm.min.js +1 -1
- package/dist/bitwrench-util-css.umd.js +1 -1
- package/dist/bitwrench-util-css.umd.min.js +1 -1
- package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
- package/dist/bitwrench.cjs.js +3 -3
- package/dist/bitwrench.cjs.min.js +2 -2
- package/dist/bitwrench.cjs.min.js.gz +0 -0
- package/dist/bitwrench.css +1 -1
- package/dist/bitwrench.es5.js +3 -3
- package/dist/bitwrench.es5.min.js +2 -2
- package/dist/bitwrench.es5.min.js.gz +0 -0
- package/dist/bitwrench.esm.js +3 -3
- package/dist/bitwrench.esm.min.js +2 -2
- package/dist/bitwrench.esm.min.js.gz +0 -0
- package/dist/bitwrench.umd.js +3 -3
- package/dist/bitwrench.umd.min.js +2 -2
- package/dist/bitwrench.umd.min.js.gz +0 -0
- package/dist/builds.json +65 -65
- package/dist/bwserve.cjs.js +2 -2
- package/dist/bwserve.esm.js +2 -2
- package/dist/sri.json +45 -45
- package/docs/README.md +76 -0
- package/docs/app-patterns.md +264 -0
- package/docs/bitwrench-mcp.md +426 -0
- package/docs/bitwrench_api.md +2232 -0
- package/docs/bw-attach.md +399 -0
- package/docs/bwserve.md +841 -0
- package/docs/cli.md +307 -0
- package/docs/component-cheatsheet.md +144 -0
- package/docs/component-library.md +1099 -0
- package/docs/framework-translation-table.md +33 -0
- package/docs/llm-bitwrench-guide.md +672 -0
- package/docs/routing.md +562 -0
- package/docs/state-management.md +767 -0
- package/docs/taco-format.md +373 -0
- package/docs/theming.md +309 -0
- package/docs/thinking-in-bitwrench.md +1457 -0
- package/docs/tutorial-bwserve.md +297 -0
- package/docs/tutorial-embedded.md +314 -0
- package/docs/tutorial-website.md +255 -0
- package/package.json +11 -3
- package/readme.html +5 -4
- package/src/mcp/knowledge.js +231 -0
- package/src/mcp/live.js +226 -0
- package/src/mcp/server.js +216 -0
- package/src/mcp/tools.js +369 -0
- package/src/mcp/transport.js +55 -0
- package/src/version.js +3 -3
|
@@ -0,0 +1,1099 @@
|
|
|
1
|
+
# Component Library
|
|
2
|
+
|
|
3
|
+
Bitwrench ships over 50 `make*()` factory functions. Each takes a props object and returns a TACO -- a plain JavaScript object that describes UI. No DOM elements are created until you pass the result to `bw.DOM()` or `bw.html()`.
|
|
4
|
+
|
|
5
|
+
> For a quick scannable reference, see [Component Cheat Sheet](component-cheatsheet.md).
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
// Every factory works the same way
|
|
9
|
+
var card = bw.makeCard({ title: 'Hello', content: 'World' });
|
|
10
|
+
|
|
11
|
+
// The result is a plain object — not a DOM element
|
|
12
|
+
typeof card; // 'object'
|
|
13
|
+
card.t; // 'div'
|
|
14
|
+
|
|
15
|
+
// Render it however you want
|
|
16
|
+
bw.DOM('#app', card); // mount to DOM
|
|
17
|
+
var html = bw.html(card); // or get HTML string
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
> **Coming from React?** Each `make*()` function is like a React component that returns JSX — except it returns a plain object instead of a virtual DOM node, and there is no build step.
|
|
21
|
+
|
|
22
|
+
> **Coming from Bootstrap?** The factory functions replace Bootstrap's HTML class conventions. Instead of memorizing `<div class="card"><div class="card-body">...`, you write `bw.makeCard({ title, content })` and the correct markup is generated for you.
|
|
23
|
+
|
|
24
|
+
## Quick Reference
|
|
25
|
+
|
|
26
|
+
| Category | Components |
|
|
27
|
+
|----------|-----------|
|
|
28
|
+
| [Layout](#layout) | makeContainer, makeRow, makeCol, makeStack |
|
|
29
|
+
| [Content](#content) | makeCard\*, makeAlert, makeBadge, makeProgress\*, makeStatCard\*, makeMediaObject, makeTimeline, makeStepper, makeListGroup, makeAvatar, makeSkeleton, makeSpinner |
|
|
30
|
+
| [Navigation](#navigation) | makeNav, makeNavbar, makeTabs\*, makeBreadcrumb, makePagination |
|
|
31
|
+
| [Buttons](#buttons) | makeButton, makeButtonGroup |
|
|
32
|
+
| [Forms](#forms) | makeForm, makeFormGroup, makeInput, makeTextarea, makeSelect, makeCheckbox, makeRadio, makeSwitch, makeRange, makeSearchInput, makeChipInput\*, makeFileUpload |
|
|
33
|
+
| [Interactive](#interactive) | makeAccordion\*, makeModal\*, makeToast\*, makeDropdown, makeCarousel\* |
|
|
34
|
+
| [Overlays](#overlays) | makeTooltip, makePopover |
|
|
35
|
+
| [Loading & Placeholder](#loading--placeholder) | makeSpinner, makeSkeleton, makeAvatar |
|
|
36
|
+
| [Page-Level](#page-level-components) | makeHero, makeSection, makeFeatureGrid, makeCTA, makeCodeDemo |
|
|
37
|
+
| [Tables & Data](#tables--data) | makeTable, makeTableFromArray, makeDataTable, makeBarChart |
|
|
38
|
+
|
|
39
|
+
\*Has imperative handles (`el.bw` methods) -- see [Component Handles](#component-handles)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Layout
|
|
44
|
+
|
|
45
|
+
### makeContainer
|
|
46
|
+
|
|
47
|
+
Centered page container.
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
bw.makeContainer({
|
|
51
|
+
fluid: false, // true = full width, false = max-width centered
|
|
52
|
+
children: [...], // content (TACO or array of TACOs)
|
|
53
|
+
className: ''
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### makeRow
|
|
58
|
+
|
|
59
|
+
Flexbox row for grid layouts.
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
bw.makeRow({
|
|
63
|
+
children: [...], // array of makeCol() TACOs
|
|
64
|
+
gap: 3, // gap size (1-5)
|
|
65
|
+
className: ''
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### makeCol
|
|
70
|
+
|
|
71
|
+
Responsive grid column.
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
bw.makeCol({
|
|
75
|
+
size: 6, // fixed: 1-12
|
|
76
|
+
// or responsive:
|
|
77
|
+
size: { xs: 12, sm: 6, md: 4, lg: 3 },
|
|
78
|
+
offset: 0, // column offset (1-12)
|
|
79
|
+
content: 'Text or TACO', // alias for children
|
|
80
|
+
children: [...],
|
|
81
|
+
className: ''
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### makeStack
|
|
86
|
+
|
|
87
|
+
Flexbox stack (vertical or horizontal).
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
bw.makeStack({
|
|
91
|
+
children: [...],
|
|
92
|
+
direction: 'vertical', // 'vertical' or 'horizontal'
|
|
93
|
+
gap: 3, // gap size (1-8)
|
|
94
|
+
className: ''
|
|
95
|
+
})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Grid example:**
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
bw.DOM('#app', bw.makeContainer({
|
|
102
|
+
children: bw.makeRow({ gap: 4, children: [
|
|
103
|
+
bw.makeCol({ size: { md: 4 }, children: bw.makeCard({ title: 'One' }) }),
|
|
104
|
+
bw.makeCol({ size: { md: 4 }, children: bw.makeCard({ title: 'Two' }) }),
|
|
105
|
+
bw.makeCol({ size: { md: 4 }, children: bw.makeCard({ title: 'Three' }) })
|
|
106
|
+
]})
|
|
107
|
+
}));
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Content
|
|
113
|
+
|
|
114
|
+
### makeCard
|
|
115
|
+
|
|
116
|
+
Content card with optional header, footer, image, and variants.
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
bw.makeCard({
|
|
120
|
+
title: 'Title',
|
|
121
|
+
subtitle: 'Subtitle',
|
|
122
|
+
content: 'Body text or TACO',
|
|
123
|
+
footer: 'Footer text',
|
|
124
|
+
header: 'Header text',
|
|
125
|
+
image: { src: 'photo.jpg', alt: 'Description' },
|
|
126
|
+
imagePosition: 'top', // 'top' | 'bottom' | 'left' | 'right'
|
|
127
|
+
variant: 'primary', // color variant
|
|
128
|
+
bordered: true,
|
|
129
|
+
shadow: 'md', // 'none' | 'sm' | 'md' | 'lg'
|
|
130
|
+
hoverable: false, // add hover shadow effect
|
|
131
|
+
className: '',
|
|
132
|
+
style: ''
|
|
133
|
+
})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### makeAlert
|
|
137
|
+
|
|
138
|
+
Dismissible notification banner.
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
bw.makeAlert({
|
|
142
|
+
title: 'Warning', // optional bold title
|
|
143
|
+
content: 'Check your input.',
|
|
144
|
+
variant: 'warning', // 'info' | 'success' | 'warning' | 'danger'
|
|
145
|
+
dismissible: true, // show close button
|
|
146
|
+
className: ''
|
|
147
|
+
})
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### makeBadge
|
|
151
|
+
|
|
152
|
+
Small status indicator.
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
bw.makeBadge({
|
|
156
|
+
text: 'New',
|
|
157
|
+
variant: 'primary',
|
|
158
|
+
pill: false, // rounded pill shape
|
|
159
|
+
className: ''
|
|
160
|
+
})
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### makeProgress
|
|
164
|
+
|
|
165
|
+
Progress bar with optional animation.
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
bw.makeProgress({
|
|
169
|
+
value: 65,
|
|
170
|
+
max: 100,
|
|
171
|
+
variant: 'primary',
|
|
172
|
+
striped: false,
|
|
173
|
+
animated: false,
|
|
174
|
+
label: '65%', // text inside the bar
|
|
175
|
+
height: '' // custom height
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### makeStatCard
|
|
180
|
+
|
|
181
|
+
Statistic display with change indicator.
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
bw.makeStatCard({
|
|
185
|
+
value: 1234,
|
|
186
|
+
label: 'Active Users',
|
|
187
|
+
change: 12.5, // positive = green arrow up, negative = red arrow down
|
|
188
|
+
format: 'number', // 'number' | 'currency' | 'percent'
|
|
189
|
+
prefix: '', // e.g. '$'
|
|
190
|
+
suffix: '', // e.g. '%'
|
|
191
|
+
icon: '',
|
|
192
|
+
variant: '',
|
|
193
|
+
className: '',
|
|
194
|
+
style: ''
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
// String shorthand:
|
|
198
|
+
bw.makeStatCard('Active Users') // creates card with label only
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### makeMediaObject
|
|
202
|
+
|
|
203
|
+
Image and text side-by-side.
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
bw.makeMediaObject({
|
|
207
|
+
src: 'avatar.jpg',
|
|
208
|
+
alt: '',
|
|
209
|
+
title: 'User Name',
|
|
210
|
+
content: 'Description text',
|
|
211
|
+
reverse: false, // image on right instead of left
|
|
212
|
+
imageSize: '3rem',
|
|
213
|
+
className: ''
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### makeTimeline
|
|
218
|
+
|
|
219
|
+
Vertical timeline with event markers.
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
bw.makeTimeline({
|
|
223
|
+
items: [
|
|
224
|
+
{ title: 'Event 1', content: 'Details...', date: '2026-01-15', variant: 'success' },
|
|
225
|
+
{ title: 'Event 2', content: 'Details...', date: '2026-02-01', variant: 'info' }
|
|
226
|
+
],
|
|
227
|
+
className: ''
|
|
228
|
+
})
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### makeStepper
|
|
232
|
+
|
|
233
|
+
Multi-step wizard indicator.
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
bw.makeStepper({
|
|
237
|
+
steps: ['Account', 'Profile', 'Review', 'Confirm'],
|
|
238
|
+
currentStep: 1, // 0-indexed; completed steps show checkmarks
|
|
239
|
+
className: ''
|
|
240
|
+
})
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Navigation
|
|
246
|
+
|
|
247
|
+
### makeNav
|
|
248
|
+
|
|
249
|
+
Tab or pill navigation.
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
bw.makeNav({
|
|
253
|
+
items: [
|
|
254
|
+
{ text: 'Home', href: '#', active: true },
|
|
255
|
+
{ text: 'About', href: '#' },
|
|
256
|
+
{ text: 'Contact', href: '#', disabled: true }
|
|
257
|
+
],
|
|
258
|
+
pills: false, // pill style instead of tabs
|
|
259
|
+
vertical: false,
|
|
260
|
+
className: ''
|
|
261
|
+
})
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### makeNavbar
|
|
265
|
+
|
|
266
|
+
Responsive navigation bar with brand and collapsible menu.
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
bw.makeNavbar({
|
|
270
|
+
brand: 'My App',
|
|
271
|
+
brandHref: '#',
|
|
272
|
+
items: [
|
|
273
|
+
{ text: 'Home', href: '#', active: true },
|
|
274
|
+
{ text: 'Docs', href: '#' }
|
|
275
|
+
],
|
|
276
|
+
dark: true, // dark background
|
|
277
|
+
className: ''
|
|
278
|
+
})
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### makeTabs (handles: setActiveTab/getActiveTab, keyboard nav, WAI-ARIA)
|
|
282
|
+
|
|
283
|
+
Tabbed content panels with click switching.
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
bw.makeTabs({
|
|
287
|
+
tabs: [
|
|
288
|
+
{ label: 'Tab 1', content: 'Panel 1 content' },
|
|
289
|
+
{ label: 'Tab 2', content: { t: 'div', c: 'Panel 2 TACO' } },
|
|
290
|
+
{ label: 'Tab 3', content: 'Panel 3 content' }
|
|
291
|
+
],
|
|
292
|
+
activeIndex: 0
|
|
293
|
+
})
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### makeBreadcrumb
|
|
297
|
+
|
|
298
|
+
Navigation breadcrumb trail.
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
bw.makeBreadcrumb({
|
|
302
|
+
items: [
|
|
303
|
+
{ text: 'Home', href: '#' },
|
|
304
|
+
{ text: 'Products', href: '#' },
|
|
305
|
+
{ text: 'Widget', active: true } // active = no link
|
|
306
|
+
]
|
|
307
|
+
})
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### makePagination
|
|
311
|
+
|
|
312
|
+
Page navigation control.
|
|
313
|
+
|
|
314
|
+
```javascript
|
|
315
|
+
bw.makePagination({
|
|
316
|
+
pages: 10,
|
|
317
|
+
currentPage: 3,
|
|
318
|
+
onPageChange: function(page) { /* load page data */ },
|
|
319
|
+
size: '', // 'sm' or 'lg'
|
|
320
|
+
className: ''
|
|
321
|
+
})
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Buttons
|
|
327
|
+
|
|
328
|
+
### makeButton
|
|
329
|
+
|
|
330
|
+
Standard button with variants.
|
|
331
|
+
|
|
332
|
+
```javascript
|
|
333
|
+
bw.makeButton({
|
|
334
|
+
text: 'Click Me',
|
|
335
|
+
variant: 'primary', // 'primary' | 'secondary' | 'success' | 'danger' |
|
|
336
|
+
// 'warning' | 'info' | 'light' | 'dark' |
|
|
337
|
+
// 'outline-primary' | 'outline-secondary' | ...
|
|
338
|
+
size: '', // 'sm' or 'lg'
|
|
339
|
+
disabled: false,
|
|
340
|
+
onclick: function() {},
|
|
341
|
+
type: 'button', // 'button' | 'submit' | 'reset'
|
|
342
|
+
className: '',
|
|
343
|
+
style: ''
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
// String shorthand:
|
|
347
|
+
bw.makeButton('OK') // primary button with text "OK"
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### makeButtonGroup
|
|
351
|
+
|
|
352
|
+
Group of buttons with shared border-radius.
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
bw.makeButtonGroup({
|
|
356
|
+
children: [
|
|
357
|
+
bw.makeButton({ text: 'Left' }),
|
|
358
|
+
bw.makeButton({ text: 'Center' }),
|
|
359
|
+
bw.makeButton({ text: 'Right' })
|
|
360
|
+
],
|
|
361
|
+
size: '', // 'sm' or 'lg'
|
|
362
|
+
vertical: false,
|
|
363
|
+
className: ''
|
|
364
|
+
})
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Forms
|
|
370
|
+
|
|
371
|
+
### makeForm
|
|
372
|
+
|
|
373
|
+
Form wrapper with submit handler.
|
|
374
|
+
|
|
375
|
+
```javascript
|
|
376
|
+
bw.makeForm({
|
|
377
|
+
children: [...], // form controls
|
|
378
|
+
onsubmit: function(e) { e.preventDefault(); },
|
|
379
|
+
className: ''
|
|
380
|
+
})
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### makeFormGroup
|
|
384
|
+
|
|
385
|
+
Label + input + help text wrapper.
|
|
386
|
+
|
|
387
|
+
```javascript
|
|
388
|
+
bw.makeFormGroup({
|
|
389
|
+
label: 'Email',
|
|
390
|
+
help: 'We will not share your email.',
|
|
391
|
+
error: '', // error message (shows red)
|
|
392
|
+
required: false,
|
|
393
|
+
className: ''
|
|
394
|
+
})
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### makeInput
|
|
398
|
+
|
|
399
|
+
Text input (supports all HTML5 types).
|
|
400
|
+
|
|
401
|
+
```javascript
|
|
402
|
+
bw.makeInput({
|
|
403
|
+
type: 'text', // 'text' | 'email' | 'password' | 'number' | 'url' | ...
|
|
404
|
+
placeholder: '',
|
|
405
|
+
value: '',
|
|
406
|
+
id: '',
|
|
407
|
+
name: '',
|
|
408
|
+
disabled: false,
|
|
409
|
+
readonly: false,
|
|
410
|
+
required: false,
|
|
411
|
+
className: '',
|
|
412
|
+
style: '',
|
|
413
|
+
oninput: function(e) {},
|
|
414
|
+
onchange: function(e) {},
|
|
415
|
+
onfocus: function(e) {},
|
|
416
|
+
onblur: function(e) {}
|
|
417
|
+
})
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### makeTextarea
|
|
421
|
+
|
|
422
|
+
Multi-line text input.
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
bw.makeTextarea({
|
|
426
|
+
placeholder: '',
|
|
427
|
+
value: '',
|
|
428
|
+
rows: 3,
|
|
429
|
+
id: '',
|
|
430
|
+
name: '',
|
|
431
|
+
disabled: false,
|
|
432
|
+
readonly: false,
|
|
433
|
+
required: false,
|
|
434
|
+
className: ''
|
|
435
|
+
})
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### makeSelect
|
|
439
|
+
|
|
440
|
+
Dropdown select.
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
bw.makeSelect({
|
|
444
|
+
options: [
|
|
445
|
+
{ value: 'us', text: 'United States' },
|
|
446
|
+
{ value: 'uk', text: 'United Kingdom' },
|
|
447
|
+
{ value: 'ca', text: 'Canada' }
|
|
448
|
+
],
|
|
449
|
+
value: 'us', // pre-selected value
|
|
450
|
+
id: '',
|
|
451
|
+
name: '',
|
|
452
|
+
disabled: false,
|
|
453
|
+
required: false,
|
|
454
|
+
className: '',
|
|
455
|
+
onchange: function(e) {}
|
|
456
|
+
})
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### makeCheckbox
|
|
460
|
+
|
|
461
|
+
Checkbox with label.
|
|
462
|
+
|
|
463
|
+
```javascript
|
|
464
|
+
bw.makeCheckbox({
|
|
465
|
+
label: 'I agree to the terms',
|
|
466
|
+
checked: false,
|
|
467
|
+
id: '',
|
|
468
|
+
name: '',
|
|
469
|
+
disabled: false,
|
|
470
|
+
value: '',
|
|
471
|
+
className: ''
|
|
472
|
+
})
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### makeRadio
|
|
476
|
+
|
|
477
|
+
Radio button.
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
bw.makeRadio({
|
|
481
|
+
label: 'Option A',
|
|
482
|
+
name: 'choice', // group name
|
|
483
|
+
value: 'a',
|
|
484
|
+
checked: false,
|
|
485
|
+
id: '',
|
|
486
|
+
disabled: false,
|
|
487
|
+
className: ''
|
|
488
|
+
})
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### makeSwitch
|
|
492
|
+
|
|
493
|
+
Toggle switch (styled checkbox).
|
|
494
|
+
|
|
495
|
+
```javascript
|
|
496
|
+
bw.makeSwitch({
|
|
497
|
+
label: 'Enable notifications',
|
|
498
|
+
checked: false,
|
|
499
|
+
id: '',
|
|
500
|
+
name: '',
|
|
501
|
+
disabled: false,
|
|
502
|
+
className: ''
|
|
503
|
+
})
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### makeRange
|
|
507
|
+
|
|
508
|
+
Range slider.
|
|
509
|
+
|
|
510
|
+
```javascript
|
|
511
|
+
bw.makeRange({
|
|
512
|
+
min: 0,
|
|
513
|
+
max: 100,
|
|
514
|
+
step: 1,
|
|
515
|
+
value: 50,
|
|
516
|
+
label: 'Volume',
|
|
517
|
+
showValue: false, // show current value next to slider
|
|
518
|
+
id: '',
|
|
519
|
+
name: '',
|
|
520
|
+
disabled: false,
|
|
521
|
+
className: ''
|
|
522
|
+
})
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### makeSearchInput
|
|
526
|
+
|
|
527
|
+
Search box with clear button.
|
|
528
|
+
|
|
529
|
+
```javascript
|
|
530
|
+
bw.makeSearchInput({
|
|
531
|
+
placeholder: 'Search...',
|
|
532
|
+
value: '',
|
|
533
|
+
onSearch: function(query) {}, // called on Enter
|
|
534
|
+
onInput: function(e) {}, // called on each keystroke
|
|
535
|
+
id: '',
|
|
536
|
+
name: '',
|
|
537
|
+
className: ''
|
|
538
|
+
})
|
|
539
|
+
|
|
540
|
+
// String shorthand:
|
|
541
|
+
bw.makeSearchInput('Search products...')
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### makeChipInput
|
|
545
|
+
|
|
546
|
+
Tag/chip input with add/remove.
|
|
547
|
+
|
|
548
|
+
```javascript
|
|
549
|
+
bw.makeChipInput({
|
|
550
|
+
chips: ['JavaScript', 'CSS'],
|
|
551
|
+
placeholder: 'Add tag...',
|
|
552
|
+
onAdd: function(text) {},
|
|
553
|
+
onRemove: function(text) {},
|
|
554
|
+
className: ''
|
|
555
|
+
})
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### makeFileUpload
|
|
559
|
+
|
|
560
|
+
Drag-and-drop file upload zone.
|
|
561
|
+
|
|
562
|
+
```javascript
|
|
563
|
+
bw.makeFileUpload({
|
|
564
|
+
accept: '.pdf,.doc', // file type filter
|
|
565
|
+
multiple: false,
|
|
566
|
+
onFiles: function(files) {},
|
|
567
|
+
text: 'Drop files here or click to browse',
|
|
568
|
+
id: '',
|
|
569
|
+
className: ''
|
|
570
|
+
})
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
---
|
|
574
|
+
|
|
575
|
+
## Interactive
|
|
576
|
+
|
|
577
|
+
### makeAccordion (handles: toggle/openAll/closeAll, ARIA)
|
|
578
|
+
|
|
579
|
+
Collapsible content sections.
|
|
580
|
+
|
|
581
|
+
```javascript
|
|
582
|
+
bw.makeAccordion({
|
|
583
|
+
items: [
|
|
584
|
+
{ title: 'Section 1', content: 'Content here...', open: true },
|
|
585
|
+
{ title: 'Section 2', content: 'More content...' },
|
|
586
|
+
{ title: 'Section 3', content: { t: 'div', c: 'TACO content' } }
|
|
587
|
+
],
|
|
588
|
+
multiOpen: false, // allow multiple sections open at once
|
|
589
|
+
className: ''
|
|
590
|
+
})
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### makeModal (handles: open/close, ESC dismiss)
|
|
594
|
+
|
|
595
|
+
Dialog overlay.
|
|
596
|
+
|
|
597
|
+
```javascript
|
|
598
|
+
bw.makeModal({
|
|
599
|
+
title: 'Confirm Action',
|
|
600
|
+
content: 'Are you sure?',
|
|
601
|
+
footer: bw.makeButtonGroup({ children: [
|
|
602
|
+
bw.makeButton({ text: 'Cancel', variant: 'secondary' }),
|
|
603
|
+
bw.makeButton({ text: 'Confirm', variant: 'danger' })
|
|
604
|
+
]}),
|
|
605
|
+
size: '', // 'sm' | 'lg' | 'xl'
|
|
606
|
+
closeButton: true, // show X in header
|
|
607
|
+
onClose: function() {},
|
|
608
|
+
className: ''
|
|
609
|
+
})
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### makeToast (handle: dismiss, auto-dismiss 5s)
|
|
613
|
+
|
|
614
|
+
Toast notification.
|
|
615
|
+
|
|
616
|
+
```javascript
|
|
617
|
+
bw.makeToast({
|
|
618
|
+
title: 'Success',
|
|
619
|
+
content: 'Your file was saved.',
|
|
620
|
+
variant: 'success',
|
|
621
|
+
autoDismiss: true,
|
|
622
|
+
delay: 5000, // ms before auto-dismiss
|
|
623
|
+
position: 'top-right', // 'top-left' | 'top-center' | 'top-right' |
|
|
624
|
+
// 'bottom-left' | 'bottom-center' | 'bottom-right'
|
|
625
|
+
className: ''
|
|
626
|
+
})
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### makeDropdown
|
|
630
|
+
|
|
631
|
+
Click-triggered dropdown menu.
|
|
632
|
+
|
|
633
|
+
```javascript
|
|
634
|
+
bw.makeDropdown({
|
|
635
|
+
trigger: 'Actions', // string or button TACO
|
|
636
|
+
items: [
|
|
637
|
+
{ text: 'Edit', onclick: function() {} },
|
|
638
|
+
{ text: 'Duplicate', onclick: function() {} },
|
|
639
|
+
{ divider: true },
|
|
640
|
+
{ text: 'Delete', onclick: function() {}, disabled: false }
|
|
641
|
+
],
|
|
642
|
+
align: 'start', // 'start' | 'end'
|
|
643
|
+
variant: 'primary',
|
|
644
|
+
className: ''
|
|
645
|
+
})
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### makeCarousel (handles: 6 methods, auto-play, keyboard)
|
|
649
|
+
|
|
650
|
+
Image carousel with controls and indicators.
|
|
651
|
+
|
|
652
|
+
```javascript
|
|
653
|
+
bw.makeCarousel({
|
|
654
|
+
items: [
|
|
655
|
+
{ src: 'slide1.jpg', alt: 'Slide 1', caption: 'First slide' },
|
|
656
|
+
{ src: 'slide2.jpg', alt: 'Slide 2', caption: 'Second slide' }
|
|
657
|
+
],
|
|
658
|
+
showControls: true,
|
|
659
|
+
showIndicators: true,
|
|
660
|
+
autoPlay: false,
|
|
661
|
+
interval: 5000, // ms between auto-advance
|
|
662
|
+
height: '300px',
|
|
663
|
+
startIndex: 0,
|
|
664
|
+
className: ''
|
|
665
|
+
})
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
670
|
+
## Overlays
|
|
671
|
+
|
|
672
|
+
### makeTooltip
|
|
673
|
+
|
|
674
|
+
Hover/focus tooltip.
|
|
675
|
+
|
|
676
|
+
```javascript
|
|
677
|
+
bw.makeTooltip({
|
|
678
|
+
content: bw.makeButton({ text: 'Hover me' }), // the trigger element
|
|
679
|
+
text: 'Tooltip text',
|
|
680
|
+
placement: 'top', // 'top' | 'bottom' | 'left' | 'right'
|
|
681
|
+
className: ''
|
|
682
|
+
})
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
### makePopover
|
|
686
|
+
|
|
687
|
+
Click-triggered rich popover.
|
|
688
|
+
|
|
689
|
+
```javascript
|
|
690
|
+
bw.makePopover({
|
|
691
|
+
trigger: bw.makeButton({ text: 'Info' }),
|
|
692
|
+
title: 'Details',
|
|
693
|
+
content: 'Extended information here...',
|
|
694
|
+
placement: 'top', // 'top' | 'bottom' | 'left' | 'right'
|
|
695
|
+
className: ''
|
|
696
|
+
})
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
---
|
|
700
|
+
|
|
701
|
+
## Loading & Placeholder
|
|
702
|
+
|
|
703
|
+
### makeSpinner
|
|
704
|
+
|
|
705
|
+
Loading spinner.
|
|
706
|
+
|
|
707
|
+
```javascript
|
|
708
|
+
bw.makeSpinner({
|
|
709
|
+
variant: 'primary',
|
|
710
|
+
size: 'md', // 'sm' | 'md' | 'lg'
|
|
711
|
+
type: 'border' // 'border' | 'grow'
|
|
712
|
+
})
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
### makeSkeleton
|
|
716
|
+
|
|
717
|
+
Content placeholder (loading state).
|
|
718
|
+
|
|
719
|
+
```javascript
|
|
720
|
+
bw.makeSkeleton({
|
|
721
|
+
variant: 'text', // 'text' | 'circle' | 'rect'
|
|
722
|
+
width: '',
|
|
723
|
+
height: '',
|
|
724
|
+
count: 1, // number of text lines
|
|
725
|
+
className: ''
|
|
726
|
+
})
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### makeAvatar
|
|
730
|
+
|
|
731
|
+
User avatar (image or initials).
|
|
732
|
+
|
|
733
|
+
```javascript
|
|
734
|
+
bw.makeAvatar({
|
|
735
|
+
src: 'photo.jpg', // image URL
|
|
736
|
+
alt: '',
|
|
737
|
+
initials: 'AC', // fallback when no src
|
|
738
|
+
size: 'md', // 'sm' | 'md' | 'lg' | 'xl'
|
|
739
|
+
variant: 'primary', // background color for initials
|
|
740
|
+
className: ''
|
|
741
|
+
})
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
---
|
|
745
|
+
|
|
746
|
+
## Page-Level Components
|
|
747
|
+
|
|
748
|
+
### makeHero
|
|
749
|
+
|
|
750
|
+
Hero section with optional background image.
|
|
751
|
+
|
|
752
|
+
```javascript
|
|
753
|
+
bw.makeHero({
|
|
754
|
+
title: 'Welcome',
|
|
755
|
+
subtitle: 'Build fast, ship faster.',
|
|
756
|
+
content: '', // additional TACO content
|
|
757
|
+
variant: 'primary', // background color
|
|
758
|
+
size: 'lg', // 'sm' | 'md' | 'lg' | 'xl'
|
|
759
|
+
centered: true,
|
|
760
|
+
backgroundImage: '', // URL for bg image
|
|
761
|
+
overlay: false, // dark overlay for text readability
|
|
762
|
+
actions: [ // array of button TACOs
|
|
763
|
+
bw.makeButton({ text: 'Get Started', variant: 'light', size: 'lg' })
|
|
764
|
+
],
|
|
765
|
+
className: ''
|
|
766
|
+
})
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
### makeSection
|
|
770
|
+
|
|
771
|
+
Semantic content section.
|
|
772
|
+
|
|
773
|
+
```javascript
|
|
774
|
+
bw.makeSection({
|
|
775
|
+
title: 'Features',
|
|
776
|
+
subtitle: 'What we offer',
|
|
777
|
+
content: 'Text or TACO',
|
|
778
|
+
variant: 'default',
|
|
779
|
+
spacing: 'md', // vertical padding
|
|
780
|
+
className: ''
|
|
781
|
+
})
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
### makeFeatureGrid
|
|
785
|
+
|
|
786
|
+
Grid of feature cards with icons.
|
|
787
|
+
|
|
788
|
+
```javascript
|
|
789
|
+
bw.makeFeatureGrid({
|
|
790
|
+
features: [
|
|
791
|
+
{ icon: '⚡', title: 'Fast', description: 'Sub-second rendering' },
|
|
792
|
+
{ icon: '📦', title: 'Small', description: 'Zero dependencies' },
|
|
793
|
+
{ icon: '🔧', title: 'Flexible', description: 'Works everywhere' }
|
|
794
|
+
],
|
|
795
|
+
columns: 3,
|
|
796
|
+
centered: true,
|
|
797
|
+
iconSize: '3rem',
|
|
798
|
+
className: ''
|
|
799
|
+
})
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
### makeCTA
|
|
803
|
+
|
|
804
|
+
Call-to-action section.
|
|
805
|
+
|
|
806
|
+
```javascript
|
|
807
|
+
bw.makeCTA({
|
|
808
|
+
title: 'Ready to get started?',
|
|
809
|
+
description: 'Join thousands of developers.',
|
|
810
|
+
actions: [
|
|
811
|
+
bw.makeButton({ text: 'Sign Up Free', variant: 'primary', size: 'lg' })
|
|
812
|
+
],
|
|
813
|
+
variant: 'light',
|
|
814
|
+
centered: true,
|
|
815
|
+
className: ''
|
|
816
|
+
})
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
### makeCodeDemo
|
|
820
|
+
|
|
821
|
+
Code example with preview.
|
|
822
|
+
|
|
823
|
+
```javascript
|
|
824
|
+
bw.makeCodeDemo({
|
|
825
|
+
title: 'Button Example',
|
|
826
|
+
description: 'A simple button.',
|
|
827
|
+
code: 'bw.makeButton({ text: "Click" })',
|
|
828
|
+
result: bw.makeButton({ text: 'Click' }),
|
|
829
|
+
language: 'javascript'
|
|
830
|
+
})
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
835
|
+
## Tables & Data
|
|
836
|
+
|
|
837
|
+
### makeTable (sortable, pagination, row selection, column renderers)
|
|
838
|
+
|
|
839
|
+
Sortable data table from an array of objects. Supports row selection, custom cell rendering, and pagination.
|
|
840
|
+
|
|
841
|
+
```javascript
|
|
842
|
+
bw.makeTable({
|
|
843
|
+
data: [
|
|
844
|
+
{ name: 'Alice', age: 30, role: 'Engineer' },
|
|
845
|
+
{ name: 'Bob', age: 25, role: 'Designer' }
|
|
846
|
+
],
|
|
847
|
+
columns: [ // optional — auto-detected from data keys
|
|
848
|
+
{ key: 'name', label: 'Name' },
|
|
849
|
+
{ key: 'age', label: 'Age' },
|
|
850
|
+
{ key: 'role', label: 'Role' }
|
|
851
|
+
],
|
|
852
|
+
sortable: true, // click column headers to sort
|
|
853
|
+
striped: false,
|
|
854
|
+
hover: false,
|
|
855
|
+
selectable: false, // click rows to toggle selection
|
|
856
|
+
onRowClick: null, // function(row, index, event) — fires on row click
|
|
857
|
+
pageSize: undefined, // set to enable pagination (e.g. 10)
|
|
858
|
+
currentPage: 1, // current page (1-based)
|
|
859
|
+
onPageChange: null, // function(newPage) — fires on page navigation
|
|
860
|
+
className: ''
|
|
861
|
+
})
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
**Cell renderers** — each column definition can include a `render` function for custom cell rendering. The function receives the cell value and the full row object, and can return a string or TACO:
|
|
865
|
+
|
|
866
|
+
```javascript
|
|
867
|
+
bw.makeTable({
|
|
868
|
+
data: users,
|
|
869
|
+
columns: [
|
|
870
|
+
{ key: 'name', label: 'Name' },
|
|
871
|
+
{ key: 'status', label: 'Status', render: function(val, row) {
|
|
872
|
+
return bw.makeBadge({ text: val, variant: val === 'active' ? 'success' : 'danger' });
|
|
873
|
+
}},
|
|
874
|
+
{ key: 'age', label: 'Age', render: function(val) {
|
|
875
|
+
return val >= 18 ? String(val) : bw.raw('<em>' + val + '</em>');
|
|
876
|
+
}}
|
|
877
|
+
]
|
|
878
|
+
})
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
**Row selection** — enables click-to-select with visual feedback:
|
|
882
|
+
|
|
883
|
+
```javascript
|
|
884
|
+
bw.makeTable({
|
|
885
|
+
data: users,
|
|
886
|
+
selectable: true,
|
|
887
|
+
onRowClick: function(row, index, event) {
|
|
888
|
+
console.log('Selected:', row.name, 'at index', index);
|
|
889
|
+
}
|
|
890
|
+
})
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
Clicking a row toggles the `bw_table_row_selected` CSS class. The `selectable` flag also enables hover highlighting automatically.
|
|
894
|
+
|
|
895
|
+
**Pagination** — set `pageSize` to limit visible rows:
|
|
896
|
+
|
|
897
|
+
```javascript
|
|
898
|
+
var page = 1;
|
|
899
|
+
function renderTable() {
|
|
900
|
+
bw.DOM('#table', bw.makeTable({
|
|
901
|
+
data: allData, // full dataset — makeTable slices internally
|
|
902
|
+
pageSize: 10,
|
|
903
|
+
currentPage: page,
|
|
904
|
+
onPageChange: function(newPage) {
|
|
905
|
+
page = newPage;
|
|
906
|
+
renderTable(); // re-render with new page
|
|
907
|
+
}
|
|
908
|
+
}));
|
|
909
|
+
}
|
|
910
|
+
renderTable();
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
When `pageSize` is set, the table is wrapped in a container with Prev/Next controls and a page indicator. The `onRowClick` index is the global index into the full dataset, not the page-local index.
|
|
914
|
+
|
|
915
|
+
### makeTableFromArray
|
|
916
|
+
|
|
917
|
+
Table from 2D arrays (CSV data, spreadsheets).
|
|
918
|
+
|
|
919
|
+
```javascript
|
|
920
|
+
bw.makeTableFromArray({
|
|
921
|
+
data: [
|
|
922
|
+
['Name', 'Age', 'Role'], // first row = headers
|
|
923
|
+
['Alice', 30, 'Engineer'],
|
|
924
|
+
['Bob', 25, 'Designer']
|
|
925
|
+
],
|
|
926
|
+
headerRow: true, // default true; false = auto-generate col0, col1, ...
|
|
927
|
+
striped: true,
|
|
928
|
+
hover: true,
|
|
929
|
+
sortable: true
|
|
930
|
+
})
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
### makeDataTable
|
|
934
|
+
|
|
935
|
+
Convenience wrapper with title and responsive scrolling.
|
|
936
|
+
|
|
937
|
+
```javascript
|
|
938
|
+
bw.makeDataTable({
|
|
939
|
+
title: 'Team Members',
|
|
940
|
+
data: [...],
|
|
941
|
+
columns: [...],
|
|
942
|
+
responsive: true, // wraps in scrollable div
|
|
943
|
+
striped: true,
|
|
944
|
+
hover: true
|
|
945
|
+
})
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
### makeBarChart
|
|
949
|
+
|
|
950
|
+
Vertical bar chart (pure CSS, no external library).
|
|
951
|
+
|
|
952
|
+
```javascript
|
|
953
|
+
bw.makeBarChart({
|
|
954
|
+
data: [
|
|
955
|
+
{ label: 'Jan', value: 4200 },
|
|
956
|
+
{ label: 'Feb', value: 5100 },
|
|
957
|
+
{ label: 'Mar', value: 3800 }
|
|
958
|
+
],
|
|
959
|
+
labelKey: 'label',
|
|
960
|
+
valueKey: 'value',
|
|
961
|
+
title: 'Monthly Revenue',
|
|
962
|
+
color: '#006666',
|
|
963
|
+
height: '200px',
|
|
964
|
+
formatValue: function(v) { return '$' + (v/1000).toFixed(1) + 'k'; },
|
|
965
|
+
showValues: true,
|
|
966
|
+
showLabels: true,
|
|
967
|
+
className: ''
|
|
968
|
+
})
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
---
|
|
972
|
+
|
|
973
|
+
## Factory dispatcher
|
|
974
|
+
|
|
975
|
+
The `bw.make()` function dispatches to any factory by type name:
|
|
976
|
+
|
|
977
|
+
```javascript
|
|
978
|
+
bw.make('card', { title: 'Hello' });
|
|
979
|
+
// equivalent to: bw.makeCard({ title: 'Hello' })
|
|
980
|
+
|
|
981
|
+
bw.make('button', { text: 'OK', variant: 'primary' });
|
|
982
|
+
// equivalent to: bw.makeButton({ text: 'OK', variant: 'primary' })
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
This enables data-driven component creation:
|
|
986
|
+
|
|
987
|
+
```javascript
|
|
988
|
+
var layout = [
|
|
989
|
+
{ type: 'card', props: { title: 'Stats', content: '42' } },
|
|
990
|
+
{ type: 'alert', props: { content: 'Warning!', variant: 'warning' } },
|
|
991
|
+
{ type: 'button', props: { text: 'Action' } }
|
|
992
|
+
];
|
|
993
|
+
|
|
994
|
+
bw.DOM('#app', {
|
|
995
|
+
t: 'div',
|
|
996
|
+
c: layout.map(function(item) { return bw.make(item.type, item.props); })
|
|
997
|
+
});
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
List available types with `Object.keys(bw.BCCL)`.
|
|
1001
|
+
|
|
1002
|
+
---
|
|
1003
|
+
|
|
1004
|
+
## Component Handles
|
|
1005
|
+
|
|
1006
|
+
All BCCL factories include `o.handle` and/or `o.slots`, giving every rendered component an imperative API via `el.bw`. Use `bw.mount()` instead of `bw.DOM()` to get the element back:
|
|
1007
|
+
|
|
1008
|
+
```javascript
|
|
1009
|
+
var el = bw.mount('#app', bw.makeCarousel({ items: slides }));
|
|
1010
|
+
el.bw.goToSlide(2);
|
|
1011
|
+
el.bw.pause();
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
Slot-based factories auto-generate `el.bw.setName()` / `el.bw.getName()` pairs:
|
|
1015
|
+
|
|
1016
|
+
```javascript
|
|
1017
|
+
var el = bw.mount('#app', bw.makeCard({ title: 'Hello', content: 'World' }));
|
|
1018
|
+
el.bw.setTitle('Updated');
|
|
1019
|
+
el.bw.setContent({ t: 'b', c: '42' }); // accepts TACO objects
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
### Handle method reference
|
|
1023
|
+
|
|
1024
|
+
| Factory | Handle methods | Slot methods |
|
|
1025
|
+
|---------|---------------|-------------|
|
|
1026
|
+
| makeCarousel | goToSlide, next, prev, getActiveIndex, pause, play | -- |
|
|
1027
|
+
| makeTabs | setActiveTab, getActiveTab | -- |
|
|
1028
|
+
| makeAccordion | toggle, openAll, closeAll | -- |
|
|
1029
|
+
| makeModal | open, close | -- |
|
|
1030
|
+
| makeProgress | setValue, getValue | -- |
|
|
1031
|
+
| makeChipInput | addChip, removeChip, getChips, clear | -- |
|
|
1032
|
+
| makeCard | -- | setTitle/getTitle, setContent/getContent, setFooter/getFooter |
|
|
1033
|
+
| makeStatCard | -- | setValue/getValue, setLabel/getLabel |
|
|
1034
|
+
|
|
1035
|
+
Build your own with `o.handle` and `o.slots`:
|
|
1036
|
+
|
|
1037
|
+
```javascript
|
|
1038
|
+
{
|
|
1039
|
+
t: 'div', c: [
|
|
1040
|
+
{ t: 'h3', a: { class: 'title' }, c: 'Default' },
|
|
1041
|
+
{ t: 'div', a: { class: 'body' }, c: 'Content' }
|
|
1042
|
+
],
|
|
1043
|
+
o: {
|
|
1044
|
+
slots: { title: '.title', body: '.body' },
|
|
1045
|
+
handle: {
|
|
1046
|
+
reset: function(el) { el.bw.setTitle('Default'); el.bw.setBody('Content'); }
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
See [State Management -- Level 1.5](state-management.md#level-15-component-handles) for the full guide.
|
|
1053
|
+
|
|
1054
|
+
---
|
|
1055
|
+
|
|
1056
|
+
## Color variants
|
|
1057
|
+
|
|
1058
|
+
Most components accept a `variant` prop. The available variants are:
|
|
1059
|
+
|
|
1060
|
+
| Variant | Description |
|
|
1061
|
+
|---------|-------------|
|
|
1062
|
+
| `primary` | Brand color (default for most components) |
|
|
1063
|
+
| `secondary` | Secondary accent |
|
|
1064
|
+
| `success` | Positive action or status |
|
|
1065
|
+
| `danger` | Destructive action or error |
|
|
1066
|
+
| `warning` | Caution or attention needed |
|
|
1067
|
+
| `info` | Informational |
|
|
1068
|
+
| `light` | Light background |
|
|
1069
|
+
| `dark` | Dark background |
|
|
1070
|
+
|
|
1071
|
+
Buttons also support outline variants: `outline-primary`, `outline-secondary`, etc.
|
|
1072
|
+
|
|
1073
|
+
## Composition
|
|
1074
|
+
|
|
1075
|
+
Because every factory returns a TACO object, you compose components with standard JavaScript:
|
|
1076
|
+
|
|
1077
|
+
```javascript
|
|
1078
|
+
// Functions as component factories
|
|
1079
|
+
function userRow(user) {
|
|
1080
|
+
return {
|
|
1081
|
+
t: 'div', a: { class: 'bw-card' }, c: [
|
|
1082
|
+
bw.makeAvatar({ initials: user.name[0], size: 'sm' }),
|
|
1083
|
+
{ t: 'span', c: user.name },
|
|
1084
|
+
bw.makeBadge({ text: user.role, variant: 'info' })
|
|
1085
|
+
]
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// Arrays for lists
|
|
1090
|
+
var userList = users.map(userRow);
|
|
1091
|
+
bw.DOM('#app', { t: 'div', c: userList });
|
|
1092
|
+
|
|
1093
|
+
// Conditionals for branching
|
|
1094
|
+
var content = hasData
|
|
1095
|
+
? bw.makeTable({ data: rows })
|
|
1096
|
+
: bw.makeAlert({ content: 'No data available', variant: 'info' });
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
See [TACO Format](taco-format.md) for more composition patterns.
|