@saltcorn/markup 0.6.2-beta.2 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/builder.d.ts +18 -0
  2. package/dist/builder.d.ts.map +1 -0
  3. package/dist/builder.js +57 -0
  4. package/dist/builder.js.map +1 -0
  5. package/dist/emergency_layout.d.ts +6 -0
  6. package/dist/emergency_layout.d.ts.map +1 -0
  7. package/dist/emergency_layout.js +38 -0
  8. package/dist/emergency_layout.js.map +1 -0
  9. package/dist/form.d.ts +12 -0
  10. package/dist/form.d.ts.map +1 -0
  11. package/dist/form.js +372 -0
  12. package/dist/form.js.map +1 -0
  13. package/dist/helpers.d.ts +58 -0
  14. package/dist/helpers.d.ts.map +1 -0
  15. package/dist/helpers.js +169 -0
  16. package/dist/helpers.js.map +1 -0
  17. package/dist/index.d.ts +21 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +158 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/layout.d.ts +22 -0
  22. package/dist/layout.d.ts.map +1 -0
  23. package/dist/layout.js +338 -0
  24. package/dist/layout.js.map +1 -0
  25. package/dist/layout_utils.d.ts +21 -0
  26. package/dist/layout_utils.d.ts.map +1 -0
  27. package/dist/layout_utils.js +272 -0
  28. package/dist/layout_utils.js.map +1 -0
  29. package/dist/mktag.d.ts +12 -0
  30. package/dist/mktag.d.ts.map +1 -0
  31. package/dist/mktag.js +100 -0
  32. package/dist/mktag.js.map +1 -0
  33. package/dist/table.d.ts +22 -0
  34. package/dist/table.d.ts.map +1 -0
  35. package/dist/table.js +51 -0
  36. package/dist/table.js.map +1 -0
  37. package/dist/tabs.d.ts +7 -0
  38. package/dist/tabs.d.ts.map +1 -0
  39. package/dist/tabs.js +34 -0
  40. package/dist/tabs.js.map +1 -0
  41. package/dist/tags.d.ts +17 -0
  42. package/dist/tags.d.ts.map +1 -0
  43. package/dist/tags.js +71 -0
  44. package/dist/tags.js.map +1 -0
  45. package/dist/tsconfig.ref.tsbuildinfo +1 -0
  46. package/package.json +25 -6
  47. package/builder.js +0 -101
  48. package/emergency_layout.js +0 -54
  49. package/form.js +0 -603
  50. package/form.test.js +0 -98
  51. package/helpers.js +0 -268
  52. package/index.js +0 -226
  53. package/layout.js +0 -590
  54. package/layout.test.js +0 -39
  55. package/layout_utils.js +0 -394
  56. package/markup.test.js +0 -104
  57. package/mktag.js +0 -105
  58. package/table.js +0 -115
  59. package/tabs.js +0 -54
  60. package/tags.js +0 -56
package/layout_utils.js DELETED
@@ -1,394 +0,0 @@
1
- /**
2
- * @category saltcorn-markup
3
- * @module layout_utils
4
- */
5
-
6
- const {
7
- ul,
8
- li,
9
- ol,
10
- a,
11
- span,
12
- hr,
13
- div,
14
- text,
15
- img,
16
- button,
17
- nav,
18
- script,
19
- domReady,
20
- footer,
21
- i,
22
- small,
23
- br,
24
- } = require("./tags");
25
-
26
- /**
27
- * @param {string} item
28
- * @returns {string}
29
- */
30
- const labelToId = (item) => text(item.replace(" ", ""));
31
-
32
- /**
33
- * @param {string} currentUrl
34
- * @param {object} item
35
- * @returns {boolean}
36
- */
37
- const active = (currentUrl, item) =>
38
- (item.link && currentUrl.startsWith(item.link)) ||
39
- (item.subitems &&
40
- item.subitems.some((si) => si.link && currentUrl.startsWith(si.link)));
41
-
42
- /**
43
- * @param {object[]} sections
44
- * @returns {object[]}
45
- */
46
- const innerSections = (sections) => {
47
- var items = [];
48
- (sections || []).forEach((section) => {
49
- (section.items || []).forEach((item) => {
50
- items.push(item);
51
- });
52
- });
53
- return items;
54
- };
55
-
56
- /**
57
- * @param {object} opts
58
- * @param {string} opts.label
59
- * @param {object[]} opts.subitems
60
- * @param {string} [opts.icon]
61
- * @param {boolean} opts.isUser
62
- * @returns {li}
63
- */
64
- const navSubitems = ({ label, subitems, icon, isUser }) =>
65
- li(
66
- { class: "nav-item dropdown" },
67
- a(
68
- {
69
- class: "nav-link dropdown-toggle",
70
- href: "#",
71
- id: `dropdown${labelToId(label)}`,
72
- role: "button",
73
- "data-toggle": "dropdown",
74
- "aria-haspopup": "true",
75
- "aria-expanded": "false",
76
- },
77
- icon ? i({ class: `fa-fw mr-05 ${icon}` }) : "",
78
- label
79
- ),
80
- div(
81
- {
82
- class: ["dropdown-menu", isUser && "dropdown-menu-right"],
83
- "aria-labelledby": `dropdown${labelToId(label)}`,
84
- },
85
- subitems.map((si) =>
86
- a(
87
- { class: ["dropdown-item", si.style || ""], href: si.link },
88
- si.icon ? i({ class: `fa-fw mr-05 ${si.icon}` }) : "",
89
- si.label
90
- )
91
- )
92
- )
93
- );
94
-
95
- /**
96
- * @param {string} currentUrl
97
- * @param {object[]} sections
98
- * @returns {div}
99
- */
100
- const rightNavBar = (currentUrl, sections) =>
101
- div(
102
- { class: "collapse navbar-collapse", id: "navbarResponsive" },
103
- ul(
104
- { class: "navbar-nav ml-auto my-2 my-lg-0" },
105
-
106
- innerSections(sections).map((s) =>
107
- s.location === "Mobile Bottom"
108
- ? ""
109
- : s.subitems
110
- ? navSubitems(s)
111
- : s.link
112
- ? li(
113
- {
114
- class: ["nav-item", active(currentUrl, s) && "active"],
115
- },
116
- a(
117
- {
118
- class: ["nav-link js-scroll-trigger", s.style || ""],
119
- href: text(s.link),
120
- },
121
- s.icon ? i({ class: `fa-fw mr-05 ${s.icon}` }) : "",
122
- text(s.label)
123
- )
124
- )
125
- : ""
126
- )
127
- )
128
- );
129
-
130
- /**
131
- * @param {object[]} sections
132
- * @returns {boolean}
133
- */
134
- const hasMobileItems = (sections) =>
135
- innerSections(sections).some((s) => s.location === "Mobile Bottom");
136
-
137
- /**
138
- * @param {string} currentUrl
139
- * @param {object[]} sections
140
- * @param {string} [cls = ""]
141
- * @param {string} [clsLink = ""]
142
- * @returns {footer|string}
143
- */
144
- const mobileBottomNavBar = (currentUrl, sections, cls = "", clsLink = "") =>
145
- hasMobileItems(sections)
146
- ? footer(
147
- {
148
- class:
149
- "bs-mobile-nav-footer d-flex justify-content-around d-sm-flex d-md-none " +
150
- cls,
151
- },
152
- innerSections(sections).map((s) =>
153
- s.location !== "Mobile Bottom"
154
- ? ""
155
- : //: s.subitems
156
- //? navSubitems(s)
157
- s.link
158
- ? div(
159
- {
160
- class: [
161
- "mt-2 text-center",
162
- active(currentUrl, s) ? "active" : "opacity-50",
163
- ],
164
- },
165
- a(
166
- {
167
- class: [s.style || "", clsLink],
168
- href: text(s.link),
169
- },
170
- s.icon ? i({ class: `fa-lg ${s.icon}` }) : "",
171
- br(),
172
- small(text(s.label))
173
- )
174
- )
175
- : ""
176
- )
177
- )
178
- : "";
179
-
180
- /**
181
- * @param {object} opts
182
- * @param {string} opts.name
183
- * @param {string} opts.logo
184
- * @returns {string[]}
185
- */
186
- const leftNavBar = ({ name, logo }) => [
187
- a(
188
- { class: "navbar-brand js-scroll-trigger", href: "/" },
189
- logo &&
190
- img({
191
- src: logo,
192
- width: "30",
193
- height: "30",
194
- class: "mx-1 d-inline-block align-top",
195
- alt: "Logo",
196
- loading: "lazy",
197
- }),
198
- name
199
- ),
200
- button(
201
- {
202
- class: "navbar-toggler navbar-toggler-right",
203
- type: "button",
204
- "data-toggle": "collapse",
205
- "data-target": "#navbarResponsive",
206
- "aria-controls": "navbarResponsive",
207
- "aria-expanded": "false",
208
- "aria-label": "Toggle navigation",
209
- },
210
- span({ class: "navbar-toggler-icon" })
211
- ),
212
- ];
213
-
214
- /**
215
- * @param {object} brand
216
- * @param {object[]} sections
217
- * @param {string} currentUrl
218
- * @param {object} opts
219
- * @param {boolean} [opts.fixedTop = true]
220
- * @returns {string}
221
- */
222
- const navbar = (brand, sections, currentUrl, opts = { fixedTop: true }) =>
223
- nav(
224
- {
225
- class: `navbar navbar-expand-md ${opts.class || ""} ${
226
- opts.colorscheme ? opts.colorscheme.toLowerCase() : "navbar-light"
227
- } ${opts.fixedTop ? "fixed-top" : ""}`,
228
- id: "mainNav",
229
- },
230
- div(
231
- { class: opts.fluid ? "container-fluid" : "container" },
232
- leftNavBar(brand),
233
- rightNavBar(currentUrl, sections)
234
- )
235
- );
236
-
237
- /**
238
- * @param {string} type
239
- * @param {string} s
240
- * @returns {string}
241
- */
242
- const alert = (type, s) => {
243
- //console.log("alert", type, s,s.length)
244
- const realtype = type === "error" ? "danger" : type;
245
- return s && s.length > 0
246
- ? `<div class="alert alert-${realtype} alert-dismissible fade show" role="alert">
247
- ${text(s)}
248
- <button type="button" class="close" data-dismiss="alert" aria-label="Close">
249
- <span aria-hidden="true">&times;</span>
250
- </button>
251
- </div>`
252
- : "";
253
- };
254
-
255
- /**
256
- * @returns {string}
257
- */
258
- const navbarSolidOnScroll = script(
259
- domReady(`$(window).scroll(function () {
260
- if ($(window).scrollTop() >= 10) {
261
- $('.navbar').css('background','white');
262
- } else {
263
- $('.navbar').css('background','transparent');
264
- }
265
- });`)
266
- );
267
-
268
- /**
269
- * @param {object} x
270
- * @param {object} s
271
- * @returns {object}
272
- */
273
- const logit = (x, s) => {
274
- if (s) console.log(s, x);
275
- else console.log(x);
276
- return x;
277
- };
278
-
279
- /**
280
- * @param {number} len
281
- * @returns {function}
282
- */
283
- const standardBreadcrumbItem = (len) => ({ href, text }, ix) =>
284
- li(
285
- {
286
- class: ["breadcrumb-item", ix == len - 1 && "active"],
287
- "aria-current": ix == len - 1 && "page",
288
- },
289
- href ? a({ href }, text) : text
290
- );
291
-
292
- /**
293
- * @param {object} opts
294
- * @param {Workflow} opts.workflow
295
- * @param {object} opts.step
296
- * @returns {string}
297
- */
298
- const workflowBreadcrumbItem = ({ workflow, step }) =>
299
- workflow.steps
300
- .map((wfstep, ix) =>
301
- li(
302
- {
303
- class: [
304
- "breadcrumb-item breadcrumb-workflow",
305
- step.currentStep - 1 === ix && "active-step font-weight-bold",
306
- ],
307
- },
308
- span(wfstep.name)
309
- )
310
- )
311
- .join("");
312
-
313
- /**
314
- * @param {object[]} crumbs
315
- * @returns {string}
316
- */
317
- const breadcrumbs = (crumbs) =>
318
- nav(
319
- { "aria-label": "breadcrumb" },
320
- ol(
321
- { class: "breadcrumb" },
322
- crumbs.map((c) =>
323
- c.workflow
324
- ? workflowBreadcrumbItem(c)
325
- : standardBreadcrumbItem(crumbs.length)(c)
326
- )
327
- )
328
- );
329
-
330
- /**
331
- * @param {object[]} headers
332
- * @returns {string}
333
- */
334
- const headersInHead = (headers) =>
335
- headers
336
- .filter((h) => h.css)
337
- .map((h) => `<link href="${h.css}" rel="stylesheet">`)
338
- .join("") +
339
- headers
340
- .filter((h) => h.style)
341
- .map((h) => `<style>${h.style}</style>`)
342
- .join("") +
343
- headers
344
- .filter((h) => h.headerTag)
345
- .map((h) => h.headerTag)
346
- .join("");
347
-
348
- /**
349
- * @param {object[]} headers
350
- * @returns {string}
351
- */
352
- const headersInBody = (headers) =>
353
- headers
354
- .filter((h) => h.script)
355
- .map(
356
- (h) =>
357
- `<script src="${h.script}" ${
358
- h.integrity
359
- ? `integrity="${h.integrity}" crossorigin="anonymous"`
360
- : ""
361
- }></script>`
362
- )
363
- .join("") +
364
- headers
365
- .filter((h) => h.scriptBody)
366
- .map((h) => `<script>${h.scriptBody}</script>`)
367
- .join("");
368
-
369
- /**
370
- * @param {object[]} tabList
371
- * @returns {ul}
372
- */
373
- const cardHeaderTabs = (tabList) =>
374
- ul(
375
- { class: "nav nav-tabs card-header-tabs" },
376
- tabList.map(({ href, label, active }) =>
377
- li(
378
- { class: "nav-item" },
379
- a({ class: ["nav-link", active && "active"], href }, label)
380
- )
381
- )
382
- );
383
-
384
- module.exports = {
385
- navbar,
386
- alert,
387
- logit,
388
- navbarSolidOnScroll,
389
- breadcrumbs,
390
- headersInHead,
391
- headersInBody,
392
- cardHeaderTabs,
393
- mobileBottomNavBar,
394
- };
package/markup.test.js DELETED
@@ -1,104 +0,0 @@
1
- const {
2
- a,
3
- input,
4
- div,
5
- ul,
6
- text,
7
- text_attr,
8
- i,
9
- hr,
10
- genericElement,
11
- } = require("./tags");
12
-
13
- describe("tags", () => {
14
- it("renders", () => {
15
- expect(a({ href: "/" }, "Home")).toBe('<a href="/">Home</a>');
16
- expect(a({ href: "/" }, ["Home", " Sweet", " Home"])).toBe(
17
- '<a href="/">Home Sweet Home</a>'
18
- );
19
- expect(a({ href: "/", class: "centre" }, "Home")).toBe(
20
- '<a href="/" class="centre">Home</a>'
21
- );
22
- expect(input({ type: "text" })).toBe('<input type="text">');
23
- expect(div(5)).toBe("<div>5</div>");
24
- expect(div()).toBe("<div></div>");
25
- expect(i()).toBe("<i></i>");
26
- expect(hr()).toBe("<hr>");
27
- expect(div(["hello ", "world"])).toBe("<div>hello world</div>");
28
- expect(ul({ class: "foo" }, [false, "hello ", "world"])).toBe(
29
- `<ul class="foo">hello world</ul>`
30
- );
31
- expect(ul({ class: "foo" }, [["hello ", "world"]])).toBe(
32
- `<ul class="foo">hello world</ul>`
33
- );
34
- expect(Array.isArray(["hello ", "world"])).toBe(true);
35
- expect(Array.isArray({})).toBe(false);
36
- expect(i({ class: "fas fa-plus-square" })).toBe(
37
- '<i class="fas fa-plus-square"></i>'
38
- );
39
- expect(genericElement("div", { class: "foo" }, "Hello")).toBe(
40
- '<div class="foo">Hello</div>'
41
- );
42
- });
43
-
44
- it("class", () => {
45
- expect(div({ class: "foo" }, 5)).toBe('<div class="foo">5</div>');
46
- expect(div({ class: false }, 5)).toBe("<div>5</div>");
47
- expect(div({ class: "foo bar" }, 5)).toBe('<div class="foo bar">5</div>');
48
- expect(div({ class: ["foo", "bar"] }, 5)).toBe(
49
- '<div class="foo bar">5</div>'
50
- );
51
- expect(div({ class: ["foo", " "] }, 5)).toBe('<div class="foo ">5</div>');
52
- expect(input({ class: ["foo", " "] })).toBe('<input class="foo ">');
53
-
54
- expect(
55
- div({ class: ["foo bar", "", undefined, null, false, "baz"] }, 5)
56
- ).toBe('<div class="foo bar baz">5</div>');
57
-
58
- expect(div({ class: [undefined, null, false] }, 5)).toBe("<div>5</div>");
59
- expect(hr({ class: "foo" })).toBe('<hr class="foo">');
60
- });
61
- it("style", () => {
62
- expect(div({ style: "color:red;border:1px solid black" }, 5)).toBe(
63
- '<div style="color:red;border:1px solid black">5</div>'
64
- );
65
- expect(div({ style: ["color:red", "border:1px solid black"] }, 5)).toBe(
66
- '<div style="color:red;border:1px solid black">5</div>'
67
- );
68
- expect(
69
- div(
70
- { style: ["color:red", false, undefined, "border:1px solid black"] },
71
- 5
72
- )
73
- ).toBe('<div style="color:red;border:1px solid black">5</div>');
74
- expect(div({ style: { color: "red", border: "1px solid black" } }, 5)).toBe(
75
- '<div style="color:red;border:1px solid black">5</div>'
76
- );
77
-
78
- expect(
79
- div({ style: { marginRight: "1px", border: "1px solid black" } }, 5)
80
- ).toBe('<div style="margin-right:1px;border:1px solid black">5</div>');
81
- //border-top-left-radius
82
- expect(
83
- div({ style: { marginRight: "1px", borderTopLeftRadius: "3px" } }, 5)
84
- ).toBe('<div style="margin-right:1px;border-top-left-radius:3px">5</div>');
85
- expect(hr({ style: { color: "red" } }, 5)).toBe('<hr style="color:red">');
86
- expect(hr({ style: {} })).toBe("<hr>");
87
- expect(hr({ style: null })).toBe("<hr>");
88
- expect(div({ class: "foo", style: null })).toBe('<div class="foo"></div>');
89
- });
90
-
91
- it("escaping", () => {
92
- expect(text("foo")).toBe("foo");
93
- expect(text_attr('" onMouseOver="alert(1);')).toBe(
94
- "&quot; onMouseOver=&quot;alert(1);"
95
- );
96
- expect(text(1)).toBe("1");
97
- expect(text(0)).toBe("0");
98
- expect(text("<script>alert(1);<script>")).toBe(
99
- "&lt;script&gt;alert(1);&lt;script&gt;"
100
- );
101
- expect(text("<p>alert<p>")).toBe("<p>alert<p>");
102
- expect(text("<kbd>ctrl<kbd>")).toBe("<kbd>ctrl<kbd>");
103
- });
104
- });
package/mktag.js DELETED
@@ -1,105 +0,0 @@
1
- /**
2
- * @category saltcorn-markup
3
- * @module mktag
4
- */
5
-
6
- //https://stackoverflow.com/a/54246501
7
- /**
8
- * @param {string} str
9
- * @returns {string}
10
- */
11
- const camelToCssCase = (str) =>
12
- str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
13
-
14
- /**
15
- * @param {string|object} cs
16
- * @returns {string}
17
- */
18
- const ppClasses = (cs) =>
19
- typeof cs === "string" ? cs : !cs ? "" : cs.filter((c) => c).join(" ");
20
-
21
- /**
22
- * @param {string|object} c
23
- * @returns {string}
24
- */
25
- const ppClass = (c) => {
26
- const clss = ppClasses(c);
27
- return clss ? `class="${clss}"` : "";
28
- };
29
-
30
- /**
31
- * @param {string|string[]|object} [cs]
32
- * @returns {string}
33
- */
34
- const ppStyles = (cs) =>
35
- typeof cs === "string"
36
- ? cs
37
- : !cs
38
- ? ""
39
- : Array.isArray(cs)
40
- ? cs.filter((c) => c).join(";")
41
- : typeof cs === "object"
42
- ? Object.entries(cs)
43
- .map(([k, v]) => `${camelToCssCase(k)}:${v}`)
44
- .join(";")
45
- : "";
46
-
47
- /**
48
- * @param {string|string[]|object} [cs]
49
- * @returns {string}
50
- */
51
- const ppStyle = (c) => {
52
- const clss = ppStyles(c);
53
- return clss ? `style="${clss}"` : "";
54
- };
55
-
56
- /**
57
- * @param {object[]} opts
58
- * @param {string} opts.k
59
- * @param {boolean} [opts.v]
60
- * @returns {string}
61
- */
62
- const ppAttrib = ([k, v]) =>
63
- typeof v === "boolean"
64
- ? v
65
- ? k
66
- : ""
67
- : typeof v === "undefined"
68
- ? ""
69
- : k === "class"
70
- ? ppClass(v)
71
- : k === "style"
72
- ? ppStyle(v)
73
- : `${k}="${v}"`;
74
-
75
- /**
76
- * @param {string} tnm
77
- * @param {boolean} voidTag
78
- * @returns {function}
79
- */
80
- const mkTag = (tnm, voidTag) => (...args) => {
81
- var body = "";
82
- var attribs = " ";
83
-
84
- const argIter = (arg) => {
85
- if (typeof arg === "undefined" || arg === null || arg === false) {
86
- //do nothing
87
- } else if (typeof arg === "string") {
88
- body += arg;
89
- } else if (typeof arg === "object") {
90
- if (Array.isArray(arg)) {
91
- arg.forEach(argIter);
92
- } else {
93
- attribs += Object.entries(arg)
94
- .map(ppAttrib)
95
- .filter((s) => s)
96
- .join(" ");
97
- }
98
- } else body += arg;
99
- };
100
- args.forEach(argIter);
101
- if (attribs === " ") attribs = "";
102
- return voidTag ? `<${tnm}${attribs}>` : `<${tnm}${attribs}>${body}</${tnm}>`;
103
- };
104
-
105
- module.exports = mkTag;
package/table.js DELETED
@@ -1,115 +0,0 @@
1
- /**
2
- * @category saltcorn-markup
3
- * @module table
4
- */
5
-
6
- const { contract, is } = require("contractis");
7
-
8
- const {
9
- a,
10
- td,
11
- tr,
12
- th,
13
- text,
14
- div,
15
- table,
16
- thead,
17
- tbody,
18
- ul,
19
- li,
20
- span,
21
- } = require("./tags");
22
- const { pagination } = require("./helpers");
23
-
24
- /**
25
- * @param {object} hdr
26
- * @returns {th}
27
- */
28
- const headerCell = (hdr) =>
29
- th(
30
- (hdr.align || hdr.width) && {
31
- style:
32
- (hdr.align ? `text-align: ` + hdr.align : "") +
33
- (hdr.width ? `width: ` + hdr.width : ""),
34
- },
35
- hdr.sortlink ? a({ href: hdr.sortlink }, hdr.label) : hdr.label
36
- );
37
-
38
- /**
39
- * @function
40
- * @param {object[]} hdrs
41
- * @param {object[]} vs
42
- * @param {object} [opts]
43
- * @returns {string}
44
- */
45
- const mkTable = contract(
46
- is.fun(
47
- [
48
- is.array(is.obj({ label: is.str, key: is.or(is.str, is.fun()) })),
49
- is.array(is.obj()),
50
- is.maybe(
51
- is.obj({
52
- pagination: is.maybe(
53
- is.obj({
54
- current_page: is.posint,
55
- pages: is.posint,
56
- get_page_link: is.fun(),
57
- })
58
- ),
59
- noHeader: is.maybe(is.bool),
60
- hover: is.maybe(is.bool),
61
- })
62
- ),
63
- ],
64
- is.str
65
- ),
66
- (hdrs, vs, opts = {}) =>
67
- div(
68
- { class: "table-responsive" },
69
- table(
70
- {
71
- class: [
72
- "table table-sm",
73
- opts.class,
74
- hdrs.some((h) => h.width) && "table-layout-fixed",
75
- (opts.onRowSelect || (opts.hover && vs && vs.length > 1)) &&
76
- "table-hover",
77
- ],
78
- style: opts.style,
79
- },
80
- !opts.noHeader && thead(tr(hdrs.map((hdr) => headerCell(hdr)))),
81
- tbody(
82
- (vs || []).map((v) =>
83
- tr(
84
- mkClickHandler(opts, v),
85
- hdrs.map((hdr) =>
86
- td(
87
- !!hdr.align && { style: "text-align:" + hdr.align },
88
- typeof hdr.key === "string" ? text(v[hdr.key]) : hdr.key(v)
89
- )
90
- )
91
- )
92
- )
93
- )
94
- ),
95
- opts.pagination && pagination(opts.pagination)
96
- )
97
- );
98
-
99
- /**
100
- * @param {object} opts
101
- * @param {object} v
102
- * @returns {object}
103
- */
104
- const mkClickHandler = (opts, v) => {
105
- var attrs = {};
106
- if (opts.onRowSelect)
107
- attrs.onclick =
108
- typeof opts.onRowSelect === "function"
109
- ? opts.onRowSelect(v)
110
- : opts.onRowSelect;
111
- if (opts.selectedId && v.id && +v.id === +opts.selectedId)
112
- attrs.class = "table-active";
113
- return attrs;
114
- };
115
- module.exports = mkTable;