@razerspine/pug-ui-kit 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ ## [1.0.1] - 2026-02-03
2
+
3
+ ### Changed
4
+ - **dataTable**: Refactored the `dataTable` mixin to improve configuration consistency.
5
+ - **dataTable**: The `options` parameter now accepts an `actions` array to define row actions (links/buttons) dynamically.
6
+
7
+ ### Removed
8
+ - **dataTable**: Removed support for the Pug `block` (slot) content for rendering actions. The `showActions` boolean option has also been removed.
9
+
10
+ ### Migration Guide
11
+ If you were using the block content for actions:
12
+ ```pug
13
+ // Old version (v1.0.0)
14
+ +dataTable(items, cols, { showActions: true })
15
+ a(href=`/edit/${item.id}`) Edit
16
+ ```
17
+ You should now update to:
18
+
19
+ ```pug
20
+ // New version (v1.0.1)
21
+ +dataTable(items, cols, {
22
+ actions: [
23
+ { label: 'Edit', url: (item) => `/edit/${item.id}` }
24
+ ]
25
+ })
26
+ ```
@@ -1,80 +1,87 @@
1
1
  //- dataTable mixin
2
2
  //- Renders a flexible table from an array of objects. Columns are derived
3
3
  //- from the provided `columns` array or automatically collected from object keys.
4
- //- Supports optional index column, optional actions column (slot), per-column
5
- //- formatters and custom header labels.
6
4
  //-
7
5
  //- Parameters:
8
6
  //- items - **Array** — Array of objects to render as rows. Each object
9
- //- represents one row; object keys map to columns. If not an
10
- //- array, an empty table is rendered.
11
- //- Example: [{ id:1, name:'Olya' }, { id:2, name:'Ivan' }]
7
+ //- represents one row.
12
8
  //- Default: []
13
9
  //- columns - **Array | undefined** — Optional ordered list of keys to use
14
- //- as columns. If omitted or empty, unique keys are collected
15
- //- from all objects in `items` and used in insertion order.
16
- //- Example: ['id','name','email']
10
+ //- as columns. If omitted, unique keys are collected from `items`.
17
11
  //- Default: auto-collected from items
18
- //- options - **Object | undefined** — Additional options:
12
+ //- options - **Object | undefined** — Configuration options:
19
13
  //- - emptyText: **String** — Text shown when no rows; Default: 'No data'.
20
14
  //- - showIndex: **Boolean** — Render leading index column; Default: false.
21
- //- - showActions: **Boolean** — Render trailing Actions column (slot); Default: true.
22
15
  //- - formatters: **Object** — Map of column -> function(value) for custom rendering.
23
16
  //- Example: { createdAt: v => new Date(v).toLocaleDateString() }.
24
- //- - labels: **Object** — Map of column -> header label string. If absent,
25
- //- header is generated by humanizing the key (underscores -> spaces, capitalized).
26
- //- Default: {}
17
+ //- - labels: **Object** — Map of column -> header label string.
18
+ //- Example: { id: 'ID', user_name: 'Name' }.
19
+ //- - actions: **Array** — List of action objects to render in the last column.
20
+ //- Replaces the deprecated block/slot mechanism.
21
+ //- Structure:
22
+ //- [
23
+ //- {
24
+ //- label: String, // Text of the link/button
25
+ //- url: Function(item), // Callback returning the URL string based on the row item
26
+ //- class: String (optional) // CSS classes for the link
27
+ //- }
28
+ //- ]
29
+ //- Default: []
27
30
  //-
28
31
  //- Behavior:
29
- //- - If `items` is empty, a single header cell spanning all columns displays `emptyText`.
30
- //- - Column order follows `columns` if provided; otherwise it follows the unique keys
31
- //- discovered across `items`.
32
- //- - For each cell, `formatters[col]` is used when present; otherwise arrays are joined,
33
- //- objects are JSON-stringified, and primitives are stringified.
34
- //- - The Actions column is a slot: when `showActions` is true, the mixin renders a `td`
35
- //- containing the caller-provided block. Inside the block the current row object is
36
- //- available as `item` and the row index as `i`.
37
- //-
38
- //- Notes and best practices:
39
- //- - Prefer passing an explicit `columns` array when you need stable column order.
40
- //- - Use `labels` for human-friendly or localized header text instead of renaming keys.
41
- //- - Keep `formatters` pure and return safe strings; if returning HTML, use `!=` in the mixin call
42
- //- or return already-escaped content carefully to avoid XSS.
43
- //- - To hide the Actions column entirely, set `showActions: false` in `options`.
44
- //- - For large datasets, consider server-side pagination or client-side slicing before passing `items`.
32
+ //- - Renders a table with Bootstrap-like classes (`table`).
33
+ //- - If `items` is empty, displays a unified row with `emptyText`.
34
+ //- - Actions are rendered as `<a>` tags in a separate column if `options.actions` is provided.
45
35
  //-
46
36
  //- Examples:
47
- //- // Basic usage with auto columns
48
- //- - const data = [{ id:1, name:'Olya' }, { id:2, name:'Ivan' }]
37
+ //- const data = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
38
+ //-
39
+ //- // 1. Basic usage
49
40
  //- +dataTable(data)
50
41
  //-
51
- //- // Explicit columns, labels and formatters
52
- //- +dataTable(data, ['id','name'], {
42
+ //- // 2. Advanced usage with Actions and Custom Labels
43
+ //- +dataTable(data, ['id', 'name'], {
53
44
  //- showIndex: true,
54
- //- showActions: false,
55
- //- labels: { id: 'ID', name: 'Full name' },
56
- //- formatters: { id: v => '#' + v }
45
+ //- labels: { name: 'Full Name' },
46
+ //- actions: [
47
+ //- {
48
+ //- label: 'Edit',
49
+ //- class: 'btn btn--text-primary btn--medium',
50
+ //- url: (item) => `/users/${item.id}/edit`
51
+ //- },
52
+ //- {
53
+ //- label: 'Delete',
54
+ //- class: 'btn btn--text-secondary btn--medium',
55
+ //- url: (item) => `/users/${item.id}/delete`
56
+ //- }
57
+ //- ]
57
58
  //- })
58
59
  //-
59
- //- // With Actions slot (edit/delete links). Inside block `item` is current row.
60
- //- +dataTable(data, ['id','name'], { showActions: true })
61
- //- a(href='/edit/#{item && item.id || ""}') Edit
62
- //- |
63
- //- a(href='/delete/#{item && item.id || ""}') Delete
60
+ //- // 3. Explicit columns, labels and formatters
61
+ //- +dataTable(data, ['id','name'], {
62
+ //- showIndex: false,
63
+ //- labels: { id: 'ID', name: 'Full name' },
64
+ //- formatters: { id: v => '#' + v }
65
+ //- })
64
66
  //-
65
- //- Keep this docblock updated when you change parameter names, defaults, or
66
- //- the mixin behavior so editor hover comments remain accurate.
67
67
  mixin dataTable(items, columns, options)
68
68
  - const _items = Array.isArray(items) ? items : [];
69
69
  - const cols = Array.isArray(columns) && columns.length ? columns : Array.from(new Set(_items.reduce((acc, it) => acc.concat(Object.keys(it || {})), [])));
70
- - const opts = Object.assign({ emptyText: 'No data', showIndex: false, showActions: false, formatters: {}, labels: {} }, options || {});
71
70
 
71
+ //- Default options
72
+ - const opts = Object.assign({ emptyText: 'No data', showIndex: false, actions: [], formatters: {}, labels: {} }, options || {});
73
+
74
+ //- Check if actions column is needed
75
+ - const hasActions = Array.isArray(opts.actions) && opts.actions.length > 0;
76
+
77
+ //- Helper: Humanize keys (user_id -> User id)
72
78
  - const humanize = function(key) {
73
79
  - if (!key && key !== 0) return '';
74
80
  - const s = String(key).replace(/_/g, ' ');
75
81
  - return s.charAt(0).toUpperCase() + s.slice(1);
76
82
  - }
77
83
 
84
+ //- Helper: Format cell values
78
85
  - const formatValue = function(v, col) {
79
86
  - if (v === null || v === undefined || v === '') return '';
80
87
  - if (opts.formatters && typeof opts.formatters[col] === 'function') return opts.formatters[col](v);
@@ -84,29 +91,33 @@ mixin dataTable(items, columns, options)
84
91
  - }
85
92
 
86
93
  if !_items.length
87
- table.table
94
+ table.table.data-table
88
95
  thead
89
96
  tr
90
- th(colspan=cols.length + (opts.showIndex ? 1 : 0) + (opts.showActions ? 1 : 0)) #{opts.emptyText}
97
+ th(colspan=cols.length + (opts.showIndex ? 1 : 0) + (hasActions ? 1 : 0)) #{opts.emptyText}
91
98
  else
92
- table.table
99
+ table.table.data-table
93
100
  thead
94
101
  tr
95
102
  if opts.showIndex
96
- th #
103
+ th.data-table__index #
97
104
  each col in cols
98
105
  - const label = (opts.labels && Object.prototype.hasOwnProperty.call(opts.labels, col)) ? opts.labels[col] : humanize(col)
99
- th #{label}
100
- if opts.showActions
101
- th Actions
106
+ th.data-table__header #{label}
107
+ if hasActions
108
+ th.data-table__actions Actions
102
109
  tbody
103
110
  each item, i in _items
104
111
  tr
105
112
  if opts.showIndex
106
- td #{i + 1}
113
+ td.data-table__index #{i + 1}
107
114
  each col in cols
108
115
  - const val = (item && Object.prototype.hasOwnProperty.call(item, col)) ? item[col] : ''
109
- td!= formatValue(val, col)
110
- if opts.showActions
111
- td
112
- block
116
+ td.data-table__cell!= formatValue(val, col)
117
+ if hasActions
118
+ td.data-table__actions-cell
119
+ each action in opts.actions
120
+ - const href = (typeof action.url === 'function') ? action.url(item) : '#'
121
+ - const className = action.class || ''
122
+ a(href=href class=className) #{action.label}
123
+ |
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "@razerspine/pug-ui-kit",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Shared Pug mixins for Webpack Starter templates",
5
+ "keywords": [
6
+ "pug",
7
+ "components",
8
+ "mixins"
9
+ ],
5
10
  "main": "index.js",
6
11
  "files": [
7
12
  "mixins",
8
13
  "index.js",
9
14
  "README.md",
10
- "LICENSE"
15
+ "LICENSE",
16
+ "CHANGELOG.md"
11
17
  ],
12
18
  "author": "Razerspine",
13
19
  "repository": {