kempo-ui 0.0.3 → 0.0.4
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.
- package/.github/workflows/publish-major.yml +39 -0
- package/.github/workflows/publish-minor.yml +39 -0
- package/.github/workflows/{publish-npm.yml → publish-patch.yml} +1 -1
- package/.vscode/settings.json +2 -0
- package/dist/kempo-hljs.css +1 -0
- package/dist/src/components/Accordion.js +36 -0
- package/dist/src/components/Card.js +37 -0
- package/dist/src/components/Collapsible.js +41 -0
- package/dist/src/components/ContentSlider.js +44 -0
- package/dist/src/components/Dialog.js +113 -0
- package/dist/src/components/Icon.js +2 -2
- package/dist/src/components/PersistantCollapsible.js +1 -0
- package/dist/src/components/PhotoViewer.js +135 -0
- package/dist/src/components/Resize.js +96 -0
- package/dist/src/components/ShowMore.js +42 -0
- package/dist/src/components/SideMenu.js +1 -1
- package/dist/src/components/Split.js +84 -0
- package/dist/src/components/Tabs.js +155 -0
- package/dist/src/components/Tags.js +69 -0
- package/dist/src/components/ThemeSwitcher.js +23 -0
- package/dist/src/components/Timestamp.js +1 -0
- package/dist/src/utils/debounce.js +1 -0
- package/dist/src/utils/drag.js +1 -0
- package/dist/src/utils/formatTimestamp.js +1 -0
- package/dist/src/utils/propConverters.js +1 -0
- package/dist/src/utils/watchWindowSize.js +1 -0
- package/docs/components/accordion.html +69 -25
- package/docs/components/card.html +6 -5
- package/docs/components/collapsible.html +198 -0
- package/docs/components/content-slider.html +56 -26
- package/docs/components/dialog.html +54 -48
- package/docs/components/focus-capture.html +2 -3
- package/docs/components/icon.html +5 -8
- package/docs/components/import.html +1 -6
- package/docs/components/persistant-collapsible.html +123 -0
- package/docs/components/photo-viewer.html +226 -0
- package/docs/components/resize.html +44 -18
- package/docs/components/show-more.html +12 -6
- package/docs/components/side-menu.html +3 -12
- package/docs/components/split.html +26 -5
- package/docs/components/tablePagination.html +4 -4
- package/docs/components/tableRecordFiltering.html +16 -3
- package/docs/components/tableRecordSelection.html +2 -2
- package/docs/components/tabs.html +24 -7
- package/docs/components/tags.html +24 -8
- package/docs/components/theme-switcher.html +3 -6
- package/docs/components/timestamp.html +20 -24
- package/docs/components/toast.html +23 -32
- package/docs/components/toggle.html +4 -3
- package/docs/kempo-hljs.css +1 -0
- package/docs/media/civic.jpg +0 -0
- package/docs/media/corvette.jpg +0 -0
- package/docs/media/evo.jpg +0 -0
- package/docs/media/gtr.jpg +0 -0
- package/docs/media/nsx.jpg +0 -0
- package/docs/nav.inc.html +11 -17
- package/docs/src/components/Accordion.js +36 -0
- package/docs/src/components/Card.js +37 -0
- package/docs/src/components/Collapsible.js +41 -0
- package/docs/src/components/ContentSlider.js +44 -0
- package/docs/src/components/Dialog.js +113 -0
- package/docs/src/components/Icon.js +2 -2
- package/docs/src/components/PersistantCollapsible.js +1 -0
- package/docs/src/components/PhotoViewer.js +135 -0
- package/docs/src/components/Resize.js +96 -0
- package/docs/src/components/ShowMore.js +42 -0
- package/docs/src/components/SideMenu.js +1 -1
- package/docs/src/components/Split.js +84 -0
- package/docs/src/components/Tabs.js +155 -0
- package/docs/src/components/Tags.js +69 -0
- package/docs/src/components/ThemeSwitcher.js +23 -0
- package/docs/src/components/Timestamp.js +1 -0
- package/docs/src/utils/debounce.js +1 -0
- package/docs/src/utils/drag.js +1 -0
- package/docs/src/utils/formatTimestamp.js +1 -0
- package/docs/src/utils/propConverters.js +1 -0
- package/docs/src/utils/watchWindowSize.js +1 -0
- package/docs/utils/debounce.html +78 -0
- package/docs/utils/drag.html +104 -0
- package/docs/utils/formatTimestamp.html +114 -0
- package/docs/utils/propConverters.html +132 -0
- package/docs/utils/watchWindowSize.html +166 -0
- package/icons/error.svg +1 -1
- package/icons/warning.svg +1 -1
- package/package.json +1 -1
- package/scripts/build.js +1 -1
- package/scripts/docs.js +4 -2
- package/src/components/Accordion.js +229 -0
- package/src/components/Collapsible.js +109 -0
- package/src/components/ContentSlider.js +205 -0
- package/src/components/Dialog.js +368 -0
- package/src/components/PersistantCollapsible.js +69 -0
- package/src/components/PhotoViewer.js +368 -0
- package/src/components/Resize.js +210 -0
- package/src/components/ShadowComponent.js +3 -1
- package/src/components/ShowMore.js +109 -0
- package/src/components/Sortable.js +193 -0
- package/src/components/Split.js +192 -0
- package/src/components/Table.js +1202 -0
- package/src/components/Tabs.js +428 -0
- package/src/components/Tags.js +253 -0
- package/src/components/Timestamp.js +31 -0
- package/src/components/Toast.js +454 -0
- package/src/components/Toggle.js +173 -0
- package/src/components/tableControls/DeleteRecord.js +29 -0
- package/src/components/tableControls/Edit.js +88 -0
- package/src/components/tableControls/ExportCSV.js +71 -0
- package/src/components/tableControls/ExportJson.js +55 -0
- package/src/components/tableControls/FieldSortHide.js +76 -0
- package/src/components/tableControls/Filters.js +114 -0
- package/src/components/tableControls/FirstPage.js +65 -0
- package/src/components/tableControls/HiddenCount.js +45 -0
- package/src/components/tableControls/Hide.js +34 -0
- package/src/components/tableControls/LastPage.js +65 -0
- package/src/components/tableControls/NextPage.js +65 -0
- package/src/components/tableControls/PageSelect.js +109 -0
- package/src/components/tableControls/PageSize.js +68 -0
- package/src/components/tableControls/PrevPage.js +65 -0
- package/src/components/tableControls/Search.js +58 -0
- package/src/components/tableControls/ShowAll.js +34 -0
- package/src/components/tableControls/TableControl.js +105 -0
- package/src/utils/debounce.js +9 -0
- package/src/utils/drag.js +80 -0
- package/src/utils/formatTimestamp.js +27 -0
- package/src/utils/toTitleCase.js +9 -0
- package/src/utils/watchWindowSize.js +16 -0
- package/dist/src/utils/cli.js +0 -1
- package/dist/src/utils/fs-utils.js +0 -1
- package/docs/components/component.html +0 -90
- package/docs/components/directory-viewer.html +0 -90
- package/docs/components/lazy-component.html +0 -84
- package/docs/components/reactive-component.html +0 -69
- package/docs/components/reactive-lazy-component.html +0 -69
- package/docs/components/search.html +0 -102
- package/docs/components/sortable.html +0 -96
- package/src/utils/cli.js +0 -43
- package/src/utils/fs-utils.js +0 -41
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default(e={})=>{let t,n,o;const{element:s,callback:a=()=>{},startCallback:r=()=>{},moveCallback:c=()=>{},endCallback:u=()=>{},preventScroll:v=!1}=e,d=s=>{v&&s.preventDefault(),clearTimeout(o);const r=s.pageX||s.touches[0].pageX,u=s.pageY||s.touches[0].pageY,d={x:r-t,y:u-n,...e};a(d),c(d)},i=s=>{clearTimeout(o);const r=s.pageX||s.changedTouches&&s.changedTouches[0].pageX||0,c=s.pageY||s.changedTouches&&s.changedTouches[0].pageY||0,v={x:r-t,y:c-n,...e};a(v),u(v),m()},p=s=>{if(s.button&&0!==s.button)return;clearTimeout(o),t=s.pageX||s.touches[0].pageX,n=s.pageY||s.touches[0].pageY;const a={x:0,y:0,...e};r(a),window.addEventListener("mousemove",d,{passive:!v}),window.addEventListener("mouseup",i,{passive:!v}),window.addEventListener("touchmove",d,{passive:!v}),window.addEventListener("touchend",i,{passive:!v})},m=()=>{window.removeEventListener("mousemove",d),window.removeEventListener("mouseup",i),window.removeEventListener("touchmove",d),window.removeEventListener("touchend",i)};return s.addEventListener("mousedown",p,{passive:!v}),s.addEventListener("touchstart",p,{passive:!v}),()=>{s.removeEventListener("mousedown",p),s.removeEventListener("touchstart",p),m()}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default(e,i,t)=>{const s=new Date(parseInt(e));if(i){const e=(e,i)=>("000"+e).slice(-1*i),t={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MM:e(s.getMonth()+1,2),M:s.getMonth()+1,DD:e(s.getDate(),2),D:s.getDate(),hh:e(s.getHours(),2),h:s.getHours(),mm:e(s.getMinutes(),2),m:s.getMinutes(),ss:e(s.getSeconds(),2),s:s.getSeconds(),iiii:e(s.getMilliseconds(),3),iii:e(s.getMilliseconds(),3),ii:e(s.getMilliseconds(),2),i:s.getMilliseconds()};return i.replace(/YYYY|YY|MM|M|DD|D|hh|h|mm|m|ss|s|iiii|iii|ii|i/g,e=>t[e])}return s.toLocaleString(t||navigator.language)};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const boolTrueFalse={fromAttribute:t=>null===t?void 0:"true"===t.toLowerCase(),toAttribute:t=>t?"true":"false"};export const boolExists={fromAttribute:t=>null!==t,toAttribute:t=>t?"":null};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import debounce from"./debounce.js";const handlers=new Set;window.addEventListener("resize",debounce(()=>{const e=window.innerWidth;handlers.forEach(n=>n(e))}));export const watchWindowSize=e=>(handlers.add(e),window.innerWidth);export const unwatchWindowSize=e=>{handlers.delete(e)};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>debounce - Kempo UI</title>
|
|
7
|
+
<link rel="stylesheet" href="../src/kempo-vars.css" />
|
|
8
|
+
<link rel="stylesheet" href="../kempo.min.css" />
|
|
9
|
+
<link rel="stylesheet" href="../src/kempo-hljs.css" />
|
|
10
|
+
<link rel="stylesheet" href="../styles.css" />
|
|
11
|
+
<script type="module">
|
|
12
|
+
import Import from '../src/components/Import.js';
|
|
13
|
+
import Icon from '../src/components/Icon.js';
|
|
14
|
+
Import.replacements.root = '../';
|
|
15
|
+
Icon.pathToIcons = ['../icons'];
|
|
16
|
+
</script>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<k-import src="../nav.inc.html"></k-import>
|
|
20
|
+
<main>
|
|
21
|
+
<h1>debounce</h1>
|
|
22
|
+
|
|
23
|
+
<details
|
|
24
|
+
class="b r mb"
|
|
25
|
+
>
|
|
26
|
+
<summary class="p">Table of Contents</summary>
|
|
27
|
+
<div class="m mt0 pl">
|
|
28
|
+
<h6>Usage</h6>
|
|
29
|
+
<a href="#basicUsage">Basic Usage</a><br />
|
|
30
|
+
<a href="#parameters">Parameters</a><br />
|
|
31
|
+
<a href="#examples">Examples</a><br />
|
|
32
|
+
</div>
|
|
33
|
+
</details>
|
|
34
|
+
|
|
35
|
+
<h3>Description</h3>
|
|
36
|
+
<p>The <code>debounce</code> utility function limits the rate at which a function can be executed. It delays the execution of a function until after a specified timeout has passed since the last time it was invoked.</p>
|
|
37
|
+
|
|
38
|
+
<h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
|
|
39
|
+
<p>Import and use the debounce function to limit function execution frequency:</p>
|
|
40
|
+
<pre><code class="hljs javascript">import debounce from './utils/debounce.js';
|
|
41
|
+
|
|
42
|
+
const handleSearch = debounce((query) => {
|
|
43
|
+
console.log('Searching for:', query);
|
|
44
|
+
}, 300);
|
|
45
|
+
|
|
46
|
+
// Will only execute after 300ms of no calls
|
|
47
|
+
handleSearch('test');</code></pre>
|
|
48
|
+
|
|
49
|
+
<h3 id="parameters"><a href="#parameters" class="no-link">Parameters</a></h3>
|
|
50
|
+
<h5><code>func<i>: Function</i></code></h5>
|
|
51
|
+
<p>The function to debounce.</p>
|
|
52
|
+
<h5><code>timeout<i>: number</i></code> (optional)</h5>
|
|
53
|
+
<p>The number of milliseconds to delay execution. Defaults to 300ms.</p>
|
|
54
|
+
|
|
55
|
+
<h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
|
|
56
|
+
|
|
57
|
+
<h4>Search Input Debouncing</h4>
|
|
58
|
+
<pre><code class="hljs javascript">const debouncedSearch = debounce((searchTerm) => {
|
|
59
|
+
// API call or expensive search operation
|
|
60
|
+
performSearch(searchTerm);
|
|
61
|
+
}, 500);
|
|
62
|
+
|
|
63
|
+
searchInput.addEventListener('input', (e) => {
|
|
64
|
+
debouncedSearch(e.target.value);
|
|
65
|
+
});</code></pre>
|
|
66
|
+
|
|
67
|
+
<h4>Window Resize Handler</h4>
|
|
68
|
+
<pre><code class="hljs javascript">const debouncedResize = debounce(() => {
|
|
69
|
+
// Expensive layout calculations
|
|
70
|
+
recalculateLayout();
|
|
71
|
+
}, 250);
|
|
72
|
+
|
|
73
|
+
window.addEventListener('resize', debouncedResize);</code></pre>
|
|
74
|
+
|
|
75
|
+
</main>
|
|
76
|
+
<div style="height:33vh"></div>
|
|
77
|
+
</body>
|
|
78
|
+
</html>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>drag - Kempo UI</title>
|
|
7
|
+
<link rel="stylesheet" href="../src/kempo-vars.css" />
|
|
8
|
+
<link rel="stylesheet" href="../kempo.min.css" />
|
|
9
|
+
<link rel="stylesheet" href="../src/kempo-hljs.css" />
|
|
10
|
+
<link rel="stylesheet" href="../styles.css" />
|
|
11
|
+
<script type="module">
|
|
12
|
+
import Import from '../src/components/Import.js';
|
|
13
|
+
import Icon from '../src/components/Icon.js';
|
|
14
|
+
Import.replacements.root = '../';
|
|
15
|
+
Icon.pathToIcons = ['../icons'];
|
|
16
|
+
</script>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<k-import src="../nav.inc.html"></k-import>
|
|
20
|
+
<main>
|
|
21
|
+
<h1>drag</h1>
|
|
22
|
+
|
|
23
|
+
<details
|
|
24
|
+
class="b r mb"
|
|
25
|
+
>
|
|
26
|
+
<summary class="p">Table of Contents</summary>
|
|
27
|
+
<div class="m mt0 pl">
|
|
28
|
+
<h6>Usage</h6>
|
|
29
|
+
<a href="#basicUsage">Basic Usage</a><br />
|
|
30
|
+
<a href="#options">Options</a><br />
|
|
31
|
+
<a href="#callbacks">Callbacks</a><br />
|
|
32
|
+
<a href="#examples">Examples</a><br />
|
|
33
|
+
</div>
|
|
34
|
+
</details>
|
|
35
|
+
|
|
36
|
+
<h3>Description</h3>
|
|
37
|
+
<p>The <code>drag</code> utility function enables drag interactions on DOM elements. It handles both mouse and touch events, providing callbacks for drag start, move, and end events.</p>
|
|
38
|
+
|
|
39
|
+
<h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
|
|
40
|
+
<p>Import and use the drag function to make elements draggable:</p>
|
|
41
|
+
<pre><code class="hljs javascript">import drag from './utils/drag.js';
|
|
42
|
+
|
|
43
|
+
const element = document.querySelector('.draggable');
|
|
44
|
+
drag({
|
|
45
|
+
element,
|
|
46
|
+
callback: (diff) => {
|
|
47
|
+
console.log('Dragged:', diff.x, diff.y);
|
|
48
|
+
}
|
|
49
|
+
});</code></pre>
|
|
50
|
+
|
|
51
|
+
<h3 id="options"><a href="#options" class="no-link">Options</a></h3>
|
|
52
|
+
<h5><code>element<i>: HTMLElement</i></code></h5>
|
|
53
|
+
<p>The DOM element to make draggable.</p>
|
|
54
|
+
<h5><code>preventScroll<i>: boolean</i></code> (optional)</h5>
|
|
55
|
+
<p>Whether to prevent scroll behavior during drag. Defaults to false.</p>
|
|
56
|
+
|
|
57
|
+
<h3 id="callbacks"><a href="#callbacks" class="no-link">Callbacks</a></h3>
|
|
58
|
+
<h5><code>callback<i>: Function</i></code> (optional)</h5>
|
|
59
|
+
<p>Called on every drag move. Receives a diff object with x, y coordinates and original options.</p>
|
|
60
|
+
<h5><code>startCallback<i>: Function</i></code> (optional)</h5>
|
|
61
|
+
<p>Called when drag starts. Receives the starting event.</p>
|
|
62
|
+
<h5><code>moveCallback<i>: Function</i></code> (optional)</h5>
|
|
63
|
+
<p>Called on every drag move (in addition to callback). Receives a diff object.</p>
|
|
64
|
+
<h5><code>endCallback<i>: Function</i></code> (optional)</h5>
|
|
65
|
+
<p>Called when drag ends. Receives the ending event.</p>
|
|
66
|
+
|
|
67
|
+
<h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
|
|
68
|
+
|
|
69
|
+
<h4>Draggable Element</h4>
|
|
70
|
+
<pre><code class="hljs javascript">const box = document.querySelector('.box');
|
|
71
|
+
let position = { x: 0, y: 0 };
|
|
72
|
+
|
|
73
|
+
drag({
|
|
74
|
+
element: box,
|
|
75
|
+
callback: (diff) => {
|
|
76
|
+
position.x += diff.x;
|
|
77
|
+
position.y += diff.y;
|
|
78
|
+
box.style.transform = `translate(${position.x}px, ${position.y}px)`;
|
|
79
|
+
}
|
|
80
|
+
});</code></pre>
|
|
81
|
+
|
|
82
|
+
<h4>Resize Handle</h4>
|
|
83
|
+
<pre><code class="hljs javascript">const resizeHandle = document.querySelector('.resize-handle');
|
|
84
|
+
const panel = document.querySelector('.panel');
|
|
85
|
+
|
|
86
|
+
drag({
|
|
87
|
+
element: resizeHandle,
|
|
88
|
+
preventScroll: true,
|
|
89
|
+
callback: (diff) => {
|
|
90
|
+
const newWidth = panel.offsetWidth + diff.x;
|
|
91
|
+
panel.style.width = Math.max(100, newWidth) + 'px';
|
|
92
|
+
},
|
|
93
|
+
startCallback: () => {
|
|
94
|
+
panel.classList.add('resizing');
|
|
95
|
+
},
|
|
96
|
+
endCallback: () => {
|
|
97
|
+
panel.classList.remove('resizing');
|
|
98
|
+
}
|
|
99
|
+
});</code></pre>
|
|
100
|
+
|
|
101
|
+
</main>
|
|
102
|
+
<div style="height:33vh"></div>
|
|
103
|
+
</body>
|
|
104
|
+
</html>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>formatTimestamp - Kempo UI</title>
|
|
7
|
+
<link rel="stylesheet" href="../src/kempo-vars.css" />
|
|
8
|
+
<link rel="stylesheet" href="../kempo.min.css" />
|
|
9
|
+
<link rel="stylesheet" href="../src/kempo-hljs.css" />
|
|
10
|
+
<link rel="stylesheet" href="../styles.css" />
|
|
11
|
+
<script type="module">
|
|
12
|
+
import Import from '../src/components/Import.js';
|
|
13
|
+
import Icon from '../src/components/Icon.js';
|
|
14
|
+
Import.replacements.root = '../';
|
|
15
|
+
Icon.pathToIcons = ['../icons'];
|
|
16
|
+
</script>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<k-import src="../nav.inc.html"></k-import>
|
|
20
|
+
<main>
|
|
21
|
+
<h1>formatTimestamp</h1>
|
|
22
|
+
|
|
23
|
+
<details
|
|
24
|
+
class="b r mb"
|
|
25
|
+
>
|
|
26
|
+
<summary class="p">Table of Contents</summary>
|
|
27
|
+
<div class="m mt0 pl">
|
|
28
|
+
<h6>Usage</h6>
|
|
29
|
+
<a href="#basicUsage">Basic Usage</a><br />
|
|
30
|
+
<a href="#parameters">Parameters</a><br />
|
|
31
|
+
<a href="#formatTokens">Format Tokens</a><br />
|
|
32
|
+
<a href="#examples">Examples</a><br />
|
|
33
|
+
</div>
|
|
34
|
+
</details>
|
|
35
|
+
|
|
36
|
+
<h3>Description</h3>
|
|
37
|
+
<p>The <code>formatTimestamp</code> utility function formats timestamps using custom format tokens or locale-specific formatting.</p>
|
|
38
|
+
|
|
39
|
+
<h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
|
|
40
|
+
<p>Import and use the formatTimestamp function to format dates:</p>
|
|
41
|
+
<pre><code class="hljs javascript">import formatTimestamp from './utils/formatTimestamp.js';
|
|
42
|
+
|
|
43
|
+
const timestamp = Date.now();
|
|
44
|
+
const formatted = formatTimestamp(timestamp, 'YYYY-MM-DD');
|
|
45
|
+
console.log(formatted); // "2025-09-19"</code></pre>
|
|
46
|
+
|
|
47
|
+
<h3 id="parameters"><a href="#parameters" class="no-link">Parameters</a></h3>
|
|
48
|
+
<h5><code>timestamp<i>: number|string</i></code></h5>
|
|
49
|
+
<p>The timestamp to format (milliseconds since epoch).</p>
|
|
50
|
+
<h5><code>format<i>: string</i></code> (optional)</h5>
|
|
51
|
+
<p>The format string using tokens. If not provided, uses locale-specific formatting.</p>
|
|
52
|
+
<h5><code>forceLocale<i>: string</i></code> (optional)</h5>
|
|
53
|
+
<p>The locale to use for formatting when no format is specified.</p>
|
|
54
|
+
|
|
55
|
+
<h3 id="formatTokens"><a href="#formatTokens" class="no-link">Format Tokens</a></h3>
|
|
56
|
+
<h5><code>YYYY</code></h5>
|
|
57
|
+
<p>4-digit year (e.g., 2025)</p>
|
|
58
|
+
<h5><code>YY</code></h5>
|
|
59
|
+
<p>2-digit year (e.g., 25)</p>
|
|
60
|
+
<h5><code>MM</code></h5>
|
|
61
|
+
<p>2-digit month (01-12)</p>
|
|
62
|
+
<h5><code>M</code></h5>
|
|
63
|
+
<p>1-digit month (1-12)</p>
|
|
64
|
+
<h5><code>DD</code></h5>
|
|
65
|
+
<p>2-digit day (01-31)</p>
|
|
66
|
+
<h5><code>D</code></h5>
|
|
67
|
+
<p>1-digit day (1-31)</p>
|
|
68
|
+
<h5><code>hh</code></h5>
|
|
69
|
+
<p>2-digit hour (00-23)</p>
|
|
70
|
+
<h5><code>h</code></h5>
|
|
71
|
+
<p>1-digit hour (0-23)</p>
|
|
72
|
+
<h5><code>mm</code></h5>
|
|
73
|
+
<p>2-digit minute (00-59)</p>
|
|
74
|
+
<h5><code>m</code></h5>
|
|
75
|
+
<p>1-digit minute (0-59)</p>
|
|
76
|
+
<h5><code>ss</code></h5>
|
|
77
|
+
<p>2-digit second (00-59)</p>
|
|
78
|
+
<h5><code>s</code></h5>
|
|
79
|
+
<p>1-digit second (0-59)</p>
|
|
80
|
+
<h5><code>iiii, iii, ii, i</code></h5>
|
|
81
|
+
<p>Milliseconds with different padding</p>
|
|
82
|
+
|
|
83
|
+
<h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
|
|
84
|
+
|
|
85
|
+
<h4>Date Formats</h4>
|
|
86
|
+
<pre><code class="hljs javascript">const timestamp = 1633024800000;
|
|
87
|
+
|
|
88
|
+
formatTimestamp(timestamp, 'YYYY-MM-DD'); // "2021-10-01"
|
|
89
|
+
formatTimestamp(timestamp, 'MM/DD/YYYY'); // "10/01/2021"
|
|
90
|
+
formatTimestamp(timestamp, 'DD-MM-YY'); // "01-10-21"</code></pre>
|
|
91
|
+
|
|
92
|
+
<h4>Time Formats</h4>
|
|
93
|
+
<pre><code class="hljs javascript">formatTimestamp(timestamp, 'hh:mm:ss'); // "00:00:00"
|
|
94
|
+
formatTimestamp(timestamp, 'h:mm'); // "0:00"
|
|
95
|
+
formatTimestamp(timestamp, 'hh:mm:ss.iii'); // "00:00:00.000"</code></pre>
|
|
96
|
+
|
|
97
|
+
<h4>Combined Formats</h4>
|
|
98
|
+
<pre><code class="hljs javascript">formatTimestamp(timestamp, 'YYYY-MM-DD hh:mm:ss');
|
|
99
|
+
// "2021-10-01 00:00:00"
|
|
100
|
+
|
|
101
|
+
formatTimestamp(timestamp, 'MM/DD/YY at h:mm');
|
|
102
|
+
// "10/01/21 at 0:00"</code></pre>
|
|
103
|
+
|
|
104
|
+
<h4>Locale Formatting</h4>
|
|
105
|
+
<pre><code class="hljs javascript">// Uses browser locale when no format specified
|
|
106
|
+
formatTimestamp(timestamp); // "10/1/2021, 12:00:00 AM"
|
|
107
|
+
|
|
108
|
+
// Force specific locale
|
|
109
|
+
formatTimestamp(timestamp, null, 'de-DE'); // German formatting</code></pre>
|
|
110
|
+
|
|
111
|
+
</main>
|
|
112
|
+
<div style="height:33vh"></div>
|
|
113
|
+
</body>
|
|
114
|
+
</html>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>propConverters - Kempo UI</title>
|
|
7
|
+
<link rel="stylesheet" href="../src/kempo-vars.css" />
|
|
8
|
+
<link rel="stylesheet" href="../kempo.min.css" />
|
|
9
|
+
<link rel="stylesheet" href="../src/kempo-hljs.css" />
|
|
10
|
+
<link rel="stylesheet" href="../styles.css" />
|
|
11
|
+
<script type="module">
|
|
12
|
+
import Import from '../src/components/Import.js';
|
|
13
|
+
import Icon from '../src/components/Icon.js';
|
|
14
|
+
Import.replacements.root = '../';
|
|
15
|
+
Icon.pathToIcons = ['../icons'];
|
|
16
|
+
</script>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<k-import src="../nav.inc.html"></k-import>
|
|
20
|
+
<main>
|
|
21
|
+
<h1>propConverters</h1>
|
|
22
|
+
|
|
23
|
+
<details
|
|
24
|
+
class="b r mb"
|
|
25
|
+
>
|
|
26
|
+
<summary class="p">Table of Contents</summary>
|
|
27
|
+
<div class="m mt0 pl">
|
|
28
|
+
<h6>Usage</h6>
|
|
29
|
+
<a href="#basicUsage">Basic Usage</a><br />
|
|
30
|
+
<a href="#boolTrueFalse">boolTrueFalse</a><br />
|
|
31
|
+
<a href="#boolExists">boolExists</a><br />
|
|
32
|
+
<a href="#examples">Examples</a><br />
|
|
33
|
+
</div>
|
|
34
|
+
</details>
|
|
35
|
+
|
|
36
|
+
<h3>Description</h3>
|
|
37
|
+
<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>
|
|
38
|
+
|
|
39
|
+
<h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
|
|
40
|
+
<p>Import and use the converters in your Lit Element component properties:</p>
|
|
41
|
+
<pre><code class="hljs javascript">import { boolTrueFalse, boolExists } from './utils/propConverters.js';
|
|
42
|
+
|
|
43
|
+
static properties = {
|
|
44
|
+
enabled: { type: Boolean, reflect: true, converter: boolTrueFalse },
|
|
45
|
+
visible: { type: Boolean, reflect: true, converter: boolExists }
|
|
46
|
+
};</code></pre>
|
|
47
|
+
|
|
48
|
+
<h3 id="boolTrueFalse"><a href="#boolTrueFalse" class="no-link">boolTrueFalse</a></h3>
|
|
49
|
+
<p>Converts between boolean values and explicit "true"/"false" string attributes.</p>
|
|
50
|
+
|
|
51
|
+
<h4>Behavior</h4>
|
|
52
|
+
<ul>
|
|
53
|
+
<li><strong>fromAttribute:</strong> "true" → true, "false" → false, null → undefined</li>
|
|
54
|
+
<li><strong>toAttribute:</strong> true → "true", false → "false"</li>
|
|
55
|
+
</ul>
|
|
56
|
+
|
|
57
|
+
<h4>HTML Usage</h4>
|
|
58
|
+
<pre><code class="hljs xml"><my-component enabled="true"></my-component>
|
|
59
|
+
<my-component enabled="false"></my-component></code></pre>
|
|
60
|
+
|
|
61
|
+
<h3 id="boolExists"><a href="#boolExists" class="no-link">boolExists</a></h3>
|
|
62
|
+
<p>Converts between boolean values and attribute presence/absence.</p>
|
|
63
|
+
|
|
64
|
+
<h4>Behavior</h4>
|
|
65
|
+
<ul>
|
|
66
|
+
<li><strong>fromAttribute:</strong> attribute present → true, attribute absent → false</li>
|
|
67
|
+
<li><strong>toAttribute:</strong> true → "", false → null (removes attribute)</li>
|
|
68
|
+
</ul>
|
|
69
|
+
|
|
70
|
+
<h4>HTML Usage</h4>
|
|
71
|
+
<pre><code class="hljs xml"><my-component visible></my-component> <!-- visible = true -->
|
|
72
|
+
<my-component></my-component> <!-- visible = false --></code></pre>
|
|
73
|
+
|
|
74
|
+
<h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
|
|
75
|
+
|
|
76
|
+
<h4>Component with Both Converters</h4>
|
|
77
|
+
<pre><code class="hljs javascript">import { LitElement, html } from 'lit';
|
|
78
|
+
import { boolTrueFalse, boolExists } from './utils/propConverters.js';
|
|
79
|
+
|
|
80
|
+
class MyComponent extends LitElement {
|
|
81
|
+
static properties = {
|
|
82
|
+
autoplay: { type: Boolean, reflect: true, converter: boolTrueFalse },
|
|
83
|
+
hidden: { type: Boolean, reflect: true, converter: boolExists },
|
|
84
|
+
loop: { type: Boolean, reflect: true, converter: boolTrueFalse }
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
constructor() {
|
|
88
|
+
super();
|
|
89
|
+
this.autoplay = false;
|
|
90
|
+
this.hidden = false;
|
|
91
|
+
this.loop = false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
render() {
|
|
95
|
+
return html`
|
|
96
|
+
<div ?hidden="${this.hidden}">
|
|
97
|
+
Content ${this.autoplay ? 'with' : 'without'} autoplay
|
|
98
|
+
${this.loop ? '(looping)' : ''}
|
|
99
|
+
</div>
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
}</code></pre>
|
|
103
|
+
|
|
104
|
+
<h4>HTML Usage Examples</h4>
|
|
105
|
+
<pre><code class="hljs xml"><!-- Using boolTrueFalse converter -->
|
|
106
|
+
<my-component autoplay="true" loop="false"></my-component>
|
|
107
|
+
|
|
108
|
+
<!-- Using boolExists converter -->
|
|
109
|
+
<my-component hidden></my-component>
|
|
110
|
+
|
|
111
|
+
<!-- Combined usage -->
|
|
112
|
+
<my-component autoplay="true" loop="true" hidden></my-component></code></pre>
|
|
113
|
+
|
|
114
|
+
<h4>When to Use Each Converter</h4>
|
|
115
|
+
<p><strong>Use boolTrueFalse when:</strong></p>
|
|
116
|
+
<ul>
|
|
117
|
+
<li>You need explicit true/false values in HTML</li>
|
|
118
|
+
<li>The attribute value is important for clarity</li>
|
|
119
|
+
<li>Working with form controls or interactive elements</li>
|
|
120
|
+
</ul>
|
|
121
|
+
|
|
122
|
+
<p><strong>Use boolExists when:</strong></p>
|
|
123
|
+
<ul>
|
|
124
|
+
<li>Following HTML standards (like hidden, disabled attributes)</li>
|
|
125
|
+
<li>The presence of the attribute is what matters</li>
|
|
126
|
+
<li>Creating more semantic HTML</li>
|
|
127
|
+
</ul>
|
|
128
|
+
|
|
129
|
+
</main>
|
|
130
|
+
<div style="height:33vh"></div>
|
|
131
|
+
</body>
|
|
132
|
+
</html>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>watchWindowSize - Kempo UI</title>
|
|
7
|
+
<link rel="stylesheet" href="../src/kempo-vars.css" />
|
|
8
|
+
<link rel="stylesheet" href="../kempo.min.css" />
|
|
9
|
+
<link rel="stylesheet" href="../src/kempo-hljs.css" />
|
|
10
|
+
<link rel="stylesheet" href="../styles.css" />
|
|
11
|
+
<script type="module">
|
|
12
|
+
import Import from '../src/components/Import.js';
|
|
13
|
+
import Icon from '../src/components/Icon.js';
|
|
14
|
+
Import.replacements.root = '../';
|
|
15
|
+
Icon.pathToIcons = ['../icons'];
|
|
16
|
+
</script>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<k-import src="../nav.inc.html"></k-import>
|
|
20
|
+
<main>
|
|
21
|
+
<h1>watchWindowSize</h1>
|
|
22
|
+
|
|
23
|
+
<details
|
|
24
|
+
class="b r mb"
|
|
25
|
+
>
|
|
26
|
+
<summary class="p">Table of Contents</summary>
|
|
27
|
+
<div class="m mt0 pl">
|
|
28
|
+
<h6>Usage</h6>
|
|
29
|
+
<a href="#basicUsage">Basic Usage</a><br />
|
|
30
|
+
<a href="#functions">Functions</a><br />
|
|
31
|
+
<a href="#examples">Examples</a><br />
|
|
32
|
+
</div>
|
|
33
|
+
</details>
|
|
34
|
+
|
|
35
|
+
<h3>Description</h3>
|
|
36
|
+
<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>
|
|
37
|
+
|
|
38
|
+
<h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
|
|
39
|
+
<p>Import and use the window size watching functions:</p>
|
|
40
|
+
<pre><code class="hljs javascript">import { watchWindowSize, unwatchWindowSize } from './utils/watchWindowSize.js';
|
|
41
|
+
|
|
42
|
+
const handler = (width) => {
|
|
43
|
+
console.log('Window width:', width);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Start watching
|
|
47
|
+
const currentWidth = watchWindowSize(handler);
|
|
48
|
+
|
|
49
|
+
// Stop watching when done
|
|
50
|
+
unwatchWindowSize(handler);</code></pre>
|
|
51
|
+
|
|
52
|
+
<h3 id="functions"><a href="#functions" class="no-link">Functions</a></h3>
|
|
53
|
+
|
|
54
|
+
<h5><code>watchWindowSize(handler)</code></h5>
|
|
55
|
+
<p>Registers a handler function to be called when the window is resized.</p>
|
|
56
|
+
<ul>
|
|
57
|
+
<li><strong>handler:</strong> Function that receives the new window width</li>
|
|
58
|
+
<li><strong>Returns:</strong> Current window width</li>
|
|
59
|
+
</ul>
|
|
60
|
+
|
|
61
|
+
<h5><code>unwatchWindowSize(handler)</code></h5>
|
|
62
|
+
<p>Unregisters a previously registered handler function.</p>
|
|
63
|
+
<ul>
|
|
64
|
+
<li><strong>handler:</strong> The same function reference that was registered</li>
|
|
65
|
+
</ul>
|
|
66
|
+
|
|
67
|
+
<h3 id="examples"><a href="#examples" class="no-link">Examples</a></h3>
|
|
68
|
+
|
|
69
|
+
<h4>Responsive Component</h4>
|
|
70
|
+
<pre><code class="hljs javascript">import { watchWindowSize, unwatchWindowSize } from './utils/watchWindowSize.js';
|
|
71
|
+
|
|
72
|
+
class ResponsiveComponent extends LitElement {
|
|
73
|
+
constructor() {
|
|
74
|
+
super();
|
|
75
|
+
this.isMobile = false;
|
|
76
|
+
this.resizeHandler = this.handleResize.bind(this);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
connectedCallback() {
|
|
80
|
+
super.connectedCallback();
|
|
81
|
+
const currentWidth = watchWindowSize(this.resizeHandler);
|
|
82
|
+
this.handleResize(currentWidth);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
disconnectedCallback() {
|
|
86
|
+
super.disconnectedCallback();
|
|
87
|
+
unwatchWindowSize(this.resizeHandler);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
handleResize(width) {
|
|
91
|
+
this.isMobile = width < 768;
|
|
92
|
+
this.requestUpdate();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
render() {
|
|
96
|
+
return html`
|
|
97
|
+
<div class="${this.isMobile ? 'mobile' : 'desktop'}">
|
|
98
|
+
Content adapts to screen size
|
|
99
|
+
</div>
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
}</code></pre>
|
|
103
|
+
|
|
104
|
+
<h4>Multiple Handlers</h4>
|
|
105
|
+
<pre><code class="hljs javascript">// Handler for navigation
|
|
106
|
+
const navHandler = (width) => {
|
|
107
|
+
const nav = document.querySelector('.navigation');
|
|
108
|
+
nav.classList.toggle('mobile', width < 1024);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Handler for sidebar
|
|
112
|
+
const sidebarHandler = (width) => {
|
|
113
|
+
const sidebar = document.querySelector('.sidebar');
|
|
114
|
+
sidebar.style.display = width < 768 ? 'none' : 'block';
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Both handlers will be called on resize
|
|
118
|
+
watchWindowSize(navHandler);
|
|
119
|
+
watchWindowSize(sidebarHandler);
|
|
120
|
+
|
|
121
|
+
// Clean up when needed
|
|
122
|
+
unwatchWindowSize(navHandler);
|
|
123
|
+
unwatchWindowSize(sidebarHandler);</code></pre>
|
|
124
|
+
|
|
125
|
+
<h4>Breakpoint Detection</h4>
|
|
126
|
+
<pre><code class="hljs javascript">const breakpoints = {
|
|
127
|
+
mobile: 768,
|
|
128
|
+
tablet: 1024,
|
|
129
|
+
desktop: 1200
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const breakpointHandler = (width) => {
|
|
133
|
+
let currentBreakpoint = 'mobile';
|
|
134
|
+
|
|
135
|
+
if (width >= breakpoints.desktop) {
|
|
136
|
+
currentBreakpoint = 'desktop';
|
|
137
|
+
} else if (width >= breakpoints.tablet) {
|
|
138
|
+
currentBreakpoint = 'tablet';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
document.body.setAttribute('data-breakpoint', currentBreakpoint);
|
|
142
|
+
|
|
143
|
+
// Dispatch custom event
|
|
144
|
+
window.dispatchEvent(new CustomEvent('breakpointchange', {
|
|
145
|
+
detail: { width, breakpoint: currentBreakpoint }
|
|
146
|
+
}));
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
watchWindowSize(breakpointHandler);</code></pre>
|
|
150
|
+
|
|
151
|
+
<h4>Performance Benefits</h4>
|
|
152
|
+
<p>The utility automatically debounces resize events, so you don't need to worry about performance:</p>
|
|
153
|
+
<pre><code class="hljs javascript">// This handler will only be called after resize events stop
|
|
154
|
+
const expensiveHandler = (width) => {
|
|
155
|
+
// Expensive DOM calculations or API calls
|
|
156
|
+
recalculateLayout();
|
|
157
|
+
updateCharts();
|
|
158
|
+
reflow();
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
watchWindowSize(expensiveHandler); // Automatically debounced</code></pre>
|
|
162
|
+
|
|
163
|
+
</main>
|
|
164
|
+
<div style="height:33vh"></div>
|
|
165
|
+
</body>
|
|
166
|
+
</html>
|
package/icons/error.svg
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240ZM330-120 120-330v-300l210-210h300l210 210v300L630-120H330Zm34-80h232l164-164v-232L596-760H364L200-596v232l164 164Zm116-280Z"/></svg>
|
package/icons/warning.svg
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="m40-120 440-760 440 760H40Zm138-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm-40-120h80v-200h-80v200Zm40-100Z"/></svg>
|
package/package.json
CHANGED
package/scripts/build.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from 'fs/promises';
|
|
|
2
2
|
import { minify } from 'terser';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import { ensureDir, copyDir, emptyDir } from '
|
|
5
|
+
import { ensureDir, copyDir, emptyDir } from 'kempo-server/utils/fs-utils';
|
|
6
6
|
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
package/scripts/docs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dirname, join } from 'path';
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
3
|
import { spawn } from 'child_process';
|
|
4
|
-
import { getArgs,
|
|
4
|
+
import { getArgs, runChildNodeProcessScript } from 'kempo-server/utils/cli';
|
|
5
5
|
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = dirname(__filename);
|
|
@@ -21,7 +21,9 @@ const {
|
|
|
21
21
|
} = options;
|
|
22
22
|
|
|
23
23
|
if(build && !noBuild){
|
|
24
|
-
|
|
24
|
+
console.log('Building component files...');
|
|
25
|
+
await runChildNodeProcessScript(join(__dirname, 'build.js'));
|
|
26
|
+
console.log('Component files built!');
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
const rootDir = 'docs';
|