@jungherz-de/notionkit-elements 1.0.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/LICENSE +21 -0
- package/README.md +90 -0
- package/dist/components/nk-ai-input-row.js +57 -0
- package/dist/components/nk-ai-msg.js +67 -0
- package/dist/components/nk-ai-thread.js +14 -0
- package/dist/components/nk-app.js +23 -0
- package/dist/components/nk-avatar-group.js +35 -0
- package/dist/components/nk-banner.js +30 -0
- package/dist/components/nk-block-host.js +35 -0
- package/dist/components/nk-board-view.js +129 -0
- package/dist/components/nk-breadcrumb.js +78 -0
- package/dist/components/nk-btn.js +107 -0
- package/dist/components/nk-callout.js +36 -0
- package/dist/components/nk-check.js +77 -0
- package/dist/components/nk-cmdk.js +221 -0
- package/dist/components/nk-code.js +66 -0
- package/dist/components/nk-comment.js +41 -0
- package/dist/components/nk-comments.js +57 -0
- package/dist/components/nk-danger-zone.js +27 -0
- package/dist/components/nk-database.js +100 -0
- package/dist/components/nk-divider.js +12 -0
- package/dist/components/nk-emoji-picker.js +112 -0
- package/dist/components/nk-empty.js +36 -0
- package/dist/components/nk-field.js +50 -0
- package/dist/components/nk-filter-bar.js +78 -0
- package/dist/components/nk-heading.js +29 -0
- package/dist/components/nk-input.js +108 -0
- package/dist/components/nk-kbd.js +15 -0
- package/dist/components/nk-member-list.js +30 -0
- package/dist/components/nk-member-row.js +46 -0
- package/dist/components/nk-mention.js +31 -0
- package/dist/components/nk-menu-item.js +68 -0
- package/dist/components/nk-menu.js +45 -0
- package/dist/components/nk-modal.js +166 -0
- package/dist/components/nk-model-card.js +89 -0
- package/dist/components/nk-page-actions.js +15 -0
- package/dist/components/nk-page-cover.js +35 -0
- package/dist/components/nk-page-title.js +71 -0
- package/dist/components/nk-page.js +71 -0
- package/dist/components/nk-pop.js +90 -0
- package/dist/components/nk-profile-row.js +25 -0
- package/dist/components/nk-progress.js +43 -0
- package/dist/components/nk-quote.js +32 -0
- package/dist/components/nk-radio.js +160 -0
- package/dist/components/nk-section-label.js +42 -0
- package/dist/components/nk-segmented.js +99 -0
- package/dist/components/nk-select.js +127 -0
- package/dist/components/nk-settings-pane.js +40 -0
- package/dist/components/nk-settings-user.js +36 -0
- package/dist/components/nk-sidebar.js +81 -0
- package/dist/components/nk-skeleton.js +31 -0
- package/dist/components/nk-slider.js +85 -0
- package/dist/components/nk-stat.js +40 -0
- package/dist/components/nk-stats.js +14 -0
- package/dist/components/nk-switch.js +69 -0
- package/dist/components/nk-synced.js +26 -0
- package/dist/components/nk-tab.js +54 -0
- package/dist/components/nk-table-view.js +109 -0
- package/dist/components/nk-tabs.js +82 -0
- package/dist/components/nk-tag.js +32 -0
- package/dist/components/nk-template-btn.js +43 -0
- package/dist/components/nk-textarea.js +95 -0
- package/dist/components/nk-theme-toggle.js +67 -0
- package/dist/components/nk-toast.js +51 -0
- package/dist/components/nk-todo.js +73 -0
- package/dist/components/nk-toggle.js +56 -0
- package/dist/components/nk-topbar.js +24 -0
- package/dist/components/nk-tree-item.js +155 -0
- package/dist/components/nk-tree.js +123 -0
- package/dist/components/nk-workspace-switcher.js +82 -0
- package/dist/components/shared/base-6gEcoatG.js +317 -0
- package/dist/components/shared/focus-DXrK9oLe.js +47 -0
- package/dist/components/shared/property-cell-Dn91uFkf.js +92 -0
- package/dist/notionkit-elements.esm.js +4639 -0
- package/dist/notionkit-elements.js +4718 -0
- package/dist/notionkit-elements.min.js +1 -0
- package/package.json +72 -0
- package/src/base.js +296 -0
- package/src/components/content/nk-callout.js +35 -0
- package/src/components/content/nk-code.js +51 -0
- package/src/components/content/nk-divider.js +11 -0
- package/src/components/content/nk-heading.js +28 -0
- package/src/components/content/nk-kbd.js +14 -0
- package/src/components/content/nk-progress.js +42 -0
- package/src/components/content/nk-quote.js +31 -0
- package/src/components/content/nk-tag.js +31 -0
- package/src/components/content/nk-todo.js +72 -0
- package/src/components/content/nk-toggle.js +55 -0
- package/src/components/data/nk-ai-input-row.js +56 -0
- package/src/components/data/nk-ai-msg.js +66 -0
- package/src/components/data/nk-ai-thread.js +13 -0
- package/src/components/data/nk-board-view.js +128 -0
- package/src/components/data/nk-comment.js +40 -0
- package/src/components/data/nk-comments.js +56 -0
- package/src/components/data/nk-database.js +99 -0
- package/src/components/data/nk-filter-bar.js +77 -0
- package/src/components/data/nk-table-view.js +108 -0
- package/src/components/forms/nk-btn.js +106 -0
- package/src/components/forms/nk-check.js +76 -0
- package/src/components/forms/nk-field.js +49 -0
- package/src/components/forms/nk-input.js +107 -0
- package/src/components/forms/nk-radio.js +159 -0
- package/src/components/forms/nk-select.js +126 -0
- package/src/components/forms/nk-slider.js +84 -0
- package/src/components/forms/nk-switch.js +68 -0
- package/src/components/forms/nk-textarea.js +94 -0
- package/src/components/overlays/nk-cmdk.js +201 -0
- package/src/components/overlays/nk-emoji-picker.js +94 -0
- package/src/components/overlays/nk-menu-item.js +67 -0
- package/src/components/overlays/nk-menu.js +44 -0
- package/src/components/overlays/nk-modal.js +165 -0
- package/src/components/overlays/nk-pop.js +89 -0
- package/src/components/overlays/nk-settings-pane.js +39 -0
- package/src/components/overlays/nk-settings-user.js +35 -0
- package/src/components/overlays/nk-toast.js +50 -0
- package/src/components/page/nk-avatar-group.js +34 -0
- package/src/components/page/nk-banner.js +29 -0
- package/src/components/page/nk-block-host.js +34 -0
- package/src/components/page/nk-danger-zone.js +26 -0
- package/src/components/page/nk-empty.js +35 -0
- package/src/components/page/nk-member-list.js +29 -0
- package/src/components/page/nk-member-row.js +45 -0
- package/src/components/page/nk-mention.js +30 -0
- package/src/components/page/nk-model-card.js +88 -0
- package/src/components/page/nk-page-actions.js +14 -0
- package/src/components/page/nk-page-cover.js +34 -0
- package/src/components/page/nk-page-title.js +70 -0
- package/src/components/page/nk-page.js +70 -0
- package/src/components/page/nk-profile-row.js +24 -0
- package/src/components/page/nk-segmented.js +98 -0
- package/src/components/page/nk-skeleton.js +30 -0
- package/src/components/page/nk-stat.js +39 -0
- package/src/components/page/nk-stats.js +13 -0
- package/src/components/page/nk-synced.js +25 -0
- package/src/components/page/nk-tab.js +53 -0
- package/src/components/page/nk-tabs.js +81 -0
- package/src/components/page/nk-template-btn.js +42 -0
- package/src/components/shell/nk-app.js +22 -0
- package/src/components/shell/nk-breadcrumb.js +77 -0
- package/src/components/shell/nk-section-label.js +41 -0
- package/src/components/shell/nk-sidebar.js +80 -0
- package/src/components/shell/nk-theme-toggle.js +66 -0
- package/src/components/shell/nk-topbar.js +23 -0
- package/src/components/shell/nk-tree-item.js +154 -0
- package/src/components/shell/nk-tree.js +122 -0
- package/src/components/shell/nk-workspace-switcher.js +81 -0
- package/src/index.js +88 -0
- package/src/util/emoji.js +17 -0
- package/src/util/focus.js +45 -0
- package/src/util/fuzzy.js +19 -0
- package/src/util/highlight.js +14 -0
- package/src/util/property-cell.js +90 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-settings-user slot="user" name="Marcel Karas" mail="marcel@…" avatar="MK"></nk-settings-user>
|
|
4
|
+
// → <div class="nk-settings-user"><div class="avatar">MK</div><div class="u-text"><div class="name">…</div><div class="mail">…</div></div></div>
|
|
5
|
+
class NkSettingsUser extends NkElement {
|
|
6
|
+
static get observedAttributes() { return ['name', 'mail', 'avatar']; }
|
|
7
|
+
|
|
8
|
+
render() {
|
|
9
|
+
const box = this.createElement('div', ['nk-settings-user']);
|
|
10
|
+
this._avatar = this.createElement('div', ['avatar']);
|
|
11
|
+
const s = this.createElement('slot', [], { name: 'avatar' });
|
|
12
|
+
s.appendChild(this._avatar);
|
|
13
|
+
const text = this.createElement('div', ['u-text']);
|
|
14
|
+
this._name = this.createElement('div', ['name']);
|
|
15
|
+
this._mail = this.createElement('div', ['mail']);
|
|
16
|
+
text.append(this._name, this._mail);
|
|
17
|
+
box.append(s, text);
|
|
18
|
+
this._wrapper.appendChild(box);
|
|
19
|
+
this._sync();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_sync() {
|
|
23
|
+
const name = this.getAttribute('name') || '';
|
|
24
|
+
this._name.textContent = name;
|
|
25
|
+
const mail = this.getAttribute('mail');
|
|
26
|
+
this._mail.textContent = mail || '';
|
|
27
|
+
this._mail.style.display = mail ? '' : 'none';
|
|
28
|
+
this._avatar.textContent = this.getAttribute('avatar') || name.split(/\s+/).map(w => w[0]).join('').slice(0, 2).toUpperCase();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onAttributeChanged() { this._sync(); }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
customElements.define('nk-settings-user', NkSettingsUser);
|
|
35
|
+
|
|
36
|
+
export { NkSettingsUser };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-sidebar slot="sidebar">
|
|
4
|
+
// <nk-workspace-switcher slot="workspace" name="Acme"></nk-workspace-switcher>
|
|
5
|
+
// <nk-tree>…</nk-tree>
|
|
6
|
+
// <nk-tree-item slot="footer" icon="⚙️">Settings</nk-tree-item>
|
|
7
|
+
// </nk-sidebar>
|
|
8
|
+
// → <aside class="nk-sidebar"><div class="nk-workspace">…</div>
|
|
9
|
+
// <div class="nk-sidebar-scroll">…</div><div class="nk-sidebar-footer">…</div></aside>
|
|
10
|
+
//
|
|
11
|
+
// The host is display:contents so the <aside> is a direct flex child of
|
|
12
|
+
// .nk-app, exactly like the class markup. Below 860px notionkit.css hides the
|
|
13
|
+
// aside; `open` brings it back as an off-canvas drawer (position only – the
|
|
14
|
+
// look is still the stylesheet's).
|
|
15
|
+
const drawerSheet = new CSSStyleSheet();
|
|
16
|
+
drawerSheet.replaceSync(`
|
|
17
|
+
@media (max-width: 860px) {
|
|
18
|
+
:host([open]) .nk-sidebar { display: flex; position: fixed; inset: 0 auto 0 0; z-index: 60; }
|
|
19
|
+
:host([open]) .nk-sidebar-backdrop { display: block; }
|
|
20
|
+
}
|
|
21
|
+
.nk-sidebar-backdrop { display: none; position: fixed; inset: 0; z-index: 59; background: var(--nk-scrim-soft); }
|
|
22
|
+
`);
|
|
23
|
+
|
|
24
|
+
class NkSidebar extends NkElement {
|
|
25
|
+
static get hostStyles() { return drawerSheet; }
|
|
26
|
+
static get observedAttributes() { return ['open']; }
|
|
27
|
+
|
|
28
|
+
render() {
|
|
29
|
+
this._backdrop = this.createElement('div', ['nk-sidebar-backdrop']);
|
|
30
|
+
this._aside = this.createElement('aside', ['nk-sidebar']);
|
|
31
|
+
this._aside.appendChild(this.createElement('slot', [], { name: 'workspace' }));
|
|
32
|
+
const scroll = this.createElement('div', ['nk-sidebar-scroll']);
|
|
33
|
+
scroll.appendChild(document.createElement('slot'));
|
|
34
|
+
this._aside.appendChild(scroll);
|
|
35
|
+
this._footer = this.createElement('div', ['nk-sidebar-footer']);
|
|
36
|
+
this._footerSlot = this.createElement('slot', [], { name: 'footer' });
|
|
37
|
+
this._footer.appendChild(this._footerSlot);
|
|
38
|
+
this._aside.appendChild(this._footer);
|
|
39
|
+
this._wrapper.appendChild(this._backdrop);
|
|
40
|
+
this._wrapper.appendChild(this._aside);
|
|
41
|
+
this._syncFooter();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
_syncFooter() {
|
|
45
|
+
const nodes = this._footerSlot.assignedElements();
|
|
46
|
+
// The footer box carries padding and a border; only render it when used.
|
|
47
|
+
this._footer.style.display = nodes.length ? '' : 'none';
|
|
48
|
+
// Footer rows are 26px in the class version (.nk-sidebar-footer .nk-tree-item).
|
|
49
|
+
for (const el of nodes) if (el.localName === 'nk-tree-item') el.setAttribute('compact', '');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setupEvents() {
|
|
53
|
+
this._onSlot = () => this._syncFooter();
|
|
54
|
+
this._onBackdrop = () => this.close();
|
|
55
|
+
this._onKey = (e) => { if (e.key === 'Escape' && this.getBoolAttr('open')) this.close(); };
|
|
56
|
+
this._footerSlot.addEventListener('slotchange', this._onSlot);
|
|
57
|
+
this._backdrop.addEventListener('click', this._onBackdrop);
|
|
58
|
+
document.addEventListener('keydown', this._onKey);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
teardownEvents() {
|
|
62
|
+
this._footerSlot?.removeEventListener('slotchange', this._onSlot);
|
|
63
|
+
this._backdrop?.removeEventListener('click', this._onBackdrop);
|
|
64
|
+
document.removeEventListener('keydown', this._onKey);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
onAttributeChanged(name) {
|
|
68
|
+
if (name === 'open') this.emit('nk-toggle', { open: this.getBoolAttr('open') });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
show() { this.setBoolAttr('open', true); }
|
|
72
|
+
close() { this.setBoolAttr('open', false); }
|
|
73
|
+
toggle() { this.setBoolAttr('open', !this.getBoolAttr('open')); }
|
|
74
|
+
|
|
75
|
+
get open() { return this.getBoolAttr('open'); }
|
|
76
|
+
set open(v) { this.setBoolAttr('open', v); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
customElements.define('nk-sidebar', NkSidebar);
|
|
80
|
+
|
|
81
|
+
export { NkSidebar };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-skeleton height="18" width="60%"></nk-skeleton>
|
|
4
|
+
// <nk-skeleton lines="3" widths="100%,85%,40%"></nk-skeleton>
|
|
5
|
+
// → <div class="nk-skeleton" style="height:…;width:…"></div> × lines
|
|
6
|
+
class NkSkeleton extends NkElement {
|
|
7
|
+
static get observedAttributes() { return ['lines', 'height', 'width', 'widths']; }
|
|
8
|
+
|
|
9
|
+
render() { this._build(); }
|
|
10
|
+
|
|
11
|
+
_build() {
|
|
12
|
+
this._wrapper.replaceChildren();
|
|
13
|
+
const lines = Math.max(1, Number(this.getAttribute('lines')) || 1);
|
|
14
|
+
const height = this.getAttribute('height') || '13';
|
|
15
|
+
const widths = (this.getAttribute('widths') || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
16
|
+
const width = this.getAttribute('width');
|
|
17
|
+
for (let i = 0; i < lines; i++) {
|
|
18
|
+
const line = this.createElement('div', ['nk-skeleton'], { 'aria-hidden': 'true' });
|
|
19
|
+
line.style.height = /^\d+(\.\d+)?$/.test(height) ? `${height}px` : height;
|
|
20
|
+
const w = widths[i] ?? width;
|
|
21
|
+
if (w) line.style.width = w;
|
|
22
|
+
this._wrapper.appendChild(line);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
onAttributeChanged() { this._build(); }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
customElements.define('nk-skeleton', NkSkeleton);
|
|
30
|
+
|
|
31
|
+
export { NkSkeleton };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { a as NkFormElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-slider name="size" min="12" max="18" value="14" show-value></nk-slider>
|
|
4
|
+
// → <input type="range" class="nk-slider"> <div class="nk-slider-value">14</div>
|
|
5
|
+
const FORWARDED = ['name', 'min', 'max', 'step', 'aria-label'];
|
|
6
|
+
|
|
7
|
+
class NkSlider extends NkFormElement {
|
|
8
|
+
static get observedAttributes() { return ['value', 'disabled', 'show-value', 'unit', ...FORWARDED]; }
|
|
9
|
+
|
|
10
|
+
render() {
|
|
11
|
+
this._input = this.createElement('input', ['nk-slider'], { type: 'range' });
|
|
12
|
+
this._out = this.createElement('div', ['nk-slider-value']);
|
|
13
|
+
this._apply();
|
|
14
|
+
this._input.value = this.getAttribute('value') ?? this._input.value;
|
|
15
|
+
this._defaultValue = this._input.value;
|
|
16
|
+
this._wrapper.appendChild(this._input);
|
|
17
|
+
this._wrapper.appendChild(this._out);
|
|
18
|
+
this._syncOut();
|
|
19
|
+
this._syncFormValue();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_apply() {
|
|
23
|
+
for (const attr of FORWARDED) {
|
|
24
|
+
const v = this.getAttribute(attr);
|
|
25
|
+
v === null ? this._input.removeAttribute(attr) : this._input.setAttribute(attr, v);
|
|
26
|
+
}
|
|
27
|
+
this._input.disabled = this.getBoolAttr('disabled') || !!this._formDisabled;
|
|
28
|
+
this._out.style.display = this.getBoolAttr('show-value') ? '' : 'none';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_syncOut() {
|
|
32
|
+
this._out.textContent = `${this._input.value}${this.getAttribute('unit') || ''}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setupEvents() {
|
|
36
|
+
this._onInput = () => {
|
|
37
|
+
this._syncOut();
|
|
38
|
+
this._syncFormValue();
|
|
39
|
+
this.emit('nk-input', { value: Number(this._input.value), name: this.name });
|
|
40
|
+
};
|
|
41
|
+
this._onChange = () => {
|
|
42
|
+
this._syncFormValue();
|
|
43
|
+
this.emit('nk-change', { value: Number(this._input.value), name: this.name });
|
|
44
|
+
this.dispatchEvent(new Event('change', { bubbles: true }));
|
|
45
|
+
};
|
|
46
|
+
this._input.addEventListener('input', this._onInput);
|
|
47
|
+
this._input.addEventListener('change', this._onChange);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
teardownEvents() {
|
|
51
|
+
this._input?.removeEventListener('input', this._onInput);
|
|
52
|
+
this._input?.removeEventListener('change', this._onChange);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
onAttributeChanged(name) {
|
|
56
|
+
if (!this._input) return;
|
|
57
|
+
if (name === 'value') this._input.value = this.getAttribute('value') ?? '';
|
|
58
|
+
else this._apply();
|
|
59
|
+
this._syncOut();
|
|
60
|
+
this._syncFormValue();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
_syncFormValue() { this.setFormValue(this._input.value); }
|
|
64
|
+
resetValue() { this._input.value = this._defaultValue; this._syncOut(); this._syncFormValue(); }
|
|
65
|
+
restoreValue(state) { if (typeof state === 'string') { this._input.value = state; this._syncOut(); this._syncFormValue(); } }
|
|
66
|
+
onFormDisabled(disabled) { this._formDisabled = disabled; this._apply(); }
|
|
67
|
+
|
|
68
|
+
focus(options) { this._input?.focus(options); }
|
|
69
|
+
|
|
70
|
+
get value() { return Number(this._input?.value ?? this.getAttribute('value')); }
|
|
71
|
+
set value(v) {
|
|
72
|
+
if (this._input) { this._input.value = v; this._syncOut(); this._syncFormValue(); }
|
|
73
|
+
else this.setAttribute('value', v);
|
|
74
|
+
}
|
|
75
|
+
get name() { return this.getAttribute('name'); }
|
|
76
|
+
set name(v) { this.setAttribute('name', v); }
|
|
77
|
+
get disabled() { return this.getBoolAttr('disabled'); }
|
|
78
|
+
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
79
|
+
get showValue() { return this.getBoolAttr('show-value'); }
|
|
80
|
+
set showValue(v) { this.setBoolAttr('show-value', v); }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
customElements.define('nk-slider', NkSlider);
|
|
84
|
+
|
|
85
|
+
export { NkSlider };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-stat label="Active pages" value="128" delta="▲ 12 this week" trend="up"></nk-stat>
|
|
4
|
+
// → <div class="nk-stat"><div class="s-label">…</div><div class="s-value">…</div><div class="s-delta up">…</div></div>
|
|
5
|
+
class NkStat extends NkElement {
|
|
6
|
+
static get observedAttributes() { return ['label', 'value', 'delta', 'trend']; }
|
|
7
|
+
|
|
8
|
+
render() {
|
|
9
|
+
const box = this.createElement('div', ['nk-stat']);
|
|
10
|
+
this._parts = {};
|
|
11
|
+
for (const [slot, cls] of [['label', 's-label'], ['value', 's-value'], ['delta', 's-delta']]) {
|
|
12
|
+
const el = this.createElement('div', [cls]);
|
|
13
|
+
const s = this.createElement('slot', [], { name: slot });
|
|
14
|
+
s.appendChild(el);
|
|
15
|
+
box.appendChild(s);
|
|
16
|
+
this._parts[slot] = el;
|
|
17
|
+
}
|
|
18
|
+
this._wrapper.appendChild(box);
|
|
19
|
+
this._sync();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_sync() {
|
|
23
|
+
for (const [slot, el] of Object.entries(this._parts)) {
|
|
24
|
+
const v = this.getAttribute(slot);
|
|
25
|
+
el.textContent = v ?? '';
|
|
26
|
+
el.style.display = v === null ? 'none' : '';
|
|
27
|
+
}
|
|
28
|
+
const trend = this.getAttribute('trend');
|
|
29
|
+
this._parts.delta.className = 's-delta' + (trend === 'up' || trend === 'down' ? ` ${trend}` : '');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
onAttributeChanged() { this._sync(); }
|
|
33
|
+
|
|
34
|
+
get value() { return this.getAttribute('value'); }
|
|
35
|
+
set value(v) { this.setAttribute('value', v); }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
customElements.define('nk-stat', NkStat);
|
|
39
|
+
|
|
40
|
+
export { NkStat };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-stats><nk-stat …></nk-stat>…</nk-stats> → <div class="nk-stats">
|
|
4
|
+
class NkStats extends NkElement {
|
|
5
|
+
render() {
|
|
6
|
+
const row = this.createElement('div', ['nk-stats']);
|
|
7
|
+
row.appendChild(document.createElement('slot'));
|
|
8
|
+
this._wrapper.appendChild(row);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
customElements.define('nk-stats', NkStats);
|
|
13
|
+
|
|
14
|
+
export { NkStats };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { a as NkFormElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-switch name="notify" checked></nk-switch>
|
|
4
|
+
// → <button class="nk-switch" role="switch" aria-checked="true">
|
|
5
|
+
// notionkit.css styles the state through [aria-checked]; the toggling is here.
|
|
6
|
+
class NkSwitch extends NkFormElement {
|
|
7
|
+
static get observedAttributes() { return ['checked', 'disabled', 'name', 'value', 'label']; }
|
|
8
|
+
|
|
9
|
+
render() {
|
|
10
|
+
this._btn = this.createElement('button', ['nk-switch'], { type: 'button', role: 'switch' });
|
|
11
|
+
this._defaultChecked = this.getBoolAttr('checked');
|
|
12
|
+
this._apply();
|
|
13
|
+
this._wrapper.appendChild(this._btn);
|
|
14
|
+
this._syncFormValue();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_apply() {
|
|
18
|
+
this._btn.setAttribute('aria-checked', this.getBoolAttr('checked') ? 'true' : 'false');
|
|
19
|
+
this._btn.disabled = this.getBoolAttr('disabled') || !!this._formDisabled;
|
|
20
|
+
const label = this.getAttribute('label');
|
|
21
|
+
label ? this._btn.setAttribute('aria-label', label) : this._btn.removeAttribute('aria-label');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setupEvents() {
|
|
25
|
+
this._onClick = () => this.toggle();
|
|
26
|
+
this._btn.addEventListener('click', this._onClick);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
teardownEvents() {
|
|
30
|
+
this._btn?.removeEventListener('click', this._onClick);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
toggle() {
|
|
34
|
+
if (this.getBoolAttr('disabled') || this._formDisabled) return;
|
|
35
|
+
this.checked = !this.checked;
|
|
36
|
+
this.emit('nk-change', { checked: this.checked, value: this.getAttribute('value') || 'on', name: this.name });
|
|
37
|
+
this.dispatchEvent(new Event('change', { bubbles: true }));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
onAttributeChanged() {
|
|
41
|
+
if (!this._btn) return;
|
|
42
|
+
this._apply();
|
|
43
|
+
this._syncFormValue();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
_syncFormValue() {
|
|
47
|
+
const val = this.getAttribute('value') || 'on';
|
|
48
|
+
this.setFormValue(this.getBoolAttr('checked') ? val : null, this.getBoolAttr('checked') ? 'checked' : 'unchecked');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
resetValue() { this.setBoolAttr('checked', this._defaultChecked); }
|
|
52
|
+
restoreValue(state) { if (state === 'checked' || state === 'unchecked') this.setBoolAttr('checked', state === 'checked'); }
|
|
53
|
+
onFormDisabled(disabled) { this._formDisabled = disabled; this._apply(); }
|
|
54
|
+
|
|
55
|
+
focus(options) { this._btn?.focus(options); }
|
|
56
|
+
|
|
57
|
+
get checked() { return this.getBoolAttr('checked'); }
|
|
58
|
+
set checked(v) { this.setBoolAttr('checked', v); }
|
|
59
|
+
get disabled() { return this.getBoolAttr('disabled'); }
|
|
60
|
+
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
61
|
+
get name() { return this.getAttribute('name'); }
|
|
62
|
+
set name(v) { this.setAttribute('name', v); }
|
|
63
|
+
get value() { return this.getAttribute('value') || 'on'; }
|
|
64
|
+
set value(v) { this.setAttribute('value', v); }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
customElements.define('nk-switch', NkSwitch);
|
|
68
|
+
|
|
69
|
+
export { NkSwitch };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-synced badge="⟳ 3 places">…</nk-synced>
|
|
4
|
+
// → <div class="nk-synced"><span class="synced-badge">⟳ 3 places</span>…</div>
|
|
5
|
+
class NkSynced extends NkElement {
|
|
6
|
+
static get observedAttributes() { return ['badge']; }
|
|
7
|
+
|
|
8
|
+
render() {
|
|
9
|
+
const box = this.createElement('div', ['nk-synced']);
|
|
10
|
+
this._badge = this.createElement('span', ['synced-badge']);
|
|
11
|
+
box.appendChild(this._badge);
|
|
12
|
+
box.appendChild(document.createElement('slot'));
|
|
13
|
+
this._wrapper.appendChild(box);
|
|
14
|
+
this._sync();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_sync() { this._badge.textContent = this.getAttribute('badge') ?? '⟳ synced'; }
|
|
18
|
+
onAttributeChanged() { this._sync(); }
|
|
19
|
+
|
|
20
|
+
get badge() { return this.getAttribute('badge'); }
|
|
21
|
+
set badge(v) { this.setAttribute('badge', v); }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
customElements.define('nk-synced', NkSynced);
|
|
25
|
+
|
|
26
|
+
export { NkSynced };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-tab value="notes" active>📝 Notes</nk-tab> → <span class="nk-tab active" role="tab">
|
|
4
|
+
class NkTab extends NkElement {
|
|
5
|
+
static get observedAttributes() { return ['active', 'value', 'disabled']; }
|
|
6
|
+
|
|
7
|
+
render() {
|
|
8
|
+
this._tab = this.createElement('span', ['nk-tab'], { role: 'tab' });
|
|
9
|
+
this._tab.appendChild(document.createElement('slot'));
|
|
10
|
+
this._wrapper.appendChild(this._tab);
|
|
11
|
+
this._sync();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
_sync() {
|
|
15
|
+
const active = this.getBoolAttr('active');
|
|
16
|
+
this._tab.classList.toggle('active', active);
|
|
17
|
+
this._tab.setAttribute('aria-selected', active ? 'true' : 'false');
|
|
18
|
+
this._tab.tabIndex = active ? 0 : -1;
|
|
19
|
+
this._tab.setAttribute('aria-disabled', this.getBoolAttr('disabled') ? 'true' : 'false');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setupEvents() {
|
|
23
|
+
this._onClick = () => this.select();
|
|
24
|
+
this._onKey = (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); this.select(); } };
|
|
25
|
+
this._tab.addEventListener('click', this._onClick);
|
|
26
|
+
this._tab.addEventListener('keydown', this._onKey);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
teardownEvents() {
|
|
30
|
+
this._tab?.removeEventListener('click', this._onClick);
|
|
31
|
+
this._tab?.removeEventListener('keydown', this._onKey);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
select() {
|
|
35
|
+
if (this.getBoolAttr('disabled')) return;
|
|
36
|
+
const ok = this.emit('nk-select', { value: this.value, label: this.textContent.trim(), item: this });
|
|
37
|
+
if (!ok) return;
|
|
38
|
+
const tabs = this.closest('nk-tabs');
|
|
39
|
+
if (tabs) tabs.value = this.value;
|
|
40
|
+
else this.setBoolAttr('active', true);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onAttributeChanged() { this._sync(); }
|
|
44
|
+
focus(o) { this._tab?.focus(o); }
|
|
45
|
+
|
|
46
|
+
get value() { return this.getAttribute('value') ?? this.textContent.trim(); }
|
|
47
|
+
set value(v) { this.setAttribute('value', v); }
|
|
48
|
+
get active() { return this.getBoolAttr('active'); }
|
|
49
|
+
set active(v) { this.setBoolAttr('active', v); }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
customElements.define('nk-tab', NkTab);
|
|
53
|
+
|
|
54
|
+
export { NkTab };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
import { c as compareBy, r as renderPropertyCell } from './shared/property-cell-Dn91uFkf.js';
|
|
3
|
+
|
|
4
|
+
// <nk-table-view name="table" label="▦ Table" count new-row sortable></nk-table-view>
|
|
5
|
+
// Standalone: view.columns = […]; view.rows = […]; Inside <nk-database> the
|
|
6
|
+
// database pushes `data`. → <div class="nk-table-wrap"><table class="nk-table">…</table><div class="nk-new-row">+ New page</div></div>
|
|
7
|
+
// Cells are plain markup from renderPropertyCell(); rows fire nk-select,
|
|
8
|
+
// checkboxes nk-change, headers nk-action { action: 'sort' } (and sort locally
|
|
9
|
+
// with `sortable`), the add row nk-action { action: 'new-row' }.
|
|
10
|
+
class NkTableView extends NkElement {
|
|
11
|
+
static get observedAttributes() { return ['name', 'label', 'badge', 'count', 'new-row', 'new-row-label', 'sortable', 'sort-key', 'sort-dir']; }
|
|
12
|
+
|
|
13
|
+
render() {
|
|
14
|
+
this._wrap = this.createElement('div', ['nk-table-wrap']);
|
|
15
|
+
this._table = this.createElement('table', ['nk-table']);
|
|
16
|
+
this._thead = document.createElement('thead');
|
|
17
|
+
this._tbody = document.createElement('tbody');
|
|
18
|
+
this._table.append(this._thead, this._tbody);
|
|
19
|
+
this._newRow = this.createElement('div', ['nk-new-row'], { role: 'button', tabindex: '0' });
|
|
20
|
+
this._wrap.append(this._table, this._newRow);
|
|
21
|
+
this._wrapper.appendChild(this._wrap);
|
|
22
|
+
this._columns ??= []; this._rows ??= [];
|
|
23
|
+
this._render();
|
|
24
|
+
this.closest('nk-database')?.requestSync?.();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_sortedRows() {
|
|
28
|
+
const key = this.getAttribute('sort-key');
|
|
29
|
+
const col = this._columns.find(c => c.key === key);
|
|
30
|
+
if (!col) return this._rows;
|
|
31
|
+
return [...this._rows].sort(compareBy(col, this.getAttribute('sort-dir') === 'desc' ? -1 : 1));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_render() {
|
|
35
|
+
if (!this._thead) return;
|
|
36
|
+
const tr = document.createElement('tr');
|
|
37
|
+
for (const col of this._columns) {
|
|
38
|
+
const th = this.createElement('th', [], { 'data-key': col.key, scope: 'col' });
|
|
39
|
+
if (col.icon) { const i = this.createElement('span', ['th-icon']); i.textContent = col.icon; th.appendChild(i); }
|
|
40
|
+
th.appendChild(document.createTextNode(col.label ?? col.key));
|
|
41
|
+
if (col.key === this.getAttribute('sort-key')) th.appendChild(document.createTextNode(this.getAttribute('sort-dir') === 'desc' ? ' ↓' : ' ↑'));
|
|
42
|
+
if (col.width) th.style.width = col.width;
|
|
43
|
+
tr.appendChild(th);
|
|
44
|
+
}
|
|
45
|
+
this._thead.replaceChildren(tr);
|
|
46
|
+
this._tbody.replaceChildren();
|
|
47
|
+
for (const row of this._sortedRows()) {
|
|
48
|
+
const r = this.createElement('tr', [], { 'data-id': row.id ?? '' });
|
|
49
|
+
for (const col of this._columns) {
|
|
50
|
+
const td = document.createElement('td');
|
|
51
|
+
td.appendChild(renderPropertyCell(col, row[col.key], row));
|
|
52
|
+
r.appendChild(td);
|
|
53
|
+
}
|
|
54
|
+
this._tbody.appendChild(r);
|
|
55
|
+
}
|
|
56
|
+
this._newRow.textContent = this.getAttribute('new-row-label') || '+ New page';
|
|
57
|
+
this._newRow.style.display = this.getBoolAttr('new-row') ? '' : 'none';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setupEvents() {
|
|
61
|
+
this._onClick = (e) => {
|
|
62
|
+
if (this._newRow.contains(e.target)) { this.emit('nk-action', { action: 'new-row' }); return; }
|
|
63
|
+
const th = e.target.closest('th[data-key]');
|
|
64
|
+
if (th) {
|
|
65
|
+
const key = th.dataset.key;
|
|
66
|
+
const dir = this.getAttribute('sort-key') === key && this.getAttribute('sort-dir') !== 'desc' ? 'desc' : 'asc';
|
|
67
|
+
const ok = this.emit('nk-action', { action: 'sort', key, value: dir });
|
|
68
|
+
if (ok && this.getBoolAttr('sortable')) { this.setAttribute('sort-key', key); this.setAttribute('sort-dir', dir); }
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (e.target.closest('input[type=checkbox], a')) return;
|
|
72
|
+
const tr = e.target.closest('tr[data-id]');
|
|
73
|
+
if (tr) { const row = this._rowById(tr.dataset.id); this.emit('nk-select', { row, id: row?.id, value: row?.id }); }
|
|
74
|
+
};
|
|
75
|
+
this._onChange = (e) => {
|
|
76
|
+
const input = e.target;
|
|
77
|
+
if (input.type !== 'checkbox') return;
|
|
78
|
+
const row = this._rowById(input.dataset.rowId);
|
|
79
|
+
if (row) row[input.dataset.key] = input.checked;
|
|
80
|
+
this.emit('nk-change', { row, key: input.dataset.key, value: input.checked });
|
|
81
|
+
};
|
|
82
|
+
this._onKey = (e) => { if ((e.key === 'Enter' || e.key === ' ') && e.target === this._newRow) { e.preventDefault(); this.emit('nk-action', { action: 'new-row' }); } };
|
|
83
|
+
this._wrap.addEventListener('click', this._onClick);
|
|
84
|
+
this._wrap.addEventListener('change', this._onChange);
|
|
85
|
+
this._wrap.addEventListener('keydown', this._onKey);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
teardownEvents() {
|
|
89
|
+
this._wrap?.removeEventListener('click', this._onClick);
|
|
90
|
+
this._wrap?.removeEventListener('change', this._onChange);
|
|
91
|
+
this._wrap?.removeEventListener('keydown', this._onKey);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
_rowById(id) { return this._rows.find(r => String(r.id) === String(id)); }
|
|
95
|
+
onAttributeChanged() { this._render(); }
|
|
96
|
+
|
|
97
|
+
get name() { return this.getAttribute('name') || 'table'; }
|
|
98
|
+
get columns() { return this._columns; }
|
|
99
|
+
set columns(v) { this._columns = Array.isArray(v) ? v : []; this._render(); }
|
|
100
|
+
get rows() { return this._rows; }
|
|
101
|
+
set rows(v) { this._rows = Array.isArray(v) ? v : []; this._render(); }
|
|
102
|
+
set data({ columns, rows }) { this.setData(columns, rows); }
|
|
103
|
+
setData(columns, rows) { this._columns = columns || []; this._rows = rows || []; this._render(); }
|
|
104
|
+
refresh() { this._render(); }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
customElements.define('nk-table-view', NkTableView);
|
|
108
|
+
|
|
109
|
+
export { NkTableView };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-tabs value="notes">
|
|
4
|
+
// <nk-tab value="notes">📝 Notes</nk-tab>
|
|
5
|
+
// <nk-tab value="tasks">✅ Tasks</nk-tab>
|
|
6
|
+
// <div slot="panel" data-tab="notes" class="nk-tab-panel">…</div>
|
|
7
|
+
// <div slot="panel" data-tab="tasks" class="nk-tab-panel">…</div>
|
|
8
|
+
// </nk-tabs>
|
|
9
|
+
// → <div class="nk-tabs" role="tablist">…</div> + the panels below it.
|
|
10
|
+
// The tabs keep one tab active and hide every panel whose data-tab does not
|
|
11
|
+
// match `value` (through the hidden attribute – the panels stay yours).
|
|
12
|
+
const KEYS = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 };
|
|
13
|
+
|
|
14
|
+
class NkTabs extends NkElement {
|
|
15
|
+
static get observedAttributes() { return ['value']; }
|
|
16
|
+
|
|
17
|
+
render() {
|
|
18
|
+
this._strip = this.createElement('div', ['nk-tabs'], { role: 'tablist' });
|
|
19
|
+
this._tabSlot = document.createElement('slot');
|
|
20
|
+
this._strip.appendChild(this._tabSlot);
|
|
21
|
+
this._panelSlot = this.createElement('slot', [], { name: 'panel' });
|
|
22
|
+
this._wrapper.append(this._strip, this._panelSlot);
|
|
23
|
+
this._sync();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get tabs() { return [...this.querySelectorAll(':scope > nk-tab')]; }
|
|
27
|
+
get panels() { return [...this.querySelectorAll(':scope > [slot="panel"]')]; }
|
|
28
|
+
|
|
29
|
+
_sync() {
|
|
30
|
+
const tabs = this.tabs;
|
|
31
|
+
if (!tabs.length) return;
|
|
32
|
+
let value = this.getAttribute('value');
|
|
33
|
+
if (value === null || !tabs.some(t => t.getAttribute('value') === value || (t.getAttribute('value') === null && t.textContent.trim() === value))) {
|
|
34
|
+
const preset = tabs.find(t => t.hasAttribute('active')) || tabs[0];
|
|
35
|
+
value = preset.getAttribute('value') ?? preset.textContent.trim();
|
|
36
|
+
}
|
|
37
|
+
for (const tab of tabs) {
|
|
38
|
+
const v = tab.getAttribute('value') ?? tab.textContent.trim();
|
|
39
|
+
if (v === value) tab.setAttribute('active', ''); else tab.removeAttribute('active');
|
|
40
|
+
}
|
|
41
|
+
for (const panel of this.panels) panel.hidden = panel.dataset.tab !== value;
|
|
42
|
+
this._value = value;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setupEvents() {
|
|
46
|
+
this._onSlot = () => this._sync();
|
|
47
|
+
this._onKey = (e) => {
|
|
48
|
+
const dir = KEYS[e.key];
|
|
49
|
+
if (!dir) return;
|
|
50
|
+
const tabs = this.tabs.filter(t => !t.hasAttribute('disabled'));
|
|
51
|
+
const i = tabs.indexOf(e.target.closest?.('nk-tab'));
|
|
52
|
+
if (i < 0 || tabs.length < 2) return;
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
const next = tabs[(i + dir + tabs.length) % tabs.length];
|
|
55
|
+
next.select();
|
|
56
|
+
next.focus();
|
|
57
|
+
};
|
|
58
|
+
this._tabSlot.addEventListener('slotchange', this._onSlot);
|
|
59
|
+
this._panelSlot.addEventListener('slotchange', this._onSlot);
|
|
60
|
+
this.addEventListener('keydown', this._onKey);
|
|
61
|
+
this._sync();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
teardownEvents() {
|
|
65
|
+
this._tabSlot?.removeEventListener('slotchange', this._onSlot);
|
|
66
|
+
this._panelSlot?.removeEventListener('slotchange', this._onSlot);
|
|
67
|
+
this.removeEventListener('keydown', this._onKey);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onAttributeChanged() {
|
|
71
|
+
const before = this._value;
|
|
72
|
+
this._sync();
|
|
73
|
+
if (this._value !== before) this.emit('nk-change', { value: this._value });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get value() { return this._value ?? this.getAttribute('value'); }
|
|
77
|
+
set value(v) { this.setAttribute('value', v); }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
customElements.define('nk-tabs', NkTabs);
|
|
81
|
+
|
|
82
|
+
export { NkTabs };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { N as NkElement } from './shared/base-6gEcoatG.js';
|
|
2
|
+
|
|
3
|
+
// <nk-tag color="blue">Text</nk-tag> — modifier class .blue becomes color="blue"
|
|
4
|
+
const COLORS = ['blue', 'green', 'orange', 'purple'];
|
|
5
|
+
|
|
6
|
+
class NkTag extends NkElement {
|
|
7
|
+
static get observedAttributes() { return ['color']; }
|
|
8
|
+
|
|
9
|
+
render() {
|
|
10
|
+
this._tag = this.createElement('span', this._computeClasses());
|
|
11
|
+
this._tag.appendChild(document.createElement('slot'));
|
|
12
|
+
this._wrapper.appendChild(this._tag);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
onAttributeChanged() {
|
|
16
|
+
if (this._tag) this._tag.className = this._computeClasses().join(' ');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_computeClasses() {
|
|
20
|
+
const classes = ['nk-tag'];
|
|
21
|
+
const color = this.getAttribute('color');
|
|
22
|
+
if (COLORS.includes(color)) classes.push(color);
|
|
23
|
+
return classes;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get color() { return this.getAttribute('color'); }
|
|
27
|
+
set color(v) { v ? this.setAttribute('color', v) : this.removeAttribute('color'); }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
customElements.define('nk-tag', NkTag);
|
|
31
|
+
|
|
32
|
+
export { NkTag };
|