@jungherz-de/notionkit-elements 1.15.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ All notable changes to NotionKit Elements are documented here. The format follow
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [1.16.0] – 2026-09-25
8
+
9
+ Built against NotionKit CSS 1.16.0 (peer `>= 1.16.0`). LearnHub checked all its open findings against 1.14.0; this release takes the fixes and small additions from that list – 3, 4, 5, 10, 11 and 15 – together with Auxdesk's finding 25. Links for steps and gallery cards and German texts follow in 1.17.0.
10
+
11
+ ### Fixed
12
+ - **`<nk-panel icon>` without `cover` keeps its icon inside the tile.** The band sat in the shadow root even without `cover`, only hidden, and `.nk-cover + .nk-page-icon` still pulled the icon 24px up, 9px over the tile's edge. The band is in the tree only with `cover` now, and follows the attribute both ways.
13
+ - **`<nk-select>` waits for the option of a value from the attribute, too.** `<nk-select value="b">` with a static first option and `b` loaded later showed the first option: the browser's preselection survived as the live selection. A value – attribute or property – whose option is missing now waits and wins once it arrives, unless someone has chosen another option in the meantime, and settling on it fires no `nk-change`. While it waits, `value` reports it; the visible selection and the form value stay as they are.
14
+ - **`<nk-progress wide>` in a panel is a 6px bar** instead of 60px and more (NotionKit 1.16.0).
15
+ - **A floating date picker or menu under `<body>` works from an open dialog.** An open `<nk-dialog>`, `<nk-modal>`, `<nk-sheet>`, the palette or – on a phone – `<nk-peek>` made every sibling inert, the floating layers under `<body>` among them, and they lay under it besides: a date picker opened from a field in a dialog showed but took no click. Floating menus and date pickers, the tooltip and the toast stay out of the inert page now, and NotionKit 1.16.0 lays them above the dialog.
16
+ - **`<nk-btn>` stretched across a column keeps its label centred** (NotionKit 1.16.0) – Auxdesk's sign-in page.
17
+
18
+ ### Added
19
+ - **`flush` on every element** drops the outer margin of its box, for a block in a flex column with a gap of its own; `--nk-block-space: 0` on the column does it for every block inside (NotionKit 1.16.0). Before, only `<nk-props>` and `<nk-panels>` had `flush`, and the margins of the others sat out of reach in their shadow roots.
20
+ - **A minified ES module: `dist/notionkit-elements.esm.min.js`**, with its source map, the same exports as `notionkit-elements.esm.js` – for an import map without a build step, where the minified bundle was an IIFE only. `@jungherz-de/notionkit-elements/esm.min.js` resolves to it.
21
+
22
+ ### Changed
23
+ - Peer `@jungherz-de/notionkit >= 1.16.0`.
24
+
7
25
  ## [1.15.0] – 2026-09-25
8
26
 
9
27
  Built against NotionKit CSS 1.15.0 (peer `>= 1.15.0`). Auxdesk's findings 22 and 23 from its jobs, messages and tickets in `<nk-table-view>`.
@@ -684,6 +702,7 @@ built and tested against NotionKit CSS 1.1.1 (peer range `>= 1.0.0`).
684
702
  import, never in the core bundle – shadow-less, adding `nk-block-host` to
685
703
  itself so the foundation's editor adapter rules apply.
686
704
 
705
+ [1.16.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.16.0
687
706
  [1.15.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.15.0
688
707
  [1.14.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.14.0
689
708
  [1.13.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.13.0
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  <h1 align="center">🧩 NotionKit Elements</h1>
2
2
 
3
3
  <p align="center">
4
- <a href="https://www.npmjs.com/package/@jungherz-de/notionkit-elements"><img src="https://img.shields.io/badge/version-1.15.0-2383e2?style=flat-square" alt="Version"></a>
4
+ <a href="https://www.npmjs.com/package/@jungherz-de/notionkit-elements"><img src="https://img.shields.io/badge/version-1.16.0-2383e2?style=flat-square" alt="Version"></a>
5
5
  <a href="#"><img src="https://img.shields.io/badge/vanilla_JS-no_dependencies-448361?style=flat-square" alt="Vanilla JS"></a>
6
6
  <a href="#"><img src="https://img.shields.io/badge/elements-88-529cca?style=flat-square" alt="88 Elements"></a>
7
7
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-9065b0?style=flat-square" alt="MIT License"></a>
8
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-v1.15.0-lightgrey?style=flat-square" alt="Changelog"></a>
8
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-v1.16.0-lightgrey?style=flat-square" alt="Changelog"></a>
9
9
  <a href="https://www.npmjs.com/package/@jungherz-de/notionkit-elements"><img src="https://img.shields.io/badge/npm-%40jungherz--de%2Fnotionkit--elements-cb3837?style=flat-square&logo=npm" alt="npm"></a>
10
10
  </p>
11
11
 
@@ -59,8 +59,8 @@ It is the **app layer** of the NotionKit family – three layers, one design lan
59
59
  | 🧩 **88 Elements** | Forms with copy field, image picker and date picker, content blocks with bookmarks, app shell & tree with the ☰ drawer and the collapsing sidebar, page shell with properties, panels, avatars and steps, overlays (modal, sheet, dialog, resizable side peek, tooltip, ⌘K palette, menus that float in and become sheets on a phone, popover, emoji picker, toast), database table, board, list, calendar & gallery with toolbar and filter pills, comments, AI thread |
60
60
  | 🎛️ **Form participation** | Input, textarea, select, switch, check, radio, slider, segmented and model card work natively with `<form>` via `ElementInternals`; radios group across shadow roots |
61
61
  | 🌗 **Theme sync** | One observer mirrors `data-theme` on `<html>` into every element |
62
- | 🪶 **Lightweight** | 280 KB minified / 56 KB gzipped (IIFE, foundation sheet included), no external dependencies |
63
- | 📦 **Four bundle shapes** | IIFE, minified IIFE, ESM, and per-component ESM entries on a stable `base.js`, which import NotionKit's sheet instead of carrying a copy |
62
+ | 🪶 **Lightweight** | 281 KB minified / 56 KB gzipped (IIFE, foundation sheet included), no external dependencies |
63
+ | 📦 **Five bundle shapes** | IIFE, minified IIFE, ESM, minified ESM with a source map (`esm.min.js`), and per-component ESM entries on a stable `base.js`, which import NotionKit's sheet instead of carrying a copy |
64
64
  | 🤖 **AI-ready** | `SKILL.md` with copy-paste markup, six app skeletons and the rules – an agent given only that file built a working app in the release test |
65
65
 
66
66
  ---
@@ -71,8 +71,8 @@ It is the **app layer** of the NotionKit family – three layers, one design lan
71
71
  <!DOCTYPE html>
72
72
  <html lang="en" data-theme="light">
73
73
  <head>
74
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
75
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
74
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
75
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
76
76
  </head>
77
77
  <body class="nk-body">
78
78
  <nk-field label="Display name" desc="Shown next to your comments">
@@ -100,9 +100,11 @@ The per-component files import NotionKit's sheet as `@jungherz-de/notionkit/noti
100
100
  <script type="importmap">{ "imports": { "@jungherz-de/notionkit/notionkit-styles.js": "/node_modules/@jungherz-de/notionkit/notionkit-styles.js" } }</script>
101
101
  ```
102
102
 
103
+ Without a build step, an import map can point at the minified module instead: `"@jungherz-de/notionkit-elements": "/node_modules/@jungherz-de/notionkit-elements/dist/notionkit-elements.esm.min.js"` – the same exports as `notionkit-elements.esm.js`, its source map beside it.
104
+
103
105
  Do not mix the full bundle with the per-component files: each brings its own `NkElement`. With the bundle, take `componentsSheet` and `NkElement` from the bundle (`NotionKitElements.componentsSheet` from the `<script>` build).
104
106
 
105
- Two prerequisites, always: `notionkit.css` on the document (the peer dependency, `>= 1.15.0`; 1.15.0 brings table text with a tone and a second line, 1.14.0 brings the gallery view and a banner action that stands at the right edge again, 1.13.0 keeps fields inside narrow panels, leaves a page without icon its padding under the cover and makes cover heights tokens, 1.12.0 brings a tag or button beside a panel's title, lists and grids without outer margin, text values, steps with states in any order and in a row, scrolling tabs, a cap for full pages and buttons per table row, 1.11.0 keeps a floating menu inside an open modal or dialog in place and inside the window and brings the banner's action as a button, fields that share a row and tooltips of several lines, 1.10.1 lets a disabled button show its tooltip, 1.10.0 brings the collapsing sidebar, the resizable side peek, the dialog and the tooltip, 1.9.0 the date picker and the calendar view, 1.8.0 the side peek, the bookmark, the copy field and pictures on the profile row, 1.7.0 the sheet, menus that float in and become sheets on a phone, the sidebar drawer, the database toolbar with filter pills and the steps, 1.7.1 minified files that carry all of it, 1.6.0 page properties, page options, list view, panels, prose and the avatar, 1.5.1 the safe areas, 1.5.0 the Notion-2025 tokens, the nine tag colours and the filled inputs; from 1.5.0 on, Elements and the foundation share one version number – the elements are built and tested against the same release) and `class="nk-body"` on `<body>`. The elements ship no visual CSS of their own – every rule comes from the foundation. The bundle injects the design tokens once as `@layer notionkit-defaults`, so any plain `:root { --nk-accent: … }` of yours re-brands every element in both themes.
107
+ Two prerequisites, always: `notionkit.css` on the document (the peer dependency, `>= 1.16.0`; 1.16.0 brings `--nk-block-space` and `flush` for blocks in a column, keeps a wide progress bar and a stretched button's label in shape and lays floating menus above dialogs, 1.15.0 brings table text with a tone and a second line, 1.14.0 brings the gallery view and a banner action that stands at the right edge again, 1.13.0 keeps fields inside narrow panels, leaves a page without icon its padding under the cover and makes cover heights tokens, 1.12.0 brings a tag or button beside a panel's title, lists and grids without outer margin, text values, steps with states in any order and in a row, scrolling tabs, a cap for full pages and buttons per table row, 1.11.0 keeps a floating menu inside an open modal or dialog in place and inside the window and brings the banner's action as a button, fields that share a row and tooltips of several lines, 1.10.1 lets a disabled button show its tooltip, 1.10.0 brings the collapsing sidebar, the resizable side peek, the dialog and the tooltip, 1.9.0 the date picker and the calendar view, 1.8.0 the side peek, the bookmark, the copy field and pictures on the profile row, 1.7.0 the sheet, menus that float in and become sheets on a phone, the sidebar drawer, the database toolbar with filter pills and the steps, 1.7.1 minified files that carry all of it, 1.6.0 page properties, page options, list view, panels, prose and the avatar, 1.5.1 the safe areas, 1.5.0 the Notion-2025 tokens, the nine tag colours and the filled inputs; from 1.5.0 on, Elements and the foundation share one version number – the elements are built and tested against the same release) and `class="nk-body"` on `<body>`. The elements ship no visual CSS of their own – every rule comes from the foundation. The bundle injects the design tokens once as `@layer notionkit-defaults`, so any plain `:root { --nk-accent: … }` of yours re-brands every element in both themes.
106
108
 
107
109
  ## Elements
108
110
 
package/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: notionkit-elements
3
- description: NotionKit Elements is a vanilla-JS Web Components library (v1.15.0) wrapping NotionKit CSS v1.15.0 – the calm, document-centric design system in the Notion idiom. 88 custom elements with the `nk-` prefix, Shadow DOM, automatic light/dark sync via data-theme on <html>, and form-associated controls. Use this reference whenever generating HTML that uses <nk-*> tags to get attributes, slots, events and composition right.
3
+ description: NotionKit Elements is a vanilla-JS Web Components library (v1.16.0) wrapping NotionKit CSS v1.16.0 – the calm, document-centric design system in the Notion idiom. 88 custom elements with the `nk-` prefix, Shadow DOM, automatic light/dark sync via data-theme on <html>, and form-associated controls. Use this reference whenever generating HTML that uses <nk-*> tags to get attributes, slots, events and composition right.
4
4
  ---
5
5
 
6
6
  # NotionKit Elements – AI Component Reference
@@ -21,8 +21,8 @@ description: NotionKit Elements is a vanilla-JS Web Components library (v1.15.0)
21
21
  <head>
22
22
  <meta charset="UTF-8">
23
23
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
24
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
25
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
24
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
25
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
26
26
  </head>
27
27
  <body class="nk-body">
28
28
  <nk-btn variant="primary">Save</nk-btn>
@@ -80,7 +80,7 @@ Never mix the full bundle with the per-component files – each brings its own `
80
80
 
81
81
  ### 3.1 `<nk-btn>` – Button
82
82
 
83
- Renders `button.nk-btn`, or `a.nk-btn` when `href` is set. Modifier classes become attributes. A slotted `<svg>` is sized by the stylesheet – pass it directly, never wrapped.
83
+ Renders `button.nk-btn`, or `a.nk-btn` when `href` is set. Modifier classes become attributes. A slotted `<svg>` is sized by the stylesheet – pass it directly, never wrapped. Stretched across a column – a full-width button on a sign-in page – it keeps its label centred.
84
84
 
85
85
  ```html
86
86
  <nk-btn variant="primary">Save</nk-btn>
@@ -218,7 +218,7 @@ A picture for a person or a workspace, on NotionKit’s profile row: round, or `
218
218
 
219
219
  ### 3.5 `<nk-calendar>` – Date picker
220
220
 
221
- Notion’s date picker as one element (NotionKit 1.9.0): a month with Today and ‹ ›, the keys, bounds and a form value. The value is a day (`YYYY-MM-DD`); with `range` an interval `start/end`, picked in two clicks in either order; with `time` a day and a time (`YYYY-MM-DDTHH:MM`). `weeks` puts the ISO calendar week in front of each row (“KW” in German), `weekend` greys the days not worked, the `days` property adds holidays (`off` with a `label`) and up to three `marks` per day in the nine colours – deadlines, milestones. Days outside `min`/`max` are announced as unavailable and cannot be picked. Arrows move by a day or a week, Home/End to the ends of the week, PageUp/PageDown by a month (with Shift a year), Enter or Space picks; one day is in the tab order. Month names, weekdays and the first day of the week come from the page’s language; `week-start="1"` fixes Monday. With `floating sheet` it is a popover that `show(anchor)` opens under a property or a cell, and a bottom sheet on a phone; a pick closes it.
221
+ Notion’s date picker as one element (NotionKit 1.9.0): a month with Today and ‹ ›, the keys, bounds and a form value. The value is a day (`YYYY-MM-DD`); with `range` an interval `start/end`, picked in two clicks in either order; with `time` a day and a time (`YYYY-MM-DDTHH:MM`). `weeks` puts the ISO calendar week in front of each row (“KW” in German), `weekend` greys the days not worked, the `days` property adds holidays (`off` with a `label`) and up to three `marks` per day in the nine colours – deadlines, milestones. Days outside `min`/`max` are announced as unavailable and cannot be picked. Arrows move by a day or a week, Home/End to the ends of the week, PageUp/PageDown by a month (with Shift a year), Enter or Space picks; one day is in the tab order. Month names, weekdays and the first day of the week come from the page’s language; `week-start="1"` fixes Monday. With `floating sheet` it is a popover that `show(anchor)` opens under a property or a cell, and a bottom sheet on a phone; a pick closes it. Put a floating one directly under `<body>`: an open `nk-dialog`, `nk-modal` or `nk-sheet` leaves it usable, so it opens from a field in a dialog as well.
222
222
 
223
223
  ```html
224
224
  <div style="display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start">
@@ -333,7 +333,7 @@ Multi-line sibling of `nk-input`. The initial value is the `value` attribute or
333
333
 
334
334
  ### 3.7 `<nk-select>` – Select
335
335
 
336
- Light-DOM `<option>` and `<optgroup>` children are copied into the shadow `<select>` and kept in step when a framework swaps them. The empty string is a valid value; a `value` naming no option leaves the selection alone. A `value` set before its option exists – a framework sets properties before children – waits and is applied once the option arrives.
336
+ Light-DOM `<option>` and `<optgroup>` children are copied into the shadow `<select>` and kept in step when a framework swaps them. The empty string is a valid value; a `value` naming no option leaves the selection alone. A `value` – attribute or property – whose option is not there yet waits and is applied once the option arrives, over the browser’s preselection of the first option, unless someone has chosen another in the meantime; settling on it fires no `nk-change`.
337
337
 
338
338
  ```html
339
339
  <nk-select name="role" value="editor">
@@ -605,7 +605,7 @@ The select option as Notion draws it, in its nine colours. The colour modifier c
605
605
 
606
606
  ### 3.15 `<nk-progress>` – Progress
607
607
 
608
- A 60px bar with an optional label. `value`/`max` set the fill; the bar carries `role="progressbar"`.
608
+ A 60px bar with an optional label. `value`/`max` set the fill; the bar carries `role="progressbar"`. `wide` fills its row, and in a flex column – a panel – it stays a 6px bar.
609
609
 
610
610
  ```html
611
611
  <nk-progress value="72" label="72%"></nk-progress>
@@ -2241,7 +2241,7 @@ Notion’s side peek: a database row opens at the right edge, full height, next
2241
2241
 
2242
2242
  ### 3.67 `<nk-dialog>` – Dialog
2243
2243
 
2244
- A question or a short form – “Move to trash?”, the name of a new view, the link between two tasks – with the contract of `nk-modal` and `nk-sheet`: `show()`, `close()`, `toggle()`, `nk-toggle`; Escape – captured, before a peek, a menu or a modal behind it – and the backdrop close it; focus moves in, to an `[autofocus]` element or the first field or button, and back; the page behind is inert and scroll-locked. It lies above the modal and the sheet. `title` is the heading, the default slot the text or the fields, `slot="actions"` the buttons, the confirming one last. A button in `slot="actions"` with a `value` closes it with that value, one anywhere inside with `data-close` too – another button with a value, an option of `nk-segmented` say, leaves it open – and so does the submit of a `<form method="dialog">` inside; before it closes, `nk-close` fires and can be cancelled – the place to check an input. `alert` for a question, `wide` (560px) for a form. `show(from)` hands focus back to `from` – the ⋯ of a menu that closed. Place it directly under `<body>`.
2244
+ A question or a short form – “Move to trash?”, the name of a new view, the link between two tasks – with the contract of `nk-modal` and `nk-sheet`: `show()`, `close()`, `toggle()`, `nk-toggle`; Escape – captured, before a peek, a menu or a modal behind it – and the backdrop close it; focus moves in, to an `[autofocus]` element or the first field or button, and back; the page behind is inert and scroll-locked. It lies above the modal and the sheet. `title` is the heading, the default slot the text or the fields, `slot="actions"` the buttons, the confirming one last. A button in `slot="actions"` with a `value` closes it with that value, one anywhere inside with `data-close` too – another button with a value, an option of `nk-segmented` say, leaves it open – and so does the submit of a `<form method="dialog">` inside; before it closes, `nk-close` fires and can be cancelled – the place to check an input. `alert` for a question, `wide` (560px) for a form. `show(from)` hands focus back to `from` – the ⋯ of a menu that closed. Place it directly under `<body>`. While it is open the page behind is inert, but floating menus and date pickers under `<body>` – and the tooltip and toast – stay usable, so a field in the dialog can open one.
2245
2245
 
2246
2246
  ```html
2247
2247
  <nk-dialog open alert title="Move “NotionKit MVP” to trash?">
@@ -2388,7 +2388,7 @@ The user card at the top of the settings nav.
2388
2388
 
2389
2389
  ### 3.71 `<nk-menu>` – Menu
2390
2390
 
2391
- A 230px context menu. Items are `nk-menu-item`s (`type="separator"` / `"label"` for the rest); ↑↓ move, Enter selects, `nk-select` bubbles up. Inside `nk-pop` or the workspace switcher it is part of their surface. With `floating` it is a menu over the page of its own, NotionKit’s `.nk-pop.floating`: `menu.show(button)` opens it under the button, right edges aligned (`align="start"`: left edges), and it fades in like the palette. A tap outside closes it and reaches nothing else; Escape and a chosen item close it, a switch row keeps it open. Opened from the keyboard, focus moves to the first item and back when it closes. Put it directly under `<body>`, like the other overlays. Floating, it opens upwards where the window ends below and there is more room above, and a menu longer than the room scrolls inside; in an `nk-modal` or `nk-dialog` it sits right as well.
2391
+ A 230px context menu. Items are `nk-menu-item`s (`type="separator"` / `"label"` for the rest); ↑↓ move, Enter selects, `nk-select` bubbles up. Inside `nk-pop` or the workspace switcher it is part of their surface. With `floating` it is a menu over the page of its own, NotionKit’s `.nk-pop.floating`: `menu.show(button)` opens it under the button, right edges aligned (`align="start"`: left edges), and it fades in like the palette. A tap outside closes it and reaches nothing else; Escape and a chosen item close it, a switch row keeps it open. Opened from the keyboard, focus moves to the first item and back when it closes. Put it directly under `<body>`, like the other overlays. Floating, it opens upwards where the window ends below and there is more room above, and a menu longer than the room scrolls inside; in an `nk-modal` or `nk-dialog` it sits right as well, and opened from one of them it stays usable – an open dialog, modal or sheet leaves floating menus alone.
2392
2392
 
2393
2393
  ```html
2394
2394
  <nk-menu>
@@ -3142,8 +3142,8 @@ Eight skeletons, one per app shape, mirroring the NotionKit CSS SKILL.md. Copy o
3142
3142
  <html lang="en" data-theme="light">
3143
3143
  <head>
3144
3144
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3145
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3146
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3145
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3146
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3147
3147
  </head>
3148
3148
  <body class="nk-body">
3149
3149
  <nk-app>
@@ -3224,8 +3224,8 @@ Rules of the shell: `nk-sidebar`, `nk-topbar` and `nk-page` are `display: conten
3224
3224
  <html lang="en" data-theme="light">
3225
3225
  <head>
3226
3226
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3227
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3228
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3227
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3228
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3229
3229
  </head>
3230
3230
  <body class="nk-body">
3231
3231
  <nk-app>
@@ -3332,8 +3332,8 @@ Data contract: `columns` describe the properties (`type`: text | select | multi-
3332
3332
  <html lang="en" data-theme="light">
3333
3333
  <head>
3334
3334
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3335
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3336
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3335
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3336
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3337
3337
  </head>
3338
3338
  <body class="nk-body">
3339
3339
  <nk-app>
@@ -3392,8 +3392,8 @@ Data contract: `columns` describe the properties (`type`: text | select | multi-
3392
3392
  <html lang="en" data-theme="light">
3393
3393
  <head>
3394
3394
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3395
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3396
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3395
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3396
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3397
3397
  </head>
3398
3398
  <body class="nk-body">
3399
3399
  <!-- your app -->
@@ -3470,8 +3470,8 @@ The open/close contract is one attribute: `settings.open = true`, `settings.show
3470
3470
  <html lang="en" data-theme="light">
3471
3471
  <head>
3472
3472
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3473
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3474
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3473
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3474
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3475
3475
  </head>
3476
3476
  <body class="nk-body">
3477
3477
  <div class="nk-page" style="padding-top:48px">
@@ -3517,8 +3517,8 @@ The open/close contract is one attribute: `settings.open = true`, `settings.show
3517
3517
  <html lang="en" data-theme="light">
3518
3518
  <head>
3519
3519
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3520
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3521
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3520
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3521
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3522
3522
  </head>
3523
3523
  <body class="nk-body">
3524
3524
  <nk-page narrow icon="📘" cover>
@@ -3562,8 +3562,8 @@ Note `narrow`: the page is the document, so there is no inner scroll wrapper –
3562
3562
  <html lang="en" data-theme="light">
3563
3563
  <head>
3564
3564
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3565
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3566
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3565
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3566
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3567
3567
  </head>
3568
3568
  <body class="nk-body">
3569
3569
  <nk-app>
@@ -3617,8 +3617,8 @@ Note `narrow`: the page is the document, so there is no inner scroll wrapper –
3617
3617
  <html lang="en" data-theme="light">
3618
3618
  <head>
3619
3619
  <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
3620
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.15.0/notionkit.min.css">
3621
- <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.15.0/dist/notionkit-elements.min.js"></script>
3620
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.16.0/notionkit.min.css">
3621
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.16.0/dist/notionkit-elements.min.js"></script>
3622
3622
  </head>
3623
3623
  <body class="nk-body">
3624
3624
  <!-- A narrow column, centred: layout is yours, so it is inline. -->
@@ -3693,6 +3693,8 @@ Form controls additionally re-dispatch a native, bubbling `change` event, so `fo
3693
3693
  | `<button class="nk-btn">` inside `<nk-btn>` | The element renders the button – slot only the label and icon |
3694
3694
  | Loading the bundle without `notionkit.css` and wondering about the serif font | The token layer only covers colours and metrics; typography comes from `.nk-body` |
3695
3695
  | `<nk-btn style="margin-top:16px">` or `nk-callout { margin: … }` | Hosts are `display: contents` and have no box – put spacing on a wrapper you own |
3696
+ | Blocks in a flex column with a `gap` that stand too far apart | `--nk-block-space: 0` on the column drops every block's outer margin; `flush` on one element drops its own. Headings keep theirs |
3697
+ | A `<nk-calendar floating>` or `<nk-menu floating>` moved into a dialog so that it can be clicked | Leave it under `<body>`: an open `nk-dialog`, `nk-modal` or `nk-sheet` keeps floating menus, date pickers, the tooltip and the toast usable |
3696
3698
  | A positioned wrapper around `<nk-menu>` to open it under a button | `<nk-menu floating sheet>` and `menu.show(button)`: it measures the button, closes on a tap outside and is a sheet on a phone |
3697
3699
  | `<nk-sheet id="more">` opened from `app.html#more` | Give the overlay an id other than the hash: the browser scrolls to the fragment target and takes the focus the overlay just gave |
3698
3700
  | `<nk-btn variant="topbar" onclick="sidebar.toggle()">☰</nk-btn>` plus a script that hides it on the desktop | `<nk-btn variant="sidebar">☰</nk-btn>` – shown below 860px only, opens the drawer |
@@ -3818,10 +3820,10 @@ Form controls additionally re-dispatch a native, bubbling `change` event, so `fo
3818
3820
  | Theme sync | one `MutationObserver` on `<html>[data-theme]`, a `Set` of instances, `.nk-wrapper[data-theme]` inside each root |
3819
3821
  | Components | `src/components/{forms,content,shell,page,overlays,data}/nk-*.js`, one tag per file, `customElements.define` at the bottom |
3820
3822
  | Build | Rollup: IIFE, minified IIFE, ESM, and per-component ESM entries on a stable `dist/components/base.js` that import NotionKit's sheet (`@jungherz-de/notionkit/notionkit-styles.js`) instead of inlining it; the full bundles inline it and export `componentsSheet` |
3821
- | Peer | `@jungherz-de/notionkit >= 1.15.0` – from 1.5.0 on the elements and the foundation share one version number; the bundle embeds that release's stylesheet, so keep them in step |
3823
+ | Peer | `@jungherz-de/notionkit >= 1.16.0` – from 1.5.0 on the elements and the foundation share one version number; the bundle embeds that release's stylesheet, so keep them in step |
3822
3824
 
3823
3825
  Lifecycle: construct (attach shadow, adopt sheets) → first connect (wrapper + `render()`) → every connect (`setupEvents()`, theme registration, light-DOM observer) → `attributeChangedCallback` → `onAttributeChanged` → disconnect (`teardownEvents()`, unregister).
3824
3826
 
3825
3827
 
3826
3828
  ---
3827
- *NotionKit Elements v1.15.0 · wrapping NotionKit CSS v1.15.0 · MIT · Jungherz GmbH*
3829
+ *NotionKit Elements v1.16.0 · wrapping NotionKit CSS v1.16.0 · MIT · Jungherz GmbH*
@@ -61,6 +61,9 @@ if (typeof window !== 'undefined' && typeof MutationObserver !== 'undefined') {
61
61
  // Layout plumbing only: how the host box participates in the outer layout, and
62
62
  // that `hidden` keeps working. :host([hidden]) has a higher specificity than
63
63
  // :host, so it wins regardless of order. The wrapper is layout-transparent.
64
+ // `flush` on any element drops the outer margin of its box (NotionKit
65
+ // 1.16.0) – for a block in a flex column with a gap of its own; a whole
66
+ // column does it for every block with --nk-block-space: 0.
64
67
 
65
68
  const hostSheets = new Map();
66
69
 
@@ -71,6 +74,7 @@ function hostSheetFor(display) {
71
74
  sheet.replaceSync(`
72
75
  :host { display: ${display}; }
73
76
  :host([hidden]) { display: none; }
77
+ :host([flush]) .nk-wrapper > * { margin-top: 0; margin-bottom: 0; }
74
78
  .nk-wrapper { display: contents; }
75
79
  `);
76
80
  hostSheets.set(display, sheet);
@@ -1,7 +1,7 @@
1
1
  import { NkFormElement } from './base.js';
2
2
  import { p as parseDay, i as isoOf, C as CHEVRONS, r as resolveLocale, f as firstWeekday, m as monthGrid, w as weekLabel, a as weekdayNames, b as isoWeek, s as stepMonth, c as addDays } from './shared/dates-a32DcW1l.js';
3
3
  import { p as placeUnder } from './shared/floating-DOK73b_D.js';
4
- import { d as deepActiveElement } from './shared/focus-BNAChOXO.js';
4
+ import { d as deepActiveElement } from './shared/focus-C4tbSNND.js';
5
5
  import '@jungherz-de/notionkit/notionkit-styles.js';
6
6
 
7
7
  // <nk-calendar name="due" value="2026-06-02" weeks weekend="6,0"></nk-calendar>
@@ -44,7 +44,7 @@ import '@jungherz-de/notionkit/notionkit-styles.js';
44
44
  // outside does. Put a floating calendar directly under <body>.
45
45
  const STEPS = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 };
46
46
  const floatSheet = new CSSStyleSheet();
47
- floatSheet.replaceSync(`:host([floating]) { display: block; position: fixed; top: 0; left: 0; z-index: 60; pointer-events: none; }`);
47
+ floatSheet.replaceSync(`:host([floating]) { display: block; position: fixed; top: 0; left: 0; z-index: 106; pointer-events: none; }`);
48
48
 
49
49
  class NkCalendar extends NkFormElement {
50
50
  static get hostStyles() { return floatSheet; }
@@ -1,5 +1,5 @@
1
1
  import { NkElement } from './base.js';
2
- import { l as lockScroll, i as inertOutside, u as unlockScroll } from './shared/focus-BNAChOXO.js';
2
+ import { l as lockScroll, i as inertOutside, u as unlockScroll } from './shared/focus-C4tbSNND.js';
3
3
  import '@jungherz-de/notionkit/notionkit-styles.js';
4
4
 
5
5
  // Subsequence scoring for the command palette: every query character must
@@ -1,5 +1,5 @@
1
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';
2
+ import { d as deepActiveElement, l as lockScroll, i as inertOutside, f as firstFocusable, u as unlockScroll } from './shared/focus-C4tbSNND.js';
3
3
  import '@jungherz-de/notionkit/notionkit-styles.js';
4
4
 
5
5
  // <nk-dialog id="trash" title="Move “Roadmap” to trash?" alert>
@@ -1,5 +1,5 @@
1
1
  import { NkElement } from './base.js';
2
- import { d as deepActiveElement } from './shared/focus-BNAChOXO.js';
2
+ import { d as deepActiveElement } from './shared/focus-C4tbSNND.js';
3
3
  import { p as placeUnder } from './shared/floating-DOK73b_D.js';
4
4
  import '@jungherz-de/notionkit/notionkit-styles.js';
5
5
 
@@ -20,7 +20,7 @@ import '@jungherz-de/notionkit/notionkit-styles.js';
20
20
  // close it too, a switch row does not. Opened from the keyboard, focus moves
21
21
  // to the first item; closing returns it to where it was.
22
22
  const floatSheet = new CSSStyleSheet();
23
- floatSheet.replaceSync(`:host([floating]) { display: block; position: fixed; top: 0; left: 0; z-index: 60; pointer-events: none; }`);
23
+ floatSheet.replaceSync(`:host([floating]) { display: block; position: fixed; top: 0; left: 0; z-index: 106; pointer-events: none; }`);
24
24
 
25
25
  class NkMenu extends NkElement {
26
26
  static get hostStyles() { return floatSheet; }
@@ -1,5 +1,5 @@
1
1
  import { NkElement } from './base.js';
2
- import { l as lockScroll, i as inertOutside, f as firstFocusable, u as unlockScroll } from './shared/focus-BNAChOXO.js';
2
+ import { l as lockScroll, i as inertOutside, f as firstFocusable, u as unlockScroll } from './shared/focus-C4tbSNND.js';
3
3
  import '@jungherz-de/notionkit/notionkit-styles.js';
4
4
 
5
5
  // <nk-modal id="settings">
@@ -43,7 +43,10 @@ class NkPanel extends NkElement {
43
43
  const href = this.getAttribute('href');
44
44
  if (href) { this._box.setAttribute('href', href); this._box.target = this.getAttribute('target') || ''; }
45
45
  const cover = this.getAttribute('cover');
46
- this._cover.style.display = cover === null ? 'none' : '';
46
+ // The band is in the tree only with `cover`: hidden, it still matched
47
+ // `.nk-cover + .nk-page-icon` and pulled a lone icon over the tile's edge.
48
+ if (cover === null) this._cover.remove();
49
+ else if (!this._cover.isConnected) this._box.prepend(this._cover);
47
50
  if (cover) { this._img.src = cover; if (!this._img.isConnected) this._cover.appendChild(this._img); }
48
51
  else this._img.remove();
49
52
  const icon = this.getAttribute('icon');
@@ -1,5 +1,5 @@
1
1
  import { NkElement } from './base.js';
2
- import { d as deepActiveElement, l as lockScroll, i as inertOutside, u as unlockScroll } from './shared/focus-BNAChOXO.js';
2
+ import { d as deepActiveElement, l as lockScroll, i as inertOutside, u as unlockScroll } from './shared/focus-C4tbSNND.js';
3
3
  import '@jungherz-de/notionkit/notionkit-styles.js';
4
4
 
5
5
  // <nk-peek id="peek" label="Database Table-View">
@@ -9,8 +9,10 @@ import '@jungherz-de/notionkit/notionkit-styles.js';
9
9
  // The light-DOM <option>s are copied into the shadow <select>. A
10
10
  // MutationObserver keeps the copy in step when a framework swaps them; the
11
11
  // empty string is a valid value; the live selection survives a rebuild. A
12
- // value set before its option exists – a framework sets properties before
13
- // children – waits and is applied once the option arrives.
12
+ // value – attribute or property – whose option is not there yet waits and
13
+ // wins over the browser's preselection once the option arrives, unless
14
+ // someone has chosen another option in the meantime; settling on it fires
15
+ // no nk-change.
14
16
  class NkSelect extends NkFormElement {
15
17
  static get observedAttributes() { return ['value', 'name', 'disabled', 'required', 'compact', 'wide', 'aria-label']; }
16
18
  static get observesLightDom() { return true; }
@@ -20,6 +22,7 @@ class NkSelect extends NkFormElement {
20
22
  this._forwardAll();
21
23
  this._wrapper.appendChild(this._select);
22
24
  this._defaultValue = this.getAttribute('value');
25
+ this._pending = this._defaultValue;
23
26
  // Children may not be parsed yet when connectedCallback runs.
24
27
  this.projectLightDom();
25
28
  requestAnimationFrame(() => this.projectLightDom());
@@ -53,11 +56,11 @@ class NkSelect extends NkFormElement {
53
56
  this._select.innerHTML = '';
54
57
  for (const node of nodes) this._select.appendChild(node.cloneNode(true));
55
58
 
56
- // A value that waited for its option first; then the live selection when
57
- // it survived; otherwise the value attribute; otherwise the browser
58
- // default (first option / `selected`).
59
- if (this._pending != null && this._applyValue(this._pending)) this._pending = null;
60
- else if (!this._applyValue(previous)) this._applyValue(this.getAttribute('value'));
59
+ // A value that waits for its option first – it keeps waiting while the
60
+ // option is missing; else the live selection when it survived; else the
61
+ // browser default (first option / `selected`).
62
+ if (this._pending != null) { if (this._applyValue(this._pending)) this._pending = null; }
63
+ else this._applyValue(previous);
61
64
  this._syncFormValue();
62
65
  }
63
66
 
@@ -86,7 +89,8 @@ class NkSelect extends NkFormElement {
86
89
  onAttributeChanged(name) {
87
90
  if (!this._select) return;
88
91
  if (name === 'value') {
89
- this._applyValue(this.getAttribute('value'));
92
+ const value = this.getAttribute('value');
93
+ this._pending = value === null || this._applyValue(value) ? null : value;
90
94
  this._syncFormValue();
91
95
  return;
92
96
  }
@@ -100,6 +104,7 @@ class NkSelect extends NkFormElement {
100
104
  }
101
105
 
102
106
  resetValue() {
107
+ this._pending = null;
103
108
  if (!this._applyValue(this._defaultValue)) this._select.selectedIndex = 0;
104
109
  this._syncFormValue();
105
110
  }
@@ -1,5 +1,5 @@
1
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';
2
+ import { d as deepActiveElement, l as lockScroll, i as inertOutside, f as firstFocusable, u as unlockScroll } from './shared/focus-C4tbSNND.js';
3
3
  import '@jungherz-de/notionkit/notionkit-styles.js';
4
4
 
5
5
  // <nk-sheet id="more" title="More">
@@ -1,5 +1,5 @@
1
1
  import { NkElement } from './base.js';
2
- import { d as deepActiveElement } from './shared/focus-BNAChOXO.js';
2
+ import { d as deepActiveElement } from './shared/focus-C4tbSNND.js';
3
3
  import '@jungherz-de/notionkit/notionkit-styles.js';
4
4
 
5
5
  // <nk-sidebar slot="sidebar">
@@ -1,6 +1,6 @@
1
1
  import { NkElement } from './base.js';
2
2
  import { a as placeNear } from './shared/floating-DOK73b_D.js';
3
- import { d as deepActiveElement } from './shared/focus-BNAChOXO.js';
3
+ import { d as deepActiveElement } from './shared/focus-C4tbSNND.js';
4
4
  import '@jungherz-de/notionkit/notionkit-styles.js';
5
5
 
6
6
  // <nk-tooltip></nk-tooltip> one for the page: every [data-tooltip]
@@ -15,7 +15,12 @@ function unlockScroll() {
15
15
  if (locks > 0 && --locks === 0) document.documentElement.style.overflow = previousOverflow;
16
16
  }
17
17
 
18
- /** Makes every sibling along `el`'s ancestor chain inert (shadow hosts included); returns the undo. */
18
+ // Floating layers under <body> that open from inside an overlay – a menu, a
19
+ // date picker – and the tooltip and toast stay usable: made inert, a date
20
+ // picker opened from a dialog showed but took no click.
21
+ const LAYERS = 'nk-menu[floating], nk-calendar[floating], nk-tooltip, nk-toast';
22
+
23
+ /** Makes every sibling along `el`'s ancestor chain inert (shadow hosts included), floating layers aside; returns the undo. */
19
24
  function inertOutside(el) {
20
25
  const made = [];
21
26
  let node = el;
@@ -23,7 +28,7 @@ function inertOutside(el) {
23
28
  const parent = node.parentNode instanceof ShadowRoot ? node.parentNode : node.parentNode;
24
29
  if (!parent) break;
25
30
  for (const sib of parent.children) {
26
- if (sib === node || sib.inert || /^(SCRIPT|STYLE|LINK|TEMPLATE)$/.test(sib.tagName)) continue;
31
+ if (sib === node || sib.inert || /^(SCRIPT|STYLE|LINK|TEMPLATE)$/.test(sib.tagName) || sib.matches(LAYERS)) continue;
27
32
  sib.inert = true;
28
33
  made.push(sib);
29
34
  }