kempo-ui 0.4.26 → 0.4.28

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 (87) hide show
  1. package/dist/utils/closestAcrossShadow.js +1 -0
  2. package/docs/components/accordion.html +3 -0
  3. package/docs/components/aside.html +3 -0
  4. package/docs/components/button.html +3 -0
  5. package/docs/components/calendar.html +3 -0
  6. package/docs/components/card.html +3 -0
  7. package/docs/components/chat.html +3 -0
  8. package/docs/components/code-editor.html +3 -0
  9. package/docs/components/color-picker.html +3 -0
  10. package/docs/components/combobox.html +3 -0
  11. package/docs/components/content-slider.html +3 -0
  12. package/docs/components/context.html +3 -0
  13. package/docs/components/dialog.html +3 -0
  14. package/docs/components/dropdown.html +3 -0
  15. package/docs/components/filter-list.html +3 -0
  16. package/docs/components/focus-capture.html +3 -0
  17. package/docs/components/html-editor.html +3 -0
  18. package/docs/components/hybrid-component.html +3 -0
  19. package/docs/components/icon.html +3 -0
  20. package/docs/components/import.html +3 -0
  21. package/docs/components/light-component.html +3 -0
  22. package/docs/components/markdown-editor.html +3 -0
  23. package/docs/components/markdown.html +3 -0
  24. package/docs/components/nav-spacer.html +3 -0
  25. package/docs/components/nav.html +3 -0
  26. package/docs/components/pagination.html +3 -0
  27. package/docs/components/photo-viewer.html +3 -0
  28. package/docs/components/progress.html +3 -0
  29. package/docs/components/resize.html +3 -0
  30. package/docs/components/segmented-control.html +3 -0
  31. package/docs/components/shadow-component.html +3 -0
  32. package/docs/components/show-more.html +3 -0
  33. package/docs/components/slider.html +3 -0
  34. package/docs/components/sortable.html +3 -0
  35. package/docs/components/speech-to-text.html +3 -0
  36. package/docs/components/spinner.html +3 -0
  37. package/docs/components/split.html +3 -0
  38. package/docs/components/table.html +3 -0
  39. package/docs/components/tableControls.html +3 -0
  40. package/docs/components/tableCustomFields.html +3 -0
  41. package/docs/components/tableFetchRecords.html +3 -0
  42. package/docs/components/tableFieldSortHide.html +3 -0
  43. package/docs/components/tablePagination.html +3 -0
  44. package/docs/components/tablePlaceholder.html +3 -0
  45. package/docs/components/tableRecordEditing.html +3 -0
  46. package/docs/components/tableRecordFiltering.html +3 -0
  47. package/docs/components/tableRecordHiding.html +3 -0
  48. package/docs/components/tableRecordSearching.html +3 -0
  49. package/docs/components/tableRecordSelection.html +3 -0
  50. package/docs/components/tableRowControls.html +3 -0
  51. package/docs/components/tableServerSync.html +3 -0
  52. package/docs/components/tableSorting.html +3 -0
  53. package/docs/components/tabs.html +3 -0
  54. package/docs/components/tags.html +3 -0
  55. package/docs/components/text-to-speech.html +3 -0
  56. package/docs/components/theme-select.html +3 -0
  57. package/docs/components/theme-switcher.html +3 -0
  58. package/docs/components/time.html +3 -0
  59. package/docs/components/timestamp.html +3 -0
  60. package/docs/components/toast.html +3 -0
  61. package/docs/components/toggle.html +3 -0
  62. package/docs/components/tree.html +3 -0
  63. package/docs/components/voice-selector.html +3 -0
  64. package/docs/index.html +9 -0
  65. package/docs/src/utils/closestAcrossShadow.js +1 -0
  66. package/docs/utils/closestAcrossShadow.html +549 -0
  67. package/docs/utils/context.html +3 -0
  68. package/docs/utils/cookie.html +3 -0
  69. package/docs/utils/debounce.html +3 -0
  70. package/docs/utils/drag.html +3 -0
  71. package/docs/utils/elevation.html +3 -0
  72. package/docs/utils/formatTimestamp.html +3 -0
  73. package/docs/utils/object.html +3 -0
  74. package/docs/utils/propConverters.html +3 -0
  75. package/docs/utils/sanitizeHtml.html +3 -0
  76. package/docs/utils/string.html +3 -0
  77. package/docs/utils/theme.html +3 -0
  78. package/docs/utils/toTitleCase.html +3 -0
  79. package/docs/utils/type.html +3 -0
  80. package/docs/utils/voice.html +3 -0
  81. package/docs/utils/wait.html +3 -0
  82. package/docs-src/index.page.html +6 -0
  83. package/docs-src/nav.fragment.html +3 -0
  84. package/docs-src/utils/closestAcrossShadow.page.html +49 -0
  85. package/package.json +1 -1
  86. package/src/utils/closestAcrossShadow.js +23 -0
  87. package/tests/utils/closestAcrossShadow.browser-test.js +90 -0
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -228,6 +228,8 @@
228
228
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
229
229
  href="../components/button.html"
230
230
  >Button<br><small>Base Component</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
232
+ href="../utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
231
233
  <k-filter-item filter-keywords="cookie utils utility"><a
232
234
  href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
233
235
  <k-filter-item filter-keywords="context utils utility"><a
@@ -360,6 +362,7 @@
360
362
 
361
363
  <h5 class="mb0">Utils</h5>
362
364
  <div class="pl mb">
365
+ <a href="../utils/closestAcrossShadow.html">closestAcrossShadow</a>
363
366
  <a href="../utils/cookie.html">cookie</a>
364
367
  <a href="../utils/context.html">context</a>
365
368
  <a href="../utils/debounce.html">debounce</a>
@@ -319,6 +319,12 @@
319
319
 
320
320
  <h2>Utils</h2>
321
321
  <div class="row -mx">
322
+ <div class="span-12 t-span-6 d-span-4 px">
323
+ <a href="{{pathToRoot}}utils/closestAcrossShadow.html" class="card mb no-link d-b">
324
+ <h3 class="tc-primary">closestAcrossShadow</h3>
325
+ <p class="tc-muted">closest() that walks past shadow-DOM boundaries to find an ancestor.</p>
326
+ </a>
327
+ </div>
322
328
  <div class="span-12 t-span-6 d-span-4 px">
323
329
  <a href="{{pathToRoot}}utils/cookie.html" class="card mb no-link d-b">
324
330
  <h3 class="tc-primary">cookie</h3>
@@ -212,6 +212,8 @@
212
212
  <k-filter-item filter-keywords="button base component keyboard disabled accessibility"><a
213
213
  href="{{pathToRoot}}components/button.html"
214
214
  >Button<br><small>Base Component</small></a></k-filter-item>
215
+ <k-filter-item filter-keywords="closestAcrossShadow closest shadow dom utils utility"><a
216
+ href="{{pathToRoot}}utils/closestAcrossShadow.html">closestAcrossShadow<br><small>Utility</small></a></k-filter-item>
215
217
  <k-filter-item filter-keywords="cookie utils utility"><a
216
218
  href="{{pathToRoot}}utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
217
219
  <k-filter-item filter-keywords="context utils utility"><a
@@ -344,6 +346,7 @@
344
346
 
345
347
  <h5 class="mb0">Utils</h5>
346
348
  <div class="pl mb">
349
+ <a href="{{pathToRoot}}utils/closestAcrossShadow.html">closestAcrossShadow</a>
347
350
  <a href="{{pathToRoot}}utils/cookie.html">cookie</a>
348
351
  <a href="{{pathToRoot}}utils/context.html">context</a>
349
352
  <a href="{{pathToRoot}}utils/debounce.html">debounce</a>
@@ -0,0 +1,49 @@
1
+ <page pageName="closestAcrossShadow" title="closestAcrossShadow - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>closestAcrossShadow</h1>
5
+ <k-accordion persistent-id="toc" class="b r mb">
6
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
7
+ <k-accordion-panel name="toc-panel">
8
+ <div class="m ">
9
+ <h6>Usage</h6>
10
+ <a href="#basicUsage">Basic Usage</a><br />
11
+ <a href="#parameters">Parameters</a><br />
12
+ <a href="#examples">Examples</a><br />
13
+ </div>
14
+ </k-accordion-panel>
15
+ </k-accordion>
16
+
17
+ <h3>Description</h3>
18
+ <p>The <code>closestAcrossShadow</code> utility works like the native
19
+ <code>Element.closest()</code>, but it does not stop at shadow-DOM boundaries.
20
+ When the current tree yields no match it continues from the host of the enclosing
21
+ shadow root and keeps walking up toward the document, returning the nearest matching
22
+ ancestor (or the element itself), or <code>null</code> if there is none.</p>
23
+ <p>This is useful when a component nested inside another component's shadow root needs
24
+ to locate a shared ancestor — for example a <a href="{{pathToRoot}}components/context.html"><code>k-context</code></a> —
25
+ which native <code>closest()</code> cannot reach because it never crosses shadow boundaries.</p>
26
+
27
+ <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
28
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> closestAcrossShadow <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/closestAcrossShadow.js'</span>;<br /><br /><span class="hljs-comment">// From inside a deeply nested component, reach a shared k-context:</span><br /><span class="hljs-keyword">const</span> ctx = closestAcrossShadow(<span class="hljs-keyword">this</span>, <span class="hljs-string">'k-context'</span>);<br /><span class="hljs-keyword">const</span> settings = ctx?.get(<span class="hljs-string">'settings'</span>);</code></pre>
29
+
30
+ <h3 id="parameters"><a href="#parameters" class="no-link">Parameters</a></h3>
31
+ <h5><code>element<i>: Element</i></code></h5>
32
+ <p>The element to start searching from. The element itself is included in the match, just like <code>closest()</code>.</p>
33
+ <h5><code>selector<i>: string</i></code></h5>
34
+ <p>A CSS selector to match ancestors against.</p>
35
+ <h5><code><i>returns</i>: Element | null</code></h5>
36
+ <p>The nearest matching ancestor across shadow boundaries, or <code>null</code> if none match.</p>
37
+
38
+ <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
39
+
40
+ <h4>Reading a context from a nested shadow component</h4>
41
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> closestAcrossShadow <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/closestAcrossShadow.js'</span>;<br /><br />connectedCallback() {<br /> <span class="hljs-keyword">super</span>.connectedCallback();<br /> <span class="hljs-keyword">const</span> ctx = closestAcrossShadow(<span class="hljs-keyword">this</span>, <span class="hljs-string">'k-context'</span>);<br /> ctx?.addEventListener(<span class="hljs-string">'context:set'</span>, () =&gt; <span class="hljs-keyword">this</span>.requestUpdate());<br />}</code></pre>
42
+
43
+ <h4>Falls back to null</h4>
44
+ <pre><code class="hljs javascript"><span class="hljs-comment">// No matching ancestor in any tree:</span><br>closestAcrossShadow(someDetachedNode, <span class="hljs-string">'.missing'</span>); <span class="hljs-comment">// =&gt; null</span></code></pre>
45
+ </content>
46
+ <content location="scripts">
47
+ <script type="module" src="{{pathToRoot}}src/components/Accordion.js"></script>
48
+ </content>
49
+ </page>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kempo-ui",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
4
4
  "type": "module",
5
5
  "description": "A Lit based web-component library",
6
6
  "main": "index.js",
@@ -0,0 +1,23 @@
1
+ /*
2
+ closestAcrossShadow
3
+
4
+ Like Element.closest(), but it does not stop at shadow-DOM boundaries. When the
5
+ current tree yields no match, it continues from the host of the enclosing shadow
6
+ root and keeps walking up toward the document. Returns the nearest matching
7
+ ancestor (or the element itself), or null if there is none.
8
+
9
+ Useful for components nested inside another component's shadow root that need to
10
+ locate a shared ancestor — e.g. a k-context — which native closest() can't reach.
11
+ */
12
+ export const closestAcrossShadow = (element, selector) => {
13
+ let node = element;
14
+ while(node){
15
+ const match = node.closest?.(selector);
16
+ if(match) return match;
17
+ const root = node.getRootNode();
18
+ node = root instanceof ShadowRoot ? root.host : null;
19
+ }
20
+ return null;
21
+ };
22
+
23
+ export default closestAcrossShadow;
@@ -0,0 +1,90 @@
1
+ import closestAcrossShadow, { closestAcrossShadow as named } from '../../src/utils/closestAcrossShadow.js';
2
+
3
+ const cleanup = (el) => {
4
+ if(el && el.parentNode){
5
+ el.parentNode.removeChild(el);
6
+ }
7
+ };
8
+
9
+ export default {
10
+ 'exports the function as default and named export': ({pass, fail}) => {
11
+ if(typeof closestAcrossShadow === 'function' && typeof named === 'function'){
12
+ pass('exported correctly as both default and named export');
13
+ } else {
14
+ fail('not exported correctly');
15
+ }
16
+ },
17
+
18
+ 'finds an ancestor within the same tree (like closest)': ({pass, fail}) => {
19
+ const root = document.createElement('div');
20
+ root.className = 'target';
21
+ root.innerHTML = '<section><span id="leaf"></span></section>';
22
+ document.body.appendChild(root);
23
+ const found = closestAcrossShadow(root.querySelector('#leaf'), '.target');
24
+ cleanup(root);
25
+ if(found === root){
26
+ pass('found ancestor in the same tree');
27
+ } else {
28
+ fail('did not find ancestor in the same tree');
29
+ }
30
+ },
31
+
32
+ 'returns the element itself when it matches': ({pass, fail}) => {
33
+ const el = document.createElement('div');
34
+ el.className = 'me';
35
+ document.body.appendChild(el);
36
+ const found = closestAcrossShadow(el, '.me');
37
+ cleanup(el);
38
+ if(found === el){
39
+ pass('returned the element itself');
40
+ } else {
41
+ fail('did not return the element itself');
42
+ }
43
+ },
44
+
45
+ 'crosses a shadow boundary to find an ancestor': ({pass, fail}) => {
46
+ const host = document.createElement('div');
47
+ host.className = 'target';
48
+ document.body.appendChild(host);
49
+ const inner = document.createElement('span');
50
+ host.attachShadow({ mode: 'open' }).appendChild(inner);
51
+ const found = closestAcrossShadow(inner, '.target');
52
+ cleanup(host);
53
+ if(found === host){
54
+ pass('crossed a shadow boundary');
55
+ } else {
56
+ fail('did not cross the shadow boundary');
57
+ }
58
+ },
59
+
60
+ 'crosses multiple nested shadow boundaries': ({pass, fail}) => {
61
+ const host = document.createElement('div');
62
+ host.className = 'target';
63
+ document.body.appendChild(host);
64
+ const mid = document.createElement('div');
65
+ host.attachShadow({ mode: 'open' }).appendChild(mid);
66
+ const leaf = document.createElement('span');
67
+ mid.attachShadow({ mode: 'open' }).appendChild(leaf);
68
+ const found = closestAcrossShadow(leaf, '.target');
69
+ cleanup(host);
70
+ if(found === host){
71
+ pass('crossed multiple nested shadow boundaries');
72
+ } else {
73
+ fail('did not cross multiple nested shadow boundaries');
74
+ }
75
+ },
76
+
77
+ 'returns null when there is no match anywhere': ({pass, fail}) => {
78
+ const host = document.createElement('div');
79
+ document.body.appendChild(host);
80
+ const inner = document.createElement('span');
81
+ host.attachShadow({ mode: 'open' }).appendChild(inner);
82
+ const found = closestAcrossShadow(inner, '.nope');
83
+ cleanup(host);
84
+ if(found === null){
85
+ pass('returned null when no match');
86
+ } else {
87
+ fail(`expected null, got ${found}`);
88
+ }
89
+ }
90
+ };