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>PersistantCollapsible - 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,105 @@
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">PersistantCollapsible</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="#customLabel">Custom Label</a><br />
24
+ <a href="#customIcon">Custom Icon</a><br />
25
+
26
+ <h6 class="mt">JavaScript Reference</h6>
27
+ <a href="#constructor">Constructor</a><br />
28
+ <a href="#requirements">Requirements</a><br />
29
+ <a href="#properties">Properties</a><br />
30
+ <a href="#methods">Methods</a><br />
28
31
  </div>
29
32
  </details>
30
33
 
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
34
  <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>
35
+ <p>The <code>k-p-collapsible</code> component extends the regular <code>k-collapsible</code> with automatic state persistence using localStorage. The component remembers its opened/closed state and restores it when the page is reloaded or reopened.</p>
36
+ <p><strong>Important:</strong> The component requires an <code>id</code> attribute to function properly, as this is used as the localStorage key.</p>
37
+
38
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-p-collapsible</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example1"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"label"</span>&gt;</span>Persistent Section<span class="hljs-tag">&lt;/<span class="hljs-name">span</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>This content's visibility state will be remembered across page reloads.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-p-collapsible</span>&gt;</span></code></pre>
39
+
40
+ <k-p-collapsible id="example1" class="mb">
41
+ <span slot="label">Persistent Section</span>
42
+ <p class="p">This content's visibility state will be remembered across page reloads. Try expanding/collapsing it and then refreshing the page.</p>
43
+ </k-p-collapsible>
37
44
 
38
- <h3 id="functions"><a href="#functions" class="no-link">Functions</a></h3>
45
+ <h3 id="customLabel"><a href="#customLabel" class="no-link">Custom Label</a></h3>
46
+ <p>You can customize the label using the <code>label</code> slot, just like with regular collapsible components.</p>
39
47
 
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>
48
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-p-collapsible</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example2"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"label"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"m0"</span>&gt;</span>Settings<span class="hljs-tag">&lt;/<span class="hljs-name">h4</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">label</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">"checkbox"</span>&gt;</span> Enable notifications<br /> <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">label</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">"checkbox"</span>&gt;</span> Auto-save<br /> <span class="hljs-tag">&lt;/<span class="hljs-name">label</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-p-collapsible</span>&gt;</span></code></pre>
49
+
50
+ <k-p-collapsible id="example2" class="mb">
51
+ <h4 slot="label" class="m0">Settings</h4>
52
+ <div class="p">
53
+ <label>
54
+ <input type="checkbox"> Enable notifications
55
+ </label><br>
56
+ <label>
57
+ <input type="checkbox"> Auto-save
58
+ </label>
59
+ </div>
60
+ </k-p-collapsible>
46
61
 
47
- <h5><code>unwatchWindowSize(handler)</code></h5>
48
- <p>Unregisters a previously registered handler function.</p>
62
+ <h3 id="customIcon"><a href="#customIcon" class="no-link">Custom Icon</a></h3>
63
+ <p>Override the default chevron icon using the <code>icon</code> slot.</p>
64
+
65
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-p-collapsible</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example3"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"label"</span>&gt;</span>Advanced Options<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">k-icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"settings"</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"icon"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-icon</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>Advanced configuration options with persistent state.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-p-collapsible</span>&gt;</span></code></pre>
66
+
67
+ <k-p-collapsible id="example3" class="mb">
68
+ <span slot="label">Advanced Options</span>
69
+ <k-icon name="settings" slot="icon"></k-icon>
70
+ <p class="p">Advanced configuration options with persistent state.</p>
71
+ </k-p-collapsible>
72
+
73
+ <h2 id="jsRef">JavaScript Reference</h2>
74
+
75
+ <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
76
+ <h6>Extends <a href="./collapsible.html">Collapsible</a></h6>
77
+ <h5>
78
+ <code>new PersistantCollapsible()</code>
79
+ </h5>
80
+ <p>Creates a new PersistantCollapsible instance. The constructor takes no parameters.</p>
81
+
82
+ <h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
49
83
  <ul>
50
- <li><strong>handler:</strong> The same function reference that was registered</li>
84
+ <li><a href="./collapsible.html">Collapsible</a></li>
51
85
  </ul>
52
86
 
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>
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>
87
+ <h3 id="properties"><a href="#properties" class="no-link">Properties</a></h3>
88
+ <p>Inherits all properties from <a href="./collapsible.html">Collapsible</a>:</p>
89
+ <h5><code>opened<i>: boolean</i></code></h5>
90
+ <p>Whether the collapsible is opened. This state is automatically persisted to localStorage. Syncs to <code>opened</code> attribute.</p>
91
+ <h5><code>id<i>: string</i></code> <strong>(Required)</strong></h5>
92
+ <p>A unique identifier for the component. This is used as the localStorage key and must be present for persistence to work. Syncs to <code>id</code> attribute.</p>
60
93
 
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>
94
+ <h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
95
+ <p>Inherits all methods from <a href="./collapsible.html">Collapsible</a>:</p>
96
+ <h5><code>open()<i>: void</i></code></h5>
97
+ <p>Opens the collapsible and saves the state to localStorage.</p>
98
+ <h5><code>close()<i>: void</i></code></h5>
99
+ <p>Closes the collapsible and saves the state to localStorage.</p>
100
+ <h5><code>toggle()<i>: void</i></code></h5>
101
+ <p>Toggles the collapsible open or closed and saves the state to localStorage.</p>
63
102
 
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>
103
+ <h4>Storage Behavior</h4>
104
+ <p>The component automatically:</p>
105
+ <ul>
106
+ <li>Loads its state from localStorage when connected to the DOM</li>
107
+ <li>Saves its state to localStorage whenever the <code>opened</code> property changes</li>
108
+ <li>Synchronizes state across browser tabs using storage events</li>
109
+ <li>Uses the storage key format: <code>PersistantCollapsible-{id}</code></li>
110
+ </ul>
67
111
 
68
112
  </main>
69
113
  <div style="height:33vh"></div>
114
+ <script type="module" src="../src/components/Import.js"></script>
115
+ <script type="module" src="../src/components/PersistantCollapsible.js"></script>
70
116
  </body>
71
117
  </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>PhotoViewer - 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,208 @@
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">PhotoViewer</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="#gallery">Gallery Navigation</a><br />
24
+ <a href="#globalNavigation">Global Navigation</a><br />
25
+ <a href="#customControls">Custom Controls</a><br />
26
+ <a href="#captions">Captions</a><br />
27
+
28
+ <h6 class="mt">JavaScript Reference</h6>
29
+ <a href="#constructor">Constructor</a><br />
30
+ <a href="#requirements">Requirements</a><br />
31
+ <a href="#properties">Properties</a><br />
32
+ <a href="#methods">Methods</a><br />
33
+ <a href="#events">Events</a><br />
34
+ <a href="#slots">Slots</a><br />
28
35
  </div>
29
36
  </details>
30
37
 
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
38
  <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>
39
+ <p>The <code>k-photo-viewer</code> component displays images with fullscreen viewing capabilities. Click on any image to open it in fullscreen mode.</p>
40
+
41
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span><br /> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/civic.jpg"</span><br /> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Honda Civic Type R"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Honda Civic Type R - Track-focused hot hatch<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-photo-viewer</span>&gt;</span></code></pre>
42
+
43
+ <div class="mb" style="max-width: 400px;">
44
+ <k-photo-viewer
45
+ src="../media/civic.jpg"
46
+ alt="Honda Civic Type R"
47
+ >
48
+ <p>Honda Civic Type R - Track-focused hot hatch</p>
49
+ </k-photo-viewer>
50
+ </div>
37
51
 
38
- <h3 id="functions"><a href="#functions" class="no-link">Functions</a></h3>
52
+ <h3 id="gallery"><a href="#gallery" class="no-link">Gallery Navigation</a></h3>
53
+ <p>When multiple PhotoViewer components are siblings, you can navigate between them using the arrow buttons in fullscreen mode or keyboard arrow keys.</p>
39
54
 
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
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"gallery"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/civic.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Honda Civic Type R"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>Honda Civic Type R<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span><br /> <span class="hljs-tag">&lt;/<span class="hljs-name">k-photo-viewer</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/corvette.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Chevrolet Corvette C8"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>Chevrolet Corvette C8<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span><br /> <span class="hljs-tag">&lt;/<span class="hljs-name">k-photo-viewer</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/evo.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Mitsubishi Lancer Evolution"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>Mitsubishi Lancer Evolution<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span><br /> <span class="hljs-tag">&lt;/<span class="hljs-name">k-photo-viewer</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></code></pre>
56
+
57
+ <div class="gallery mb" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; max-width: 800px;">
58
+ <k-photo-viewer
59
+ src="../media/civic.jpg"
60
+ alt="Honda Civic Type R"
61
+ >
62
+ <h6 class="m0">Honda Civic Type R</h6>
63
+ </k-photo-viewer>
64
+ <k-photo-viewer
65
+ src="../media/corvette.jpg"
66
+ alt="Chevrolet Corvette C8"
67
+ >
68
+ <h6 class="m0">Chevrolet Corvette C8</h6>
69
+ </k-photo-viewer>
70
+ <k-photo-viewer
71
+ src="../media/evo.jpg"
72
+ alt="Mitsubishi Lancer Evolution"
73
+ >
74
+ <h6 class="m0">Mitsubishi Lancer Evolution</h6>
75
+ </k-photo-viewer>
76
+ </div>
77
+
78
+ <h3 id="globalNavigation"><a href="#globalNavigation" class="no-link">Global Navigation</a></h3>
79
+ <p>With the <code>global</code> attribute, PhotoViewers can navigate between all instances on the page, not just siblings.</p>
80
+
81
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span><br /> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/gtr.jpg"</span><br /> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Nissan GT-R"</span><br /> <span class="hljs-attr">global</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>Nissan GT-R (Global Navigation)<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-photo-viewer</span>&gt;</span></code></pre>
82
+
83
+ <div class="mb" style="max-width: 300px;">
84
+ <k-photo-viewer
85
+ src="../media/gtr.jpg"
86
+ alt="Nissan GT-R"
87
+ global
88
+ >
89
+ <h6 class="m0">Nissan GT-R (Global Navigation)</h6>
90
+ <p class="m0 small">This viewer can navigate to all photos on the page</p>
91
+ </k-photo-viewer>
92
+ </div>
93
+
94
+ <h3 id="customControls"><a href="#customControls" class="no-link">Custom Controls</a></h3>
95
+ <p>Customize the fullscreen controls using slots and disable keyboard controls if needed.</p>
96
+
97
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span><br /> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/nsx.jpg"</span><br /> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Honda NSX"</span><br /> <span class="hljs-attr">keyboard-controls</span>=<span class="hljs-string">"false"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"close"</span>&gt;</span>✕<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"prev"</span>&gt;</span>◀<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"next"</span>&gt;</span>▶<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>Honda NSX<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>&gt;</span>Custom controls, keyboard disabled<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-photo-viewer</span>&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span><br /> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/evo.jpg"</span><br /> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Mitsubishi Lancer Evolution"</span><br /> <span class="hljs-attr">keyboard-controls</span>=<span class="hljs-string">"false"</span><br />&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"close"</span>&gt;</span>✕<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"prev"</span>&gt;</span>◀<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"next"</span>&gt;</span>▶<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>Mitsubishi Lancer Evolution<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>&gt;</span>Custom controls, keyboard disabled<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br /><span class="hljs-tag">&lt;/<span class="hljs-name">k-photo-viewer</span>&gt;</span></code></pre>
98
+
99
+ <div class="mb" style="max-width: 350px;">
100
+ <k-photo-viewer
101
+ src="../media/nsx.jpg"
102
+ alt="Honda NSX"
103
+ keyboard-controls="false"
104
+ >
105
+ <span slot="close">✕</span>
106
+ <span slot="prev">◀</span>
107
+ <span slot="next">▶</span>
108
+ <h6 class="m0">Honda NSX</h6>
109
+ <p class="m0">Custom controls, keyboard disabled</p>
110
+ </k-photo-viewer>
111
+ <k-photo-viewer
112
+ src="../media/evo.jpg"
113
+ alt="Mitsubishi Lancer Evolution"
114
+ keyboard-controls="false"
115
+ >
116
+ <span slot="close">✕</span>
117
+ <span slot="prev">◀</span>
118
+ <span slot="next">▶</span>
119
+ <h6 class="m0">Mitsubishi Lancer Evolution</h6>
120
+ <p class="m0">Custom controls, keyboard disabled</p>
121
+ </k-photo-viewer>
122
+ </div>
123
+
124
+ <h3 id="captions"><a href="#captions" class="no-link">Captions</a></h3>
125
+ <p>Use different captions for thumbnail view and fullscreen view using slots.</p>
126
+
127
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-photo-viewer</span><br /> <span class="hljs-attr">src</span>=<span class="hljs-string">"../media/corvette.jpg"</span><br /> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Chevrolet Corvette C8"</span><br />&gt;</span><br /> <span class="hljs-comment">&lt;!-- Default caption (thumbnail view) --&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>Corvette C8<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span><br /> <br /> <span class="hljs-comment">&lt;!-- Fullscreen caption --&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"fullscreen-caption"</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>2020 Chevrolet Corvette C8 Stingray<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span><br /> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The first mid-engine Corvette featuring a 6.2L V8 engine<span class="hljs-tag">&lt;/<span class="hljs-name">p</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-photo-viewer</span>&gt;</span></code></pre>
128
+
129
+ <div class="mb" style="max-width: 400px;">
130
+ <k-photo-viewer
131
+ src="../media/corvette.jpg"
132
+ alt="Chevrolet Corvette C8"
133
+ >
134
+ <h6 class="m0">Corvette C8</h6>
135
+ <div slot="fullscreen-caption">
136
+ <h4>2020 Chevrolet Corvette C8 Stingray</h4>
137
+ <p>The first mid-engine Corvette featuring a 6.2L V8 engine producing 495 horsepower</p>
138
+ </div>
139
+ </k-photo-viewer>
140
+ </div>
46
141
 
47
- <h5><code>unwatchWindowSize(handler)</code></h5>
48
- <p>Unregisters a previously registered handler function.</p>
142
+ <h2 id="jsRef">JavaScript Reference</h2>
143
+
144
+ <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
145
+ <h6>Extends <a href="./ShadowComponent.html">ShadowComponent</a></h6>
146
+ <h5>
147
+ <code>new PhotoViewer()</code>
148
+ </h5>
149
+ <p>Creates a new PhotoViewer instance. Configuration is done through attributes or properties.</p>
150
+
151
+ <h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
49
152
  <ul>
50
- <li><strong>handler:</strong> The same function reference that was registered</li>
153
+ <li><a href="./ShadowComponent.html">ShadowComponent</a></li>
154
+ <li><a href="./icon.html">Icon</a></li>
51
155
  </ul>
52
156
 
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>
157
+ <h3 id="properties"><a href="#properties" class="no-link">Properties</a></h3>
158
+ <h5><code>src<i>: string</i></code></h5>
159
+ <p>The URL of the image to display. Syncs with the <code>src</code> attribute.</p>
160
+ <h5><code>alt<i>: string</i></code></h5>
161
+ <p>Alternative text for the image. Syncs with the <code>alt</code> attribute.</p>
162
+ <h5><code>fullscreen<i>: boolean</i></code></h5>
163
+ <p>Whether the photo viewer is currently in fullscreen mode. Syncs with the <code>fullscreen</code> attribute.</p>
164
+ <h5><code>keyboardControls<i>: boolean</i></code></h5>
165
+ <p>Whether keyboard controls are enabled (default: true). When enabled: Enter opens fullscreen, ESC closes, arrow keys navigate. Syncs with the <code>keyboard-controls</code> attribute.</p>
166
+ <h5><code>global<i>: boolean</i></code></h5>
167
+ <p>Whether navigation should include all PhotoViewers on the page (true) or just siblings (false, default). Syncs with the <code>global</code> attribute.</p>
57
168
 
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>
169
+ <h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
170
+ <h5><code>open()<i>: void</i></code></h5>
171
+ <p>Opens the photo viewer in fullscreen mode.</p>
172
+ <h5><code>close()<i>: void</i></code></h5>
173
+ <p>Closes the fullscreen mode.</p>
174
+ <h5><code>toggle()<i>: void</i></code></h5>
175
+ <p>Toggles between fullscreen and normal mode.</p>
60
176
 
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>
177
+ <h3 id="events"><a href="#events" class="no-link">Events</a></h3>
178
+ <h5><code>fullscreenchange</code></h5>
179
+ <p>Fired when the fullscreen state changes. Event detail contains <code>{ fullscreen: boolean }</code>.</p>
180
+ <h5><code>fullscreen</code></h5>
181
+ <p>Fired when entering fullscreen mode.</p>
182
+ <h5><code>fullscreenclose</code></h5>
183
+ <p>Fired when exiting fullscreen mode.</p>
63
184
 
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>
185
+ <h3 id="slots"><a href="#slots" class="no-link">Slots</a></h3>
186
+ <h5><code>default</code></h5>
187
+ <p>Caption content displayed below the thumbnail image.</p>
188
+ <h5><code>fullscreen-caption</code></h5>
189
+ <p>Caption content displayed in fullscreen mode. If not provided, the default slot content is cloned.</p>
190
+ <h5><code>close</code></h5>
191
+ <p>Custom close button content. Defaults to a close icon.</p>
192
+ <h5><code>prev</code></h5>
193
+ <p>Custom previous button content. Defaults to a chevron-left icon.</p>
194
+ <h5><code>next</code></h5>
195
+ <p>Custom next button content. Defaults to a chevron-right icon.</p>
196
+
197
+ <h4>Keyboard Controls</h4>
198
+ <p>When <code>keyboard-controls</code> is enabled (default):</p>
199
+ <ul>
200
+ <li><strong>Enter</strong>: Open fullscreen when focused on thumbnail</li>
201
+ <li><strong>Escape</strong>: Close fullscreen</li>
202
+ <li><strong>Arrow Left</strong>: Navigate to previous photo</li>
203
+ <li><strong>Arrow Right</strong>: Navigate to next photo</li>
204
+ </ul>
205
+
206
+ <h4>Navigation Behavior</h4>
207
+ <p>Navigation between photos works as follows:</p>
208
+ <ul>
209
+ <li><strong>Sibling mode</strong> (default): Navigate only between PhotoViewer components that are direct siblings</li>
210
+ <li><strong>Global mode</strong>: Navigate between all PhotoViewer components on the page</li>
211
+ <li><strong>Wrap-around</strong>: Navigation wraps from last to first photo and vice versa</li>
212
+ <li><strong>Auto-hide</strong>: Navigation buttons are hidden when only one photo is available</li>
213
+ </ul>
67
214
 
68
215
  </main>
69
216
  <div style="height:33vh"></div>
217
+ <script type="module" src="../src/components/Import.js"></script>
218
+ <script type="module" src="../src/components/PhotoViewer.js"></script>
70
219
  </body>
71
220
  </html>