@jungherz-de/notionkit-elements 1.5.1 → 1.5.3

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.
Files changed (84) hide show
  1. package/README.md +4 -4
  2. package/dist/components/nk-ai-input-row.js +1 -1
  3. package/dist/components/nk-ai-msg.js +1 -1
  4. package/dist/components/nk-ai-thread.js +1 -1
  5. package/dist/components/nk-app.js +1 -1
  6. package/dist/components/nk-avatar-group.js +1 -1
  7. package/dist/components/nk-banner.js +1 -1
  8. package/dist/components/nk-block-host.js +1 -1
  9. package/dist/components/nk-board-view.js +1 -1
  10. package/dist/components/nk-breadcrumb.js +1 -1
  11. package/dist/components/nk-btn.js +1 -1
  12. package/dist/components/nk-callout.js +1 -1
  13. package/dist/components/nk-check.js +1 -1
  14. package/dist/components/nk-cmdk.js +1 -1
  15. package/dist/components/nk-code.js +1 -1
  16. package/dist/components/nk-comment.js +1 -1
  17. package/dist/components/nk-comments.js +1 -1
  18. package/dist/components/nk-danger-zone.js +16 -7
  19. package/dist/components/nk-database.js +1 -1
  20. package/dist/components/nk-divider.js +1 -1
  21. package/dist/components/nk-emoji-picker.js +1 -1
  22. package/dist/components/nk-empty.js +16 -5
  23. package/dist/components/nk-field.js +1 -1
  24. package/dist/components/nk-fields.js +1 -1
  25. package/dist/components/nk-filter-bar.js +1 -1
  26. package/dist/components/nk-heading.js +1 -1
  27. package/dist/components/nk-input.js +1 -1
  28. package/dist/components/nk-kbd.js +1 -1
  29. package/dist/components/nk-member-list.js +1 -1
  30. package/dist/components/nk-member-row.js +1 -1
  31. package/dist/components/nk-mention.js +1 -1
  32. package/dist/components/nk-menu-item.js +1 -1
  33. package/dist/components/nk-menu.js +1 -1
  34. package/dist/components/nk-modal.js +1 -1
  35. package/dist/components/nk-model-card.js +10 -5
  36. package/dist/components/nk-page-actions.js +1 -1
  37. package/dist/components/nk-page-cover.js +1 -1
  38. package/dist/components/nk-page-title.js +1 -1
  39. package/dist/components/nk-page.js +1 -1
  40. package/dist/components/nk-pop.js +1 -1
  41. package/dist/components/nk-profile-row.js +1 -1
  42. package/dist/components/nk-progress.js +1 -1
  43. package/dist/components/nk-quote.js +1 -1
  44. package/dist/components/nk-radio.js +1 -1
  45. package/dist/components/nk-section-label.js +1 -1
  46. package/dist/components/nk-segmented.js +1 -1
  47. package/dist/components/nk-select.js +1 -1
  48. package/dist/components/nk-settings-pane.js +8 -3
  49. package/dist/components/nk-settings-user.js +1 -1
  50. package/dist/components/nk-sidebar.js +1 -1
  51. package/dist/components/nk-skeleton.js +1 -1
  52. package/dist/components/nk-slider.js +1 -1
  53. package/dist/components/nk-stat.js +1 -1
  54. package/dist/components/nk-stats.js +1 -1
  55. package/dist/components/nk-switch.js +1 -1
  56. package/dist/components/nk-synced.js +1 -1
  57. package/dist/components/nk-tab-bar-item.js +1 -1
  58. package/dist/components/nk-tab-bar.js +1 -1
  59. package/dist/components/nk-tab.js +1 -1
  60. package/dist/components/nk-table-view.js +1 -1
  61. package/dist/components/nk-tabs.js +1 -1
  62. package/dist/components/nk-tag.js +1 -1
  63. package/dist/components/nk-template-btn.js +1 -1
  64. package/dist/components/nk-textarea.js +1 -1
  65. package/dist/components/nk-theme-toggle.js +1 -1
  66. package/dist/components/nk-toast.js +19 -1
  67. package/dist/components/nk-todo.js +1 -1
  68. package/dist/components/nk-toggle.js +1 -1
  69. package/dist/components/nk-topbar.js +1 -1
  70. package/dist/components/nk-tree-item.js +1 -1
  71. package/dist/components/nk-tree.js +1 -1
  72. package/dist/components/nk-workspace-switcher.js +1 -1
  73. package/dist/components/shared/base-C3eJwHKA.js +366 -0
  74. package/dist/notionkit-elements.esm.js +86 -19
  75. package/dist/notionkit-elements.js +86 -19
  76. package/dist/notionkit-elements.min.js +1 -1
  77. package/package.json +3 -3
  78. package/src/base.js +19 -0
  79. package/src/components/overlays/nk-settings-pane.js +7 -2
  80. package/src/components/overlays/nk-toast.js +18 -0
  81. package/src/components/page/nk-danger-zone.js +15 -6
  82. package/src/components/page/nk-empty.js +15 -4
  83. package/src/components/page/nk-model-card.js +9 -4
  84. package/dist/components/shared/base-BPIvRI6K.js +0 -347
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungherz-de/notionkit-elements",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
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.5.1"
61
+ "@jungherz-de/notionkit": ">=1.5.3"
62
62
  },
63
63
  "devDependencies": {
64
- "@jungherz-de/notionkit": "^1.5.1",
64
+ "@jungherz-de/notionkit": "^1.5.3",
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
@@ -236,6 +236,25 @@ export class NkElement extends HTMLElement {
236
236
 
237
237
  // ── Utilities ──
238
238
 
239
+ /**
240
+ * For elements whose heading arrives as `title` – nk-settings-pane,
241
+ * nk-danger-zone, nk-empty, nk-model-card. `title` is also the global HTML
242
+ * attribute, and a title on the host shows as a browser tooltip over the
243
+ * whole element. So the value is read into this._titleText and the
244
+ * attribute is taken off the host; a later setAttribute('title') arrives
245
+ * through attributeChangedCallback and is taken the same way. The removal
246
+ * fires the callback with null, which is ignored – only '' clears the
247
+ * heading. The element's own `title` accessor answers from the stored
248
+ * value, so a framework that binds `title` as a property never puts an
249
+ * attribute on the host at all. Returns whether a value was taken.
250
+ */
251
+ takeTitle(value = this.getAttribute('title')) {
252
+ if (value === null) return false;
253
+ this._titleText = value;
254
+ this.removeAttribute('title');
255
+ return true;
256
+ }
257
+
239
258
  getBoolAttr(name) {
240
259
  return this.hasAttribute(name);
241
260
  }
@@ -1,6 +1,7 @@
1
1
  import { NkElement } from '../../base.js';
2
2
 
3
3
  // <nk-settings-pane name="profile" label="My profile" icon="👤" group="Account" title="My profile" active>…</nk-settings-pane>
4
+ // `title` is the heading, never a tooltip – see NkElement.takeTitle().
4
5
  // → <section class="nk-settings-pane active"><h2>My profile</h2>…</section>
5
6
  // `label`, `icon` and `group` feed the nav that <nk-modal> renders; `title`
6
7
  // renders the pane heading (child-combinator rule, so it lives here). Slotted
@@ -14,22 +15,26 @@ class NkSettingsPane extends NkElement {
14
15
  this._section.appendChild(this._h2);
15
16
  this._section.appendChild(document.createElement('slot'));
16
17
  this._wrapper.appendChild(this._section);
18
+ this.takeTitle();
17
19
  this._sync();
18
20
  }
19
21
 
20
22
  _sync() {
21
- const title = this.getAttribute('title');
23
+ const title = this._titleText;
22
24
  this._h2.textContent = title || '';
23
25
  this._h2.style.display = title ? '' : 'none';
24
26
  this._section.classList.toggle('active', this.getBoolAttr('active'));
25
27
  this._section.setAttribute('aria-label', this.getAttribute('label') || title || this.getAttribute('name') || '');
26
28
  }
27
29
 
28
- onAttributeChanged(name) {
30
+ onAttributeChanged(name, _old, value) {
31
+ if (name === 'title' && !this.takeTitle(value)) return;
29
32
  this._sync();
30
33
  if (['label', 'icon', 'group', 'name'].includes(name)) this.closest('nk-modal')?.requestNav?.();
31
34
  }
32
35
 
36
+ get title() { return this._titleText ?? ''; }
37
+ set title(v) { this._titleText = v == null ? '' : String(v); if (this._initialized) this._sync(); }
33
38
  get name() { return this.getAttribute('name') ?? this.getAttribute('label') ?? ''; }
34
39
  get active() { return this.getBoolAttr('active'); }
35
40
  set active(v) { this.setBoolAttr('active', v); }
@@ -3,6 +3,9 @@ import { NkElement } from '../../base.js';
3
3
  // <nk-toast id="toast"></nk-toast> … toast.show('Saved');
4
4
  // → <div class="nk-toast show">✓ Saved</div>
5
5
  // One node, bottom-centred, auto-hides after `duration` ms (default 2200).
6
+ // Above a tab bar at the bottom of the screen it rises 12px over the bar:
7
+ // notionkit.css does that for class markup with :has(), which cannot see
8
+ // into shadow roots, so the element measures the bar when it opens.
6
9
  class NkToast extends NkElement {
7
10
  static get observedAttributes() { return ['open', 'duration', 'icon']; }
8
11
 
@@ -16,12 +19,27 @@ class NkToast extends NkElement {
16
19
  }
17
20
 
18
21
  _sync() {
22
+ if (this.getBoolAttr('open')) this._lift();
19
23
  this._box.classList.toggle('show', this.getBoolAttr('open'));
20
24
  const icon = this.getAttribute('icon') ?? '✓';
21
25
  this._icon.textContent = icon;
22
26
  this._icon.style.display = icon ? '' : 'none';
23
27
  }
24
28
 
29
+ // A bar counts when it is rendered and ends near the bottom of the viewport –
30
+ // the app's own bar, fixed, sticky or floating. A tab bar shown as a preview
31
+ // somewhere in a page does not lift the toast.
32
+ _lift() {
33
+ const bars = [...document.querySelectorAll('.nk-tab-bar')];
34
+ for (const host of document.querySelectorAll('nk-tab-bar')) {
35
+ const bar = host.shadowRoot?.querySelector('.nk-tab-bar');
36
+ if (bar) bars.push(bar);
37
+ }
38
+ const rect = bars.map(b => b.getBoundingClientRect())
39
+ .find(r => r.height > 0 && r.top < innerHeight && r.bottom > innerHeight - 60);
40
+ this._box.style.bottom = rect ? `${Math.round(innerHeight - rect.top + 12)}px` : '';
41
+ }
42
+
25
43
  /** Shows `message` (or the slotted content when omitted) and hides it again after `duration`. */
26
44
  show(message, { duration } = {}) {
27
45
  if (message !== undefined) this._msg.textContent = message;
@@ -2,24 +2,33 @@ import { NkElement } from '../../base.js';
2
2
 
3
3
  // <nk-danger-zone title="Danger zone">…</nk-danger-zone>
4
4
  // → <div class="nk-danger-zone"><div class="dz-title">Danger zone</div>…</div>
5
+ // `title` is the heading, never a tooltip – see NkElement.takeTitle().
5
6
  class NkDangerZone extends NkElement {
6
7
  static get observedAttributes() { return ['title']; }
7
8
 
8
9
  render() {
9
10
  const box = this.createElement('div', ['nk-danger-zone']);
10
- this._title = this.createElement('div', ['dz-title']);
11
- box.appendChild(this._title);
11
+ this._titleEl = this.createElement('div', ['dz-title']);
12
+ box.appendChild(this._titleEl);
12
13
  box.appendChild(document.createElement('slot'));
13
14
  this._wrapper.appendChild(box);
15
+ this.takeTitle();
14
16
  this._sync();
15
17
  }
16
18
 
17
19
  _sync() {
18
- const t = this.getAttribute('title');
19
- this._title.textContent = t || '';
20
- this._title.style.display = t ? '' : 'none';
20
+ const t = this._titleText;
21
+ this._titleEl.textContent = t || '';
22
+ this._titleEl.style.display = t ? '' : 'none';
21
23
  }
22
- onAttributeChanged() { this._sync(); }
24
+
25
+ onAttributeChanged(name, _old, value) {
26
+ if (name === 'title' && !this.takeTitle(value)) return;
27
+ this._sync();
28
+ }
29
+
30
+ get title() { return this._titleText ?? ''; }
31
+ set title(v) { this._titleText = v == null ? '' : String(v); if (this._initialized) this._sync(); }
23
32
  }
24
33
 
25
34
  customElements.define('nk-danger-zone', NkDangerZone);
@@ -1,7 +1,9 @@
1
1
  import { NkElement } from '../../base.js';
2
2
 
3
3
  // <nk-empty icon="🗂️" title="No entries yet" desc="Create the first one."><nk-btn variant="primary" small>+ New</nk-btn></nk-empty>
4
- // → <div class="nk-empty"><div class="e-icon">🗂️</div><div class="e-title">…</div><div class="e-desc">…</div>…</div>
4
+ // → <div class="nk-empty"><div class="e-icon">🗂️</div><div class="e-title">…</div><div class="e-desc">…</div><div class="e-actions">…</div></div>
5
+ // `title` is the heading, never a tooltip – see NkElement.takeTitle(). The
6
+ // default slot sits in .e-actions, so several buttons keep 8px apart.
5
7
  class NkEmpty extends NkElement {
6
8
  static get observedAttributes() { return ['icon', 'title', 'desc']; }
7
9
 
@@ -15,20 +17,29 @@ class NkEmpty extends NkElement {
15
17
  box.appendChild(s);
16
18
  this._parts[slot] = el;
17
19
  }
18
- box.appendChild(document.createElement('slot'));
20
+ const actions = this.createElement('div', ['e-actions']);
21
+ actions.appendChild(document.createElement('slot'));
22
+ box.appendChild(actions);
19
23
  this._wrapper.appendChild(box);
24
+ this.takeTitle();
20
25
  this._sync();
21
26
  }
22
27
 
23
28
  _sync() {
24
29
  for (const [slot, el] of Object.entries(this._parts)) {
25
- const v = this.getAttribute(slot);
30
+ const v = slot === 'title' ? this._titleText : this.getAttribute(slot);
26
31
  el.textContent = v || '';
27
32
  el.style.display = v ? '' : 'none';
28
33
  }
29
34
  }
30
35
 
31
- onAttributeChanged() { this._sync(); }
36
+ onAttributeChanged(name, _old, value) {
37
+ if (name === 'title' && !this.takeTitle(value)) return;
38
+ this._sync();
39
+ }
40
+
41
+ get title() { return this._titleText ?? ''; }
42
+ set title(v) { this._titleText = v == null ? '' : String(v); if (this._initialized) this._sync(); }
32
43
  }
33
44
 
34
45
  customElements.define('nk-empty', NkEmpty);
@@ -3,7 +3,8 @@ import { NkFormElement } from '../../base.js';
3
3
  // <nk-model-card name="model" value="gpt" title="Mona Pro" desc="Best for long documents" selected></nk-model-card>
4
4
  // → <div class="nk-model-card selected"><div class="m-radio"></div><div><div class="m-name">…</div><div class="m-desc">…</div></div></div>
5
5
  // Cards with the same `name` in the same tree behave like radios and submit
6
- // the selected value with the form.
6
+ // the selected value with the form. `title` is the card's name, never a
7
+ // tooltip – see NkElement.takeTitle().
7
8
  class NkModelCard extends NkFormElement {
8
9
  static get observedAttributes() { return ['name', 'value', 'title', 'desc', 'selected', 'disabled']; }
9
10
 
@@ -21,6 +22,7 @@ class NkModelCard extends NkFormElement {
21
22
  this._card.appendChild(text);
22
23
  this._wrapper.appendChild(this._card);
23
24
  this._defaultSelected = this.getBoolAttr('selected');
25
+ this.takeTitle();
24
26
  this._sync();
25
27
  if (this.getBoolAttr('selected')) this._unselectPeers();
26
28
  }
@@ -30,7 +32,7 @@ class NkModelCard extends NkFormElement {
30
32
  this._card.classList.toggle('selected', on);
31
33
  this._card.setAttribute('aria-checked', on ? 'true' : 'false');
32
34
  this._card.setAttribute('aria-disabled', this.getBoolAttr('disabled') ? 'true' : 'false');
33
- this._name.textContent = this.getAttribute('title') || '';
35
+ this._name.textContent = this._titleText || '';
34
36
  const desc = this.getAttribute('desc');
35
37
  this._desc.textContent = desc || '';
36
38
  this._desc.style.display = desc ? '' : 'none';
@@ -64,11 +66,12 @@ class NkModelCard extends NkFormElement {
64
66
  if (this.getBoolAttr('disabled') || this.getBoolAttr('selected')) return;
65
67
  this.setBoolAttr('selected', true);
66
68
  this.emit('nk-change', { value: this.value, name: this.name, checked: true });
67
- this.emit('nk-select', { value: this.value, label: this.getAttribute('title') });
69
+ this.emit('nk-select', { value: this.value, label: this.title });
68
70
  this.dispatchEvent(new Event('change', { bubbles: true }));
69
71
  }
70
72
 
71
- onAttributeChanged(name) {
73
+ onAttributeChanged(name, _old, value) {
74
+ if (name === 'title' && !this.takeTitle(value)) return;
72
75
  this._sync();
73
76
  if (name === 'selected' && this.getBoolAttr('selected')) this._unselectPeers();
74
77
  }
@@ -76,6 +79,8 @@ class NkModelCard extends NkFormElement {
76
79
  resetValue() { this.setBoolAttr('selected', this._defaultSelected); }
77
80
  focus(o) { this._card?.focus(o); }
78
81
 
82
+ get title() { return this._titleText ?? ''; }
83
+ set title(v) { this._titleText = v == null ? '' : String(v); if (this._initialized) this._sync(); }
79
84
  get selected() { return this.getBoolAttr('selected'); }
80
85
  set selected(v) { this.setBoolAttr('selected', v); }
81
86
  get value() { return this.getAttribute('value') || 'on'; }