kempo-ui 0.0.11 → 0.0.13

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 (47) hide show
  1. package/docs/components/accordion.html +122 -32
  2. package/docs/components/card.html +57 -41
  3. package/docs/components/collapsible.html +158 -36
  4. package/docs/components/content-slider.html +182 -35
  5. package/docs/components/dialog.html +79 -45
  6. package/docs/components/focus-capture.html +78 -40
  7. package/docs/components/hybrid-component.html +72 -34
  8. package/docs/components/icon.html +122 -41
  9. package/docs/components/import.html +39 -41
  10. package/docs/components/light-component.html +60 -35
  11. package/docs/components/persistant-collapsible.html +84 -38
  12. package/docs/components/photo-viewer.html +186 -37
  13. package/docs/components/resize.html +140 -38
  14. package/docs/components/shadow-component.html +53 -39
  15. package/docs/components/show-more.html +93 -40
  16. package/docs/components/side-menu.html +122 -38
  17. package/docs/components/sortable.html +94 -36
  18. package/docs/components/split.html +112 -39
  19. package/docs/components/table.html +269 -31
  20. package/docs/components/tableControls.html +54 -51
  21. package/docs/components/tableCustomFields.html +90 -51
  22. package/docs/components/tableFetchRecords.html +89 -49
  23. package/docs/components/tableFieldSortHide.html +52 -51
  24. package/docs/components/tablePagination.html +77 -51
  25. package/docs/components/tableRecordEditing.html +121 -51
  26. package/docs/components/tableRecordFiltering.html +63 -49
  27. package/docs/components/tableRecordHiding.html +56 -50
  28. package/docs/components/tableRecordSearching.html +52 -51
  29. package/docs/components/tableRecordSelection.html +53 -52
  30. package/docs/components/tableRowControls.html +56 -52
  31. package/docs/components/tableSorting.html +50 -51
  32. package/docs/components/tabs.html +147 -43
  33. package/docs/components/tags.html +72 -38
  34. package/docs/components/theme-switcher.html +86 -36
  35. package/docs/components/timestamp.html +44 -38
  36. package/docs/components/toast.html +25 -44
  37. package/docs/components/toggle.html +119 -39
  38. package/docs/components/tree.html +145 -39
  39. package/docs/dev.config.json +1 -1
  40. package/docs/index.html +209 -55
  41. package/docs/utils/debounce.html +31 -28
  42. package/docs/utils/drag.html +42 -28
  43. package/docs/utils/formatTimestamp.html +67 -28
  44. package/docs/utils/propConverters.html +80 -23
  45. package/docs/utils/toTitleCase.html +24 -28
  46. package/docs/utils/watchWindowSize.html +96 -5
  47. package/package.json +1 -1
@@ -3,9 +3,8 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>watchWindowSize - Kempo UI</title>
7
- <link rel="stylesheet" href="../kempo-vars.css" />
8
- <link rel="stylesheet" href="../kempo.min.css" />
6
+ <title>Dialog - Components - Kempo Docs - A Web Components Solution</title>
7
+ <link rel="stylesheet" href="../kempo-vars.css" /><link rel="stylesheet" href="../kempo.min.css" />
9
8
  <link rel="stylesheet" href="../kempo-hljs.css" />
10
9
  <link rel="stylesheet" href="../styles.css" />
11
10
  <script>window.litDisableBundleWarning = true;</script>
@@ -14,58 +13,93 @@
14
13
  <body>
15
14
  <k-import src="../nav.inc.html"></k-import>
16
15
  <main>
17
- <h1>watchWindowSize</h1>
18
-
19
- <details
20
- class="b r mb"
21
- >
16
+ <h1 class="ta-center">Dialog</h1>
17
+
18
+ <details class="b r mb">
22
19
  <summary class="p">Table of Contents</summary>
23
20
  <div class="m mt0 pl">
24
- <h6>Usage</h6>
21
+ <h6>Examples</h6>
25
22
  <a href="#basicUsage">Basic Usage</a><br />
26
- <a href="#functions">Functions</a><br />
27
- <a href="#examples">Examples</a><br />
23
+ <a href="#titles">Titles</a><br />
24
+ <a href="#actionButtons">Action Buttons</a><br />
25
+ <a href="#jsUsage">JavaScript Usage</a><br />
26
+
27
+ <h6 class="mt">JavaScript Reference</h6>
28
+ <a href="#constructor">Constructor</a><br />
29
+ <a href="#requirements">Requirements</a><br />
30
+ <a href="#properties">Properties</a><br />
31
+ <a href="#methods">Methods</a><br />
32
+ <a href="#staticMethods">Static Methods</a><br />
28
33
  </div>
29
34
  </details>
30
35
 
31
- <h3>Description</h3>
32
- <p>The <code>watchWindowSize</code> utility provides a debounced way to monitor window resize events. It manages multiple handlers efficiently and automatically debounces resize events to improve performance.</p>
33
-
34
36
  <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
35
- <p>Import and use the window size watching functions:</p>
36
- <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { watchWindowSize, unwatchWindowSize } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/watchWindowSize.js'</span>;<br /><br /><span class="hljs-keyword">const</span> handler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Window width:'</span>, width);<br />};<br /><br /><span class="hljs-comment">// Start watching</span><br /><span class="hljs-keyword">const</span> currentWidth = watchWindowSize(handler);<br /><br /><span class="hljs-comment">// Stop watching when done</span><br />unwatchWindowSize(handler);</code></pre>
37
-
38
- <h3 id="functions"><a href="#functions" class="no-link">Functions</a></h3>
39
-
40
- <h5><code>watchWindowSize(handler)</code></h5>
41
- <p>Registers a handler function to be called when the window is resized.</p>
42
- <ul>
43
- <li><strong>handler:</strong> Function that receives the new window width</li>
44
- <li><strong>Returns:</strong> Current window width</li>
45
- </ul>
46
-
47
- <h5><code>unwatchWindowSize(handler)</code></h5>
48
- <p>Unregisters a previously registered handler function.</p>
49
- <ul>
50
- <li><strong>handler:</strong> The same function reference that was registered</li>
51
- </ul>
37
+ <p>Create dialogs using the <code>k-dialog</code> component. Open the dialog by calling the <code>open()</code> method, and close it by calling the <code>close()</code> method. Or it can be closed using the dialog's GUI (clicking the overlay, clicking the close button, or the cancel or confirm action buttons).</p>
38
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-dialog</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d1"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p"</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-dialog</span>&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"doument.getElementById('d1').open()"</span>&gt;</span>Open Dialog<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></code></pre>
39
+ <button class="openDialog mb" data-dialog="d1" slot="right">Open Dialog</button>
40
+ <k-dialog id="d1">
41
+ <p class="p">Hello World</p>
42
+ </k-dialog>
52
43
 
53
- <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
54
-
55
- <h4>Responsive Component</h4>
56
- <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { watchWindowSize, unwatchWindowSize } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/watchWindowSize.js'</span>;<br /><br /><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ResponsiveComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LitElement</span> </span>{<br /> <span class="hljs-keyword">constructor</span>() {<br /> <span class="hljs-keyword">super</span>();<br /> <span class="hljs-keyword">this</span>.isMobile = <span class="hljs-literal">false</span>;<br /> <span class="hljs-keyword">this</span>.resizeHandler = <span class="hljs-keyword">this</span>.handleResize.bind(<span class="hljs-keyword">this</span>);<br /> }<br /><br /> connectedCallback() {<br /> <span class="hljs-keyword">super</span>.connectedCallback();<br /> <span class="hljs-keyword">const</span> currentWidth = watchWindowSize(<span class="hljs-keyword">this</span>.resizeHandler);<br /> <span class="hljs-keyword">this</span>.handleResize(currentWidth);<br /> }<br /><br /> disconnectedCallback() {<br /> <span class="hljs-keyword">super</span>.disconnectedCallback();<br /> unwatchWindowSize(<span class="hljs-keyword">this</span>.resizeHandler);<br /> }<br /><br /> handleResize(width) {<br /> <span class="hljs-keyword">this</span>.isMobile = width &lt; <span class="hljs-number">768</span>;<br /> <span class="hljs-keyword">this</span>.requestUpdate();<br /> }<br /><br /> render() {<br /> <span class="hljs-keyword">return</span> html`<span class="xml"><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"</span></span></span><span class="hljs-subst">${<span class="hljs-keyword">this</span>.isMobile ? <span class="hljs-string">'mobile'</span> : <span class="hljs-string">'desktop'</span>}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span><br /> Content adapts to screen size<br /> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> `</span>;<br /> }<br />}</code></pre>
44
+ <h3 id="titles"><a href="#titles" class="no-link">Titles</a></h3>
45
+ <p>Assign an element to the <code>title</code> slot to have it appear as the dialog title.</p>
46
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-dialog</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d2"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span><br /> <span class="hljs-attr">class</span>=<span class="hljs-string">"m0 px"</span><br /> <span class="hljs-attr">slot</span>=<span class="hljs-string">"title"</span><br /> &gt;</span>This is a fact<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p"</span>&gt;</span>A hotdog is a sandwhich<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-dialog</span>&gt;</span></code></pre>
47
+ <button class="openDialog mb" data-dialog="d2" slot="right">Open Dialog</button>
48
+ <k-dialog
49
+ id="d2"
50
+ >
51
+ <h6
52
+ class="m0 px"
53
+ slot="title"
54
+ >This is a fact</h6>
55
+ <p class="p">A hotdog is a sandwhich</p>
56
+ </k-dialog>
57
57
 
58
- <h4>Multiple Handlers</h4>
59
- <pre><code class="hljs javascript"><span class="hljs-comment">// Handler for navigation</span><br /><span class="hljs-keyword">const</span> navHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">const</span> nav = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.navigation'</span>);<br /> nav.classList.toggle(<span class="hljs-string">'mobile'</span>, width &lt; <span class="hljs-number">1024</span>);<br />};<br /><br /><span class="hljs-comment">// Handler for sidebar</span><br /><span class="hljs-keyword">const</span> sidebarHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">const</span> sidebar = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.sidebar'</span>);<br /> sidebar.style.display = width &lt; <span class="hljs-number">768</span> ? <span class="hljs-string">'none'</span> : <span class="hljs-string">'block'</span>;<br />};<br /><br /><span class="hljs-comment">// Both handlers will be called on resize</span><br />watchWindowSize(navHandler);<br />watchWindowSize(sidebarHandler);<br /><br /><span class="hljs-comment">// Clean up when needed</span><br />unwatchWindowSize(navHandler);<br />unwatchWindowSize(sidebarHandler);</code></pre>
58
+ <h3 id="actionButtons"><a href="#actionButtons" class="no-link">Action Buttons</a></h3>
59
+ <p>Add a cancel button using the <code>cancel-text</code> attribute.</p>
60
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-dialog</span><br /> <span class="hljs-attr">id</span>=<span class="hljs-string">"d4"</span><br /> <span class="hljs-attr">cancel-text</span>=<span class="hljs-string">"Absolutly Not"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p"</span>&gt;</span>Mint and Chocolate belong together<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-dialog</span>&gt;</span></code></pre>
61
+ <button class="openDialog mb" data-dialog="d4" slot="right">Open Dialog</button>
62
+ <k-dialog
63
+ id="d4"
64
+ cancel-text="Absolutly Not"
65
+ >
66
+ <p class="p">Mint and Chocolate belong together</p>
67
+ </k-dialog>
60
68
 
61
- <h4>Breakpoint Detection</h4>
62
- <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> breakpoints = {<br /> <span class="hljs-attr">mobile</span>: <span class="hljs-number">768</span>,<br /> <span class="hljs-attr">tablet</span>: <span class="hljs-number">1024</span>,<br /> <span class="hljs-attr">desktop</span>: <span class="hljs-number">1200</span><br />};<br /><br /><span class="hljs-keyword">const</span> breakpointHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">let</span> currentBreakpoint = <span class="hljs-string">'mobile'</span>;<br /> <br /> <span class="hljs-keyword">if</span> (width &gt;= breakpoints.desktop) {<br /> currentBreakpoint = <span class="hljs-string">'desktop'</span>;<br /> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (width &gt;= breakpoints.tablet) {<br /> currentBreakpoint = <span class="hljs-string">'tablet'</span>;<br /> }<br /> <br /> <span class="hljs-built_in">document</span>.body.setAttribute(<span class="hljs-string">'data-breakpoint'</span>, currentBreakpoint);<br /> <br /> <span class="hljs-comment">// Dispatch custom event</span><br /> <span class="hljs-built_in">window</span>.dispatchEvent(<span class="hljs-keyword">new</span> CustomEvent(<span class="hljs-string">'breakpointchange'</span>, {<br /> <span class="hljs-attr">detail</span>: { width, <span class="hljs-attr">breakpoint</span>: currentBreakpoint }<br /> }));<br />};<br /><br />watchWindowSize(breakpointHandler);</code></pre>
69
+ <p>Add a confirm button using the <code>confirm-text</code> attribute.</p>
70
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-dialog</span><br /> <span class="hljs-attr">id</span>=<span class="hljs-string">"d5"</span><br /> <span class="hljs-attr">confirm-text</span>=<span class="hljs-string">"Confirm"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p"</span>&gt;</span>Spaghetti is the greatest food<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-dialog</span>&gt;</span></code></pre>
71
+ <button class="openDialog mb" data-dialog="d5" slot="right">Open Dialog</button>
72
+ <k-dialog
73
+ id="d5"
74
+ confirm-text="Confirm"
75
+ >
76
+ <p class="p">Spaghetti is the greatest food</p>
77
+ </k-dialog>
63
78
 
64
- <h4>Performance Benefits</h4>
65
- <p>The utility automatically debounces resize events, so you don't need to worry about performance:</p>
66
- <pre><code class="hljs javascript"><span class="hljs-comment">// This handler will only be called after resize events stop</span><br /><span class="hljs-keyword">const</span> expensiveHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-comment">// Expensive DOM calculations or API calls</span><br /> recalculateLayout();<br /> updateCharts();<br /> reflow();<br />};<br /><br />watchWindowSize(expensiveHandler); <span class="hljs-comment">// Automatically debounced</span></code></pre>
79
+ <p>Try it with both a cancel and confirm button.</p>
80
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-dialog</span><br /> <span class="hljs-attr">id</span>=<span class="hljs-string">"d6"</span><br /> <span class="hljs-attr">cancel-text</span>=<span class="hljs-string">"It should be outlawed"</span><br /> <span class="hljs-attr">confirm-text</span>=<span class="hljs-string">"Of course it is"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p"</span>&gt;</span>Ranch is gross<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-dialog</span>&gt;</span></code></pre>
81
+ <button class="openDialog mb" data-dialog="d6" slot="right">Open Dialog</button>
82
+ <k-dialog
83
+ id="d6"
84
+ cancel-text="It should be outlawed"
85
+ confirm-text="Of course it is"
86
+ >
87
+ <p class="p">Ranch is gross</p>
88
+ </k-dialog>
67
89
 
68
- </main>
69
- <div style="height:33vh"></div>
90
+ <h3 id="jsUsage"><a href="#jsUsage" class="no-link">JavaScript Usage</a></h3>
91
+ <h5>Create Dialog</h5>
92
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"d7"</span>&gt;</span>Open Dialog<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript"><br /> <span class="hljs-keyword">import</span> Dialog <span class="hljs-keyword">from</span> <span class="hljs-string">'/src/components/Dialog.js'</span>;<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'d7'</span>).addEventListener(<span class="hljs-string">'click'</span>, () =&gt; {<br /> Dialog.create(<span class="hljs-string">'&lt;p&gt;Hello World&lt;/p&gt;'</span>);<br /> });<br /></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre>
93
+ <button id="d7" class="mb">Open Dialog</button>
94
+ <script type="module" src="./init.js"></script>
95
+ <script type="module" src="../src/components/Dialog.js"></script>
96
+ <script>
97
+ document.querySelectorAll('.openDialog').forEach( $btn => {
98
+ $btn.addEventListener('click', () => {
99
+ const $dialog = document.getElementById($btn.dataset.dialog);
100
+ if($dialog) $dialog.open();
101
+ });
102
+ });
103
+ </script>
70
104
  </body>
71
- </html>
105
+ </html>
@@ -3,9 +3,8 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>watchWindowSize - Kempo UI</title>
7
- <link rel="stylesheet" href="../kempo-vars.css" />
8
- <link rel="stylesheet" href="../kempo.min.css" />
6
+ <title>FocusCapture - Components - Kempo Docs - A Web Components Solution</title>
7
+ <link rel="stylesheet" href="../kempo-vars.css" /><link rel="stylesheet" href="../kempo.min.css" />
9
8
  <link rel="stylesheet" href="../kempo-hljs.css" />
10
9
  <link rel="stylesheet" href="../styles.css" />
11
10
  <script>window.litDisableBundleWarning = true;</script>
@@ -13,59 +12,98 @@
13
12
  </head>
14
13
  <body>
15
14
  <k-import src="../nav.inc.html"></k-import>
15
+ <h1 class="ta-center">FocusCapture</h1>
16
16
  <main>
17
- <h1>watchWindowSize</h1>
18
-
19
- <details
20
- class="b r mb"
21
- >
17
+ <details class="b r mb">
22
18
  <summary class="p">Table of Contents</summary>
23
19
  <div class="m mt0 pl">
24
- <h6>Usage</h6>
20
+ <h6>Examples</h6>
25
21
  <a href="#basicUsage">Basic Usage</a><br />
26
- <a href="#functions">Functions</a><br />
27
- <a href="#examples">Examples</a><br />
22
+ <a href="#dialogExample">Dialog Example</a><br />
23
+
24
+ <h6 class="mt">JavaScript Reference</h6>
25
+ <a href="#constructor">Constructor</a><br />
26
+ <a href="#requirements">Requirements</a><br />
27
+ <a href="#properties">Properties</a><br />
28
+ <a href="#methods">Methods</a><br />
28
29
  </div>
29
30
  </details>
30
31
 
31
- <h3>Description</h3>
32
- <p>The <code>watchWindowSize</code> utility provides a debounced way to monitor window resize events. It manages multiple handlers efficiently and automatically debounces resize events to improve performance.</p>
33
-
34
32
  <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
35
- <p>Import and use the window size watching functions:</p>
36
- <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { watchWindowSize, unwatchWindowSize } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/watchWindowSize.js'</span>;<br /><br /><span class="hljs-keyword">const</span> handler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Window width:'</span>, width);<br />};<br /><br /><span class="hljs-comment">// Start watching</span><br /><span class="hljs-keyword">const</span> currentWidth = watchWindowSize(handler);<br /><br /><span class="hljs-comment">// Stop watching when done</span><br />unwatchWindowSize(handler);</code></pre>
33
+ <p>The <code>k-focus-capture</code> component traps focus within its children. When focus reaches the end of the focusable elements, it cycles back to the first focusable element. This is useful for modal dialogs, side menus, or any UI where you want to keep focus contained within a specific area.</p>
34
+ <div class="row -mx">
35
+ <div class="col m-span-12 px">
36
+ <k-card label="HTML">
37
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-focus-capture</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb"</span>&gt;</span>First Button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Input field"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb"</span> /&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb"</span>&gt;</span>Second Button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-b mb"</span>&gt;</span>Link<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br /> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-focus-capture</span>&gt;</span></code></pre>
38
+ </k-card>
39
+ </div>
40
+ <div class="col m-span-12 px">
41
+ <k-card label="Output">
42
+ <p class="mb"><em>Tab through the elements below. Focus will cycle back to the first element after the last one.</em></p>
43
+ <k-focus-capture>
44
+ <div class="card">
45
+ <button class="mb">First Button</button>
46
+ <input type="text" placeholder="Input field" class="mb" />
47
+ <button class="mb">Second Button</button>
48
+ <a href="#" class="d-b mb">Link</a>
49
+ </div>
50
+ </k-focus-capture>
51
+ </k-card>
52
+ </div>
53
+ </div>
37
54
 
38
- <h3 id="functions"><a href="#functions" class="no-link">Functions</a></h3>
39
-
40
- <h5><code>watchWindowSize(handler)</code></h5>
41
- <p>Registers a handler function to be called when the window is resized.</p>
42
- <ul>
43
- <li><strong>handler:</strong> Function that receives the new window width</li>
44
- <li><strong>Returns:</strong> Current window width</li>
45
- </ul>
55
+ <h3 id="dialogExample"><a href="#dialogExample" class="no-link">Dialog Example</a></h3>
56
+ <p>FocusCapture is used internally by the <a href="dialog.html">Dialog</a> and <a href="side-menu.html">SideMenu</a> components. You do not need to add it yourself. Open the dialog below and tab through the elements to see how focus is trapped within the dialog.</p>
57
+ <div class="row -mx">
58
+ <div class="col m-span-12 px">
59
+ <k-card label="HTML">
60
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-dialog</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"focusDialog"</span> <span class="hljs-attr">cancel-text</span>=<span class="hljs-string">"Close"</span> <span class="hljs-attr">confirm-text</span>=<span class="hljs-string">"Submit"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"title"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"m0 px"</span>&gt;</span>Focus Capture Dialog<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Tab through the elements. Focus stays trapped in the dialog.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Name"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb"</span> /&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb"</span> /&gt;</span><br /> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-dialog</span>&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"document.getElementById('focusDialog').open()"</span>&gt;</span>Open Dialog<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></code></pre>
61
+ </k-card>
62
+ </div>
63
+ <div class="col m-span-12 px">
64
+ <k-card label="Output">
65
+ <button onclick="document.getElementById('focusDialog').open()">Open Dialog</button>
66
+ <k-dialog
67
+ id="focusDialog"
68
+ cancel-text="Close"
69
+ confirm-text="Submit"
70
+ >
71
+ <h6 slot="title" class="m0 px">Focus Capture Dialog</h6>
72
+ <div class="p">
73
+ <p>Tab through the elements. Focus stays trapped in the dialog.</p>
74
+ <input type="text" placeholder="Name" class="mb" />
75
+ <input type="email" placeholder="Email" class="mb" />
76
+ </div>
77
+ </k-dialog>
78
+ </k-card>
79
+ </div>
80
+ </div>
46
81
 
47
- <h5><code>unwatchWindowSize(handler)</code></h5>
48
- <p>Unregisters a previously registered handler function.</p>
49
- <ul>
50
- <li><strong>handler:</strong> The same function reference that was registered</li>
51
- </ul>
82
+ <h2 id="jsRef">JavaScript Reference</h2>
52
83
 
53
- <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
54
-
55
- <h4>Responsive Component</h4>
56
- <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { watchWindowSize, unwatchWindowSize } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/watchWindowSize.js'</span>;<br /><br /><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ResponsiveComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LitElement</span> </span>{<br /> <span class="hljs-keyword">constructor</span>() {<br /> <span class="hljs-keyword">super</span>();<br /> <span class="hljs-keyword">this</span>.isMobile = <span class="hljs-literal">false</span>;<br /> <span class="hljs-keyword">this</span>.resizeHandler = <span class="hljs-keyword">this</span>.handleResize.bind(<span class="hljs-keyword">this</span>);<br /> }<br /><br /> connectedCallback() {<br /> <span class="hljs-keyword">super</span>.connectedCallback();<br /> <span class="hljs-keyword">const</span> currentWidth = watchWindowSize(<span class="hljs-keyword">this</span>.resizeHandler);<br /> <span class="hljs-keyword">this</span>.handleResize(currentWidth);<br /> }<br /><br /> disconnectedCallback() {<br /> <span class="hljs-keyword">super</span>.disconnectedCallback();<br /> unwatchWindowSize(<span class="hljs-keyword">this</span>.resizeHandler);<br /> }<br /><br /> handleResize(width) {<br /> <span class="hljs-keyword">this</span>.isMobile = width &lt; <span class="hljs-number">768</span>;<br /> <span class="hljs-keyword">this</span>.requestUpdate();<br /> }<br /><br /> render() {<br /> <span class="hljs-keyword">return</span> html`<span class="xml"><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"</span></span></span><span class="hljs-subst">${<span class="hljs-keyword">this</span>.isMobile ? <span class="hljs-string">'mobile'</span> : <span class="hljs-string">'desktop'</span>}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span><br /> Content adapts to screen size<br /> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> `</span>;<br /> }<br />}</code></pre>
84
+ <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
85
+ <h6>Extends LitElement</h6>
86
+ <h5>
87
+ <code>new FocusCapture()</code>
88
+ </h5>
57
89
 
58
- <h4>Multiple Handlers</h4>
59
- <pre><code class="hljs javascript"><span class="hljs-comment">// Handler for navigation</span><br /><span class="hljs-keyword">const</span> navHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">const</span> nav = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.navigation'</span>);<br /> nav.classList.toggle(<span class="hljs-string">'mobile'</span>, width &lt; <span class="hljs-number">1024</span>);<br />};<br /><br /><span class="hljs-comment">// Handler for sidebar</span><br /><span class="hljs-keyword">const</span> sidebarHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">const</span> sidebar = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.sidebar'</span>);<br /> sidebar.style.display = width &lt; <span class="hljs-number">768</span> ? <span class="hljs-string">'none'</span> : <span class="hljs-string">'block'</span>;<br />};<br /><br /><span class="hljs-comment">// Both handlers will be called on resize</span><br />watchWindowSize(navHandler);<br />watchWindowSize(sidebarHandler);<br /><br /><span class="hljs-comment">// Clean up when needed</span><br />unwatchWindowSize(navHandler);<br />unwatchWindowSize(sidebarHandler);</code></pre>
90
+ <h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
91
+ <ul>
92
+ <li>Lit</li>
93
+ </ul>
60
94
 
61
- <h4>Breakpoint Detection</h4>
62
- <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> breakpoints = {<br /> <span class="hljs-attr">mobile</span>: <span class="hljs-number">768</span>,<br /> <span class="hljs-attr">tablet</span>: <span class="hljs-number">1024</span>,<br /> <span class="hljs-attr">desktop</span>: <span class="hljs-number">1200</span><br />};<br /><br /><span class="hljs-keyword">const</span> breakpointHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">let</span> currentBreakpoint = <span class="hljs-string">'mobile'</span>;<br /> <br /> <span class="hljs-keyword">if</span> (width &gt;= breakpoints.desktop) {<br /> currentBreakpoint = <span class="hljs-string">'desktop'</span>;<br /> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (width &gt;= breakpoints.tablet) {<br /> currentBreakpoint = <span class="hljs-string">'tablet'</span>;<br /> }<br /> <br /> <span class="hljs-built_in">document</span>.body.setAttribute(<span class="hljs-string">'data-breakpoint'</span>, currentBreakpoint);<br /> <br /> <span class="hljs-comment">// Dispatch custom event</span><br /> <span class="hljs-built_in">window</span>.dispatchEvent(<span class="hljs-keyword">new</span> CustomEvent(<span class="hljs-string">'breakpointchange'</span>, {<br /> <span class="hljs-attr">detail</span>: { width, <span class="hljs-attr">breakpoint</span>: currentBreakpoint }<br /> }));<br />};<br /><br />watchWindowSize(breakpointHandler);</code></pre>
95
+ <h3 id="properties"><a href="#properties" class="no-link">Properties</a></h3>
96
+ <h5><code>afterFocus<i>: function</i></code></h5>
97
+ <p>A method that is called when focus reaches the end capture element. By default, it finds the first focusable element within the component and focuses it. Focusable elements include: <code>button</code>, <code>[href]</code>, <code>input</code>, <code>select</code>, <code>textarea</code>, and <code>[tabindex]:not([tabindex="-1"])</code>.</p>
63
98
 
64
- <h4>Performance Benefits</h4>
65
- <p>The utility automatically debounces resize events, so you don't need to worry about performance:</p>
66
- <pre><code class="hljs javascript"><span class="hljs-comment">// This handler will only be called after resize events stop</span><br /><span class="hljs-keyword">const</span> expensiveHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-comment">// Expensive DOM calculations or API calls</span><br /> recalculateLayout();<br /> updateCharts();<br /> reflow();<br />};<br /><br />watchWindowSize(expensiveHandler); <span class="hljs-comment">// Automatically debounced</span></code></pre>
99
+ <h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
100
+ <h5><code>render()<i>: TemplateResult</i></code></h5>
101
+ <p>Renders the component with a slot for children and an invisible div with <code>tabindex="0"</code> that captures focus and cycles it back to the beginning.</p>
67
102
 
68
103
  </main>
69
104
  <div style="height:33vh"></div>
105
+ <script type="module" src="../src/components/Import.js"></script>
106
+ <script type="module" src="../src/components/FocusCapture.js"></script>
107
+ <script type="module" src="../src/components/Dialog.js"></script>
70
108
  </body>
71
109
  </html>
@@ -3,9 +3,8 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>watchWindowSize - Kempo UI</title>
7
- <link rel="stylesheet" href="../kempo-vars.css" />
8
- <link rel="stylesheet" href="../kempo.min.css" />
6
+ <title>HybridComponent - Base Components - Kempo Docs - A Web Components Solution</title>
7
+ <link rel="stylesheet" href="../kempo-vars.css" /><link rel="stylesheet" href="../kempo.min.css" />
9
8
  <link rel="stylesheet" href="../kempo-hljs.css" />
10
9
  <link rel="stylesheet" href="../styles.css" />
11
10
  <script>window.litDisableBundleWarning = true;</script>
@@ -13,59 +12,98 @@
13
12
  </head>
14
13
  <body>
15
14
  <k-import src="../nav.inc.html"></k-import>
15
+ <h1 class="ta-center">HybridComponent</h1>
16
16
  <main>
17
- <h1>watchWindowSize</h1>
18
-
19
- <details
20
- class="b r mb"
21
- >
17
+ <details class="b r mb">
22
18
  <summary class="p">Table of Contents</summary>
23
19
  <div class="m mt0 pl">
24
- <h6>Usage</h6>
20
+ <h6>Guide</h6>
21
+ <a href="#overview">Overview</a><br />
25
22
  <a href="#basicUsage">Basic Usage</a><br />
26
- <a href="#functions">Functions</a><br />
27
- <a href="#examples">Examples</a><br />
23
+ <a href="#whenToUse">When to Use</a><br />
24
+
25
+ <h6 class="mt">JavaScript Reference</h6>
26
+ <a href="#constructor">Constructor</a><br />
27
+ <a href="#requirements">Requirements</a><br />
28
+ <a href="#properties">Properties</a><br />
29
+ <a href="#methods">Methods</a><br />
28
30
  </div>
29
31
  </details>
30
32
 
31
- <h3>Description</h3>
32
- <p>The <code>watchWindowSize</code> utility provides a debounced way to monitor window resize events. It manages multiple handlers efficiently and automatically debounces resize events to improve performance.</p>
33
+ <h3 id="overview"><a href="#overview" class="no-link">Overview</a></h3>
34
+ <p>HybridComponent is a base class that extends <a href="shadow-component.html">ShadowComponent</a> and provides both shadow DOM rendering with Kempo CSS styles AND light DOM rendering. Use this when you want your component to:</p>
35
+ <ul>
36
+ <li>Have shadow DOM with Kempo CSS for internal UI elements</li>
37
+ <li>Also render content to the light DOM alongside natural children</li>
38
+ <li>Combine the benefits of both shadow and light DOM</li>
39
+ </ul>
40
+ <p>Components like <a href="collapsible.html">Collapsible</a>, <a href="dialog.html">Dialog</a>, and <a href="side-menu.html">SideMenu</a> extend HybridComponent.</p>
33
41
 
34
42
  <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
35
- <p>Import and use the window size watching functions:</p>
36
- <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { watchWindowSize, unwatchWindowSize } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/watchWindowSize.js'</span>;<br /><br /><span class="hljs-keyword">const</span> handler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Window width:'</span>, width);<br />};<br /><br /><span class="hljs-comment">// Start watching</span><br /><span class="hljs-keyword">const</span> currentWidth = watchWindowSize(handler);<br /><br /><span class="hljs-comment">// Stop watching when done</span><br />unwatchWindowSize(handler);</code></pre>
43
+ <p>Create a custom component by extending HybridComponent and implementing both <code>render()</code> for shadow DOM and <code>renderLightDom()</code> for light DOM:</p>
44
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> HybridComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./HybridComponent.js'</span>;<br /><span class="hljs-keyword">import</span> { html, css } <span class="hljs-keyword">from</span> <span class="hljs-string">'../lit-all.min.js'</span>;<br /><br /><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MyHybridComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">HybridComponent</span> {<br /> <span class="hljs-keyword">static</span> properties = {<br /> <span class="hljs-attr">title</span>: { <span class="hljs-attr">type</span>: <span class="hljs-title class_">String</span> }<br /> };<br /><br /> <span class="hljs-keyword">static</span> styles = css<span class="hljs-string">`<br /> :host {<br /> display: block;<br /> }<br /> .shadow-content {<br /> background: var(--c_primary);<br /> color: var(--tc_on_primary);<br /> padding: var(--spacer);<br /> }<br /> `</span>;<br /><br /> <span class="hljs-title function_">constructor</span>() {<br /> <span class="hljs-variable language_">super</span>();<br /> <span class="hljs-variable language_">this</span>.title = <span class="hljs-string">'Hybrid'</span>;<br /> }<br /><br /> <span class="hljs-comment">// Shadow DOM content with Kempo CSS styles</span><br /> <span class="hljs-title function_">render</span>() {<br /> <span class="hljs-keyword">return</span> html<span class="hljs-string">`<br /> &lt;div class="shadow-content"&gt;<br /> &lt;h3&gt;<span class="hljs-subst">${<span class="hljs-variable language_">this</span>.title}</span> Component&lt;/h3&gt;<br /> &lt;slot name="lightRoot"&gt;&lt;/slot&gt;<br /> &lt;/div&gt;<br /> `</span>;<br /> }<br /><br /> <span class="hljs-comment">// Light DOM content alongside natural children</span><br /> <span class="hljs-title function_">renderLightDom</span>() {<br /> <span class="hljs-keyword">return</span> html<span class="hljs-string">`<br /> &lt;p class="p"&gt;This is rendered to light DOM&lt;/p&gt;<br /> &lt;slot&gt;&lt;/slot&gt;<br /> `</span>;<br /> }<br />}<br /><br /><span class="hljs-variable language_">customElements</span>.<span class="hljs-title function_">define</span>(<span class="hljs-string">'my-hybrid-component'</span>, MyHybridComponent);</code></pre>
45
+
46
+ <p><strong>Important:</strong> The default <code>render()</code> method includes <code>&lt;slot name="lightRoot"&gt;&lt;/slot&gt;</code> which is where the light DOM content appears. If you override <code>render()</code>, make sure to include this slot.</p>
37
47
 
38
- <h3 id="functions"><a href="#functions" class="no-link">Functions</a></h3>
48
+ <p><strong>Also Important:</strong> Always call <code>super.updated()</code> when overriding the <code>updated()</code> lifecycle method:</p>
49
+ <pre><code class="hljs javascript"><span class="hljs-title function_">updated</span>(changedProperties) {<br /> <span class="hljs-variable language_">super</span>.<span class="hljs-title function_">updated</span>(); <span class="hljs-comment">// Required!</span><br /> <br /> <span class="hljs-comment">// Your custom logic here</span><br />}</code></pre>
50
+
51
+ <h3 id="whenToUse"><a href="#whenToUse" class="no-link">When to Use</a></h3>
52
+ <p>Use HybridComponent when:</p>
53
+ <ul>
54
+ <li>You need styled internal UI elements (buttons, headers, etc.) in shadow DOM</li>
55
+ <li>You also need to render content to light DOM alongside natural children</li>
56
+ <li>You want Kempo CSS styles for your component UI but need flexibility for user content</li>
57
+ </ul>
39
58
 
40
- <h5><code>watchWindowSize(handler)</code></h5>
41
- <p>Registers a handler function to be called when the window is resized.</p>
59
+ <p><strong>Example use cases:</strong></p>
42
60
  <ul>
43
- <li><strong>handler:</strong> Function that receives the new window width</li>
44
- <li><strong>Returns:</strong> Current window width</li>
61
+ <li><strong>Dialog:</strong> Shadow DOM for styled dialog chrome (header, footer, overlay), light DOM for user content</li>
62
+ <li><strong>Collapsible:</strong> Shadow DOM for toggle button, light DOM for collapsible content</li>
63
+ <li><strong>SideMenu:</strong> Shadow DOM for menu structure and styling, light DOM for menu items</li>
45
64
  </ul>
46
65
 
47
- <h5><code>unwatchWindowSize(handler)</code></h5>
48
- <p>Unregisters a previously registered handler function.</p>
66
+ <p>Use <a href="shadow-component.html">ShadowComponent</a> instead when you only need shadow DOM.</p>
67
+ <p>Use <a href="light-component.html">LightComponent</a> instead when you only need light DOM.</p>
68
+
69
+ <h2 id="jsRef">JavaScript Reference</h2>
70
+
71
+ <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
72
+ <h6>Extends ShadowComponent</h6>
73
+ <h5><code>new HybridComponent()</code></h5>
74
+ <p>Creates a new HybridComponent instance with both shadow DOM (with Kempo CSS) and light DOM rendering.</p>
75
+
76
+ <h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
49
77
  <ul>
50
- <li><strong>handler:</strong> The same function reference that was registered</li>
78
+ <li>Lit (html, render)</li>
79
+ <li><a href="shadow-component.html">ShadowComponent</a></li>
51
80
  </ul>
52
81
 
53
- <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
54
-
55
- <h4>Responsive Component</h4>
56
- <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { watchWindowSize, unwatchWindowSize } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/watchWindowSize.js'</span>;<br /><br /><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ResponsiveComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LitElement</span> </span>{<br /> <span class="hljs-keyword">constructor</span>() {<br /> <span class="hljs-keyword">super</span>();<br /> <span class="hljs-keyword">this</span>.isMobile = <span class="hljs-literal">false</span>;<br /> <span class="hljs-keyword">this</span>.resizeHandler = <span class="hljs-keyword">this</span>.handleResize.bind(<span class="hljs-keyword">this</span>);<br /> }<br /><br /> connectedCallback() {<br /> <span class="hljs-keyword">super</span>.connectedCallback();<br /> <span class="hljs-keyword">const</span> currentWidth = watchWindowSize(<span class="hljs-keyword">this</span>.resizeHandler);<br /> <span class="hljs-keyword">this</span>.handleResize(currentWidth);<br /> }<br /><br /> disconnectedCallback() {<br /> <span class="hljs-keyword">super</span>.disconnectedCallback();<br /> unwatchWindowSize(<span class="hljs-keyword">this</span>.resizeHandler);<br /> }<br /><br /> handleResize(width) {<br /> <span class="hljs-keyword">this</span>.isMobile = width &lt; <span class="hljs-number">768</span>;<br /> <span class="hljs-keyword">this</span>.requestUpdate();<br /> }<br /><br /> render() {<br /> <span class="hljs-keyword">return</span> html`<span class="xml"><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"</span></span></span><span class="hljs-subst">${<span class="hljs-keyword">this</span>.isMobile ? <span class="hljs-string">'mobile'</span> : <span class="hljs-string">'desktop'</span>}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span><br /> Content adapts to screen size<br /> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> `</span>;<br /> }<br />}</code></pre>
82
+ <h3 id="properties"><a href="#properties" class="no-link">Properties</a></h3>
83
+ <h5><code>lightRoot<i>: HTMLElement</i></code></h5>
84
+ <p>A container element with <code>display: contents</code> that holds the rendered light DOM content. It has <code>slot="lightRoot"</code> to connect it to the shadow DOM slot. Created automatically by <code>createRenderRoot()</code>.</p>
85
+
86
+ <h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
87
+ <h5><code>createRenderRoot()<i>: Element</i></code></h5>
88
+ <p>Creates both shadow DOM (via <code>super.createRenderRoot()</code>) and light DOM render containers. This method:</p>
89
+ <ul>
90
+ <li>Calls the parent ShadowComponent's <code>createRenderRoot()</code> to set up shadow DOM with Kempo CSS</li>
91
+ <li>Creates a <code>lightRoot</code> div with <code>display: contents</code> and <code>slot="lightRoot"</code></li>
92
+ <li>Appends <code>lightRoot</code> to the component element</li>
93
+ <li>Returns the shadow render container</li>
94
+ </ul>
57
95
 
58
- <h4>Multiple Handlers</h4>
59
- <pre><code class="hljs javascript"><span class="hljs-comment">// Handler for navigation</span><br /><span class="hljs-keyword">const</span> navHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">const</span> nav = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.navigation'</span>);<br /> nav.classList.toggle(<span class="hljs-string">'mobile'</span>, width &lt; <span class="hljs-number">1024</span>);<br />};<br /><br /><span class="hljs-comment">// Handler for sidebar</span><br /><span class="hljs-keyword">const</span> sidebarHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">const</span> sidebar = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.sidebar'</span>);<br /> sidebar.style.display = width &lt; <span class="hljs-number">768</span> ? <span class="hljs-string">'none'</span> : <span class="hljs-string">'block'</span>;<br />};<br /><br /><span class="hljs-comment">// Both handlers will be called on resize</span><br />watchWindowSize(navHandler);<br />watchWindowSize(sidebarHandler);<br /><br /><span class="hljs-comment">// Clean up when needed</span><br />unwatchWindowSize(navHandler);<br />unwatchWindowSize(sidebarHandler);</code></pre>
96
+ <h5><code>updated()<i>: void</i></code></h5>
97
+ <p>Called automatically by Lit when the component updates. Renders the result of <code>renderLightDom()</code> into <code>lightRoot</code>. Override this method if needed, but always call <code>super.updated()</code>.</p>
60
98
 
61
- <h4>Breakpoint Detection</h4>
62
- <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> breakpoints = {<br /> <span class="hljs-attr">mobile</span>: <span class="hljs-number">768</span>,<br /> <span class="hljs-attr">tablet</span>: <span class="hljs-number">1024</span>,<br /> <span class="hljs-attr">desktop</span>: <span class="hljs-number">1200</span><br />};<br /><br /><span class="hljs-keyword">const</span> breakpointHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-keyword">let</span> currentBreakpoint = <span class="hljs-string">'mobile'</span>;<br /> <br /> <span class="hljs-keyword">if</span> (width &gt;= breakpoints.desktop) {<br /> currentBreakpoint = <span class="hljs-string">'desktop'</span>;<br /> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (width &gt;= breakpoints.tablet) {<br /> currentBreakpoint = <span class="hljs-string">'tablet'</span>;<br /> }<br /> <br /> <span class="hljs-built_in">document</span>.body.setAttribute(<span class="hljs-string">'data-breakpoint'</span>, currentBreakpoint);<br /> <br /> <span class="hljs-comment">// Dispatch custom event</span><br /> <span class="hljs-built_in">window</span>.dispatchEvent(<span class="hljs-keyword">new</span> CustomEvent(<span class="hljs-string">'breakpointchange'</span>, {<br /> <span class="hljs-attr">detail</span>: { width, <span class="hljs-attr">breakpoint</span>: currentBreakpoint }<br /> }));<br />};<br /><br />watchWindowSize(breakpointHandler);</code></pre>
99
+ <h5><code>renderLightDom()<i>: TemplateResult</i></code></h5>
100
+ <p>Override this method to define what should be rendered to the light DOM. Returns an empty template by default. Use Lit's <code>html</code> tagged template literal to return your content. Typically includes a <code>&lt;slot&gt;&lt;/slot&gt;</code> for natural children.</p>
63
101
 
64
- <h4>Performance Benefits</h4>
65
- <p>The utility automatically debounces resize events, so you don't need to worry about performance:</p>
66
- <pre><code class="hljs javascript"><span class="hljs-comment">// This handler will only be called after resize events stop</span><br /><span class="hljs-keyword">const</span> expensiveHandler = <span class="hljs-function">(<span class="hljs-params">width</span>) =&gt;</span> {<br /> <span class="hljs-comment">// Expensive DOM calculations or API calls</span><br /> recalculateLayout();<br /> updateCharts();<br /> reflow();<br />};<br /><br />watchWindowSize(expensiveHandler); <span class="hljs-comment">// Automatically debounced</span></code></pre>
102
+ <h5><code>render()<i>: TemplateResult</i></code></h5>
103
+ <p>Override this method to define what should be rendered to the shadow DOM. The default implementation returns <code>html`&lt;slot name="lightRoot"&gt;&lt;/slot&gt;`</code> which displays the light DOM content. When overriding, make sure to include this slot where you want the light DOM content to appear.</p>
67
104
 
68
105
  </main>
69
106
  <div style="height:33vh"></div>
107
+ <script type="module" src="../src/components/Import.js"></script>
70
108
  </body>
71
109
  </html>