@jungherz-de/notionkit-elements 1.16.0 → 1.17.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +64 -6
  3. package/SKILL.md +59 -53
  4. package/dist/components/base.js +102 -3
  5. package/dist/components/nk-ai-input-row.js +6 -3
  6. package/dist/components/nk-board-view.js +2 -2
  7. package/dist/components/nk-breadcrumb.js +2 -1
  8. package/dist/components/nk-calendar-view.js +8 -5
  9. package/dist/components/nk-calendar.js +10 -7
  10. package/dist/components/nk-cmdk.js +6 -2
  11. package/dist/components/nk-comments.js +5 -3
  12. package/dist/components/nk-copy-field.js +6 -3
  13. package/dist/components/nk-emoji-picker.js +6 -2
  14. package/dist/components/nk-filter-bar.js +10 -8
  15. package/dist/components/nk-gallery-view.js +29 -7
  16. package/dist/components/nk-image-picker.js +7 -3
  17. package/dist/components/nk-list-view.js +3 -2
  18. package/dist/components/nk-modal.js +3 -1
  19. package/dist/components/nk-page-title.js +2 -1
  20. package/dist/components/nk-page.js +3 -1
  21. package/dist/components/nk-peek.js +6 -3
  22. package/dist/components/nk-sidebar.js +5 -2
  23. package/dist/components/nk-steps.js +20 -4
  24. package/dist/components/nk-synced.js +2 -1
  25. package/dist/components/nk-table-view.js +3 -2
  26. package/dist/components/nk-theme-toggle.js +5 -2
  27. package/dist/components/nk-tree-item.js +3 -1
  28. package/dist/components/shared/{property-cell-BSVcETss.js → property-cell-DcsfnUNF.js} +15 -5
  29. package/dist/notionkit-elements.esm.js +265 -70
  30. package/dist/notionkit-elements.esm.min.js +1 -1
  31. package/dist/notionkit-elements.esm.min.js.map +1 -1
  32. package/dist/notionkit-elements.js +267 -69
  33. package/dist/notionkit-elements.min.js +1 -1
  34. package/package.json +3 -3
  35. package/src/base.js +32 -2
  36. package/src/components/data/nk-ai-input-row.js +6 -3
  37. package/src/components/data/nk-board-view.js +2 -2
  38. package/src/components/data/nk-calendar-view.js +7 -4
  39. package/src/components/data/nk-comments.js +5 -3
  40. package/src/components/data/nk-filter-bar.js +10 -8
  41. package/src/components/data/nk-gallery-view.js +29 -7
  42. package/src/components/data/nk-list-view.js +2 -1
  43. package/src/components/data/nk-table-view.js +2 -1
  44. package/src/components/forms/nk-calendar.js +10 -7
  45. package/src/components/forms/nk-copy-field.js +6 -3
  46. package/src/components/forms/nk-image-picker.js +7 -3
  47. package/src/components/overlays/nk-cmdk.js +6 -2
  48. package/src/components/overlays/nk-emoji-picker.js +6 -2
  49. package/src/components/overlays/nk-modal.js +3 -1
  50. package/src/components/overlays/nk-peek.js +6 -3
  51. package/src/components/page/nk-page-title.js +2 -1
  52. package/src/components/page/nk-page.js +3 -1
  53. package/src/components/page/nk-steps.js +20 -4
  54. package/src/components/page/nk-synced.js +2 -1
  55. package/src/components/shell/nk-breadcrumb.js +2 -1
  56. package/src/components/shell/nk-sidebar.js +5 -2
  57. package/src/components/shell/nk-theme-toggle.js +5 -2
  58. package/src/components/shell/nk-tree-item.js +3 -1
  59. package/src/index.js +5 -1
  60. package/src/util/property-cell.js +14 -4
  61. package/src/util/strings.js +73 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ 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.17.0] – 2026-09-25
8
+
9
+ Built against NotionKit CSS 1.17.0 (peer `>= 1.17.0`). The rest of LearnHub's consolidated list: German texts in the elements (finding 9) and steps and gallery cards as links (6 and 16), under one link contract. Additive – with `lang="en"` every text stays as it was.
10
+
11
+ ### Added
12
+ - **The elements speak English and German.** Button labels, placeholders and the names a screen reader announces – 38 texts, from Copy, Today and + New page to the names of the palette and the modal – come from a dictionary after the element's language: its nearest `lang` attribute, across shadow roots, else `<html lang>`. `de`, `de-DE` or `de-AT` give German, everything else English. An attribute on the element still wins, so a label with a meaning of its own stays. The fixed accessible names – Message, Send, Breadcrumb, Command palette, Comment, Search emoji, Settings, Title, Change icon – come from the same dictionary; before, they could not be changed at all. README lists every key with its attribute, English and German.
13
+ - **`setStrings(strings, lang?)` and `builtInStrings(lang)`**, from the bundle and from `base.js`: add or replace texts for every language or for one – a language of its own too. The elements on the page take them at once, and again when `<html lang>` changes.
14
+ - **`this.str(key)` and `onStringsChanged()` on `NkElement`**: a project's own element reads the dictionary in its language, its own keys too, and applies new texts when they change.
15
+ - **Percentages as `Intl` writes them.** A progress cell, a board card and a gallery card write 45 as `45%` in English and `45 %` in German, with a no-break space – the column's `locale` first, else the page's language. `formatPercent(column, value)` is exported beside `formatDate()`.
16
+ - **`<nk-steps>`: a step with `href` is a link.** Its label becomes `<a class="st-label" href>`, with or without `selectable`, and opens in a new tab with a middle click or offers "Copy link" – for chapters whose addresses are shared. Steps without `href` stay buttons.
17
+ - **`<nk-gallery-view href-key>`: cards as links.** `href-key` names the row field with a card's address – a string or `{ href }`. Such a card is `<a class="nk-card" href>` in a `.card-item` that carries `role="listitem"`; rows without an address and galleries without `href-key` stay as they were.
18
+ - **The link contract, for both:** a plain left click and Enter fire the cancelable `nk-select` as before – `{ index, value, step }` and `{ row, id, value }`; cancel it and the browser stays, for a router of your own, otherwise it follows the link (and a step becomes current). A middle click or one with Cmd, Ctrl, Shift or Alt fires nothing and does what a link does; Space on a link card scrolls, like on any link. The mark beside a step's link counts as the link.
19
+
20
+ ### Changed
21
+ - **The German demo sets no text attributes any more.** `de/app.html` takes Kopieren, Heute, Seitenleiste schließen and the others from `<html lang="de">`; `app.html` dropped the English ones it only carried to be translated. The docs have a Languages section, show the defaults of text attributes in both languages and write percentages and the new-row text in the page's language.
22
+
7
23
  ## [1.16.0] – 2026-09-25
8
24
 
9
25
  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.
@@ -702,6 +718,7 @@ built and tested against NotionKit CSS 1.1.1 (peer range `>= 1.0.0`).
702
718
  import, never in the core bundle – shadow-less, adding `nk-block-host` to
703
719
  itself so the foundation's editor adapter rules apply.
704
720
 
721
+ [1.17.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.17.0
705
722
  [1.16.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.16.0
706
723
  [1.15.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.15.0
707
724
  [1.14.0]: https://github.com/JUNGHERZ/NotionKit-Elements/releases/tag/v1.14.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.16.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.17.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.16.0-lightgrey?style=flat-square" alt="Changelog"></a>
8
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-v1.17.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,7 +59,7 @@ 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** | 281 KB minified / 56 KB gzipped (IIFE, foundation sheet included), no external dependencies |
62
+ | 🪶 **Lightweight** | 286 KB minified / 57 KB gzipped (IIFE, foundation sheet included), no external dependencies |
63
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
 
@@ -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.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>
74
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
75
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.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">
@@ -104,7 +104,7 @@ Without a build step, an import map can point at the minified module instead: `"
104
104
 
105
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).
106
106
 
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.
107
+ Two prerequisites, always: `notionkit.css` on the document (the peer dependency, `>= 1.17.0`; 1.17.0 brings a step's label and a gallery card as links, 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.
108
108
 
109
109
  ## Elements
110
110
 
@@ -119,6 +119,64 @@ Two prerequisites, always: `notionkit.css` on the document (the peer dependency,
119
119
 
120
120
  Static content goes in through attributes and slots, dynamic data through properties (`tree.data`, `database.rows`, `palette.commands`). Interactions fire custom events with fixed names: `nk-select`, `nk-change`, `nk-view-change`, `nk-command`, `nk-toggle`, `nk-submit`, `nk-action`. No fetching, no two-way binding – the elements render what they get.
121
121
 
122
+ ## Languages
123
+
124
+ The texts the elements bring along – button labels, placeholders and the names a screen reader announces – come in English and German. The language is the element's own: its nearest `lang` attribute, across shadow roots, else `<html lang>`; `de`, `de-DE` or `de-AT` give German, everything else English. An attribute on the element still wins, so a label with a meaning of its own stays (`choose-label="Upload logo"`).
125
+
126
+ ```js
127
+ import { setStrings, builtInStrings } from '@jungherz-de/notionkit-elements'; // or from '…/base.js' with single elements
128
+ setStrings({ newPage: '+ New course' }); // every language
129
+ setStrings({ copy: 'Copier', close: 'Fermer' }, 'fr'); // a language of its own
130
+ builtInStrings('de'); // the keys and the German texts, a copy
131
+ ```
132
+
133
+ The elements on the page take new texts at once, after `setStrings()` and when `<html lang>` changes. An element of your own built on `NkElement` reads the same dictionary with `this.str('key')` – your keys too – and applies it again in `onStringsChanged()`. Percentages follow the language as well: a progress value of 45 reads `45%` in English and `45 %` in German, with a no-break space, as `Intl.NumberFormat` writes it (a column's `locale` first). Dates and month names already did.
134
+
135
+ | Key | Element | Attribute | English | German |
136
+ |---|---|---|---|---|
137
+ | `copy` | `nk-copy-field` | `copy-label` | Copy | Kopieren |
138
+ | `copied` | `nk-copy-field` | `copied-label` | Copied | Kopiert |
139
+ | `show` | `nk-copy-field` | `show-label` | Show | Zeigen |
140
+ | `hide` | `nk-copy-field` | `hide-label` | Hide | Verbergen |
141
+ | `uploadImage` | `nk-image-picker` | `choose-label` | Upload image | Bild hochladen |
142
+ | `changeImage` | `nk-image-picker` | `change-label` | Change image | Bild ändern |
143
+ | `remove` | `nk-image-picker` | `remove-label` | Remove | Entfernen |
144
+ | `close` | `nk-peek` | `close-label` | Close | Schließen |
145
+ | `resize` | `nk-peek` | `resize-label` | Resize | Breite ändern |
146
+ | `today` | `nk-calendar`, `nk-calendar-view` | `today-label` | Today | Heute |
147
+ | `previousMonth` | `nk-calendar`, `nk-calendar-view` | `prev-label` | Previous month | Voriger Monat |
148
+ | `nextMonth` | `nk-calendar`, `nk-calendar-view` | `next-label` | Next month | Nächster Monat |
149
+ | `clear` | `nk-calendar` | `clear-label` | Clear | Leeren |
150
+ | `time` | `nk-calendar` | `time-label` | Time | Uhrzeit |
151
+ | `filter` | `nk-filter-bar` | `filter-label` | Filter | Filter |
152
+ | `sort` | `nk-filter-bar` | `sort-label` | Sort | Sortieren |
153
+ | `addFilter` | `nk-filter-bar` | `add-label` | + Filter | + Filter |
154
+ | `removeFilter` | `nk-filter-bar` | `remove-label` | Remove filter | Filter entfernen |
155
+ | `search` | `nk-filter-bar` | `placeholder` | Search … | Suchen … |
156
+ | `closeSidebar` | `nk-sidebar` | `collapse-label` | Close sidebar | Seitenleiste schließen |
157
+ | `newPage` | `nk-table-view`, `nk-list-view`, `nk-gallery-view` | `new-row-label` | + New page | + Neue Seite |
158
+ | `commentPlaceholder` | `nk-comments` | `placeholder` | Comment … | Kommentieren … |
159
+ | `send` | `nk-comments`, `nk-ai-input-row` | `send-label` (comments) | Send | Senden |
160
+ | `askPlaceholder` | `nk-ai-input-row` | `placeholder` | Ask something … | Frag etwas … |
161
+ | `commandPlaceholder` | `nk-cmdk` | `placeholder` | Search or type a command … | Suchen oder Befehl eingeben … |
162
+ | `emojiPlaceholder` | `nk-emoji-picker` | `placeholder` | Search… | Suchen … |
163
+ | `toggleTheme` | `nk-theme-toggle` | `title` | Toggle light / dark | Hell / Dunkel |
164
+ | `synced` | `nk-synced` | `badge` | ⟳ synced | ⟳ synchronisiert |
165
+ | `message` | `nk-ai-input-row` | – | Message | Nachricht |
166
+ | `comment` | `nk-comments` | – | Comment | Kommentar |
167
+ | `commandPalette` | `nk-cmdk` | – | Command palette | Befehlspalette |
168
+ | `searchEmoji` | `nk-emoji-picker` | – | Search emoji | Emoji suchen |
169
+ | `settings` | `nk-modal` | – | Settings | Einstellungen |
170
+ | `title` | `nk-page-title` (editable) | – | Title | Titel |
171
+ | `changeIcon` | `nk-page` | – | Change icon | Symbol ändern |
172
+ | `breadcrumb` | `nk-breadcrumb` | – | Breadcrumb | Pfad |
173
+ | `add` | `nk-tree-item` | – | Add | Hinzufügen |
174
+ | `more` | `nk-tree-item` | – | More | Mehr |
175
+
176
+ ## Links
177
+
178
+ A step of `<nk-steps>` with `href` and a card of `<nk-gallery-view>` whose row has an address in the field named by `href-key` are real links: they open in a new tab with a middle click and offer "Copy link" in the context menu. A plain left click, and Enter, fire the cancelable `nk-select` as before; cancel it and the browser stays, for a router of your own. A middle click or one with Cmd, Ctrl, Shift or Alt fires nothing and does what a link does. Steps and rows without an address stay buttons and cards.
179
+
122
180
  ## How it works
123
181
 
124
182
  - Each element's shadow root adopts the NotionKit **components** sheet only; tokens are inherited from the document. A `.nk-wrapper` inside the root mirrors `data-theme` from `<html>` – one observer for all instances.
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.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.
3
+ description: NotionKit Elements is a vanilla-JS Web Components library (v1.17.0) wrapping NotionKit CSS v1.17.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.16.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.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>
24
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
25
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.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>
@@ -72,6 +72,8 @@ Never mix the full bundle with the per-component files – each brings its own `
72
72
  | Light-DOM children | Elements that copy children (`nk-select` options, breadcrumb crumbs) watch them; `element.refresh()` is the escape hatch. The empty string is a valid value. |
73
73
  | Moving elements | An element moved in the DOM keeps working – listeners and theme registration are re-armed on every connect. |
74
74
  | Attributes are live | Every documented attribute re-renders when changed after connect (`stat.setAttribute('value', '129')`, `el.open = true`); properties reflect to attributes where a setter is listed. |
75
+ | Language | The texts an element brings along – button labels, placeholders, accessible names – come in English and German after its nearest `lang` (across shadow roots), else `<html lang>`. An attribute on the element wins. `setStrings({ key: '…' }, lang?)` adds or replaces texts, and the elements on the page take them at once; your own `NkElement` reads them with `this.str('key')`. Percentages follow as `Intl` writes them (`45 %` in German). |
76
+ | Links | A step of `nk-steps` with `href` and a card of `nk-gallery-view` whose row has an address (`href-key`) are real `<a href>`: a middle click opens a new tab, the context menu copies the link. A plain click or Enter fires the cancelable `nk-select` – cancel it to route yourself; middle and modified clicks fire nothing. |
75
77
 
76
78
 
77
79
  # 3. Element Catalog (88 elements)
@@ -160,10 +162,10 @@ A value to take along – a link, an address, a key – as tall as an input, wit
160
162
  | `mono` | boolean | – | Monospace – addresses, keys, code. |
161
163
  | `wrap` | boolean | – | A long value breaks instead of an ellipsis. |
162
164
  | `wide` | boolean | – | Fills the row. |
163
- | `copy-label` | string | `Copy` | Button text. |
164
- | `copied-label` | string | `Copied` | Text for the moment after. |
165
- | `show-label` | string | `Show` | Reveal (secret). |
166
- | `hide-label` | string | `Hide` | Mask again. |
165
+ | `copy-label` | string | `Copy · Kopieren` | Button text. |
166
+ | `copied-label` | string | `Copied · Kopiert` | Text for the moment after. |
167
+ | `show-label` | string | `Show · Zeigen` | Reveal (secret). |
168
+ | `hide-label` | string | `Hide · Verbergen` | Mask again. |
167
169
 
168
170
  **Events:** `nk-action` `{ action: 'copy', value, ok }` – Copy clicked; `ok` is false where the clipboard refused.
169
171
 
@@ -198,9 +200,9 @@ A picture for a person or a workspace, on NotionKit’s profile row: round, or `
198
200
  | `quality` | 0–1 | `0.82` | JPEG / WebP quality. |
199
201
  | `accept` | string | `image/*` | File dialog filter. |
200
202
  | `label` | string | – | Names the group. |
201
- | `choose-label` | string | `Upload image` | Without a picture. |
202
- | `change-label` | string | `Change image` | With a picture. |
203
- | `remove-label` | string | `Remove` | Remove button. |
203
+ | `choose-label` | string | `Upload image · Bild hochladen` | Without a picture. |
204
+ | `change-label` | string | `Change image · Bild ändern` | With a picture. |
205
+ | `remove-label` | string | `Remove · Entfernen` | Remove button. |
204
206
 
205
207
  **Events:** `nk-change` `{ dataUrl, width, height, size }` – A picture chosen – or removed, with an empty dataUrl. · `nk-error` `{ message, name }` – The file cannot be decoded.
206
208
 
@@ -247,12 +249,12 @@ Notion’s date picker as one element (NotionKit 1.9.0): a month with Today and
247
249
  | `open` | boolean | – | Floating: shown. |
248
250
  | `align` | end | start | `end` | Floating: right or left edge on the anchor’s. |
249
251
  | `label` | string | – | Names the month group for screen readers. |
250
- | `today-label` | string | `Today` | Today button. |
251
- | `prev-label` | string | `Previous month` | Names ‹. |
252
- | `next-label` | string | `Next month` | Names ›. |
252
+ | `today-label` | string | `Today · Heute` | Today button. |
253
+ | `prev-label` | string | `Previous month · Voriger Monat` | Names ‹. |
254
+ | `next-label` | string | `Next month · Nächster Monat` | Names ›. |
253
255
  | `week-label` | string | `W · KW` | Head of the week column. |
254
- | `time-label` | string | `Time` | Names the time field. |
255
- | `clear-label` | string | `Clear` | Clear button. |
256
+ | `time-label` | string | `Time · Uhrzeit` | Names the time field. |
257
+ | `clear-label` | string | `Clear · Leeren` | Clear button. |
256
258
  | `name` | string | – | Form field name (FormData key). |
257
259
  | `disabled` | boolean | – | Disables the control. |
258
260
  | `required` | boolean | – | A value is required; validity is set on the host. |
@@ -938,7 +940,7 @@ The left rail: workspace slot on top, a scrolling default slot for the tree, a p
938
940
  | `open` | boolean | – | Drawer state on small screens (no effect on desktop). |
939
941
  | `collapsible` | boolean | – | Shows the « that collapses it on the desktop, and ⌘\. |
940
942
  | `collapsed` | boolean | – | Collapsed on the desktop (no effect on a phone). |
941
- | `collapse-label` | string | `Close sidebar` | Name and tooltip of the «. |
943
+ | `collapse-label` | string | `Close sidebar · Seitenleiste schließen` | Name and tooltip of the «. |
942
944
 
943
945
  **Slots:** `workspace` – `nk-workspace-switcher`. · `(default)` – The tree (scrolls). · `footer` – Pinned bottom rows (Settings, Trash).
944
946
 
@@ -1624,7 +1626,7 @@ Content that appears in several places, framed with a badge.
1624
1626
 
1625
1627
  | Attribute | Type | Default | Description |
1626
1628
  |---|---|---|---|
1627
- | `badge` | string | `⟳ synced` | Badge text. |
1629
+ | `badge` | string | `⟳ synced · ⟳ synchronisiert` | Badge text. |
1628
1630
 
1629
1631
  **Slots:** `(default)` – Content.
1630
1632
 
@@ -1739,13 +1741,13 @@ Plain `<button value>` children stay in the light DOM (the stylesheet’s slotte
1739
1741
 
1740
1742
  ### 3.52 `<nk-steps>` – Steps
1741
1743
 
1742
- A short flow – connecting an account, setting up a model – calm and vertical: a numbered circle per step joined by a hairline, done steps with a check on the green tag, the current one ringed in the accent and marked `aria-current="step"`. `current` counts from 1; one past the last marks every step done, and `next()` moves on. The `steps` attribute is a comma-separated list; the property also takes `{ label, desc }` objects for a line under the label. A `state` in such an object – `done`, `skipped` or `open` – wins over the order, for a wizard that lets a step be skipped while a later one is done; a skipped step shows a dashed ring around a dash. `selectable` makes each label a button: a click or Enter fires `nk-select { index, value, step }` – `index` counts from 1, like `current` – and, unless cancelled, makes that step current. `horizontal` sets the steps in one row above a wizard.
1744
+ A short flow – connecting an account, setting up a model – calm and vertical: a numbered circle per step joined by a hairline, done steps with a check on the green tag, the current one ringed in the accent and marked `aria-current="step"`. `current` counts from 1; one past the last marks every step done, and `next()` moves on. The `steps` attribute is a comma-separated list; the property also takes `{ label, desc }` objects for a line under the label. A `state` in such an object – `done`, `skipped` or `open` – wins over the order, for a wizard that lets a step be skipped while a later one is done; a skipped step shows a dashed ring around a dash. `selectable` makes each label a button: a click or Enter fires `nk-select { index, value, step }` – `index` counts from 1, like `current` – and, unless cancelled, makes that step current. A step with `href` shows its label as a link, with or without `selectable` – to open a chapter in a new tab or copy its address. A plain click, and Enter, fire the same `nk-select`; cancel it and the browser stays, for a router of your own. A middle click or one with Cmd, Ctrl, Shift or Alt fires nothing and does what a link does. `horizontal` sets the steps in one row above a wizard.
1743
1745
 
1744
1746
  ```html
1745
1747
  <nk-steps label="Connect your own model" current="2"></nk-steps>
1746
1748
  <script>{ document.currentScript.previousElementSibling.steps = [{ label: 'Choose a provider', desc: 'Anthropic' }, 'Enter the API key', 'Test the connection']; }</script>
1747
1749
  <div style="margin-top:16px"><nk-steps id="stepsWizard" label="Connect your own model" current="3" horizontal selectable></nk-steps></div>
1748
- <script>{ document.getElementById('stepsWizard').steps = [{ label: 'Choose a provider', state: 'done' }, { label: 'Enter the API key', desc: 'skipped', state: 'skipped' }, 'Test the connection']; }</script>
1750
+ <script>{ document.getElementById('stepsWizard').steps = [{ label: 'Choose a provider', state: 'done', href: '#nk-steps' }, { label: 'Enter the API key', desc: 'skipped', state: 'skipped' }, 'Test the connection']; }</script>
1749
1751
  ```
1750
1752
 
1751
1753
  | Attribute | Type | Default | Description |
@@ -1756,7 +1758,7 @@ A short flow – connecting an account, setting up a model – calm and vertical
1756
1758
  | `selectable` | boolean | – | Labels are buttons that jump to their step. |
1757
1759
  | `horizontal` | boolean | – | One row above a wizard. |
1758
1760
 
1759
- **Events:** `nk-select` `{ index, value, step }` – A step clicked (with `selectable`); cancel it to stay.
1761
+ **Events:** `nk-select` `{ index, value, step }` – A step clicked (with `selectable`, or its link with a plain click or Enter); cancel it to stay.
1760
1762
 
1761
1763
  **Properties:** `steps`, `current`, `selectable`, `horizontal` · **Methods:** `next()`, `select(index)`
1762
1764
 
@@ -1770,7 +1772,7 @@ A short flow – connecting an account, setting up a model – calm and vertical
1770
1772
  <li class="nk-step"><span class="st-mark">3</span><span>Test the connection</span></li>
1771
1773
  </ol>
1772
1774
  <div style="margin-top:16px"><ol class="nk-steps horizontal" aria-label="Connect your own model">
1773
- <li class="nk-step done"><span class="st-mark">✓</span><button type="button" class="st-label">Choose a provider</button></li>
1775
+ <li class="nk-step done"><span class="st-mark">✓</span><a class="st-label" href="#nk-steps">Choose a provider</a></li>
1774
1776
  <li class="nk-step skipped"><span class="st-mark">–</span><button type="button" class="st-label">Enter the API key<span class="st-desc">skipped</span></button></li>
1775
1777
  <li class="nk-step current" aria-current="step"><span class="st-mark">3</span><button type="button" class="st-label">Test the connection</button></li>
1776
1778
  </ol></div>
@@ -2205,12 +2207,12 @@ Notion’s side peek: a database row opens at the right edge, full height, next
2205
2207
  |---|---|---|---|
2206
2208
  | `open` | boolean | – | Shown. |
2207
2209
  | `label` | string | – | The dialog’s name – the entry’s title. |
2208
- | `close-label` | string | `Close` | Name of ». |
2210
+ | `close-label` | string | `Close · Schließen` | Name of ». |
2209
2211
  | `resizable` | boolean | – | The left edge makes it wider or narrower – pointer and arrow keys; the width is the token `--nk-peek-width` on `:root`. |
2210
2212
  | `width` | px | `560` | Sets the width, within min and max. |
2211
2213
  | `min` | px | `380` | Narrowest. |
2212
2214
  | `max` | px | `window − 320` | Widest. |
2213
- | `resize-label` | string | `Resize` | Name of the edge. |
2215
+ | `resize-label` | string | `Resize · Breite ändern` | Name of the edge. |
2214
2216
  | `inset` | boolean | – | While open on the desktop, the page’s `nk-app` makes room instead of lying under it – for a chart whose bars must stay visible. |
2215
2217
 
2216
2218
  **Slots:** `(default)` – The page: title, properties, prose, comments. · `actions` – Buttons beside » – open as page, share.
@@ -2682,7 +2684,7 @@ Renders `columns` × `rows` as the NotionKit table. Cells are polymorphic (`text
2682
2684
  | `badge` | string | – | Tab badge. |
2683
2685
  | `count` | boolean | – | Row count as badge. |
2684
2686
  | `new-row` | boolean | – | Show the add row. |
2685
- | `new-row-label` | string | `+ New page` | Its text. |
2687
+ | `new-row-label` | string | `+ New page · + Neue Seite` | Its text. |
2686
2688
  | `sortable` | boolean | – | Header click sorts locally. |
2687
2689
  | `sort-key` | string | – | Sorted column. |
2688
2690
  | `sort-dir` | asc | desc | – | Direction. |
@@ -2794,7 +2796,7 @@ The third database view: one line per row – icon and title, the `meta-keys` on
2794
2796
  | `title-key` | string | – | Title column. |
2795
2797
  | `meta-keys` | list | – | Comma-separated columns on the right. |
2796
2798
  | `new-row` | boolean | – | Show the add row. |
2797
- | `new-row-label` | string | `+ New page` | Its text. |
2799
+ | `new-row-label` | string | `+ New page · + Neue Seite` | Its text. |
2798
2800
 
2799
2801
  **Events:** `nk-select` `{ row, id }` – Row clicked or Enter. · `nk-action` `{ action: 'new-row' }` – Add row clicked.
2800
2802
 
@@ -2852,9 +2854,9 @@ The fourth database view (NotionKit 1.9.0): a month, the rows as cards on their
2852
2854
  | `weekend` | list | – | Weekdays not worked, washed – `6,0`. |
2853
2855
  | `today` | YYYY-MM-DD | – | Another today – for tests and docs. |
2854
2856
  | `locale` | BCP 47 | `lang` | Language of the names and the week. |
2855
- | `today-label` | string | `Today` | Today button. |
2856
- | `prev-label` | string | `Previous month` | Names ‹. |
2857
- | `next-label` | string | `Next month` | Names ›. |
2857
+ | `today-label` | string | `Today · Heute` | Today button. |
2858
+ | `prev-label` | string | `Previous month · Voriger Monat` | Names ‹. |
2859
+ | `next-label` | string | `Next month · Nächster Monat` | Names ›. |
2858
2860
  | `week-label` | string | `W · KW` | Head of the week column. |
2859
2861
 
2860
2862
  **Events:** `nk-select` `{ row, id }` – Card clicked or Enter. · `nk-month` `{ month }` – Another month shown.
@@ -2882,7 +2884,7 @@ The fourth database view (NotionKit 1.9.0): a month, the rows as cards on their
2882
2884
 
2883
2885
  ### 3.82 `<nk-gallery-view>` – Gallery view
2884
2886
 
2885
- The fifth database view: the rows as cards with a picture on top, in a grid that fills the row – Notion’s gallery, for a course catalog or a reading list. `cover-key` names the row field with the picture’s URL (default: `cover`); a row without one shows the cover gradient, `no-cover` leaves the pictures out. The picture stands in 2:1, cropped to fill; `fit` shows it whole, for logos. `size` small, medium or large sets the card size – columns from 180, 260 or 340px. Cards show the title and the `meta-keys` (default: the select and date columns) and fire `nk-select` on a click, Enter or Space; `new-row` adds the add card.
2887
+ The fifth database view: the rows as cards with a picture on top, in a grid that fills the row – Notion’s gallery, for a course catalog or a reading list. `cover-key` names the row field with the picture’s URL (default: `cover`); a row without one shows the cover gradient, `no-cover` leaves the pictures out. The picture stands in 2:1, cropped to fill; `fit` shows it whole, for logos. `size` small, medium or large sets the card size – columns from 180, 260 or 340px. Cards show the title and the `meta-keys` (default: the select and date columns) and fire `nk-select` on a click, Enter or Space; `new-row` adds the add card. `href-key` names the row field with a card’s address: such a card is a link, `<a class="nk-card" href>` in a `.card-item` that carries the list item’s role – to open a course in a new tab or copy its address. A plain click, and Enter, fire the same `nk-select`; cancel it and the browser stays. A middle click or one with Cmd, Ctrl, Shift or Alt fires nothing and does what a link does.
2886
2888
 
2887
2889
  ```html
2888
2890
  <nk-gallery-view meta-keys="status,due" new-row></nk-gallery-view>
@@ -2916,14 +2918,15 @@ The fifth database view: the rows as cards with a picture on top, in a grid that
2916
2918
  | `fit` | boolean | – | Show a picture whole instead of cropped. |
2917
2919
  | `title-key` | string | – | Title column. |
2918
2920
  | `meta-keys` | list | – | Comma-separated columns under the title. |
2921
+ | `href-key` | string | – | Row field with the card’s address; such a card is a link. |
2919
2922
  | `new-row` | boolean | – | Show the add card. |
2920
- | `new-row-label` | string | `+ New page` | Its text. |
2923
+ | `new-row-label` | string | `+ New page · + Neue Seite` | Its text. |
2921
2924
 
2922
- **Events:** `nk-select` `{ row, id, value }` – Card clicked, Enter or Space. · `nk-action` `{ action: 'new-row' }` – Add card clicked.
2925
+ **Events:** `nk-select` `{ row, id, value }` – Card clicked, Enter or Space; a link card with a plain click or Enter – cancel it to stay. · `nk-action` `{ action: 'new-row' }` – Add card clicked.
2923
2926
 
2924
2927
  **Properties:** `columns`, `rows`, `data` · **Methods:** `refresh()`
2925
2928
 
2926
- **Replaces:** `.nk-gallery`, `.small`, `.large`, `.fit`, `.nk-card`, `.nk-cover`, `.card-title`, `.card-meta`, `.nk-new-row`
2929
+ **Replaces:** `.nk-gallery`, `.small`, `.large`, `.fit`, `.nk-card`, `.card-item`, `.nk-cover`, `.card-title`, `.card-meta`, `.nk-new-row`
2927
2930
 
2928
2931
  ```html
2929
2932
  <!-- equivalent class markup -->
@@ -2954,8 +2957,8 @@ The filters in effect as NotionKit’s filter pills – `.active` with an accent
2954
2957
  | `no-filter` | boolean | – | Hide the Filter tool. |
2955
2958
  | `no-sort` | boolean | – | Hide the Sort tool. |
2956
2959
  | `filter-label` | string | `Filter` | Text of the Filter tool. |
2957
- | `sort-label` | string | `Sort` | Text of the Sort tool. |
2958
- | `remove-label` | string | `Remove filter` | The ×’s name, followed by the pill’s text. |
2960
+ | `sort-label` | string | `Sort · Sortieren` | Text of the Sort tool. |
2961
+ | `remove-label` | string | `Remove filter · Filter entfernen` | The ×’s name, followed by the pill’s text. |
2959
2962
  | `search` | boolean | – | Show the search field. |
2960
2963
  | `placeholder` | string | – | Search placeholder. |
2961
2964
 
@@ -2988,7 +2991,7 @@ A left-ruled thread of `nk-comment`s with an input row. Enter or the button fire
2988
2991
  | Attribute | Type | Default | Description |
2989
2992
  |---|---|---|---|
2990
2993
  | `placeholder` | string | – | Input placeholder. |
2991
- | `send-label` | string | `Send` | Button text. |
2994
+ | `send-label` | string | `Send · Senden` | Button text. |
2992
2995
  | `no-input` | boolean | – | Read-only thread. |
2993
2996
  | `disabled` | boolean | – | Input disabled. |
2994
2997
 
@@ -3142,8 +3145,8 @@ Eight skeletons, one per app shape, mirroring the NotionKit CSS SKILL.md. Copy o
3142
3145
  <html lang="en" data-theme="light">
3143
3146
  <head>
3144
3147
  <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.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>
3148
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3149
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3147
3150
  </head>
3148
3151
  <body class="nk-body">
3149
3152
  <nk-app>
@@ -3224,8 +3227,8 @@ Rules of the shell: `nk-sidebar`, `nk-topbar` and `nk-page` are `display: conten
3224
3227
  <html lang="en" data-theme="light">
3225
3228
  <head>
3226
3229
  <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.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>
3230
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3231
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3229
3232
  </head>
3230
3233
  <body class="nk-body">
3231
3234
  <nk-app>
@@ -3332,8 +3335,8 @@ Data contract: `columns` describe the properties (`type`: text | select | multi-
3332
3335
  <html lang="en" data-theme="light">
3333
3336
  <head>
3334
3337
  <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.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>
3338
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3339
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3337
3340
  </head>
3338
3341
  <body class="nk-body">
3339
3342
  <nk-app>
@@ -3392,8 +3395,8 @@ Data contract: `columns` describe the properties (`type`: text | select | multi-
3392
3395
  <html lang="en" data-theme="light">
3393
3396
  <head>
3394
3397
  <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.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>
3398
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3399
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3397
3400
  </head>
3398
3401
  <body class="nk-body">
3399
3402
  <!-- your app -->
@@ -3470,8 +3473,8 @@ The open/close contract is one attribute: `settings.open = true`, `settings.show
3470
3473
  <html lang="en" data-theme="light">
3471
3474
  <head>
3472
3475
  <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.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>
3476
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3477
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3475
3478
  </head>
3476
3479
  <body class="nk-body">
3477
3480
  <div class="nk-page" style="padding-top:48px">
@@ -3517,8 +3520,8 @@ The open/close contract is one attribute: `settings.open = true`, `settings.show
3517
3520
  <html lang="en" data-theme="light">
3518
3521
  <head>
3519
3522
  <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.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>
3523
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3524
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3522
3525
  </head>
3523
3526
  <body class="nk-body">
3524
3527
  <nk-page narrow icon="📘" cover>
@@ -3562,8 +3565,8 @@ Note `narrow`: the page is the document, so there is no inner scroll wrapper –
3562
3565
  <html lang="en" data-theme="light">
3563
3566
  <head>
3564
3567
  <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.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>
3568
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3569
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3567
3570
  </head>
3568
3571
  <body class="nk-body">
3569
3572
  <nk-app>
@@ -3617,8 +3620,8 @@ Note `narrow`: the page is the document, so there is no inner scroll wrapper –
3617
3620
  <html lang="en" data-theme="light">
3618
3621
  <head>
3619
3622
  <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.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>
3623
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1.17.0/notionkit.min.css">
3624
+ <script src="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit-elements@1.17.0/dist/notionkit-elements.min.js"></script>
3622
3625
  </head>
3623
3626
  <body class="nk-body">
3624
3627
  <!-- A narrow column, centred: layout is yours, so it is inline. -->
@@ -3707,6 +3710,8 @@ Form controls additionally re-dispatch a native, bubbling `change` event, so `fo
3707
3710
  | A padding on the page while the side peek is open, or a peek wider by CSS | `<nk-peek resizable inset>` – the width is `--nk-peek-width`, `nk-resize` to keep it |
3708
3711
  | A hand-built month grid, or `<input type="date">` for a date property | `<nk-calendar floating sheet>` and `picker.show(cell)` – the table's `nk-select` names the `key` and the `cell`; `range` for start and end, `weeks` for calendar weeks, `days` for holidays and marks |
3709
3712
  | Rows laid out in a table of weeks to show them by date | `<nk-calendar-view date-key="due">` in `<nk-database>` – a tab like table and board |
3713
+ | German labels on every instance (`copy-label="Kopieren"`, `today-label="Heute"`, `new-row-label="+ Neue Seite"` …) | `<html lang="de">` – the elements bring the German texts, the accessible names too; keep an attribute for a label with a meaning of its own, `setStrings()` for another language |
3714
+ | `<nk-steps selectable>` or a gallery whose `nk-select` sets `location.href` | `href` on the step, `href-key` on the gallery: a real link opens in a new tab and can be copied; cancel `nk-select` to route yourself |
3710
3715
 
3711
3716
 
3712
3717
  # 7. Quick Reference
@@ -3818,12 +3823,13 @@ Form controls additionally re-dispatch a native, bubbling `change` event, so `fo
3818
3823
  | Base classes `NkElement` / `NkFormElement` | `src/base.js` – shadow root, adopted `componentsSheet`, theme wrapper, `render/setupEvents/teardownEvents/onAttributeChanged/projectLightDom/refresh`, ElementInternals |
3819
3824
  | Token injection | `src/base.js` – once per page, `@layer notionkit-defaults { tokensCss }` appended to `document.adoptedStyleSheets` |
3820
3825
  | Theme sync | one `MutationObserver` on `<html>[data-theme]`, a `Set` of instances, `.nk-wrapper[data-theme]` inside each root |
3826
+ | Texts | `src/util/strings.js` – the English and German dictionary and `setStrings()`; `NkElement#str(key)` reads it in the element's language, `onStringsChanged()` runs after `setStrings()` and when `<html lang>` changes |
3821
3827
  | Components | `src/components/{forms,content,shell,page,overlays,data}/nk-*.js`, one tag per file, `customElements.define` at the bottom |
3822
3828
  | 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` |
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 |
3829
+ | Peer | `@jungherz-de/notionkit >= 1.17.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 |
3824
3830
 
3825
3831
  Lifecycle: construct (attach shadow, adopt sheets) → first connect (wrapper + `render()`) → every connect (`setupEvents()`, theme registration, light-DOM observer) → `attributeChangedCallback` → `onAttributeChanged` → disconnect (`teardownEvents()`, unregister).
3826
3832
 
3827
3833
 
3828
3834
  ---
3829
- *NotionKit Elements v1.16.0 · wrapping NotionKit CSS v1.16.0 · MIT · Jungherz GmbH*
3835
+ *NotionKit Elements v1.17.0 · wrapping NotionKit CSS v1.17.0 · MIT · Jungherz GmbH*
@@ -1,5 +1,79 @@
1
1
  import { tokensCss, componentsSheet } from '@jungherz-de/notionkit/notionkit-styles.js';
2
2
 
3
+ // The texts the elements show and announce by themselves – button labels,
4
+ // placeholders, accessible names – in English and German (NotionKit
5
+ // Elements 1.17.0). The language is the element's own: the nearest `lang`
6
+ // attribute, across shadow roots, else <html lang>; German for "de…",
7
+ // English for anything else. setStrings() adds or replaces texts, for one
8
+ // language or for all of them, and an attribute on the element wins over
9
+ // every one of these.
10
+ const BUILT_IN = {
11
+ en: {
12
+ copy: 'Copy', copied: 'Copied', show: 'Show', hide: 'Hide',
13
+ uploadImage: 'Upload image', changeImage: 'Change image', remove: 'Remove',
14
+ close: 'Close', resize: 'Resize',
15
+ today: 'Today', previousMonth: 'Previous month', nextMonth: 'Next month', clear: 'Clear', time: 'Time',
16
+ filter: 'Filter', sort: 'Sort', addFilter: '+ Filter', removeFilter: 'Remove filter', search: 'Search …',
17
+ closeSidebar: 'Close sidebar', newPage: '+ New page',
18
+ commentPlaceholder: 'Comment …', send: 'Send', askPlaceholder: 'Ask something …',
19
+ commandPlaceholder: 'Search or type a command …', emojiPlaceholder: 'Search…',
20
+ toggleTheme: 'Toggle light / dark', synced: '⟳ synced',
21
+ message: 'Message', breadcrumb: 'Breadcrumb', commandPalette: 'Command palette', comment: 'Comment',
22
+ searchEmoji: 'Search emoji', settings: 'Settings', title: 'Title', changeIcon: 'Change icon',
23
+ add: 'Add', more: 'More',
24
+ },
25
+ de: {
26
+ copy: 'Kopieren', copied: 'Kopiert', show: 'Zeigen', hide: 'Verbergen',
27
+ uploadImage: 'Bild hochladen', changeImage: 'Bild ändern', remove: 'Entfernen',
28
+ close: 'Schließen', resize: 'Breite ändern',
29
+ today: 'Heute', previousMonth: 'Voriger Monat', nextMonth: 'Nächster Monat', clear: 'Leeren', time: 'Uhrzeit',
30
+ filter: 'Filter', sort: 'Sortieren', addFilter: '+ Filter', removeFilter: 'Filter entfernen', search: 'Suchen …',
31
+ closeSidebar: 'Seitenleiste schließen', newPage: '+ Neue Seite',
32
+ commentPlaceholder: 'Kommentieren …', send: 'Senden', askPlaceholder: 'Frag etwas …',
33
+ commandPlaceholder: 'Suchen oder Befehl eingeben …', emojiPlaceholder: 'Suchen …',
34
+ toggleTheme: 'Hell / Dunkel', synced: '⟳ synchronisiert',
35
+ message: 'Nachricht', breadcrumb: 'Pfad', commandPalette: 'Befehlspalette', comment: 'Kommentar',
36
+ searchEmoji: 'Emoji suchen', settings: 'Einstellungen', title: 'Titel', changeIcon: 'Symbol ändern',
37
+ add: 'Hinzufügen', more: 'Mehr',
38
+ },
39
+ };
40
+ const custom = {};
41
+ const listeners = new Set();
42
+
43
+ /**
44
+ * Adds or replaces texts: setStrings({ copy: 'Copy link' }) for every
45
+ * language, setStrings({ copy: 'Copier' }, 'fr') for one – a language of its
46
+ * own too. The elements on the page take them at once.
47
+ */
48
+ function setStrings(strings, lang = '*') {
49
+ const key = String(lang).toLowerCase().split('-')[0];
50
+ custom[key] = { ...custom[key], ...strings };
51
+ for (const fn of listeners) fn();
52
+ }
53
+
54
+ /** The keys and texts built in for a language ('en' or 'de'), for an app that fills in its own. */
55
+ function builtInStrings(lang = 'en') {
56
+ return { ...(BUILT_IN[String(lang).toLowerCase().split('-')[0]] || BUILT_IN.en) };
57
+ }
58
+
59
+ /** Called after every setStrings(); base.js hands the change on to the elements. */
60
+ function onStringsChange(fn) { listeners.add(fn); }
61
+
62
+ /** The language of `el`: its nearest lang attribute, across shadow roots, else the page's; the primary subtag. */
63
+ function langOf(el) {
64
+ for (let node = el; node; node = node.getRootNode?.().host) {
65
+ const hit = node.closest?.('[lang]');
66
+ if (hit) return hit.getAttribute('lang').toLowerCase().split('-')[0];
67
+ }
68
+ return (document.documentElement.lang || 'en').toLowerCase().split('-')[0];
69
+ }
70
+
71
+ /** The text `key` for `el`: its language's own set by setStrings(), then the one for every language, the built-in one, English. */
72
+ function str(key, el) {
73
+ const lang = langOf(el);
74
+ return custom[lang]?.[key] ?? custom['*']?.[key] ?? BUILT_IN[lang]?.[key] ?? BUILT_IN.en[key] ?? key;
75
+ }
76
+
3
77
  // ============================================================
4
78
  // NotionKit Elements – base classes
5
79
  //
@@ -50,10 +124,20 @@ function syncAllThemes() {
50
124
  for (const instance of instances) instance._syncTheme(theme);
51
125
  }
52
126
 
127
+ // The built-in texts follow the language (1.17.0): setStrings() and a new
128
+ // lang on <html> reach the elements already on the page, too.
129
+ function syncAllStrings() {
130
+ for (const instance of instances) instance.onStringsChanged();
131
+ }
132
+ onStringsChange(syncAllStrings);
133
+
53
134
  if (typeof window !== 'undefined' && typeof MutationObserver !== 'undefined') {
54
- new MutationObserver(syncAllThemes).observe(document.documentElement, {
135
+ new MutationObserver(records => {
136
+ if (records.some(r => r.attributeName === 'data-theme')) syncAllThemes();
137
+ if (records.some(r => r.attributeName === 'lang')) syncAllStrings();
138
+ }).observe(document.documentElement, {
55
139
  attributes: true,
56
- attributeFilter: ['data-theme']
140
+ attributeFilter: ['data-theme', 'lang']
57
141
  });
58
142
  }
59
143
 
@@ -198,6 +282,21 @@ class NkElement extends HTMLElement {
198
282
  this._wrapper?.setAttribute('data-theme', theme);
199
283
  }
200
284
 
285
+ /**
286
+ * The text `key` in this element's language – its nearest lang attribute,
287
+ * across shadow roots, else the page's: the one setStrings() gave, else the
288
+ * built-in English or German one (1.17.0). A project's own element reads
289
+ * its texts here too, after setStrings({ myKey: '…' }).
290
+ */
291
+ str(key) { return str(key, this); }
292
+
293
+ /**
294
+ * The texts may have changed: setStrings() ran or <html lang> changed.
295
+ * Components with built-in texts apply them again here; an attribute on
296
+ * the element still wins.
297
+ */
298
+ onStringsChanged() {}
299
+
201
300
  _upgradeOwnProperties() {
202
301
  for (const key of Object.keys(this)) {
203
302
  if (key.startsWith('_')) continue;
@@ -347,4 +446,4 @@ class NkFormElement extends NkElement {
347
446
  }
348
447
  }
349
448
 
350
- export { NkElement, NkFormElement, getCurrentTheme };
449
+ export { NkElement, NkFormElement, builtInStrings, getCurrentTheme, setStrings };