kempo-ui 0.3.5 → 0.3.7

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 (146) hide show
  1. package/AGENTS.md +2 -1
  2. package/dist/components/Aside.js +1 -1
  3. package/dist/components/Main.js +1 -1
  4. package/docs/components/accordion.html +240 -8
  5. package/docs/components/aside-items.html +13 -9
  6. package/docs/components/aside-menu.html +13 -9
  7. package/docs/components/aside-push.html +11 -6
  8. package/docs/components/aside.html +289 -115
  9. package/docs/components/card.html +238 -7
  10. package/docs/components/color-picker.html +245 -14
  11. package/docs/components/content-slider.html +240 -8
  12. package/docs/components/context.html +241 -7
  13. package/docs/components/dialog.html +238 -7
  14. package/docs/components/dropdown.html +238 -7
  15. package/docs/components/filter-list.html +239 -10
  16. package/docs/components/focus-capture.html +241 -10
  17. package/docs/components/html-editor.html +266 -35
  18. package/docs/components/hybrid-component.html +238 -6
  19. package/docs/components/icon.html +239 -9
  20. package/docs/components/import.html +239 -8
  21. package/docs/components/light-component.html +239 -7
  22. package/docs/components/nav.html +240 -8
  23. package/docs/components/photo-viewer.html +239 -9
  24. package/docs/components/resize.html +240 -9
  25. package/docs/components/shadow-component.html +239 -7
  26. package/docs/components/show-more.html +237 -8
  27. package/docs/components/sortable.html +239 -8
  28. package/docs/components/spinner.html +237 -6
  29. package/docs/components/split.html +241 -10
  30. package/docs/components/table.html +241 -11
  31. package/docs/components/tableControls.html +240 -7
  32. package/docs/components/tableCustomFields.html +241 -8
  33. package/docs/components/tableFetchRecords.html +239 -7
  34. package/docs/components/tableFieldSortHide.html +239 -7
  35. package/docs/components/tablePagination.html +246 -13
  36. package/docs/components/tablePlaceholder.html +241 -8
  37. package/docs/components/tableRecordEditing.html +241 -8
  38. package/docs/components/tableRecordFiltering.html +239 -7
  39. package/docs/components/tableRecordHiding.html +241 -9
  40. package/docs/components/tableRecordSearching.html +239 -7
  41. package/docs/components/tableRecordSelection.html +240 -7
  42. package/docs/components/tableRowControls.html +241 -8
  43. package/docs/components/tableServerSync.html +245 -11
  44. package/docs/components/tableSorting.html +239 -7
  45. package/docs/components/tabs.html +240 -7
  46. package/docs/components/tags.html +239 -7
  47. package/docs/components/theme-select.html +239 -7
  48. package/docs/components/theme-switcher.html +240 -8
  49. package/docs/components/timestamp.html +239 -8
  50. package/docs/components/toast.html +240 -8
  51. package/docs/components/toggle.html +240 -9
  52. package/docs/components/tree.html +239 -8
  53. package/docs/index.html +244 -6
  54. package/docs/prod.config.json +0 -4
  55. package/docs/src/components/Aside.js +1 -1
  56. package/docs/src/components/Main.js +1 -1
  57. package/docs/utils/context.html +237 -6
  58. package/docs/utils/cookie.html +251 -21
  59. package/docs/utils/debounce.html +236 -5
  60. package/docs/utils/drag.html +236 -5
  61. package/docs/utils/elevation.html +238 -6
  62. package/docs/utils/formatTimestamp.html +239 -9
  63. package/docs/utils/object.html +236 -5
  64. package/docs/utils/propConverters.html +233 -3
  65. package/docs/utils/string.html +236 -5
  66. package/docs/utils/theme.html +237 -6
  67. package/docs/utils/toTitleCase.html +239 -9
  68. package/docs/utils/type.html +236 -5
  69. package/docs/utils/wait.html +236 -5
  70. package/docs-src/.config.js +16 -0
  71. package/docs-src/bare.template.html +16 -0
  72. package/docs-src/components/accordion.page.html +201 -0
  73. package/docs-src/components/aside-items.page.html +36 -0
  74. package/docs-src/components/aside-menu.page.html +36 -0
  75. package/docs-src/components/aside-push.page.html +20 -0
  76. package/docs-src/components/aside.page.html +494 -0
  77. package/docs-src/components/card.page.html +78 -0
  78. package/docs-src/components/color-picker.page.html +559 -0
  79. package/docs-src/components/content-slider.page.html +266 -0
  80. package/docs-src/components/context.page.html +214 -0
  81. package/docs-src/components/dialog.page.html +365 -0
  82. package/docs-src/components/dropdown.page.html +300 -0
  83. package/docs-src/components/filter-list.page.html +117 -0
  84. package/docs-src/components/focus-capture.page.html +97 -0
  85. package/docs-src/components/html-editor.page.html +423 -0
  86. package/docs-src/components/hybrid-component.page.html +96 -0
  87. package/docs-src/components/icon.page.html +208 -0
  88. package/docs-src/components/import.page.html +76 -0
  89. package/docs-src/components/light-component.page.html +99 -0
  90. package/docs-src/components/nav.page.html +106 -0
  91. package/docs-src/components/photo-viewer.page.html +253 -0
  92. package/docs-src/components/resize.page.html +161 -0
  93. package/docs-src/components/shadow-component.page.html +84 -0
  94. package/docs-src/components/show-more.page.html +113 -0
  95. package/docs-src/components/sortable.page.html +117 -0
  96. package/docs-src/components/spinner.page.html +197 -0
  97. package/docs-src/components/split.page.html +195 -0
  98. package/docs-src/components/table.page.html +283 -0
  99. package/docs-src/components/tableControls.page.html +64 -0
  100. package/docs-src/components/tableCustomFields.page.html +124 -0
  101. package/docs-src/components/tableFetchRecords.page.html +95 -0
  102. package/docs-src/components/tableFieldSortHide.page.html +56 -0
  103. package/docs-src/components/tablePagination.page.html +85 -0
  104. package/docs-src/components/tablePlaceholder.page.html +73 -0
  105. package/docs-src/components/tableRecordEditing.page.html +161 -0
  106. package/docs-src/components/tableRecordFiltering.page.html +69 -0
  107. package/docs-src/components/tableRecordHiding.page.html +65 -0
  108. package/docs-src/components/tableRecordSearching.page.html +56 -0
  109. package/docs-src/components/tableRecordSelection.page.html +60 -0
  110. package/docs-src/components/tableRowControls.page.html +62 -0
  111. package/docs-src/components/tableServerSync.page.html +129 -0
  112. package/docs-src/components/tableSorting.page.html +54 -0
  113. package/docs-src/components/tabs.page.html +201 -0
  114. package/docs-src/components/tags.page.html +157 -0
  115. package/docs-src/components/theme-select.page.html +106 -0
  116. package/docs-src/components/theme-switcher.page.html +122 -0
  117. package/docs-src/components/timestamp.page.html +109 -0
  118. package/docs-src/components/toast.page.html +338 -0
  119. package/docs-src/components/toggle.page.html +177 -0
  120. package/docs-src/components/tree.page.html +356 -0
  121. package/docs-src/default.template.html +28 -0
  122. package/docs-src/index.page.html +312 -0
  123. package/docs-src/nav.fragment.html +228 -0
  124. package/docs-src/utils/context.page.html +143 -0
  125. package/docs-src/utils/cookie.page.html +128 -0
  126. package/docs-src/utils/debounce.page.html +42 -0
  127. package/docs-src/utils/drag.page.html +64 -0
  128. package/docs-src/utils/elevation.page.html +144 -0
  129. package/docs-src/utils/formatTimestamp.page.html +76 -0
  130. package/docs-src/utils/object.page.html +76 -0
  131. package/docs-src/utils/propConverters.page.html +73 -0
  132. package/docs-src/utils/string.page.html +66 -0
  133. package/docs-src/utils/theme.page.html +136 -0
  134. package/docs-src/utils/toTitleCase.page.html +52 -0
  135. package/docs-src/utils/type.page.html +31 -0
  136. package/docs-src/utils/wait.page.html +31 -0
  137. package/package.json +4 -4
  138. package/scripts/build.js +5 -0
  139. package/scripts/docs.js +5 -52
  140. package/src/components/Aside.js +12 -1
  141. package/src/components/Main.js +1 -1
  142. package/tests/components/Aside.browser-test.js +75 -0
  143. package/docs/dev.config.json +0 -20
  144. package/docs/nav-1.inc.html +0 -168
  145. package/docs/nav.inc.html +0 -168
  146. package/docs/nav.inc.js +0 -70
@@ -0,0 +1,76 @@
1
+ <page pageName="formatTimestamp" title="formatTimestamp - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>formatTimestamp</h1>
5
+
6
+ <k-accordion persistent-id="toc" class="b r mb">
7
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
8
+ <k-accordion-panel name="toc-panel">
9
+ <div class="m">
10
+ <h6>Usage</h6>
11
+ <a href="#basicUsage">Basic Usage</a><br />
12
+ <a href="#parameters">Parameters</a><br />
13
+ <a href="#formatTokens">Format Tokens</a><br />
14
+ <a href="#examples">Examples</a><br />
15
+ </div>
16
+ </k-accordion-panel>
17
+ </k-accordion>
18
+
19
+ <h3>Description</h3>
20
+ <p>The <code>formatTimestamp</code> utility function formats timestamps using custom format tokens or locale-specific formatting.</p>
21
+
22
+ <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
23
+ <p>Import and use the formatTimestamp function to format dates:</p>
24
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> formatTimestamp <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/formatTimestamp.js'</span>;<br /><br /><span class="hljs-keyword">const</span> timestamp = <span class="hljs-built_in">Date</span>.now();<br /><span class="hljs-keyword">const</span> formatted = formatTimestamp(timestamp, <span class="hljs-string">'YYYY-MM-DD'</span>);<br /><span class="hljs-built_in">console</span>.log(formatted); <span class="hljs-comment">// "2025-09-19"</span></code></pre>
25
+
26
+ <h3 id="parameters"><a href="#parameters" class="no-link">Parameters</a></h3>
27
+ <h5><code>timestamp<i>: number|string</i></code></h5>
28
+ <p>The timestamp to format (milliseconds since epoch).</p>
29
+ <h5><code>format<i>: string</i></code> (optional)</h5>
30
+ <p>The format string using tokens. If not provided, uses locale-specific formatting.</p>
31
+ <h5><code>forceLocale<i>: string</i></code> (optional)</h5>
32
+ <p>The locale to use for formatting when no format is specified.</p>
33
+
34
+ <h3 id="formatTokens"><a href="#formatTokens" class="no-link">Format Tokens</a></h3>
35
+ <h5><code>YYYY</code></h5>
36
+ <p>4-digit year (e.g., 2025)</p>
37
+ <h5><code>YY</code></h5>
38
+ <p>2-digit year (e.g., 25)</p>
39
+ <h5><code>MM</code></h5>
40
+ <p>2-digit month (01-12)</p>
41
+ <h5><code>M</code></h5>
42
+ <p>1-digit month (1-12)</p>
43
+ <h5><code>DD</code></h5>
44
+ <p>2-digit day (01-31)</p>
45
+ <h5><code>D</code></h5>
46
+ <p>1-digit day (1-31)</p>
47
+ <h5><code>hh</code></h5>
48
+ <p>2-digit hour (00-23)</p>
49
+ <h5><code>h</code></h5>
50
+ <p>1-digit hour (0-23)</p>
51
+ <h5><code>mm</code></h5>
52
+ <p>2-digit minute (00-59)</p>
53
+ <h5><code>m</code></h5>
54
+ <p>1-digit minute (0-59)</p>
55
+ <h5><code>ss</code></h5>
56
+ <p>2-digit second (00-59)</p>
57
+ <h5><code>s</code></h5>
58
+ <p>1-digit second (0-59)</p>
59
+ <h5><code>iiii, iii, ii, i</code></h5>
60
+ <p>Milliseconds with different padding</p>
61
+
62
+ <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
63
+
64
+ <h4>Date Formats</h4>
65
+ <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> timestamp = <span class="hljs-number">1633024800000</span>;<br /><br />formatTimestamp(timestamp, <span class="hljs-string">'YYYY-MM-DD'</span>); <span class="hljs-comment">// "2021-10-01"</span><br />formatTimestamp(timestamp, <span class="hljs-string">'MM/DD/YYYY'</span>); <span class="hljs-comment">// "10/01/2021"</span><br />formatTimestamp(timestamp, <span class="hljs-string">'DD-MM-YY'</span>); <span class="hljs-comment">// "01-10-21"</span></code></pre>
66
+
67
+ <h4>Time Formats</h4>
68
+ <pre><code class="hljs javascript">formatTimestamp(timestamp, <span class="hljs-string">'hh:mm:ss'</span>); <span class="hljs-comment">// "00:00:00"</span><br />formatTimestamp(timestamp, <span class="hljs-string">'h:mm'</span>); <span class="hljs-comment">// "0:00"</span><br />formatTimestamp(timestamp, <span class="hljs-string">'hh:mm:ss.iii'</span>); <span class="hljs-comment">// "00:00:00.000"</span></code></pre>
69
+
70
+ <h4>Combined Formats</h4>
71
+ <pre><code class="hljs javascript">formatTimestamp(timestamp, <span class="hljs-string">'YYYY-MM-DD hh:mm:ss'</span>); <br /><span class="hljs-comment">// "2021-10-01 00:00:00"</span><br /><br />formatTimestamp(timestamp, <span class="hljs-string">'MM/DD/YY at h:mm'</span>);<br /><span class="hljs-comment">// "10/01/21 at 0:00"</span></code></pre>
72
+
73
+ <h4>Locale Formatting</h4>
74
+ <pre><code class="hljs javascript"><span class="hljs-comment">// Uses browser locale when no format specified</span><br />formatTimestamp(timestamp); <span class="hljs-comment">// "10/1/2021, 12:00:00 AM"</span><br /><br /><span class="hljs-comment">// Force specific locale</span><br />formatTimestamp(timestamp, <span class="hljs-literal">null</span>, <span class="hljs-string">'de-DE'</span>); <span class="hljs-comment">// German formatting</span></code></pre>
75
+ </content>
76
+ </page>
@@ -0,0 +1,76 @@
1
+ <page pageName="Object Utilities" title="Object Utilities - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>Object Utilities</h1>
5
+
6
+ <k-accordion persistent-id="toc" class="b r mb">
7
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
8
+ <k-accordion-panel name="toc-panel">
9
+ <div class="m ">
10
+ <h6>Functions</h6>
11
+ <a href="#toJson">toJson</a><br />
12
+ <a href="#flattenObject">flattenObject</a><br />
13
+ <a href="#flattenedObjects">flattenedObjects</a><br />
14
+ <a href="#objectSummary">objectSummary</a><br />
15
+ <a href="#clone">clone</a><br />
16
+ <a href="#equalObjs">equalObjs</a><br />
17
+ <a href="#prune">prune</a><br />
18
+ <a href="#getAllKeys">getAllKeys</a><br />
19
+ <a href="#getDifferencesKeys">getDifferencesKeys</a><br />
20
+ <a href="#diff">diff</a><br />
21
+ <a href="#mapObject">mapObject</a><br />
22
+ </div>
23
+ </k-accordion-panel>
24
+ </k-accordion>
25
+
26
+ <h3>Description</h3>
27
+ <p>The object utilities module provides functions for manipulating, transforming, and analyzing JavaScript objects, including JSON serialization, flattening, cloning, comparison, and more.</p>
28
+
29
+ <h3 id="toJson"><a href="#toJson" class="no-link">toJson</a></h3>
30
+ <p>Converts an object to JSON string with special handling for circular references, DOM elements, and functions.</p>
31
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { toJson } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br /><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">name</span>: <span class="hljs-string">'test'</span>, <span class="hljs-attr">func</span>: () => {} };<br />toJson(obj); <span class="hljs-comment">// '{"name":"test","func":"&lt;&lt;Function func&gt;&gt;"}'</span></code></pre>
32
+
33
+ <h3 id="flattenObject"><a href="#flattenObject" class="no-link">flattenObject</a></h3>
34
+ <p>Flattens a nested object into a single-level object with dot-notation keys.</p>
35
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { flattenObject } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br /><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">user</span>: { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> } };<br />flattenObject(obj); <span class="hljs-comment">// { "user.name": "John", "user.age": 30 }</span></code></pre>
36
+
37
+ <h3 id="flattenedObjects"><a href="#flattenedObjects" class="no-link">flattenedObjects</a></h3>
38
+ <p>Flattens multiple objects and returns them as an array.</p>
39
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { flattenedObjects } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br />flattenedObjects({<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>}, {<span class="hljs-attr">b</span>: <span class="hljs-number">2</span>}); <span class="hljs-comment">// [{ "a": 1 }, { "b": 2 }]</span></code></pre>
40
+
41
+ <h3 id="objectSummary"><a href="#objectSummary" class="no-link">objectSummary</a></h3>
42
+ <p>Creates a summary string representation of an object.</p>
43
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { objectSummary } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br /><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">30</span> };<br />objectSummary(obj); <span class="hljs-comment">// "name = John, age = 30"</span></code></pre>
44
+
45
+ <h3 id="clone"><a href="#clone" class="no-link">clone</a></h3>
46
+ <p>Creates a deep clone of an object with special handling for different types.</p>
47
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { clone } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br /><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">items</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>] };<br />clone(obj); <span class="hljs-comment">// { items: [1, 2, 3] } (new array)</span></code></pre>
48
+
49
+ <h3 id="equalObjs"><a href="#equalObjs" class="no-link">equalObjs</a></h3>
50
+ <p>Checks if multiple objects are equal by comparing their JSON representations.</p>
51
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { equalObjs } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br />equalObjs({<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>}, {<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>}); <span class="hljs-comment">// true</span><br />equalObjs({<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>}, {<span class="hljs-attr">a</span>: <span class="hljs-number">2</span>}); <span class="hljs-comment">// false</span></code></pre>
52
+
53
+ <h3 id="prune"><a href="#prune" class="no-link">prune</a></h3>
54
+ <p>Removes empty/undefined properties from an object recursively.</p>
55
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { prune } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br /><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">empty</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">nested</span>: { <span class="hljs-attr">value</span>: <span class="hljs-literal">null</span> } };<br />prune(obj); <span class="hljs-comment">// { name: "John" }</span></code></pre>
56
+
57
+ <h3 id="getAllKeys"><a href="#getAllKeys" class="no-link">getAllKeys</a></h3>
58
+ <p>Gets all unique keys from multiple objects.</p>
59
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { getAllKeys } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br />getAllKeys({<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">2</span>}, {<span class="hljs-attr">b</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">c</span>: <span class="hljs-number">4</span>}); <span class="hljs-comment">// ["a", "b", "c"]</span></code></pre>
60
+
61
+ <h3 id="getDifferencesKeys"><a href="#getDifferencesKeys" class="no-link">getDifferencesKeys</a></h3>
62
+ <p>Gets keys that have different values across multiple objects.</p>
63
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { getDifferencesKeys } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br />getDifferencesKeys({<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">2</span>}, {<span class="hljs-attr">a</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">3</span>}); <span class="hljs-comment">// ["b"]</span></code></pre>
64
+
65
+ <h3 id="diff"><a href="#diff" class="no-link">diff</a></h3>
66
+ <p>Computes the differences between two objects.</p>
67
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { diff } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br /><span class="hljs-keyword">const</span> obj1 = { <span class="hljs-attr">a</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">2</span> };<br /><span class="hljs-keyword">const</span> obj2 = { <span class="hljs-attr">a</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">3</span> };<br />diff(obj1, obj2); <span class="hljs-comment">// { "b": { newValue: 2, oldValue: 3 } }</span></code></pre>
68
+
69
+ <h3 id="mapObject"><a href="#mapObject" class="no-link">mapObject</a></h3>
70
+ <p>Maps over an object's entries using a function that returns [newKey, newValue].</p>
71
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { mapObject } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/object.js'</span>;<br /><br /><span class="hljs-keyword">const</span> obj = { <span class="hljs-attr">a</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">2</span> };<br />mapObject(obj, (k, v) => [`new_${k}`, v * <span class="hljs-number">2</span>]); <span class="hljs-comment">// { new_a: 2, new_b: 4 }</span></code></pre>
72
+ </content>
73
+ <content location="scripts">
74
+ <script type="module" src="{{pathToRoot}}src/components/Accordion.js"></script>
75
+ </content>
76
+ </page>
@@ -0,0 +1,73 @@
1
+ <page pageName="propConverters" title="propConverters - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>propConverters</h1>
5
+
6
+ <details
7
+ class="b r mb"
8
+ >
9
+ <summary class="p">Table of Contents</summary>
10
+ <div class="m mt0 pl">
11
+ <h6>Usage</h6>
12
+ <a href="#basicUsage">Basic Usage</a><br />
13
+ <a href="#boolTrueFalse">boolTrueFalse</a><br />
14
+ <a href="#boolExists">boolExists</a><br />
15
+ <a href="#examples">Examples</a><br />
16
+ </div>
17
+ </details>
18
+
19
+ <h3>Description</h3>
20
+ <p>The <code>propConverters</code> module provides Lit Element property converters for handling boolean attributes in web components. These converters manage the conversion between JavaScript boolean values and HTML attribute strings.</p>
21
+
22
+ <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
23
+ <p>Import and use the converters in your Lit Element component properties:</p>
24
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { boolTrueFalse, boolExists } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/propConverters.js'</span>;<br /><br /><span class="hljs-keyword">static</span> properties = {<br /> <span class="hljs-attr">enabled</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">reflect</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">converter</span>: boolTrueFalse },<br /> <span class="hljs-attr">visible</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">reflect</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">converter</span>: boolExists }<br />};</code></pre>
25
+
26
+ <h3 id="boolTrueFalse"><a href="#boolTrueFalse" class="no-link">boolTrueFalse</a></h3>
27
+ <p>Converts between boolean values and explicit "true"/"false" string attributes.</p>
28
+
29
+ <h4>Behavior</h4>
30
+ <ul>
31
+ <li><strong>fromAttribute:</strong> "true" → true, "false" → false, null → undefined</li>
32
+ <li><strong>toAttribute:</strong> true → "true", false → "false"</li>
33
+ </ul>
34
+
35
+ <h4>HTML Usage</h4>
36
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span> <span class="hljs-attr">enabled</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span> <span class="hljs-attr">enabled</span>=<span class="hljs-string">"false"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span></code></pre>
37
+
38
+ <h3 id="boolExists"><a href="#boolExists" class="no-link">boolExists</a></h3>
39
+ <p>Converts between boolean values and attribute presence/absence.</p>
40
+
41
+ <h4>Behavior</h4>
42
+ <ul>
43
+ <li><strong>fromAttribute:</strong> attribute present → true, attribute absent → false</li>
44
+ <li><strong>toAttribute:</strong> true → "", false → null (removes attribute)</li>
45
+ </ul>
46
+
47
+ <h4>HTML Usage</h4>
48
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span> <span class="hljs-attr">visible</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span> <span class="hljs-comment">&lt;!-- visible = true --&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span> <span class="hljs-comment">&lt;!-- visible = false --&gt;</span></code></pre>
49
+
50
+ <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
51
+
52
+ <h4>Component with Both Converters</h4>
53
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { LitElement, html } <span class="hljs-keyword">from</span> <span class="hljs-string">'lit'</span>;<br /><span class="hljs-keyword">import</span> { boolTrueFalse, boolExists } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/propConverters.js'</span>;<br /><br /><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LitElement</span> </span>{<br /> <span class="hljs-keyword">static</span> properties = {<br /> <span class="hljs-attr">autoplay</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">reflect</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">converter</span>: boolTrueFalse },<br /> <span class="hljs-attr">hidden</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">reflect</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">converter</span>: boolExists },<br /> <span class="hljs-attr">loop</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Boolean</span>, <span class="hljs-attr">reflect</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">converter</span>: boolTrueFalse }<br /> };<br /><br /> <span class="hljs-keyword">constructor</span>() {<br /> <span class="hljs-keyword">super</span>();<br /> <span class="hljs-keyword">this</span>.autoplay = <span class="hljs-literal">false</span>;<br /> <span class="hljs-keyword">this</span>.hidden = <span class="hljs-literal">false</span>;<br /> <span class="hljs-keyword">this</span>.loop = <span class="hljs-literal">false</span>;<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">hidden</span>=<span class="hljs-string">"</span></span></span><span class="hljs-subst">${<span class="hljs-keyword">this</span>.hidden}</span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span>&gt;</span><br /> Content </span><span class="hljs-subst">${<span class="hljs-keyword">this</span>.autoplay ? <span class="hljs-string">'with'</span> : <span class="hljs-string">'without'</span>}</span><span class="xml"> autoplay<br /> </span><span class="hljs-subst">${<span class="hljs-keyword">this</span>.loop ? <span class="hljs-string">'(looping)'</span> : <span class="hljs-string">''</span>}</span><span class="xml"><br /> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br /> `</span>;<br /> }<br />}</code></pre>
54
+
55
+ <h4>HTML Usage Examples</h4>
56
+ <pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- Using boolTrueFalse converter --&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span> <span class="hljs-attr">autoplay</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">loop</span>=<span class="hljs-string">"false"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span><br /><br /><span class="hljs-comment">&lt;!-- Using boolExists converter --&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span> <span class="hljs-attr">hidden</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span><br /><br /><span class="hljs-comment">&lt;!-- Combined usage --&gt;</span><br /><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span> <span class="hljs-attr">autoplay</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">loop</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">hidden</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span></code></pre>
57
+
58
+ <h4>When to Use Each Converter</h4>
59
+ <p><strong>Use boolTrueFalse when:</strong></p>
60
+ <ul>
61
+ <li>You need explicit true/false values in HTML</li>
62
+ <li>The attribute value is important for clarity</li>
63
+ <li>Working with form controls or interactive elements</li>
64
+ </ul>
65
+
66
+ <p><strong>Use boolExists when:</strong></p>
67
+ <ul>
68
+ <li>Following HTML standards (like hidden, disabled attributes)</li>
69
+ <li>The presence of the attribute is what matters</li>
70
+ <li>Creating more semantic HTML</li>
71
+ </ul>
72
+ </content>
73
+ </page>
@@ -0,0 +1,66 @@
1
+ <page pageName="String Utilities" title="String Utilities - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>String Utilities</h1>
5
+
6
+ <k-accordion persistent-id="toc" class="b r mb">
7
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
8
+ <k-accordion-panel name="toc-panel">
9
+ <div class="m ">
10
+ <h6>Functions</h6>
11
+ <a href="#camelToDash">camelToDash</a><br />
12
+ <a href="#dashToCamel">dashToCamel</a><br />
13
+ <a href="#isCamelCase">isCamelCase</a><br />
14
+ <a href="#getCase">getCase</a><br />
15
+ <a href="#escapeHTML">escapeHTML</a><br />
16
+ <a href="#unescapeHTML">unescapeHTML</a><br />
17
+ <a href="#trim">trim</a><br />
18
+ <a href="#compoundKey">compoundKey</a><br />
19
+ <a href="#toTitleCase">toTitleCase</a><br />
20
+ </div>
21
+ </k-accordion-panel>
22
+ </k-accordion>
23
+
24
+ <h3>Description</h3>
25
+ <p>The string utilities module provides a collection of functions for manipulating and transforming strings, including case conversions, HTML escaping, and key manipulation.</p>
26
+
27
+ <h3 id="camelToDash"><a href="#camelToDash" class="no-link">camelToDash</a></h3>
28
+ <p>Converts camelCase strings to dash-case.</p>
29
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { camelToDash } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />camelToDash(<span class="hljs-string">'camelCase'</span>); <span class="hljs-comment">// "camel-case"</span></code></pre>
30
+
31
+ <h3 id="dashToCamel"><a href="#dashToCamel" class="no-link">dashToCamel</a></h3>
32
+ <p>Converts dash-case strings to camelCase.</p>
33
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { dashToCamel } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />dashToCamel(<span class="hljs-string">'dash-case'</span>); <span class="hljs-comment">// "dashCase"</span></code></pre>
34
+
35
+ <h3 id="isCamelCase"><a href="#isCamelCase" class="no-link">isCamelCase</a></h3>
36
+ <p>Checks if a string is in camelCase format.</p>
37
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { isCamelCase } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />isCamelCase(<span class="hljs-string">'camelCase'</span>); <span class="hljs-comment">// true</span><br />isCamelCase(<span class="hljs-string">'dash-case'</span>); <span class="hljs-comment">// false</span></code></pre>
38
+
39
+ <h3 id="getCase"><a href="#getCase" class="no-link">getCase</a></h3>
40
+ <p>Returns an object with both camel and dash versions of the string.</p>
41
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { getCase } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />getCase(<span class="hljs-string">'camelCase'</span>); <span class="hljs-comment">// { camel: "camelCase", dash: "camel-case" }</span><br />getCase(<span class="hljs-string">'dash-case'</span>); <span class="hljs-comment">// { camel: "dashCase", dash: "dash-case" }</span></code></pre>
42
+
43
+ <h3 id="escapeHTML"><a href="#escapeHTML" class="no-link">escapeHTML</a></h3>
44
+ <p>Escapes HTML special characters in a string.</p>
45
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { escapeHTML } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />escapeHTML(<span class="hljs-string">'&lt;script&gt;'</span>); <span class="hljs-comment">// "&amp;lt;script&amp;gt;"</span></code></pre>
46
+
47
+ <h3 id="unescapeHTML"><a href="#unescapeHTML" class="no-link">unescapeHTML</a></h3>
48
+ <p>Unescapes HTML entities in a string.</p>
49
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { unescapeHTML } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />unescapeHTML(<span class="hljs-string">'&amp;lt;script&amp;gt;'</span>); <span class="hljs-comment">// "&lt;script&gt;"</span></code></pre>
50
+
51
+ <h3 id="trim"><a href="#trim" class="no-link">trim</a></h3>
52
+ <p>Trims specified characters from the start and end of a string.</p>
53
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { trim } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />trim(<span class="hljs-string">'.key.value.'</span>, <span class="hljs-string">'.'</span>); <span class="hljs-comment">// "key.value"</span></code></pre>
54
+
55
+ <h3 id="compoundKey"><a href="#compoundKey" class="no-link">compoundKey</a></h3>
56
+ <p>Joins an array of keys into a compound key string.</p>
57
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { compoundKey } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />compoundKey([<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>]); <span class="hljs-comment">// "a.b.c"</span></code></pre>
58
+
59
+ <h3 id="toTitleCase"><a href="#toTitleCase" class="no-link">toTitleCase</a></h3>
60
+ <p>Converts strings to title case format, handling camelCase, snake_case, kebab-case, and regular text.</p>
61
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { toTitleCase } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br />toTitleCase(<span class="hljs-string">'helloWorld'</span>); <span class="hljs-comment">// "Hello World"</span><br />toTitleCase(<span class="hljs-string">'hello-world'</span>); <span class="hljs-comment">// "Hello World"</span><br />toTitleCase(<span class="hljs-string">'hello_world'</span>); <span class="hljs-comment">// "Hello World"</span></code></pre>
62
+ </content>
63
+ <content location="scripts">
64
+ <script type="module" src="{{pathToRoot}}src/components/Accordion.js"></script>
65
+ </content>
66
+ </page>
@@ -0,0 +1,136 @@
1
+ <page pageName="Theme Utility" title="Theme Utility - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>Theme Utility</h1>
5
+
6
+ <k-accordion persistent-id="toc" class="b r mb">
7
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
8
+ <k-accordion-panel name="toc-panel">
9
+ <div class="m ">
10
+ <h6>Usage</h6>
11
+ <a href="#basicUsage">Basic Usage</a><br />
12
+ <a href="#api">API Methods</a><br />
13
+ <a href="#examples">Examples</a><br />
14
+ </div>
15
+ </k-accordion-panel>
16
+ </k-accordion>
17
+
18
+ <h3>Description</h3>
19
+ <p>The <code>theme</code> utility provides a centralized way to manage the application's theme state. It handles theme persistence via localStorage, automatic system preference detection, and reactive updates across components. This utility works independently of the ThemeSwitcher component, allowing any part of your application to read, set, or subscribe to theme changes.</p>
20
+
21
+ <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
22
+ <p>Import and use the theme utility to manage application themes:</p>
23
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> theme <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/theme.js'</span>;<br /><br /><span class="hljs-comment">// Get current theme</span><br /><span class="hljs-keyword">const</span> currentTheme = theme.get(); <span class="hljs-comment">// 'auto', 'light', or 'dark'</span><br /><br /><span class="hljs-comment">// Set theme</span><br />theme.set(<span class="hljs-string">'dark'</span>);<br /><br /><span class="hljs-comment">// Subscribe to theme changes</span><br /><span class="hljs-keyword">const</span> unsubscribe = theme.subscribe(<span class="hljs-function">(<span class="hljs-params">newTheme</span>) =&gt;</span> {<br /> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Theme changed to:'</span>, newTheme);<br />});</code></pre>
24
+
25
+ <h3 id="api"><a href="#api" class="no-link">API Methods</a></h3>
26
+
27
+ <h4><code>theme.get()</code></h4>
28
+ <p>Returns the current theme value.</p>
29
+ <h5>Returns: <code>string</code></h5>
30
+ <p>One of: <code>'auto'</code>, <code>'light'</code>, or <code>'dark'</code></p>
31
+ <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> currentTheme = theme.get();<br /><span class="hljs-built_in">console</span>.log(currentTheme); <span class="hljs-comment">// 'auto', 'light', or 'dark'</span></code></pre>
32
+
33
+ <h4><code>theme.set(value)</code></h4>
34
+ <p>Sets the theme and automatically persists it to localStorage and updates the DOM.</p>
35
+ <h5><code>value<i>: string</i></code></h5>
36
+ <p>The theme to set. Must be one of: <code>'auto'</code>, <code>'light'</code>, or <code>'dark'</code></p>
37
+ <pre><code class="hljs javascript">theme.set(<span class="hljs-string">'dark'</span>);</code></pre>
38
+
39
+ <h4><code>theme.subscribe(callback)</code></h4>
40
+ <p>Subscribes to theme changes. The callback is immediately invoked with the current theme, then called again whenever the theme changes.</p>
41
+ <h5><code>callback<i>: Function</i></code></h5>
42
+ <p>Function to call when the theme changes. Receives the new theme value as an argument.</p>
43
+ <h5>Returns: <code>Function</code></h5>
44
+ <p>An unsubscribe function to remove the subscription.</p>
45
+ <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> unsubscribe = theme.subscribe(<span class="hljs-function">(<span class="hljs-params">newTheme</span>) =&gt;</span> {<br /> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Theme is now:'</span>, newTheme);<br />});<br /><br /><span class="hljs-comment">// Later, stop listening</span><br />unsubscribe();</code></pre>
46
+
47
+ <h4><code>theme.getCalculated()</code></h4>
48
+ <p>Returns the effective theme, resolving <code>'auto'</code> to either <code>'light'</code> or <code>'dark'</code> based on the user's system preference.</p>
49
+ <h5>Returns: <code>string</code></h5>
50
+ <p>Either <code>'light'</code> or <code>'dark'</code></p>
51
+ <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> effectiveTheme = theme.getCalculated();<br /><span class="hljs-built_in">console</span>.log(effectiveTheme); <span class="hljs-comment">// Always 'light' or 'dark'</span></code></pre>
52
+
53
+ <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
54
+
55
+ <h4>Reading Theme Without Component</h4>
56
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> theme <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/theme.js'</span>;<br /><br /><span class="hljs-comment">// Get theme anywhere in your app</span><br /><span class="hljs-keyword">const</span> currentTheme = theme.get();<br /><span class="hljs-keyword">const</span> isDark = theme.getCalculated() === <span class="hljs-string">'dark'</span>;<br /><br /><span class="hljs-keyword">if</span>(isDark){<br /> <span class="hljs-comment">// Apply dark-specific logic</span><br />}</code></pre>
57
+
58
+ <h4>Component Subscribing to Theme</h4>
59
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { LitElement, html } <span class="hljs-keyword">from</span> <span class="hljs-string">'lit'</span>;<br /><span class="hljs-keyword">import</span> theme <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/theme.js'</span>;<br /><br /><span class="hljs-keyword">class</span> <span class="hljs-title class_">MyComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">LitElement</span> {<br /> <span class="hljs-keyword">static</span> properties = {<br /> <span class="hljs-attr">theme</span>: { <span class="hljs-attr">type</span>: <span class="hljs-title class_">String</span> }<br /> };<br /><br /> <span class="hljs-title function_">connectedCallback</span>() {<br /> <span class="hljs-variable language_">super</span>.<span class="hljs-title function_">connectedCallback</span>();<br /> <span class="hljs-variable language_">this</span>.<span class="hljs-property">unsubscribe</span> = theme.<span class="hljs-title function_">subscribe</span>(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {<br /> <span class="hljs-variable language_">this</span>.<span class="hljs-property">theme</span> = t;<br /> });<br /> }<br /><br /> <span class="hljs-title function_">disconnectedCallback</span>() {<br /> <span class="hljs-variable language_">super</span>.<span class="hljs-title function_">disconnectedCallback</span>();<br /> <span class="hljs-keyword">if</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">unsubscribe</span>) <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">unsubscribe</span>();<br /> }<br /><br /> <span class="hljs-title function_">render</span>() {<br /> <span class="hljs-keyword">return</span> html<span class="hljs-string">`&lt;p&gt;Current theme: ${this.theme}&lt;/p&gt;`</span>;<br /> }<br />}</code></pre>
60
+
61
+ <h4>Setting Theme Programmatically</h4>
62
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> theme <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils/theme.js'</span>;<br /><br /><span class="hljs-comment">// Set theme based on user preference from API</span><br /><span class="hljs-keyword">const</span> userPreferences = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetchUserPreferences</span>();<br />theme.<span class="hljs-title function_">set</span>(userPreferences.<span class="hljs-property">theme</span>);<br /><br /><span class="hljs-comment">// Toggle between light and dark</span><br /><span class="hljs-keyword">const</span> <span class="hljs-title function_">toggleTheme</span> = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {<br /> <span class="hljs-keyword">const</span> current = theme.<span class="hljs-title function_">get</span>();<br /> <span class="hljs-keyword">if</span>(current === <span class="hljs-string">'dark'</span>) theme.<span class="hljs-title function_">set</span>(<span class="hljs-string">'light'</span>);<br /> <span class="hljs-keyword">else</span> theme.<span class="hljs-title function_">set</span>(<span class="hljs-string">'dark'</span>);<br />};</code></pre>
63
+
64
+ <h4>Working Example</h4>
65
+ <div class="row -mx mb">
66
+ <div class="col d-span-6 m-span-12 px">
67
+ <k-card label="HTML & JavaScript">
68
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"theme-demo"</span>&gt;</span>
69
+ <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Current theme: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"theme-display"</span>&gt;</span>auto<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
70
+ <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Calculated: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"calculated-display"</span>&gt;</span>dark<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
71
+ <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"set-auto"</span>&gt;</span>Auto<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
72
+ <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"set-light"</span>&gt;</span>Light<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
73
+ <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"set-dark"</span>&gt;</span>Dark<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
74
+ <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
75
+
76
+ <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">
77
+ <span class="hljs-keyword">import</span> theme <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/theme.js'</span>;
78
+
79
+ <span class="hljs-comment">// Subscribe to updates</span>
80
+ theme.subscribe(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
81
+ <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'theme-display'</span>).textContent = t;
82
+ <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'calculated-display'</span>).textContent =
83
+ theme.<span class="hljs-title function_">getCalculated</span>();
84
+ });
85
+
86
+ <span class="hljs-comment">// Button handlers</span>
87
+ <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'set-auto'</span>)
88
+ .<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> theme.<span class="hljs-title function_">set</span>(<span class="hljs-string">'auto'</span>));
89
+ <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'set-light'</span>)
90
+ .<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> theme.<span class="hljs-title function_">set</span>(<span class="hljs-string">'light'</span>));
91
+ <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'set-dark'</span>)
92
+ .<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> theme.<span class="hljs-title function_">set</span>(<span class="hljs-string">'dark'</span>));
93
+ </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre>
94
+ </k-card>
95
+ </div>
96
+ <div class="col d-span-6 m-span-12 px">
97
+ <k-card label="Results">
98
+ <div id="theme-demo">
99
+ <p>Current theme: <strong id="theme-display">auto</strong></p>
100
+ <p>Calculated: <strong id="calculated-display">dark</strong></p>
101
+ <button id="set-auto">Auto</button>
102
+ <button id="set-light" class="primary">Light</button>
103
+ <button id="set-dark" class="danger">Dark</button>
104
+ </div>
105
+ </k-card>
106
+ </div>
107
+ </div>
108
+
109
+ <h3>Automatic Features</h3>
110
+ <h4>localStorage Persistence</h4>
111
+ <p>The theme utility automatically saves the current theme to <code>localStorage</code> with the key <code>'theme'</code>. This means the user's theme preference persists across page reloads and browser sessions.</p>
112
+
113
+ <h4>DOM Attribute Updates & Kempo CSS Integration</h4>
114
+ <p>Whenever the theme changes, it's automatically applied to <code>document.documentElement</code> as a <code>theme</code> attribute. This sets the <code>color-scheme</code> property which enables Kempo CSS's <code>light-dark()</code> function to work correctly.</p>
115
+ <p>Kempo CSS provides theme-aware CSS custom properties that automatically adapt to light and dark modes. See the <a href="https://dustinpoissant.github.io/kempo-css/" target="_blank" rel="noopener noreferrer">Kempo CSS documentation</a> for details on available color variables and theming.</p>
116
+
117
+ <h4>System Preference Detection</h4>
118
+ <p>When the theme is set to <code>'auto'</code>, the utility monitors the system's <code>prefers-color-scheme</code> media query and updates the <code>auto-theme</code> attribute on the document element. The <code>getCalculated()</code> method resolves the actual theme based on this preference.</p>
119
+ </content>
120
+ <content location="scripts">
121
+ <script type="module" src="{{pathToRoot}}src/components/Accordion.js"></script>
122
+ <script type="module" src="{{pathToRoot}}src/components/Card.js"></script>
123
+ <script type="module">
124
+ import theme from '{{pathToRoot}}src/utils/theme.js';
125
+
126
+ theme.subscribe(t => {
127
+ document.getElementById('theme-display').textContent = t;
128
+ document.getElementById('calculated-display').textContent = theme.getCalculated();
129
+ });
130
+
131
+ document.getElementById('set-auto').addEventListener('click', () => theme.set('auto'));
132
+ document.getElementById('set-light').addEventListener('click', () => theme.set('light'));
133
+ document.getElementById('set-dark').addEventListener('click', () => theme.set('dark'));
134
+ </script>
135
+ </content>
136
+ </page>
@@ -0,0 +1,52 @@
1
+ <page pageName="toTitleCase" title="toTitleCase - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>toTitleCase</h1>
5
+
6
+ <k-accordion persistent-id="toc" class="b r mb">
7
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
8
+ <k-accordion-panel name="toc-panel">
9
+ <div class="m">
10
+ <h6>Usage</h6>
11
+ <a href="#basicUsage">Basic Usage</a><br />
12
+ <a href="#parameters">Parameters</a><br />
13
+ <a href="#returnValue">Return Value</a><br />
14
+ <a href="#examples">Examples</a><br />
15
+ </div>
16
+ </k-accordion-panel>
17
+ </k-accordion>
18
+
19
+ <h3>Description</h3>
20
+ <p>The <code>toTitleCase</code> utility function converts strings to title case format. It handles camelCase, snake_case, kebab-case, and regular text, converting them into properly capitalized title case with spaces between words.</p>
21
+ <p><strong>Note:</strong> This function is now part of the string utilities module.</p>
22
+
23
+ <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
24
+ <p>Import and use the toTitleCase function to convert strings to title case:</p>
25
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { toTitleCase } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/string.js'</span>;<br /><br /><span class="hljs-keyword">const</span> result = <span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'helloWorld'</span>);<br /><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(result); <span class="hljs-comment">// "Hello World"</span></code></pre>
26
+
27
+ <h3 id="parameters"><a href="#parameters" class="no-link">Parameters</a></h3>
28
+ <h5><code>str<i>: string</i></code></h5>
29
+ <p>The string to convert to title case. Can be in any format (camelCase, snake_case, kebab-case, or regular text).</p>
30
+
31
+ <h3 id="returnValue"><a href="#returnValue" class="no-link">Return Value</a></h3>
32
+ <h5><code><i>string</i></code></h5>
33
+ <p>The input string converted to title case with proper spacing and capitalization.</p>
34
+
35
+ <h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
36
+
37
+ <h4>Converting camelCase</h4>
38
+ <pre><code class="hljs javascript"><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'firstName'</span>); <span class="hljs-comment">// "First Name"</span><br /><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'customerAddress'</span>); <span class="hljs-comment">// "Customer Address"</span><br /><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'userId'</span>); <span class="hljs-comment">// "User Id"</span></code></pre>
39
+
40
+ <h4>Converting snake_case</h4>
41
+ <pre><code class="hljs javascript"><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'first_name'</span>); <span class="hljs-comment">// "First Name"</span><br /><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'customer_address'</span>); <span class="hljs-comment">// "Customer Address"</span><br /><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'user_id'</span>); <span class="hljs-comment">// "User Id"</span></code></pre>
42
+
43
+ <h4>Converting kebab-case</h4>
44
+ <pre><code class="hljs javascript"><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'first-name'</span>); <span class="hljs-comment">// "First Name"</span><br /><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'customer-address'</span>); <span class="hljs-comment">// "Customer Address"</span><br /><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'user-id'</span>); <span class="hljs-comment">// "User Id"</span></code></pre>
45
+
46
+ <h4>Converting regular text</h4>
47
+ <pre><code class="hljs javascript"><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'hello world'</span>); <span class="hljs-comment">// "Hello World"</span><br /><span class="hljs-title function_">toTitleCase</span>(<span class="hljs-string">'the quick brown fox'</span>); <span class="hljs-comment">// "The Quick Brown Fox"</span></code></pre>
48
+
49
+ <h4>Practical Use Case: Table Column Headers</h4>
50
+ <pre><code class="hljs javascript"><span class="hljs-keyword">const</span> columns = [<span class="hljs-string">'firstName'</span>, <span class="hljs-string">'lastName'</span>, <span class="hljs-string">'emailAddress'</span>];<br /><br /><span class="hljs-keyword">const</span> headers = columns.<span class="hljs-title function_">map</span>(<span class="hljs-function"><span class="hljs-params">col</span> =&gt;</span> <span class="hljs-title function_">toTitleCase</span>(col));<br /><span class="hljs-comment">// ["First Name", "Last Name", "Email Address"]</span></code></pre>
51
+ </content>
52
+ </page>
@@ -0,0 +1,31 @@
1
+ <page pageName="Type Utilities" title="Type Utilities - Kempo UI">
2
+ <content location="header"></content>
3
+ <content>
4
+ <h1>Type Utilities</h1>
5
+
6
+ <k-accordion persistent-id="toc" class="b r mb">
7
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
8
+ <k-accordion-panel name="toc-panel">
9
+ <div class="m ">
10
+ <h6>Functions</h6>
11
+ <a href="#typeOf">typeOf</a><br />
12
+ <a href="#isType">isType</a><br />
13
+ </div>
14
+ </k-accordion-panel>
15
+ </k-accordion>
16
+
17
+ <h3>Description</h3>
18
+ <p>The type utilities module provides functions for checking and identifying JavaScript value types, including enhanced type detection for arrays, elements, and null values.</p>
19
+
20
+ <h3 id="typeOf"><a href="#typeOf" class="no-link">typeOf</a></h3>
21
+ <p>Returns the type of a value as a string, with enhanced detection for arrays, DOM elements, and null.</p>
22
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { typeOf } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/type.js'</span>;<br /><br />typeOf(<span class="hljs-string">'hello'</span>); <span class="hljs-comment">// "string"</span><br />typeOf(<span class="hljs-number">42</span>); <span class="hljs-comment">// "number"</span><br />typeOf([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]); <span class="hljs-comment">// "array"</span><br />typeOf(<span class="hljs-literal">null</span>); <span class="hljs-comment">// "null"</span><br />typeOf(document.body); <span class="hljs-comment">// "element" (in browser)</span></code></pre>
23
+
24
+ <h3 id="isType"><a href="#isType" class="no-link">isType</a></h3>
25
+ <p>Checks if a value is of a specific type.</p>
26
+ <pre><code class="hljs javascript"><span class="hljs-keyword">import</span> { isType } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/utils/type.js'</span>;<br /><br />isType(<span class="hljs-string">'hello'</span>, <span class="hljs-string">'string'</span>); <span class="hljs-comment">// true</span><br />isType([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], <span class="hljs-string">'array'</span>); <span class="hljs-comment">// true</span><br />isType(<span class="hljs-literal">null</span>, <span class="hljs-string">'null'</span>); <span class="hljs-comment">// true</span><br />isType(<span class="hljs-number">42</span>, <span class="hljs-string">'string'</span>); <span class="hljs-comment">// false</span></code></pre>
27
+ </content>
28
+ <content location="scripts">
29
+ <script type="module" src="{{pathToRoot}}src/components/Accordion.js"></script>
30
+ </content>
31
+ </page>