@jungherz-de/notionkit-elements 1.0.1 → 1.1.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/README.md +10 -10
- package/dist/components/nk-ai-input-row.js +1 -1
- package/dist/components/nk-ai-msg.js +1 -1
- package/dist/components/nk-ai-thread.js +1 -1
- package/dist/components/nk-app.js +1 -1
- package/dist/components/nk-avatar-group.js +1 -1
- package/dist/components/nk-banner.js +1 -1
- package/dist/components/nk-block-host.js +1 -1
- package/dist/components/nk-board-view.js +1 -1
- package/dist/components/nk-breadcrumb.js +1 -1
- package/dist/components/nk-btn.js +1 -1
- package/dist/components/nk-callout.js +1 -1
- package/dist/components/nk-check.js +1 -1
- package/dist/components/nk-cmdk.js +1 -1
- package/dist/components/nk-code.js +1 -1
- package/dist/components/nk-comment.js +1 -1
- package/dist/components/nk-comments.js +1 -1
- package/dist/components/nk-danger-zone.js +1 -1
- package/dist/components/nk-database.js +1 -1
- package/dist/components/nk-divider.js +1 -1
- package/dist/components/nk-emoji-picker.js +1 -1
- package/dist/components/nk-empty.js +1 -1
- package/dist/components/nk-field.js +1 -1
- package/dist/components/nk-filter-bar.js +1 -1
- package/dist/components/nk-heading.js +1 -1
- package/dist/components/nk-input.js +2 -2
- package/dist/components/nk-kbd.js +1 -1
- package/dist/components/nk-member-list.js +1 -1
- package/dist/components/nk-member-row.js +1 -1
- package/dist/components/nk-mention.js +1 -1
- package/dist/components/nk-menu-item.js +1 -1
- package/dist/components/nk-menu.js +1 -1
- package/dist/components/nk-modal.js +1 -1
- package/dist/components/nk-model-card.js +1 -1
- package/dist/components/nk-page-actions.js +1 -1
- package/dist/components/nk-page-cover.js +1 -1
- package/dist/components/nk-page-title.js +1 -1
- package/dist/components/nk-page.js +1 -1
- package/dist/components/nk-pop.js +1 -1
- package/dist/components/nk-profile-row.js +1 -1
- package/dist/components/nk-progress.js +1 -1
- package/dist/components/nk-quote.js +1 -1
- package/dist/components/nk-radio.js +1 -1
- package/dist/components/nk-section-label.js +1 -1
- package/dist/components/nk-segmented.js +1 -1
- package/dist/components/nk-select.js +2 -2
- package/dist/components/nk-settings-pane.js +1 -1
- package/dist/components/nk-settings-user.js +1 -1
- package/dist/components/nk-sidebar.js +1 -1
- package/dist/components/nk-skeleton.js +1 -1
- package/dist/components/nk-slider.js +1 -1
- package/dist/components/nk-stat.js +1 -1
- package/dist/components/nk-stats.js +1 -1
- package/dist/components/nk-switch.js +1 -1
- package/dist/components/nk-synced.js +1 -1
- package/dist/components/nk-tab-bar-item.js +83 -0
- package/dist/components/nk-tab-bar.js +83 -0
- package/dist/components/nk-tab.js +1 -1
- package/dist/components/nk-table-view.js +1 -1
- package/dist/components/nk-tabs.js +1 -1
- package/dist/components/nk-tag.js +1 -1
- package/dist/components/nk-template-btn.js +1 -1
- package/dist/components/nk-textarea.js +2 -2
- package/dist/components/nk-theme-toggle.js +1 -1
- package/dist/components/nk-toast.js +1 -1
- package/dist/components/nk-todo.js +1 -1
- package/dist/components/nk-toggle.js +1 -1
- package/dist/components/nk-topbar.js +1 -1
- package/dist/components/nk-tree-item.js +1 -1
- package/dist/components/nk-tree.js +1 -1
- package/dist/components/nk-workspace-switcher.js +1 -1
- package/dist/components/shared/base-BavgHsS-.js +347 -0
- package/dist/notionkit-elements.esm.js +197 -7
- package/dist/notionkit-elements.js +198 -6
- package/dist/notionkit-elements.min.js +1 -1
- package/package.json +3 -3
- package/src/base.js +31 -1
- package/src/components/forms/nk-input.js +1 -1
- package/src/components/forms/nk-select.js +1 -1
- package/src/components/forms/nk-textarea.js +1 -1
- package/src/components/shell/nk-tab-bar-item.js +82 -0
- package/src/components/shell/nk-tab-bar.js +82 -0
- package/src/index.js +2 -0
- package/dist/components/shared/base-6gEcoatG.js +0 -317
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jungherz-de/notionkit-elements",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.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)",
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
"dark-mode"
|
|
59
59
|
],
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@jungherz-de/notionkit": ">=1.
|
|
61
|
+
"@jungherz-de/notionkit": ">=1.2.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@jungherz-de/notionkit": "^1.
|
|
64
|
+
"@jungherz-de/notionkit": "^1.2.0",
|
|
65
65
|
"@rollup/plugin-node-resolve": "^15.0.0",
|
|
66
66
|
"@rollup/plugin-terser": "^0.4.0",
|
|
67
67
|
"rollup": "^4.0.0",
|
package/src/base.js
CHANGED
|
@@ -137,6 +137,12 @@ export class NkElement extends HTMLElement {
|
|
|
137
137
|
|
|
138
138
|
connectedCallback() {
|
|
139
139
|
if (!this._initialized) {
|
|
140
|
+
// A framework may have set properties on the instance before the
|
|
141
|
+
// definition arrived (hybrids binds checked="${bool}" as a property
|
|
142
|
+
// while the element is still a plain HTMLElement). Such an own property
|
|
143
|
+
// shadows the accessor on the prototype for good; re-apply it through
|
|
144
|
+
// the setter so the attribute – and with it render() – sees the value.
|
|
145
|
+
this._upgradeOwnProperties();
|
|
140
146
|
this._initialized = true;
|
|
141
147
|
|
|
142
148
|
// The wrapper mirrors data-theme from <html> so [data-theme]-keyed
|
|
@@ -187,6 +193,18 @@ export class NkElement extends HTMLElement {
|
|
|
187
193
|
this._wrapper?.setAttribute('data-theme', theme);
|
|
188
194
|
}
|
|
189
195
|
|
|
196
|
+
_upgradeOwnProperties() {
|
|
197
|
+
for (const key of Object.keys(this)) {
|
|
198
|
+
if (key.startsWith('_')) continue;
|
|
199
|
+
let proto = Object.getPrototypeOf(this), desc;
|
|
200
|
+
while (proto && proto !== HTMLElement.prototype && !(desc = Object.getOwnPropertyDescriptor(proto, key))) proto = Object.getPrototypeOf(proto);
|
|
201
|
+
if (!desc?.set) continue;
|
|
202
|
+
const value = this[key];
|
|
203
|
+
delete this[key];
|
|
204
|
+
this[key] = value;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
190
208
|
/** Subclasses override to build the inner DOM inside this._wrapper. Runs once. */
|
|
191
209
|
render() {}
|
|
192
210
|
|
|
@@ -268,9 +286,21 @@ export class NkFormElement extends NkElement {
|
|
|
268
286
|
checkValidity() { return this._internals.checkValidity(); }
|
|
269
287
|
reportValidity() { return this._internals.reportValidity(); }
|
|
270
288
|
|
|
289
|
+
connectedCallback() {
|
|
290
|
+
const first = !this._initialized;
|
|
291
|
+
super.connectedCallback();
|
|
292
|
+
// A `disabled` attribute in the markup fires formDisabledCallback on
|
|
293
|
+
// parse or upgrade – before the first connect, when nothing is rendered
|
|
294
|
+
// yet. The state was remembered below; apply it now that render() ran.
|
|
295
|
+
if (first && this._formDisabled) this.onFormDisabled(true);
|
|
296
|
+
}
|
|
297
|
+
|
|
271
298
|
formResetCallback() { this.resetValue(); }
|
|
272
299
|
formStateRestoreCallback(state, mode) { this.restoreValue(state, mode); }
|
|
273
|
-
formDisabledCallback(disabled) {
|
|
300
|
+
formDisabledCallback(disabled) {
|
|
301
|
+
this._formDisabled = disabled;
|
|
302
|
+
if (this._initialized) this.onFormDisabled(disabled);
|
|
303
|
+
}
|
|
274
304
|
|
|
275
305
|
/** Subclasses override. */
|
|
276
306
|
resetValue() {}
|
|
@@ -21,7 +21,7 @@ class NkInput extends NkFormElement {
|
|
|
21
21
|
|
|
22
22
|
_forward(attr) {
|
|
23
23
|
if (BOOLEANS.includes(attr)) {
|
|
24
|
-
this._input[attr === 'readonly' ? 'readOnly' : attr] = this.getBoolAttr(attr);
|
|
24
|
+
this._input[attr === 'readonly' ? 'readOnly' : attr] = this.getBoolAttr(attr) || (attr === 'disabled' && !!this._formDisabled);
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
const v = this.getAttribute(attr);
|
|
@@ -27,7 +27,7 @@ class NkSelect extends NkFormElement {
|
|
|
27
27
|
name ? this._select.setAttribute('name', name) : this._select.removeAttribute('name');
|
|
28
28
|
const label = this.getAttribute('aria-label');
|
|
29
29
|
label ? this._select.setAttribute('aria-label', label) : this._select.removeAttribute('aria-label');
|
|
30
|
-
this._select.disabled = this.getBoolAttr('disabled');
|
|
30
|
+
this._select.disabled = this.getBoolAttr('disabled') || !!this._formDisabled;
|
|
31
31
|
this._select.required = this.getBoolAttr('required');
|
|
32
32
|
this._select.classList.toggle('compact', this.getBoolAttr('compact'));
|
|
33
33
|
}
|
|
@@ -19,7 +19,7 @@ class NkTextarea extends NkFormElement {
|
|
|
19
19
|
|
|
20
20
|
_forward(attr) {
|
|
21
21
|
if (BOOLEANS.includes(attr)) {
|
|
22
|
-
this._input[attr === 'readonly' ? 'readOnly' : attr] = this.getBoolAttr(attr);
|
|
22
|
+
this._input[attr === 'readonly' ? 'readOnly' : attr] = this.getBoolAttr(attr) || (attr === 'disabled' && !!this._formDisabled);
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
const v = this.getAttribute(attr);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { NkElement } from '../../base.js';
|
|
2
|
+
|
|
3
|
+
// <nk-tab-bar-item icon="📥" value="inbox" active>Inbox</nk-tab-bar-item>
|
|
4
|
+
// → <button class="nk-tab-bar-item active" type="button">
|
|
5
|
+
// <span class="icon">📥</span><span class="label">Inbox</span></button>
|
|
6
|
+
//
|
|
7
|
+
// One destination of <nk-tab-bar>. A click emits nk-select (cancelable);
|
|
8
|
+
// inside a bar it then moves the bar's `value`, standalone it sets its own
|
|
9
|
+
// `active`. With `href` it navigates afterwards, with `drawer` it opens the
|
|
10
|
+
// nearest <nk-sidebar> as a drawer instead of becoming active – the usual
|
|
11
|
+
// fifth item ("More"). The icon is an attribute or a `slot="icon"` node.
|
|
12
|
+
class NkTabBarItem extends NkElement {
|
|
13
|
+
static get observedAttributes() { return ['icon', 'label', 'value', 'href', 'active', 'disabled', 'drawer']; }
|
|
14
|
+
|
|
15
|
+
render() {
|
|
16
|
+
this._btn = this.createElement('button', ['nk-tab-bar-item'], { type: 'button' });
|
|
17
|
+
this._iconSlot = this.createElement('slot', [], { name: 'icon' });
|
|
18
|
+
this._icon = this.createElement('span', ['icon'], { 'aria-hidden': 'true' });
|
|
19
|
+
this._iconSlot.appendChild(this._icon);
|
|
20
|
+
this._label = this.createElement('span', ['label']);
|
|
21
|
+
this._labelSlot = document.createElement('slot');
|
|
22
|
+
this._labelText = document.createTextNode('');
|
|
23
|
+
this._labelSlot.appendChild(this._labelText);
|
|
24
|
+
this._label.appendChild(this._labelSlot);
|
|
25
|
+
this._btn.append(this._iconSlot, this._label);
|
|
26
|
+
this._wrapper.appendChild(this._btn);
|
|
27
|
+
this._sync();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_sync() {
|
|
31
|
+
this._icon.textContent = this.getAttribute('icon') ?? '';
|
|
32
|
+
this._labelText.data = this.getAttribute('label') ?? '';
|
|
33
|
+
const active = this.getBoolAttr('active');
|
|
34
|
+
this._btn.classList.toggle('active', active);
|
|
35
|
+
active ? this._btn.setAttribute('aria-current', 'page') : this._btn.removeAttribute('aria-current');
|
|
36
|
+
this._btn.disabled = this.getBoolAttr('disabled');
|
|
37
|
+
const href = this.getAttribute('href');
|
|
38
|
+
href ? this._btn.setAttribute('data-href', href) : this._btn.removeAttribute('data-href');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setupEvents() {
|
|
42
|
+
this._onClick = () => this.select();
|
|
43
|
+
this._btn.addEventListener('click', this._onClick);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
teardownEvents() {
|
|
47
|
+
this._btn?.removeEventListener('click', this._onClick);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
select() {
|
|
51
|
+
if (this.getBoolAttr('disabled')) return;
|
|
52
|
+
const href = this.getAttribute('href');
|
|
53
|
+
const ok = this.emit('nk-select', { value: this.value, label: this.label, href, item: this, drawer: this.getBoolAttr('drawer') });
|
|
54
|
+
if (!ok) return;
|
|
55
|
+
if (this.getBoolAttr('drawer')) {
|
|
56
|
+
const sidebar = this.closest('nk-app')?.querySelector('nk-sidebar') ?? document.querySelector('nk-sidebar');
|
|
57
|
+
sidebar?.toggle?.();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const bar = this.closest('nk-tab-bar');
|
|
61
|
+
if (bar) bar.value = this.value;
|
|
62
|
+
else this.setBoolAttr('active', true);
|
|
63
|
+
if (href) location.assign(href);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onAttributeChanged() { this._sync(); }
|
|
67
|
+
focus(o) { this._btn?.focus(o); }
|
|
68
|
+
|
|
69
|
+
get value() { return this.getAttribute('value') ?? this.label; }
|
|
70
|
+
set value(v) { this.setAttribute('value', v); }
|
|
71
|
+
get label() { return this.getAttribute('label') ?? this.textContent.trim(); }
|
|
72
|
+
set label(v) { this.setAttribute('label', v); }
|
|
73
|
+
get active() { return this.getBoolAttr('active'); }
|
|
74
|
+
set active(v) { this.setBoolAttr('active', v); }
|
|
75
|
+
get disabled() { return this.getBoolAttr('disabled'); }
|
|
76
|
+
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
77
|
+
get drawer() { return this.getBoolAttr('drawer'); }
|
|
78
|
+
set drawer(v) { this.setBoolAttr('drawer', v); }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
customElements.define('nk-tab-bar-item', NkTabBarItem);
|
|
82
|
+
export { NkTabBarItem };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { NkElement } from '../../base.js';
|
|
2
|
+
|
|
3
|
+
// <nk-tab-bar value="inbox">
|
|
4
|
+
// <nk-tab-bar-item icon="🏠" value="home">Home</nk-tab-bar-item>
|
|
5
|
+
// <nk-tab-bar-item icon="📥" value="inbox">Inbox</nk-tab-bar-item>
|
|
6
|
+
// <nk-tab-bar-item icon="☰" drawer>More</nk-tab-bar-item>
|
|
7
|
+
// </nk-tab-bar>
|
|
8
|
+
// → <nav class="nk-tab-bar">…</nav>
|
|
9
|
+
//
|
|
10
|
+
// The thumb-reachable twin of the sidebar for phones and installed PWAs. As
|
|
11
|
+
// the last child of <nk-app> it is slotted into .nk-main below the scrolling
|
|
12
|
+
// page, so it never moves and needs no bottom padding anywhere. The
|
|
13
|
+
// stylesheet hides it above 860px – there the sidebar is the navigation –
|
|
14
|
+
// and shows it below; `always` shows it at every width (previews, phone
|
|
15
|
+
// frames), `floating` makes it a capsule. Exactly one item is `active`; a
|
|
16
|
+
// `drawer` item opens the sidebar instead of becoming active.
|
|
17
|
+
class NkTabBar extends NkElement {
|
|
18
|
+
static get observedAttributes() { return ['value', 'always', 'floating', 'label']; }
|
|
19
|
+
|
|
20
|
+
render() {
|
|
21
|
+
this._bar = this.createElement('nav', ['nk-tab-bar']);
|
|
22
|
+
this._slot = document.createElement('slot');
|
|
23
|
+
this._bar.appendChild(this._slot);
|
|
24
|
+
this._wrapper.appendChild(this._bar);
|
|
25
|
+
this._syncBar();
|
|
26
|
+
this._sync();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get items() { return [...this.querySelectorAll(':scope > nk-tab-bar-item')]; }
|
|
30
|
+
|
|
31
|
+
// Attribute access only: on the first connect the children are in the DOM
|
|
32
|
+
// but not yet upgraded, so their accessors do not exist.
|
|
33
|
+
_valueOf(item) { return item.getAttribute('value') ?? item.getAttribute('label') ?? item.textContent.trim(); }
|
|
34
|
+
|
|
35
|
+
_syncBar() {
|
|
36
|
+
this._bar.classList.toggle('always', this.getBoolAttr('always'));
|
|
37
|
+
this._bar.classList.toggle('floating', this.getBoolAttr('floating'));
|
|
38
|
+
const label = this.getAttribute('label');
|
|
39
|
+
label ? this._bar.setAttribute('aria-label', label) : this._bar.removeAttribute('aria-label');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_sync() {
|
|
43
|
+
const items = this.items.filter(i => !i.hasAttribute('drawer'));
|
|
44
|
+
if (!items.length) return;
|
|
45
|
+
let value = this.getAttribute('value');
|
|
46
|
+
if (value === null || !items.some(i => this._valueOf(i) === value)) {
|
|
47
|
+
const preset = items.find(i => i.hasAttribute('active')) || items[0];
|
|
48
|
+
value = this._valueOf(preset);
|
|
49
|
+
}
|
|
50
|
+
for (const item of items) {
|
|
51
|
+
if (this._valueOf(item) === value) item.setAttribute('active', ''); else item.removeAttribute('active');
|
|
52
|
+
}
|
|
53
|
+
this._value = value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
setupEvents() {
|
|
57
|
+
this._onSlot = () => this._sync();
|
|
58
|
+
this._slot.addEventListener('slotchange', this._onSlot);
|
|
59
|
+
this._sync();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
teardownEvents() {
|
|
63
|
+
this._slot?.removeEventListener('slotchange', this._onSlot);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onAttributeChanged(name) {
|
|
67
|
+
if (name !== 'value') { this._syncBar(); return; }
|
|
68
|
+
const before = this._value;
|
|
69
|
+
this._sync();
|
|
70
|
+
if (this._value !== before) this.emit('nk-change', { value: this._value });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get value() { return this._value ?? this.getAttribute('value'); }
|
|
74
|
+
set value(v) { this.setAttribute('value', v); }
|
|
75
|
+
get always() { return this.getBoolAttr('always'); }
|
|
76
|
+
set always(v) { this.setBoolAttr('always', v); }
|
|
77
|
+
get floating() { return this.getBoolAttr('floating'); }
|
|
78
|
+
set floating(v) { this.setBoolAttr('floating', v); }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
customElements.define('nk-tab-bar', NkTabBar);
|
|
82
|
+
export { NkTabBar };
|
package/src/index.js
CHANGED
|
@@ -39,6 +39,8 @@ export { NkTreeItem } from './components/shell/nk-tree-item.js';
|
|
|
39
39
|
export { NkTopbar } from './components/shell/nk-topbar.js';
|
|
40
40
|
export { NkBreadcrumb } from './components/shell/nk-breadcrumb.js';
|
|
41
41
|
export { NkThemeToggle } from './components/shell/nk-theme-toggle.js';
|
|
42
|
+
export { NkTabBar } from './components/shell/nk-tab-bar.js';
|
|
43
|
+
export { NkTabBarItem } from './components/shell/nk-tab-bar-item.js';
|
|
42
44
|
|
|
43
45
|
// Wave 3 – page shell & blocks
|
|
44
46
|
export { NkPage } from './components/page/nk-page.js';
|