@jungherz-de/notionkit-elements 1.13.0 → 1.14.0
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 +15 -0
- package/README.md +11 -11
- package/SKILL.md +107 -48
- package/dist/components/nk-gallery-view.js +114 -0
- package/dist/notionkit-elements.esm.js +111 -3
- package/dist/notionkit-elements.js +111 -2
- package/dist/notionkit-elements.min.js +1 -1
- package/package.json +3 -3
- package/src/components/data/nk-gallery-view.js +111 -0
- package/src/index.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jungherz-de/notionkit-elements",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Vanilla JavaScript Web Components wrapping the NotionKit CSS foundation – <nk-*> custom elements with Shadow DOM, automatic theme sync and native form participation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jungherz GmbH <info@jungherz.com> (https://www.jungherz.com)",
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
"dark-mode"
|
|
63
63
|
],
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@jungherz-de/notionkit": ">=1.
|
|
65
|
+
"@jungherz-de/notionkit": ">=1.14.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@jungherz-de/notionkit": "^1.
|
|
68
|
+
"@jungherz-de/notionkit": "^1.14.0",
|
|
69
69
|
"@playwright/test": "^1.50.0",
|
|
70
70
|
"@rollup/plugin-node-resolve": "^15.0.0",
|
|
71
71
|
"@rollup/plugin-terser": "^0.4.0",
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { NkElement } from '../../base.js';
|
|
2
|
+
import { renderPropertyCell } from '../../util/property-cell.js';
|
|
3
|
+
|
|
4
|
+
// <nk-gallery-view name="gallery" label="🖼 Gallery" meta-keys="status,due" new-row></nk-gallery-view>
|
|
5
|
+
// The fifth database view (NotionKit 1.14.0): the rows as cards with a
|
|
6
|
+
// picture on top, in a grid that fills the row – Notion's gallery, for a
|
|
7
|
+
// course catalog or a reading list. `cover-key` names the row field with the
|
|
8
|
+
// picture's URL (default: cover); a row without one shows the cover
|
|
9
|
+
// gradient, and `no-cover` leaves the pictures out. `size` small | medium |
|
|
10
|
+
// large sets the card size, `fit` shows a picture whole instead of cropped.
|
|
11
|
+
// Cards show the title column and the `meta-keys` (default: select and date
|
|
12
|
+
// columns). Standalone: view.columns = […]; view.rows = […]. Inside
|
|
13
|
+
// <nk-database> the database pushes the data. A card fires nk-select
|
|
14
|
+
// { row, id, value } on a click, Enter or Space, like a row of the table;
|
|
15
|
+
// the add card nk-action { action: 'new-row' }.
|
|
16
|
+
// → <div class="nk-gallery" role="list"><div class="nk-card" role="listitem" tabindex="0">
|
|
17
|
+
// <div class="nk-cover"><img src="…" alt=""></div><div class="card-title">🧭 …</div><div class="card-meta">…</div></div>
|
|
18
|
+
// <div class="nk-new-row">+ New page</div></div>
|
|
19
|
+
const SIZES = ['small', 'large'];
|
|
20
|
+
|
|
21
|
+
class NkGalleryView extends NkElement {
|
|
22
|
+
static get observedAttributes() { return ['name', 'label', 'badge', 'count', 'cover-key', 'no-cover', 'size', 'fit', 'title-key', 'meta-keys', 'new-row', 'new-row-label']; }
|
|
23
|
+
|
|
24
|
+
render() {
|
|
25
|
+
this._grid = this.createElement('div', ['nk-gallery'], { role: 'list' });
|
|
26
|
+
this._wrapper.appendChild(this._grid);
|
|
27
|
+
this._columns ??= []; this._rows ??= [];
|
|
28
|
+
this._render();
|
|
29
|
+
this.closest('nk-database')?.requestSync?.();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_titleColumn() {
|
|
33
|
+
const key = this.getAttribute('title-key');
|
|
34
|
+
return this._columns.find(c => c.key === key) || this._columns.find(c => c.title) || this._columns[0] || null;
|
|
35
|
+
}
|
|
36
|
+
_metaColumns() {
|
|
37
|
+
const keys = (this.getAttribute('meta-keys') || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
38
|
+
if (keys.length) return keys.map(k => this._columns.find(c => c.key === k)).filter(Boolean);
|
|
39
|
+
return this._columns.filter(c => c.type === 'select' || c.type === 'date');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_render() {
|
|
43
|
+
if (!this._grid) return;
|
|
44
|
+
const size = this.getAttribute('size');
|
|
45
|
+
this._grid.className = ['nk-gallery', SIZES.includes(size) && size, this.getBoolAttr('fit') && 'fit'].filter(Boolean).join(' ');
|
|
46
|
+
const title = this._titleColumn(), meta = this._metaColumns();
|
|
47
|
+
const coverKey = this.getAttribute('cover-key') || 'cover', covers = !this.getBoolAttr('no-cover');
|
|
48
|
+
this._grid.replaceChildren();
|
|
49
|
+
for (const row of this._rows) {
|
|
50
|
+
const card = this.createElement('div', ['nk-card'], { role: 'listitem', tabindex: '0', 'data-id': row.id ?? '' });
|
|
51
|
+
if (covers) {
|
|
52
|
+
const cover = this.createElement('div', ['nk-cover']);
|
|
53
|
+
if (row[coverKey]) cover.appendChild(this.createElement('img', [], { src: row[coverKey], alt: '' }));
|
|
54
|
+
card.appendChild(cover);
|
|
55
|
+
}
|
|
56
|
+
const t = this.createElement('div', ['card-title']);
|
|
57
|
+
t.textContent = `${row.icon ? row.icon + ' ' : ''}${title ? row[title.key] ?? '' : ''}`;
|
|
58
|
+
const m = this.createElement('div', ['card-meta']);
|
|
59
|
+
for (const c of meta) {
|
|
60
|
+
const v = row[c.key];
|
|
61
|
+
if (v === undefined || v === null || v === '') continue;
|
|
62
|
+
const s = document.createElement('span');
|
|
63
|
+
if (c.type === 'progress') s.textContent = `▰ ${v}%`;
|
|
64
|
+
else if (c.type === 'date') s.textContent = `📅 ${v}`;
|
|
65
|
+
else s.appendChild(renderPropertyCell(c, v, row));
|
|
66
|
+
m.appendChild(s);
|
|
67
|
+
}
|
|
68
|
+
card.append(t, m);
|
|
69
|
+
this._grid.appendChild(card);
|
|
70
|
+
}
|
|
71
|
+
if (this.getBoolAttr('new-row')) {
|
|
72
|
+
const add = this.createElement('div', ['nk-new-row'], { role: 'button', tabindex: '0', 'data-add': '' });
|
|
73
|
+
add.textContent = this.getAttribute('new-row-label') || '+ New page';
|
|
74
|
+
this._grid.appendChild(add);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setupEvents() {
|
|
79
|
+
this._onClick = (e) => {
|
|
80
|
+
if (e.target.closest('[data-add]')) { this.emit('nk-action', { action: 'new-row' }); return; }
|
|
81
|
+
const card = e.target.closest('.nk-card');
|
|
82
|
+
if (card) { const row = this._rowById(card.dataset.id); this.emit('nk-select', { row, id: row?.id, value: row?.id }); }
|
|
83
|
+
};
|
|
84
|
+
this._onKey = (e) => {
|
|
85
|
+
if (e.key !== 'Enter' && e.key !== ' ') return;
|
|
86
|
+
if (e.target.matches?.('.nk-card, [data-add]')) { e.preventDefault(); e.target.click(); }
|
|
87
|
+
};
|
|
88
|
+
this._grid.addEventListener('click', this._onClick);
|
|
89
|
+
this._grid.addEventListener('keydown', this._onKey);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
teardownEvents() {
|
|
93
|
+
this._grid?.removeEventListener('click', this._onClick);
|
|
94
|
+
this._grid?.removeEventListener('keydown', this._onKey);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_rowById(id) { return this._rows.find(r => String(r.id) === String(id)); }
|
|
98
|
+
onAttributeChanged() { this._render(); }
|
|
99
|
+
|
|
100
|
+
get name() { return this.getAttribute('name') || 'gallery'; }
|
|
101
|
+
get columns() { return this._columns; }
|
|
102
|
+
set columns(v) { this._columns = Array.isArray(v) ? v : []; this._render(); }
|
|
103
|
+
get rows() { return this._rows; }
|
|
104
|
+
set rows(v) { this._rows = Array.isArray(v) ? v : []; this._render(); }
|
|
105
|
+
set data({ columns, rows }) { this.setData(columns, rows); }
|
|
106
|
+
setData(columns, rows) { this._columns = columns || []; this._rows = rows || []; this._render(); }
|
|
107
|
+
refresh() { this._render(); }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
customElements.define('nk-gallery-view', NkGalleryView);
|
|
111
|
+
export { NkGalleryView };
|
package/src/index.js
CHANGED
|
@@ -110,6 +110,7 @@ export { NkTableView } from './components/data/nk-table-view.js';
|
|
|
110
110
|
export { NkBoardView } from './components/data/nk-board-view.js';
|
|
111
111
|
export { NkListView } from './components/data/nk-list-view.js';
|
|
112
112
|
export { NkCalendarView } from './components/data/nk-calendar-view.js';
|
|
113
|
+
export { NkGalleryView } from './components/data/nk-gallery-view.js';
|
|
113
114
|
export { NkFilterBar } from './components/data/nk-filter-bar.js';
|
|
114
115
|
export { NkComments } from './components/data/nk-comments.js';
|
|
115
116
|
export { NkComment } from './components/data/nk-comment.js';
|