@jungherz-de/notionkit-elements 1.5.3 → 1.7.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 +27 -18
- package/dist/components/base.js +346 -0
- package/dist/components/nk-ai-input-row.js +2 -1
- package/dist/components/nk-ai-msg.js +10 -3
- package/dist/components/nk-ai-thread.js +2 -1
- package/dist/components/nk-app.js +2 -1
- package/dist/components/nk-avatar-group.js +2 -1
- package/dist/components/nk-avatar.js +57 -0
- package/dist/components/nk-banner.js +2 -1
- package/dist/components/nk-block-host.js +2 -1
- package/dist/components/nk-board-view.js +4 -2
- package/dist/components/nk-breadcrumb.js +2 -1
- package/dist/components/nk-btn.js +31 -4
- package/dist/components/nk-callout.js +2 -1
- package/dist/components/nk-check.js +2 -1
- package/dist/components/nk-cmdk.js +3 -2
- package/dist/components/nk-code.js +2 -1
- package/dist/components/nk-comment.js +9 -6
- package/dist/components/nk-comments.js +2 -1
- package/dist/components/nk-danger-zone.js +2 -1
- package/dist/components/nk-database.js +16 -6
- package/dist/components/nk-divider.js +2 -1
- package/dist/components/nk-emoji-picker.js +2 -1
- package/dist/components/nk-empty.js +2 -1
- package/dist/components/nk-field.js +2 -1
- package/dist/components/nk-fields.js +2 -1
- package/dist/components/nk-filter-bar.js +59 -37
- package/dist/components/nk-heading.js +2 -1
- package/dist/components/nk-input.js +2 -1
- package/dist/components/nk-kbd.js +2 -1
- package/dist/components/nk-list-view.js +96 -0
- package/dist/components/nk-member-list.js +2 -1
- package/dist/components/nk-member-row.js +10 -6
- package/dist/components/nk-mention.js +2 -1
- package/dist/components/nk-menu-item.js +27 -3
- package/dist/components/nk-menu.js +88 -2
- package/dist/components/nk-modal.js +3 -2
- package/dist/components/nk-model-card.js +2 -1
- package/dist/components/nk-page-actions.js +2 -1
- package/dist/components/nk-page-cover.js +12 -11
- package/dist/components/nk-page-title.js +2 -1
- package/dist/components/nk-page.js +12 -4
- package/dist/components/nk-panel.js +61 -0
- package/dist/components/nk-panels.js +18 -0
- package/dist/components/nk-pop.js +2 -1
- package/dist/components/nk-profile-row.js +2 -1
- package/dist/components/nk-progress.js +5 -2
- package/dist/components/nk-prop.js +54 -0
- package/dist/components/nk-props.js +21 -0
- package/dist/components/nk-quote.js +2 -1
- package/dist/components/nk-radio.js +2 -1
- package/dist/components/nk-section-label.js +2 -1
- package/dist/components/nk-segmented.js +21 -1
- package/dist/components/nk-select.js +2 -1
- package/dist/components/nk-settings-pane.js +2 -1
- package/dist/components/nk-settings-user.js +2 -1
- package/dist/components/nk-sheet.js +97 -0
- package/dist/components/nk-sidebar.js +17 -37
- package/dist/components/nk-skeleton.js +2 -1
- package/dist/components/nk-slider.js +2 -1
- package/dist/components/nk-stat.js +2 -1
- package/dist/components/nk-stats.js +2 -1
- package/dist/components/nk-steps.js +61 -0
- package/dist/components/nk-switch.js +2 -1
- package/dist/components/nk-synced.js +2 -1
- package/dist/components/nk-tab-bar-item.js +2 -1
- package/dist/components/nk-tab-bar.js +2 -1
- package/dist/components/nk-tab.js +2 -1
- package/dist/components/nk-table-view.js +6 -2
- package/dist/components/nk-tabs.js +2 -1
- package/dist/components/nk-tag.js +2 -1
- package/dist/components/nk-template-btn.js +2 -1
- package/dist/components/nk-textarea.js +2 -1
- package/dist/components/nk-theme-toggle.js +2 -1
- package/dist/components/nk-toast.js +2 -1
- package/dist/components/nk-todo.js +2 -1
- package/dist/components/nk-toggle.js +2 -1
- package/dist/components/nk-topbar.js +2 -1
- package/dist/components/nk-tree-item.js +2 -1
- package/dist/components/nk-tree.js +2 -1
- package/dist/components/nk-workspace-switcher.js +2 -1
- package/dist/components/shared/avatar-BiqCaHOt.js +19 -0
- package/dist/components/shared/{focus-DXrK9oLe.js → focus-BNAChOXO.js} +12 -4
- package/dist/components/shared/{property-cell-CtXQpUjQ.js → property-cell-o7N30kAQ.js} +8 -3
- package/dist/notionkit-elements.esm.js +759 -120
- package/dist/notionkit-elements.js +767 -119
- package/dist/notionkit-elements.min.js +1 -1
- package/package.json +7 -6
- package/src/components/content/nk-progress.js +3 -1
- package/src/components/data/nk-ai-msg.js +8 -2
- package/src/components/data/nk-comment.js +7 -5
- package/src/components/data/nk-database.js +14 -5
- package/src/components/data/nk-filter-bar.js +57 -36
- package/src/components/data/nk-list-view.js +93 -0
- package/src/components/data/nk-table-view.js +2 -0
- package/src/components/forms/nk-btn.js +29 -3
- package/src/components/overlays/nk-menu-item.js +25 -2
- package/src/components/overlays/nk-menu.js +86 -1
- package/src/components/overlays/nk-sheet.js +95 -0
- package/src/components/page/nk-avatar.js +55 -0
- package/src/components/page/nk-member-row.js +8 -5
- package/src/components/page/nk-page-cover.js +10 -10
- package/src/components/page/nk-page.js +10 -3
- package/src/components/page/nk-panel.js +59 -0
- package/src/components/page/nk-panels.js +16 -0
- package/src/components/page/nk-prop.js +52 -0
- package/src/components/page/nk-props.js +19 -0
- package/src/components/page/nk-segmented.js +19 -0
- package/src/components/page/nk-steps.js +59 -0
- package/src/components/shell/nk-sidebar.js +15 -36
- package/src/index.js +18 -0
- package/src/util/avatar.js +17 -0
- package/src/util/focus.js +11 -3
- package/src/util/property-cell.js +7 -3
- package/dist/components/shared/base-C3eJwHKA.js +0 -366
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import { d as deepActiveElement, l as lockScroll, i as inertOutside, f as firstFocusable, u as unlockScroll } from './shared/focus-BNAChOXO.js';
|
|
3
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
4
|
+
|
|
5
|
+
// <nk-sheet id="more" title="More">
|
|
6
|
+
// <nk-tree manual>
|
|
7
|
+
// <nk-section-label>Favourites</nk-section-label>
|
|
8
|
+
// <nk-tree-item icon="🚀">NotionKit MVP</nk-tree-item>
|
|
9
|
+
// </nk-tree>
|
|
10
|
+
// </nk-sheet>
|
|
11
|
+
// → <div class="nk-sheet-backdrop open"><div class="nk-sheet" role="dialog">
|
|
12
|
+
// <div class="sh-grabber"></div><div class="sh-title">More</div>…</div></div>
|
|
13
|
+
//
|
|
14
|
+
// A bottom sheet (NotionKit 1.7.0) with nk-modal's contract: show(), close()
|
|
15
|
+
// and toggle(), Escape and the backdrop close it, focus moves in and back
|
|
16
|
+
// out, the page behind is scroll-locked and inert. It lies above the tab
|
|
17
|
+
// bar; rows inside are 40px high. `title` is the heading shown under the
|
|
18
|
+
// grabber and the dialog's name, never a tooltip – see NkElement.takeTitle().
|
|
19
|
+
// Choosing a row does not close the sheet – the app decides (nk-select
|
|
20
|
+
// bubbles out). Put the element directly under <body>: a transformed
|
|
21
|
+
// ancestor would trap the fixed backdrop.
|
|
22
|
+
class NkSheet extends NkElement {
|
|
23
|
+
static get observedAttributes() { return ['open', 'title']; }
|
|
24
|
+
|
|
25
|
+
render() {
|
|
26
|
+
this.takeTitle();
|
|
27
|
+
this._backdrop = this.createElement('div', ['nk-sheet-backdrop']);
|
|
28
|
+
this._backdrop.inert = true;
|
|
29
|
+
this._box = this.createElement('div', ['nk-sheet'], { role: 'dialog', 'aria-modal': 'true', tabindex: '-1' });
|
|
30
|
+
this._heading = this.createElement('div', ['sh-title'], { id: 'title' });
|
|
31
|
+
this._box.append(this.createElement('div', ['sh-grabber']), this._heading, document.createElement('slot'));
|
|
32
|
+
this._backdrop.appendChild(this._box);
|
|
33
|
+
this._wrapper.appendChild(this._backdrop);
|
|
34
|
+
this._syncTitle();
|
|
35
|
+
this._syncOpen();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_syncTitle() {
|
|
39
|
+
const text = this._titleText || '';
|
|
40
|
+
this._heading.textContent = text;
|
|
41
|
+
this._heading.hidden = !text;
|
|
42
|
+
if (text) this._box.setAttribute('aria-labelledby', 'title');
|
|
43
|
+
else this._box.removeAttribute('aria-labelledby');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
_syncOpen() {
|
|
47
|
+
const open = this.getBoolAttr('open');
|
|
48
|
+
this._backdrop.classList.toggle('open', open);
|
|
49
|
+
this._backdrop.inert = !open;
|
|
50
|
+
if (open === this._wasOpen) return;
|
|
51
|
+
this._wasOpen = open;
|
|
52
|
+
if (open) {
|
|
53
|
+
this._returnFocus = deepActiveElement();
|
|
54
|
+
lockScroll();
|
|
55
|
+
this._undoInert = inertOutside(this);
|
|
56
|
+
requestAnimationFrame(() => (firstFocusable(this) || this._box).focus({ preventScroll: true }));
|
|
57
|
+
} else {
|
|
58
|
+
unlockScroll();
|
|
59
|
+
this._undoInert?.(); this._undoInert = null;
|
|
60
|
+
const back = this._returnFocus;
|
|
61
|
+
if (back && typeof back.focus === 'function' && back.isConnected) back.focus({ preventScroll: true });
|
|
62
|
+
this._returnFocus = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setupEvents() {
|
|
67
|
+
this._onBackdrop = (e) => { if (e.target === this._backdrop) this.close(); };
|
|
68
|
+
this._onKey = (e) => { if (e.key === 'Escape' && this.getBoolAttr('open')) { e.stopPropagation(); this.close(); } };
|
|
69
|
+
this._backdrop.addEventListener('click', this._onBackdrop);
|
|
70
|
+
document.addEventListener('keydown', this._onKey);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
teardownEvents() {
|
|
74
|
+
this._backdrop?.removeEventListener('click', this._onBackdrop);
|
|
75
|
+
document.removeEventListener('keydown', this._onKey);
|
|
76
|
+
if (this._wasOpen) { unlockScroll(); this._undoInert?.(); this._undoInert = null; this._wasOpen = false; }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
onAttributeChanged(name, oldValue, value) {
|
|
80
|
+
if (name === 'title') { if (this.takeTitle(value)) this._syncTitle(); return; }
|
|
81
|
+
this._syncOpen();
|
|
82
|
+
this.emit('nk-toggle', { open: this.getBoolAttr('open') });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
show() { this.setBoolAttr('open', true); }
|
|
86
|
+
close() { this.setBoolAttr('open', false); }
|
|
87
|
+
toggle() { this.setBoolAttr('open', !this.getBoolAttr('open')); }
|
|
88
|
+
|
|
89
|
+
get open() { return this.getBoolAttr('open'); }
|
|
90
|
+
set open(v) { this.setBoolAttr('open', v); }
|
|
91
|
+
get title() { return this._titleText ?? ''; }
|
|
92
|
+
set title(v) { this._titleText = v == null ? '' : String(v); if (this._initialized) this._syncTitle(); }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
customElements.define('nk-sheet', NkSheet);
|
|
96
|
+
|
|
97
|
+
export { NkSheet };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-sidebar slot="sidebar">
|
|
4
5
|
// <nk-workspace-switcher slot="workspace" name="Acme"></nk-workspace-switcher>
|
|
@@ -10,42 +11,12 @@ import { N as NkElement } from './shared/base-C3eJwHKA.js';
|
|
|
10
11
|
//
|
|
11
12
|
// The host is display:contents so the <aside> is a direct flex child of
|
|
12
13
|
// .nk-app, exactly like the class markup. Below 860px notionkit.css hides the
|
|
13
|
-
// aside; `open` brings it back as
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// value is held for the whole duration, so closing animates too) and
|
|
19
|
-
// @starting-style gives the first frame after display: none its start
|
|
20
|
-
// values. `position: fixed` lives on the plain .nk-sidebar, not on the open
|
|
21
|
-
// state – while closing, the aside is still displayed and must not fall
|
|
22
|
-
// back into the flow. Browsers without either feature switch hard, as
|
|
23
|
-
// before; prefers-reduced-motion switches hard on purpose.
|
|
24
|
-
const drawerSheet = new CSSStyleSheet();
|
|
25
|
-
drawerSheet.replaceSync(`
|
|
26
|
-
.nk-sidebar-backdrop { display: none; position: fixed; inset: 0; z-index: 59; background: var(--nk-scrim-soft); }
|
|
27
|
-
@media (max-width: 860px) {
|
|
28
|
-
.nk-sidebar {
|
|
29
|
-
position: fixed; inset: 0 auto 0 0; z-index: 60;
|
|
30
|
-
transform: translateX(-100%);
|
|
31
|
-
transition: background .25s ease, transform .24s cubic-bezier(.2, .8, .25, 1), display .24s;
|
|
32
|
-
transition-behavior: allow-discrete;
|
|
33
|
-
}
|
|
34
|
-
:host([open]) .nk-sidebar { display: flex; transform: none; }
|
|
35
|
-
@starting-style { :host([open]) .nk-sidebar { transform: translateX(-100%); } }
|
|
36
|
-
.nk-sidebar-backdrop {
|
|
37
|
-
opacity: 0;
|
|
38
|
-
transition: opacity .24s ease, display .24s;
|
|
39
|
-
transition-behavior: allow-discrete;
|
|
40
|
-
}
|
|
41
|
-
:host([open]) .nk-sidebar-backdrop { display: block; opacity: 1; }
|
|
42
|
-
@starting-style { :host([open]) .nk-sidebar-backdrop { opacity: 0; } }
|
|
43
|
-
}
|
|
44
|
-
@media (prefers-reduced-motion: reduce) { .nk-sidebar, .nk-sidebar-backdrop { transition: none; } }
|
|
45
|
-
`);
|
|
46
|
-
|
|
14
|
+
// aside; `open` brings it back as a drawer over the page. The drawer is the
|
|
15
|
+
// stylesheet's since NotionKit 1.7.0 (.nk-sidebar.open, .nk-sidebar-backdrop
|
|
16
|
+
// .open) – the sidebar slides and the scrim fades by the same rules as the
|
|
17
|
+
// class markup; the element toggles the two classes. <nk-btn variant="sidebar">
|
|
18
|
+
// in the topbar is the ☰ that opens it.
|
|
47
19
|
class NkSidebar extends NkElement {
|
|
48
|
-
static get hostStyles() { return drawerSheet; }
|
|
49
20
|
static get observedAttributes() { return ['open']; }
|
|
50
21
|
|
|
51
22
|
render() {
|
|
@@ -62,6 +33,13 @@ class NkSidebar extends NkElement {
|
|
|
62
33
|
this._wrapper.appendChild(this._backdrop);
|
|
63
34
|
this._wrapper.appendChild(this._aside);
|
|
64
35
|
this._syncFooter();
|
|
36
|
+
this._syncOpen();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_syncOpen() {
|
|
40
|
+
const open = this.getBoolAttr('open');
|
|
41
|
+
this._aside.classList.toggle('open', open);
|
|
42
|
+
this._backdrop.classList.toggle('open', open);
|
|
65
43
|
}
|
|
66
44
|
|
|
67
45
|
_syncFooter() {
|
|
@@ -88,7 +66,9 @@ class NkSidebar extends NkElement {
|
|
|
88
66
|
}
|
|
89
67
|
|
|
90
68
|
onAttributeChanged(name) {
|
|
91
|
-
if (name
|
|
69
|
+
if (name !== 'open') return;
|
|
70
|
+
this._syncOpen();
|
|
71
|
+
this.emit('nk-toggle', { open: this.getBoolAttr('open') });
|
|
92
72
|
}
|
|
93
73
|
|
|
94
74
|
show() { this.setBoolAttr('open', true); }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-skeleton height="18" width="60%"></nk-skeleton>
|
|
4
5
|
// <nk-skeleton lines="3" widths="100%,85%,40%"></nk-skeleton>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkFormElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-slider name="size" min="12" max="18" value="14" show-value></nk-slider>
|
|
4
5
|
// → <input type="range" class="nk-slider"> <div class="nk-slider-value">14</div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-stat label="Active pages" value="128" delta="▲ 12 this week" trend="up"></nk-stat>
|
|
4
5
|
// → <div class="nk-stat"><div class="s-label">…</div><div class="s-value">…</div><div class="s-delta up">…</div></div>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
3
|
+
|
|
4
|
+
// <nk-steps label="Connect your own model" current="2"
|
|
5
|
+
// steps="Choose a provider, Enter the API key, Test the connection"></nk-steps>
|
|
6
|
+
// steps.steps = [{ label: 'Choose a provider', desc: 'Anthropic' }, 'Enter the API key', …];
|
|
7
|
+
// → <ol class="nk-steps" aria-label="…">
|
|
8
|
+
// <li class="nk-step done"><span class="st-mark">✓</span><span>Choose a provider<span class="st-desc">Anthropic</span></span></li>
|
|
9
|
+
// <li class="nk-step current" aria-current="step"><span class="st-mark">2</span><span>Enter the API key</span></li>
|
|
10
|
+
// <li class="nk-step"><span class="st-mark">3</span><span>Test the connection</span></li></ol>
|
|
11
|
+
// A setup in a few steps (NotionKit 1.7.0). `current` counts from 1; the
|
|
12
|
+
// steps before it are done, one past the last marks all of them done. The
|
|
13
|
+
// `steps` attribute is a comma-separated list; the property also takes
|
|
14
|
+
// { label, desc } objects for a line under the label.
|
|
15
|
+
class NkSteps extends NkElement {
|
|
16
|
+
static get observedAttributes() { return ['steps', 'current', 'label']; }
|
|
17
|
+
|
|
18
|
+
render() {
|
|
19
|
+
this._list = this.createElement('ol', ['nk-steps']);
|
|
20
|
+
this._wrapper.appendChild(this._list);
|
|
21
|
+
this._sync();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_items() {
|
|
25
|
+
if (this._steps) return this._steps;
|
|
26
|
+
return (this.getAttribute('steps') || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_sync() {
|
|
30
|
+
const label = this.getAttribute('label');
|
|
31
|
+
if (label) this._list.setAttribute('aria-label', label); else this._list.removeAttribute('aria-label');
|
|
32
|
+
const current = this.current;
|
|
33
|
+
this._list.replaceChildren(...this._items().map((step, i) => {
|
|
34
|
+
const n = i + 1, { label: text, desc } = typeof step === 'object' && step ? step : { label: String(step) };
|
|
35
|
+
const li = this.createElement('li', ['nk-step']);
|
|
36
|
+
li.classList.toggle('done', n < current);
|
|
37
|
+
li.classList.toggle('current', n === current);
|
|
38
|
+
if (n === current) li.setAttribute('aria-current', 'step');
|
|
39
|
+
const mark = this.createElement('span', ['st-mark'], { 'aria-hidden': 'true' });
|
|
40
|
+
mark.textContent = n < current ? '✓' : String(n);
|
|
41
|
+
const body = document.createElement('span');
|
|
42
|
+
body.textContent = text ?? '';
|
|
43
|
+
if (desc) { const d = this.createElement('span', ['st-desc']); d.textContent = desc; body.appendChild(d); }
|
|
44
|
+
li.append(mark, body);
|
|
45
|
+
return li;
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
onAttributeChanged() { this._sync(); }
|
|
50
|
+
|
|
51
|
+
get steps() { return this._items(); }
|
|
52
|
+
set steps(v) { this._steps = Array.isArray(v) ? v : null; if (this._list) this._sync(); }
|
|
53
|
+
get current() { const n = parseInt(this.getAttribute('current'), 10); return Number.isFinite(n) ? n : 1; }
|
|
54
|
+
set current(v) { this.setAttribute('current', String(v)); }
|
|
55
|
+
/** Moves on to the next step; returns the new current step. */
|
|
56
|
+
next() { this.current = Math.min(this.current + 1, this._items().length + 1); return this.current; }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
customElements.define('nk-steps', NkSteps);
|
|
60
|
+
|
|
61
|
+
export { NkSteps };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkFormElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-switch name="notify" checked></nk-switch>
|
|
4
5
|
// → <button class="nk-switch" role="switch" aria-checked="true">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-synced badge="⟳ 3 places">…</nk-synced>
|
|
4
5
|
// → <div class="nk-synced"><span class="synced-badge">⟳ 3 places</span>…</div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-tab-bar-item icon="📥" value="inbox" active>Inbox</nk-tab-bar-item>
|
|
4
5
|
// → <button class="nk-tab-bar-item active" type="button">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-tab value="notes" active>📝 Notes</nk-tab> → <span class="nk-tab active" role="tab">
|
|
4
5
|
class NkTab extends NkElement {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as compareBy, r as renderPropertyCell } from './shared/property-cell-
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import { c as compareBy, r as renderPropertyCell } from './shared/property-cell-o7N30kAQ.js';
|
|
3
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
4
|
+
import './shared/avatar-BiqCaHOt.js';
|
|
3
5
|
|
|
4
6
|
// <nk-table-view name="table" label="▦ Table" count new-row sortable wrap></nk-table-view>
|
|
5
7
|
// `wrap` lets cell text break (`.nk-table.wrap`), like Notion's "wrap column".
|
|
@@ -50,6 +52,8 @@ class NkTableView extends NkElement {
|
|
|
50
52
|
const r = this.createElement('tr', [], { 'data-id': row.id ?? '' });
|
|
51
53
|
for (const col of this._columns) {
|
|
52
54
|
const td = document.createElement('td');
|
|
55
|
+
// Numbers right-aligned in figures of equal width, as Notion sets them.
|
|
56
|
+
if (col.type === 'number') td.className = 'num';
|
|
53
57
|
td.appendChild(renderPropertyCell(col, row[col.key], row));
|
|
54
58
|
r.appendChild(td);
|
|
55
59
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-tag color="blue">Text</nk-tag> — modifier class .blue becomes color="blue".
|
|
4
5
|
// Notion's nine select colours; without `color` the stylesheet draws the grey tag.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-template-btn icon="📅" value="week-plan">Insert week plan</nk-template-btn>
|
|
4
5
|
// → <button class="nk-template-btn">📅 Insert week plan</button>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkFormElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-textarea name="bio" rows="3" wide>Text</nk-textarea> → <textarea class="nk-textarea wide">
|
|
4
5
|
// The initial value is the `value` attribute, or the element's text content.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement, getCurrentTheme } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-theme-toggle slot="actions"></nk-theme-toggle>
|
|
4
5
|
// → <button class="nk-topbar-btn nk-theme-toggle">🌙</button>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkFormElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-todo name="task" value="1" checked>Write the docs</nk-todo>
|
|
4
5
|
// → <label class="nk-todo"><input type="checkbox"><span>Write the docs</span></label>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NkElement } from './base.js';
|
|
2
|
+
import '@jungherz-de/notionkit/notionkit-styles.js';
|
|
2
3
|
|
|
3
4
|
// <nk-toggle label="Details" open>Body…</nk-toggle>
|
|
4
5
|
// → <details class="nk-toggle" open><summary>Details</summary><div class="toggle-body">…</div></details>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Shared by every element that draws an avatar: nk-avatar itself, member
|
|
2
|
+
// rows, comments and the person cells of a database view.
|
|
3
|
+
const AVATAR_COLORS = ['gray', 'brown', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink', 'red'];
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Paints an .nk-avatar. One of Notion's nine colour names becomes its class,
|
|
7
|
+
* so the tokens decide the shade in each theme; any other value – a hex, a
|
|
8
|
+
* gradient, a var() – is taken as an inline background, as before 1.6.0.
|
|
9
|
+
* Without a colour the avatar keeps the stylesheet's gradient.
|
|
10
|
+
*/
|
|
11
|
+
function paintAvatar(el, color) {
|
|
12
|
+
for (const c of AVATAR_COLORS) el.classList.toggle(c, c === color);
|
|
13
|
+
el.style.background = color && !AVATAR_COLORS.includes(color) ? color : '';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** "Sara Lindt" → "SL". */
|
|
17
|
+
const initialsOf = name => String(name || '').split(/\s+/).map(w => w[0]).filter(Boolean).join('').slice(0, 2).toUpperCase();
|
|
18
|
+
|
|
19
|
+
export { initialsOf as i, paintAvatar as p };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
// Overlay plumbing shared by nk-modal and nk-
|
|
2
|
-
// refcount,
|
|
3
|
-
// assistive technology stay inside – nested shadow roots included
|
|
1
|
+
// Overlay plumbing shared by nk-modal, nk-sheet, nk-cmdk and nk-menu: body
|
|
2
|
+
// scroll lock with a refcount, `inert` on everything outside the overlay so
|
|
3
|
+
// focus and assistive technology stay inside – nested shadow roots included –
|
|
4
|
+
// and the focused element behind shadow hosts, to return focus to.
|
|
4
5
|
let locks = 0, previousOverflow = '';
|
|
5
6
|
|
|
6
7
|
function lockScroll() {
|
|
@@ -31,6 +32,13 @@ function inertOutside(el) {
|
|
|
31
32
|
return () => { for (const c of made) c.inert = false; };
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
/** The focused element itself, looking into shadow roots (document.activeElement stops at the host). */
|
|
36
|
+
function deepActiveElement() {
|
|
37
|
+
let el = document.activeElement;
|
|
38
|
+
while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;
|
|
39
|
+
return el;
|
|
40
|
+
}
|
|
41
|
+
|
|
34
42
|
/** The first tabbable element inside a light-DOM subtree, looking into shadow roots. */
|
|
35
43
|
function firstFocusable(root) {
|
|
36
44
|
const SEL = 'a[href], button:not([disabled]), input:not([disabled]):not([type=hidden]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable="true"], [contenteditable="plaintext-only"]';
|
|
@@ -44,4 +52,4 @@ function firstFocusable(root) {
|
|
|
44
52
|
return walk(root);
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
export { firstFocusable as f, inertOutside as i, lockScroll as l, unlockScroll as u };
|
|
55
|
+
export { deepActiveElement as d, firstFocusable as f, inertOutside as i, lockScroll as l, unlockScroll as u };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { i as initialsOf, p as paintAvatar } from './avatar-BiqCaHOt.js';
|
|
2
|
+
|
|
1
3
|
// Polymorphic property renderer for database views. Returns plain DOM built
|
|
2
4
|
// from NotionKit classes – deliberately not a custom element: every cell rule
|
|
3
5
|
// starts with `.nk-table`, so a cell inside its own shadow root would never
|
|
@@ -5,6 +7,7 @@
|
|
|
5
7
|
//
|
|
6
8
|
// column: { key, label, type, icon, options: [{ value, label, color }], title }
|
|
7
9
|
// types: text | select | multi-select | date | person | checkbox | url | number | progress
|
|
10
|
+
|
|
8
11
|
const el = (tag, cls, text) => { const n = document.createElement(tag); if (cls) n.className = cls; if (text != null) n.textContent = text; return n; };
|
|
9
12
|
const COLORS = ['gray', 'brown', 'orange', 'yellow', 'green', 'blue', 'purple', 'pink', 'red'];
|
|
10
13
|
|
|
@@ -38,14 +41,16 @@ function renderPropertyCell(column, value, row = {}) {
|
|
|
38
41
|
case 'person': {
|
|
39
42
|
const cell = el('span', 'person-cell');
|
|
40
43
|
const p = typeof value === 'string' ? { name: value } : value;
|
|
41
|
-
|
|
42
|
-
avatar
|
|
44
|
+
// color: one of Notion's nine names, or any CSS background; none – the avatar gradient.
|
|
45
|
+
const avatar = el('span', 'nk-avatar small', p.initials || p.avatar || initialsOf(p.name));
|
|
46
|
+
paintAvatar(avatar, p.color);
|
|
43
47
|
cell.append(avatar, document.createTextNode(' ' + (p.name || '')));
|
|
44
48
|
return cell;
|
|
45
49
|
}
|
|
46
50
|
case 'checkbox': return checkbox(column, !!value, row);
|
|
47
51
|
case 'url': { const a = el('a', null, String(value).replace(/^https?:\/\//, '')); a.href = String(value); a.target = '_blank'; a.rel = 'noopener'; return a; }
|
|
48
|
-
|
|
52
|
+
// column.locale / column.format: Intl.NumberFormat locale and options, e.g. { minimumFractionDigits: 1 }.
|
|
53
|
+
case 'number': return el('span', null, typeof value === 'number' ? value.toLocaleString(column.locale, column.format) : String(value));
|
|
49
54
|
case 'progress': return progress(Number(value) || 0);
|
|
50
55
|
default: {
|
|
51
56
|
if (column.title) {
|