kempo-ui 0.2.3 → 0.3.0
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/dist/components/Context.js +1 -0
- package/dist/components/Table.js +6 -5
- package/docs/components/aside-items.html +1 -0
- package/docs/components/aside-menu.html +1 -0
- package/docs/components/aside-push.html +1 -0
- package/docs/components/aside.html +6 -2
- package/docs/components/context.html +231 -0
- package/docs/components/nav.html +7 -2
- package/docs/components/table.html +13 -1
- package/docs/components/tableControls.html +2 -1
- package/docs/components/tableCustomFields.html +28 -2
- package/docs/components/tableFetchRecords.html +2 -1
- package/docs/components/tableFieldSortHide.html +2 -1
- package/docs/components/tablePagination.html +2 -1
- package/docs/components/tableRecordEditing.html +33 -1
- package/docs/components/tableRecordFiltering.html +2 -1
- package/docs/components/tableRecordHiding.html +2 -1
- package/docs/components/tableRecordSearching.html +2 -1
- package/docs/components/tableRecordSelection.html +2 -1
- package/docs/components/tableRowControls.html +2 -1
- package/docs/components/tableServerSync.html +1 -0
- package/docs/components/tableSorting.html +2 -1
- package/docs/icons/npm.svg +1 -0
- package/docs/index.html +6 -0
- package/docs/nav-1.inc.html +5 -2
- package/docs/nav.inc.html +4 -1
- package/docs/src/components/Context.js +1 -0
- package/docs/src/components/Table.js +6 -5
- package/docs/utils/elevation.html +6 -2
- package/icons/npm.svg +1 -0
- package/llm.txt +1 -0
- package/package.json +1 -1
- package/src/components/Context.js +84 -0
- package/src/components/Table.js +7 -4
- package/tests/components/Context.browser-test.js +238 -0
- package/tests/components/Table.browser-test.js +132 -0
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
<h1 class="ta-center">Table - Field Sort and Hide</h1>
|
|
56
56
|
<k-main>
|
|
57
57
|
|
|
58
|
-
<a href="./
|
|
58
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
59
59
|
|
|
60
60
|
<p>This example shows how to use the <code><k-tc-field-sort-hide></code> component to allow users to show or hide fields in the table, and sort fields.</p>
|
|
61
61
|
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-table</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"fieldVisibilityExample"</span>></span><br /> <span class="hljs-tag"><<span class="hljs-name">k-tc-field-sort-hide</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"top"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-tc-field-sort-hide</span>></span><br /><span class="hljs-tag"></<span class="hljs-name">k-table</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/src/components/tableControls/FieldSortHide.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'fieldVisibilityExample'</span>).setRecords(contacts);<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
</k-main>
|
|
70
70
|
<div style="height: 33.333vh"></div>
|
|
71
71
|
<script type="module" src="../src/components/Import.js"></script>
|
|
72
|
+
<div style="height:33vh"></div>
|
|
72
73
|
<script type="module" src="../src/components/Main.js"></script>
|
|
73
74
|
</body>
|
|
74
75
|
</html>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<k-import src="../nav-1.inc.html"></k-import>
|
|
54
54
|
<h1 class="ta-center">Table - Pagination</h1>
|
|
55
55
|
<k-main>
|
|
56
|
-
<a href="./
|
|
56
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
57
57
|
<p>The table component supports pagination, enable it by adding the <code>enable-pages</code> attribute to the <code>k-table</code> element.</p>
|
|
58
58
|
<p>You can optionally set the page size and page size options by setting the <code>page-size</code> and <code>page-size-options</code> attributes respectively. <code>page-size-options</code> must be in the format of an array of numbers (with brackets).</p>
|
|
59
59
|
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
<script type="module" src="../src/components/tableControls/NextPage.js"></script>
|
|
97
97
|
<script type="module" src="../src/components/tableControls/LastPage.js"></script>
|
|
98
98
|
<script type="module" src="../src/components/tableControls/PageSelect.js"></script>
|
|
99
|
+
<div style="height:33vh"></div>
|
|
99
100
|
<script type="module" src="../src/components/tableControls/PageSize.js"></script>
|
|
100
101
|
</body>
|
|
101
102
|
</html>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<k-import src="../nav-1.inc.html"></k-import>
|
|
54
54
|
<h1 class="ta-center">Table - Record Editing</h1>
|
|
55
55
|
<k-main>
|
|
56
|
-
<a href="./
|
|
56
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
57
57
|
|
|
58
58
|
<p>The table component supports record editing. To allow for editing add the "edit" control to the "before" or "after" controls. You may define a "type" on the field, which will tell the table to use a specific editor for that field. If you do not define a "type" it will attempt to find the correct type using the value.</p>
|
|
59
59
|
<p>You can also define a custom editor by adding a generator function to the <code>Table.editors</code> object that will generate an input (or select). This will be global to all tables on the page.</p>
|
|
@@ -136,11 +136,43 @@
|
|
|
136
136
|
]
|
|
137
137
|
});
|
|
138
138
|
</script>
|
|
139
|
+
|
|
140
|
+
<h3>Non-Editable Fields</h3>
|
|
141
|
+
<p>Set <code>editable: false</code> on a field definition to make it read-only during record editing. The cell will display its value normally while the row is in edit mode. This is useful for fields like IDs or calculated values that should not be changed directly.</p>
|
|
142
|
+
|
|
143
|
+
<pre><code class="hljs javascript"><span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">'nonEditableFieldExample'</span>).<span class="hljs-title function_">setData</span>({<br> <span class="hljs-attr">records</span>: contacts,<br> <span class="hljs-attr">fields</span>: [{<br> <span class="hljs-attr">name</span>: <span class="hljs-string">'name'</span>,<br> <span class="hljs-attr">label</span>: <span class="hljs-string">'Name'</span>,<br> <span class="hljs-attr">editable</span>: <span class="hljs-literal">false</span><br> }, {<br> <span class="hljs-attr">name</span>: <span class="hljs-string">'email'</span>,<br> <span class="hljs-attr">label</span>: <span class="hljs-string">'Email'</span><br> }, {<br> <span class="hljs-attr">name</span>: <span class="hljs-string">'birthday'</span>,<br> <span class="hljs-attr">label</span>: <span class="hljs-string">'Birthday'</span>,<br> <span class="hljs-attr">type</span>: <span class="hljs-string">'date'</span><br> }]<br>});</code></pre>
|
|
144
|
+
|
|
145
|
+
<k-table id="nonEditableFieldExample">
|
|
146
|
+
<k-tc-edit slot="after"></k-tc-edit>
|
|
147
|
+
</k-table>
|
|
148
|
+
<script type="module">
|
|
149
|
+
await window.customElements.whenDefined('k-table');
|
|
150
|
+
document.getElementById('nonEditableFieldExample').setData({
|
|
151
|
+
records: contacts,
|
|
152
|
+
fields: [
|
|
153
|
+
{
|
|
154
|
+
name: 'name',
|
|
155
|
+
label: 'Name',
|
|
156
|
+
editable: false
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'email',
|
|
160
|
+
label: 'Email'
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'birthday',
|
|
164
|
+
label: 'Birthday',
|
|
165
|
+
type: 'date'
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
});
|
|
169
|
+
</script>
|
|
139
170
|
</k-main>
|
|
140
171
|
<div style="height: 33.333vh"></div>
|
|
141
172
|
<script type="module" src="../src/components/Import.js"></script>
|
|
142
173
|
<script type="module" src="../src/components/Main.js"></script>
|
|
143
174
|
<script type="module" src="../src/components/Table.js"></script>
|
|
175
|
+
<div style="height:33vh"></div>
|
|
144
176
|
<script type="module" src="../src/components/tableControls/Edit.js"></script>
|
|
145
177
|
</body>
|
|
146
178
|
</html>
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
<h1 class="ta-center">Table - Record Filtering</h1>
|
|
56
56
|
<k-main>
|
|
57
57
|
|
|
58
|
-
<a href="./
|
|
58
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
59
59
|
|
|
60
60
|
<p>Record filtering is a feature that allows users to filter the records displayed in the table. The table component provides a filter control that can be used to filter records based on the values in the columns. This control uses a Dialog to display the current filters and allows the user to create filters.</p>
|
|
61
61
|
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
</k-main>
|
|
83
83
|
<div style="height: 33.333vh"></div>
|
|
84
84
|
<script type="module" src="../src/components/Import.js"></script>
|
|
85
|
+
<div style="height:33vh"></div>
|
|
85
86
|
<script type="module" src="../src/components/Main.js"></script>
|
|
86
87
|
</body>
|
|
87
88
|
</html>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
<h1 class="ta-center">Table - Record Hiding</h1>
|
|
55
55
|
<k-main>
|
|
56
56
|
|
|
57
|
-
<a href="./
|
|
57
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
58
58
|
|
|
59
59
|
<p>The table component supports record hiding. To allow for hiding add the "hide" control to the "before" or "after" controls. There is a built-in "showAll" control that can be added to the "top" or "bottom" controls to reveal previously hidden fields.</p>
|
|
60
60
|
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
<script type="module" src="../src/components/Table.js"></script>
|
|
78
78
|
<script type="module" src="../src/components/tableControls/Hide.js"></script>
|
|
79
79
|
<script type="module" src="../src/components/tableControls/HiddenCount.js"></script>
|
|
80
|
+
<div style="height:33vh"></div>
|
|
80
81
|
<script type="module" src="../src/components/tableControls/ShowAll.js"></script>
|
|
81
82
|
</body>
|
|
82
83
|
</html>
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
<h1 class="ta-center">Table - Record Searching</h1>
|
|
56
56
|
<k-main>
|
|
57
57
|
|
|
58
|
-
<a href="./
|
|
58
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
59
59
|
|
|
60
60
|
<p>The search control (aka quick filter) is a feature that allows users to filter the records displayed in the table. The control is a search input that can be used to filter records based on the values in the columns.</p>
|
|
61
61
|
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-table</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"quickFilterExample"</span>></span><br /> <span class="hljs-tag"><<span class="hljs-name">k-tc-search</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"top"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width: 20rem"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-tc-search</span>></span><br /><span class="hljs-tag"></<span class="hljs-name">k-table</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/src/components/tableControls/Search.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'quickFilterExample'</span>).setRecords(contacts);<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
</k-main>
|
|
70
70
|
<div style="height: 33.333vh"></div>
|
|
71
71
|
<script type="module" src="../src/components/Import.js"></script>
|
|
72
|
+
<div style="height:33vh"></div>
|
|
72
73
|
<script type="module" src="../src/components/Main.js"></script>
|
|
73
74
|
</body>
|
|
74
75
|
</html>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<k-import src="../nav-1.inc.html"></k-import>
|
|
54
54
|
<h1 class="ta-center">Table - Record Selection</h1>
|
|
55
55
|
<k-main>
|
|
56
|
-
<a href="./
|
|
56
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
57
57
|
|
|
58
58
|
<p>The table component supports record selection. You can enable selection by setting the <code>enable-selection</code> attribute to <code>true</code>. This will add a checkbox to each row and a "Select All" checkbox to the header.</p>
|
|
59
59
|
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
<div style="height: 33.333vh"></div>
|
|
72
72
|
<script type="module" src="../src/components/Import.js"></script>
|
|
73
73
|
<script type="module" src="../src/components/Main.js"></script>
|
|
74
|
+
<div style="height:33vh"></div>
|
|
74
75
|
<script type="module" src="../src/components/Table.js"></script>
|
|
75
76
|
</body>
|
|
76
77
|
</html>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
<h1 class="ta-center">Table - Row Controls</h1>
|
|
55
55
|
<k-main>
|
|
56
56
|
|
|
57
|
-
<a href="./
|
|
57
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
58
58
|
<p>The table component can display controls before or after each row. Each control is defined by an icon name, a callback function, and optionally an HTML string or a render function. Use <code>slot="before"</code> to add the control before each row, and use <code>slot="after"</code> to add the control after each row.</p>
|
|
59
59
|
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-table</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"rowControlsExample"</span>></span><br /> <span class="hljs-tag"><<span class="hljs-name">k-tc-export-json</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"before"</span> <span class="hljs-attr">max-width</span>=<span class="hljs-string">"40"</span>></span><br /> <span class="hljs-tag"><<span class="hljs-name">k-icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"export-file"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-icon</span>></span><br /> <span class="hljs-tag"></<span class="hljs-name">k-tc-export-json</span>></span><br /> <span class="hljs-tag"><<span class="hljs-name">k-tc-delete-record</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"after"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-tc-delete-record</span>></span><br /><span class="hljs-tag"></<span class="hljs-name">k-table</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-keyword">await</span> <span class="hljs-built_in">window</span>.customElements.whenDefined(<span class="hljs-string">'k-table'</span>);<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'rowControlsExample'</span>).setRecords(contacts);<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
60
60
|
<k-table id="rowControlsExample">
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
<script type="module" src="../src/components/tableControls/ExportJson.js"></script>
|
|
74
74
|
<script type="module" src="../src/components/tableControls/DeleteRecord.js"></script>
|
|
75
75
|
<script type="module" src="../src/components/Import.js"></script>
|
|
76
|
+
<div style="height:33vh"></div>
|
|
76
77
|
<script type="module" src="../src/components/Main.js"></script>
|
|
77
78
|
</body>
|
|
78
79
|
</html>
|
|
@@ -139,6 +139,7 @@
|
|
|
139
139
|
<script type="module" src="../src/components/tableControls/Edit.js"></script>
|
|
140
140
|
<script type="module" src="../src/components/tableControls/DeleteRecord.js"></script>
|
|
141
141
|
<script type="module" src="../src/components/tableControls/DeleteSelected.js"></script>
|
|
142
|
+
<div style="height:33vh"></div>
|
|
142
143
|
<script type="module" src="../src/components/Toast.js"></script>
|
|
143
144
|
</body>
|
|
144
145
|
</html>
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
<h1 class="ta-center">Table - Sorting</h1>
|
|
56
56
|
<k-main>
|
|
57
57
|
|
|
58
|
-
<a href="./
|
|
58
|
+
<a href="./table.html"><h5>Back to Table Component Documentation</h5></a>
|
|
59
59
|
|
|
60
60
|
<p>The sorting feature allows users to sort the records displayed in the table by clicking on the column headers. This is enabled by setting the <code>enable-sorting="true"</code> attribute.</p>
|
|
61
61
|
<p>Once enabled the user can sort the records by clicking on the fields.</p>
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
</k-main>
|
|
68
68
|
<div style="height: 33.333vh"></div>
|
|
69
69
|
<script type="module" src="../src/components/Import.js"></script>
|
|
70
|
+
<div style="height:33vh"></div>
|
|
70
71
|
<script type="module" src="../src/components/Main.js"></script>
|
|
71
72
|
</body>
|
|
72
73
|
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z"/></svg>
|
package/docs/index.html
CHANGED
|
@@ -77,6 +77,12 @@
|
|
|
77
77
|
<p class="tc-muted">Swipeable carousel for images and content with navigation controls.</p>
|
|
78
78
|
</a>
|
|
79
79
|
</div>
|
|
80
|
+
<div class="span-12 t-span-6 d-span-4 px">
|
|
81
|
+
<a href="./components/context.html" class="card mb no-link d-b">
|
|
82
|
+
<h3 class="tc-primary">Context</h3>
|
|
83
|
+
<p class="tc-muted">Non-rendering state container for sharing data and notifying descendant components of changes.</p>
|
|
84
|
+
</a>
|
|
85
|
+
</div>
|
|
80
86
|
<div class="span-12 t-span-6 d-span-4 px">
|
|
81
87
|
<a href="./components/dialog.html" class="card mb no-link d-b">
|
|
82
88
|
<h3 class="tc-primary">Dialog</h3>
|
package/docs/nav-1.inc.html
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
<k-filter-item filter-keywords="card components"><a href="../components/card.html">Card<br><small>Component</small></a></k-filter-item>
|
|
26
26
|
<k-filter-item filter-keywords="color picker colorpicker components"><a href="../components/color-picker.html">Color Picker<br><small>Component</small></a></k-filter-item>
|
|
27
27
|
<k-filter-item filter-keywords="content slider components"><a href="../components/content-slider.html">Content Slider<br><small>Component</small></a></k-filter-item>
|
|
28
|
+
<k-filter-item filter-keywords="context state global components"><a href="../components/context.html">Context<br><small>Component</small></a></k-filter-item>
|
|
28
29
|
<k-filter-item filter-keywords="dialog modal popup components"><a href="../components/dialog.html">Dialog<br><small>Component</small></a></k-filter-item>
|
|
29
30
|
<k-filter-item filter-keywords="dropdown select components"><a href="../components/dropdown.html">Dropdown<br><small>Component</small></a></k-filter-item>
|
|
30
31
|
<k-filter-item filter-keywords="filter list filterlist components"><a href="../components/filter-list.html">Filter List<br><small>Component</small></a></k-filter-item>
|
|
@@ -80,8 +81,9 @@
|
|
|
80
81
|
</div>
|
|
81
82
|
</div>
|
|
82
83
|
<div class="flex"></div>
|
|
83
|
-
<a href="https://github.com/dustinpoissant/kempo-ui?tab=License-1-ov-file#creative-commons-attribution-noncommercial-sharealike-20"><k-icon name="license"></k-icont></a>
|
|
84
|
-
<a href="https://
|
|
84
|
+
<a href="https://github.com/dustinpoissant/kempo-ui?tab=License-1-ov-file#creative-commons-attribution-noncommercial-sharealike-20" target="_blank"><k-icon name="license"></k-icont></a>
|
|
85
|
+
<a href="https://www.npmjs.com/package/kempo-ui" target="_blank"><k-icon name="npm"></k-icont></a>
|
|
86
|
+
<a href="https://github.com/dustinpoissant/kempo-ui" target="_blank"><k-icon name="github-mark"></k-icont></a>
|
|
85
87
|
<k-theme-switcher></k-theme-switcher>
|
|
86
88
|
</k-nav>
|
|
87
89
|
<div style="width: 100%; height: 4rem;"></div>
|
|
@@ -102,6 +104,7 @@
|
|
|
102
104
|
<a href="../components/card.html">Card</a>
|
|
103
105
|
<a href="../components/color-picker.html">ColorPicker</a>
|
|
104
106
|
<a href="../components/content-slider.html">Content Slider</a>
|
|
107
|
+
<a href="../components/context.html">Context</a>
|
|
105
108
|
<a href="../components/dialog.html">Dialog</a>
|
|
106
109
|
<a href="../components/dropdown.html">Dropdown</a>
|
|
107
110
|
<a href="../components/filter-list.html">Filter List</a>
|
package/docs/nav.inc.html
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
<k-filter-item filter-keywords="card components"><a href="./components/card.html">Card<br><small>Component</small></a></k-filter-item>
|
|
26
26
|
<k-filter-item filter-keywords="color picker colorpicker components"><a href="./components/color-picker.html">Color Picker<br><small>Component</small></a></k-filter-item>
|
|
27
27
|
<k-filter-item filter-keywords="content slider components"><a href="./components/content-slider.html">Content Slider<br><small>Component</small></a></k-filter-item>
|
|
28
|
+
<k-filter-item filter-keywords="context state global components"><a href="./components/context.html">Context<br><small>Component</small></a></k-filter-item>
|
|
28
29
|
<k-filter-item filter-keywords="dialog modal popup components"><a href="./components/dialog.html">Dialog<br><small>Component</small></a></k-filter-item>
|
|
29
30
|
<k-filter-item filter-keywords="dropdown select components"><a href="./components/dropdown.html">Dropdown<br><small>Component</small></a></k-filter-item>
|
|
30
31
|
<k-filter-item filter-keywords="filter list filterlist components"><a href="./components/filter-list.html">Filter List<br><small>Component</small></a></k-filter-item>
|
|
@@ -80,7 +81,8 @@
|
|
|
80
81
|
</div>
|
|
81
82
|
</div>
|
|
82
83
|
<div class="flex"></div>
|
|
83
|
-
<a href="https://github.com/dustinpoissant/kempo-ui?tab=License-1-ov-file#creative-commons-attribution-noncommercial-sharealike-20" target="_blank"><k-icon name="license"></k-icont></a>
|
|
84
|
+
<a href="https://github.com/dustinpoissant/kempo-ui?tab=License-1-ov-file#creative-commons-attribution-noncommercial-sharealike-20" target="_blank" target="_blank"><k-icon name="license"></k-icont></a>
|
|
85
|
+
<a href="https://www.npmjs.com/package/kempo-ui" target="_blank"><k-icon name="npm"></k-icont></a>
|
|
84
86
|
<a href="https://github.com/dustinpoissant/kempo-ui" target="_blank"><k-icon name="github-mark"></k-icont></a>
|
|
85
87
|
<k-theme-switcher></k-theme-switcher>
|
|
86
88
|
</k-nav>
|
|
@@ -103,6 +105,7 @@
|
|
|
103
105
|
<a href="./components/card.html">Card</a>
|
|
104
106
|
<a href="./components/color-picker.html">ColorPicker</a>
|
|
105
107
|
<a href="./components/content-slider.html">Content Slider</a>
|
|
108
|
+
<a href="./components/context.html">Context</a>
|
|
106
109
|
<a href="./components/dialog.html">Dialog</a>
|
|
107
110
|
<a href="./components/dropdown.html">Dropdown</a>
|
|
108
111
|
<a href="./components/filter-list.html">Filter List</a>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{html}from"../lit-all.min.js";import LightComponent from"./LightComponent.js";export default class Context extends LightComponent{static properties={data:{type:String,reflect:!0}};constructor(){super(),this.data="{}"}connectedCallback(){super.connectedCallback(),this.style.display="contents"}set(t,e){const s=JSON.parse(this.data||"{}"),a=!(t in s),n=s[t];s[t]=e,this.data=JSON.stringify(s),this.dispatchEvent(new CustomEvent(a?"context:create":"context:set",{detail:a?{key:t,value:e}:{key:t,value:e,oldValue:n},bubbles:!0,composed:!0}))}get(t){return JSON.parse(this.data||"{}")[t]}has(t){return t in JSON.parse(this.data||"{}")}delete(t){const e=JSON.parse(this.data||"{}");if(!(t in e))return;const s=e[t];delete e[t],this.data=JSON.stringify(e),this.dispatchEvent(new CustomEvent("context:delete",{detail:{key:t,value:s},bubbles:!0,composed:!0}))}clear(){for(const t of Object.keys(JSON.parse(this.data||"{}")))this.delete(t)}getData(){return JSON.parse(this.data||"{}")}renderLightDom(){return html``}}customElements.define("k-context",Context);
|
|
@@ -19,15 +19,15 @@ import{html,css,unsafeStatic,literal}from"../lit-all.min.js";import ShadowCompon
|
|
|
19
19
|
@change=${t=>this.handleRecordSelectionChange(e,t)}
|
|
20
20
|
/>
|
|
21
21
|
</td>
|
|
22
|
-
`),this.hasBeforeControls()&&t.push(this.renderBeforeControlsTemplate()),this.fields.forEach(({name:s,formatter:i,calculator:r,type:o,editor:n,hidden:l})=>{if(l)return;let
|
|
22
|
+
`),this.hasBeforeControls()&&t.push(this.renderBeforeControlsTemplate()),this.fields.forEach(({name:s,formatter:i,calculator:r,type:o,editor:n,hidden:l,editable:a})=>{if(l)return;let d=e[s]||"";t.push(html`
|
|
23
23
|
<td class="cell" data-field=${s}>
|
|
24
|
-
${e[editing]?this.renderEditingCell(e,s,
|
|
24
|
+
${e[editing]?this.renderEditingCell(e,s,d,r,n,o,a):this.renderDisplayCell(e,s,d,r,i)}
|
|
25
25
|
</td>
|
|
26
26
|
`)}),this.hasAfterControls()&&t.push(this.renderAfterControlsTemplate()),html`
|
|
27
27
|
<tr class="record ${e[editing]?"editing":""}" data-index=${e[index]}>
|
|
28
28
|
${t}
|
|
29
29
|
</tr>
|
|
30
|
-
`}renderEditingCell(e,t,s,i,r,o){if(i)return html`<input disabled .value=${i(e,this)} />`;if(r){const e=r(s);return html`${e}`}switch(o||typeof s){case"number":return html`<input type="number" .value=${s} />`;case"date":return html`<input type="date" .value=${s} />`;case"boolean":return html`
|
|
30
|
+
`}renderEditingCell(e,t,s,i,r,o,n){if(!1===n)return this.renderDisplayCell(e,t,s,i,null);if(i)return html`<input disabled .value=${i(e,this)} />`;if(r){const e=r(s);return html`${e}`}switch(o||typeof s){case"number":return html`<input type="number" .value=${s} />`;case"date":return html`<input type="date" .value=${s} />`;case"boolean":return html`
|
|
31
31
|
<select .value=${s}>
|
|
32
32
|
<option value="true" ?selected=${s}>True</option>
|
|
33
33
|
<option value="false" ?selected=${!s}>False</option>
|
|
@@ -40,7 +40,7 @@ import{html,css,unsafeStatic,literal}from"../lit-all.min.js";import ShadowCompon
|
|
|
40
40
|
<td class="cell controls controls-after">
|
|
41
41
|
<div>${e}</div>
|
|
42
42
|
</td>
|
|
43
|
-
`}hasBeforeControls(){return!!this.querySelector('[slot="before"]')}hasAfterControls(){return!!this.querySelector('[slot="after"]')}hasTopControls(){return!!this.querySelector('[slot="top"]')}hasBottomControls(){return!!this.querySelector(":scope > :not([slot])")}editRecord(e){e[editing]=!0;const t=this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`);t&&(t.classList.add("editing"),t.setAttribute("editing","true"),t.querySelectorAll(".cell[data-field]").forEach(t=>{const s=t.dataset.field,i=this.fields.find(e=>e.name===s);if(i){const r=e[s]||"";if(t.innerHTML="",i.calculator){const s=document.createElement("input");s.disabled=!0,s.value=i.calculator(e,this),t.appendChild(s)}else if(i.editor)t.appendChild(i.editor(r));else{const e=i.type||typeof r,s=Table.editors[e]||Table.editors.string;t.appendChild(s(r))}}})),this.dispatchEvent(new CustomEvent("editingChange",{detail:{record:e,editing:!0},bubbles:!0}))}saveEditedRecord(e){const t=this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`),s={};t&&t.querySelectorAll(".cell[data-field]").forEach(e=>{const t=e.dataset.field,i=this.fields.find(e=>e.name===t);if(i&&!i.calculator){const i=e.querySelector("input, select");i&&(s[t]=i.value)}});const i=()=>{Object.assign(e,s),e[editing]=!1,t&&(t.classList.remove("editing"),t.removeAttribute("editing"),t.querySelectorAll(".cell[data-field]").forEach(t=>{const s=t.dataset.field,i=this.fields.find(e=>e.name===s);if(i){const r=e[s]||"";i.calculator?t.textContent=i.calculator(e,this):i.formatter?t.innerHTML=i.formatter(r):t.textContent=r}})),this.dispatchEvent(new CustomEvent("editingChange",{detail:{record:e,editing:!1},bubbles:!0}))};if(Object.keys(s).some(t=>String(e[t]??"")!==s[t]))if(this.requestEdit){t?.classList.add("pending");const r=()=>{t?.classList.remove("pending"),i()},o=()=>{t?.classList.remove("pending")};this.dispatchEvent(new CustomEvent("requestSave",{detail:{record:e,newData:s,approve:r,reject:o},bubbles:!0}))}else i();else this.cancelEditedRecord(e)}cancelEditedRecord(e){e[editing]=!1;const t=this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`);t&&(t.classList.remove("editing"),t.removeAttribute("editing"),t.querySelectorAll(".cell[data-field]").forEach(t=>{const s=t.dataset.field,i=this.fields.find(e=>e.name===s);if(i){const r=e[s]||"";i.calculator?t.textContent=i.calculator(e,this):i.formatter?t.innerHTML=i.formatter(r):t.textContent=r}})),this.dispatchEvent(new CustomEvent("editingChange",{detail:{record:e,editing:!1},bubbles:!0}))}recordIsEditing(e){return e[editing]}getCurrentPage(){return this.currentPage}getTotalPages(){return Math.ceil(this.getDisplayedRecords().length/this.pageSize)}setPage(e){e<1||e>this.getTotalPages()||(this.currentPage=e,this.requestUpdate(),this.dispatchEvent(new CustomEvent("pageChange",{bubbles:!0})))}firstPage(){1!==this.currentPage&&this.setPage(1)}nextPage(){this.currentPage<this.getTotalPages()&&this.setPage(this.currentPage+1)}prevPage(){this.currentPage>1&&this.setPage(this.currentPage-1)}lastPage(){this.currentPage!==this.getTotalPages()&&this.setPage(this.getTotalPages())}setPageSize(e){this.pageSize=e,this.currentPage=1,this.requestUpdate(),this.dispatchEvent(new CustomEvent("pageSizeChange",{bubbles:!0}))}getPageSize(){return this.pageSize}getPageSizeOptions(){return this.pageSizeOptions}getFieldLabel(e){const t=this.fields.find(t=>t.name===e);return t?t.label:toTitleCase(e)}setPageSizeOptions(e){this.pageSizeOptions=e,this.requestUpdate()}setData({records:e=!1,fields:t=!1,pageSize:s=!1,pageSizeOptions:i=!1,currentPage:r=!1,enableSelection:o}={}){let n=!1,l=this.getTotalPages(),a=this.currentPage;e&&(this.records=e.map(e=>({...e})),this.records.forEach((e,t)=>{e[index]=t,e[selected]=!1,e[hidden]=!1,e[editing]=!1}),this.fields=t||Table.extractFieldsFromRecords(this.records),n=!0),s&&(this.pageSize=s,n=!0),i&&(this.pageSizeOptions=i),r&&(this.currentPage=r,n=!0),void 0!==o&&(this.enableSelection=o,n=!0),n&&this.requestUpdate();const d=this.getTotalPages();d!==l&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:this.getTotalPages()},bubbles:!0})),a>d&&this.setPage(d)}setRecords(e,t){let s=this.getTotalPages(),i=this.currentPage;this.records=e.map(e=>({...e})),this.records.forEach((e,t)=>{e[index]=t,e[selected]=!1,e[hidden]=!1,e[editing]=!1}),this.fields=t||Table.extractFieldsFromRecords(this.records),this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordsSet",{detail:{records:e},bubbles:!0}));const r=this.getTotalPages();r!==s&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:this.getTotalPages()},bubbles:!0})),i>r&&this.setPage(r)}setupFetchRecords(e,t){const s=this.records.length,i=this.getTotalPages();if(s<e){this.records.length=e,this.records.fill(null,s),this.requestUpdate();const t=this.getTotalPages();t!==i&&setTimeout(()=>{this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:t},bubbles:!0}))},0)}this.addEventListener("fetchRecords",async e=>{if(this.fetchPending)return;this.fetchPending=!0;const{start:s,count:i}=e.detail,r=await t(s,i);r.forEach((e,t)=>{e[index]=s+t,void 0===e[selected]&&(e[selected]=!1),void 0===e[hidden]&&(e[hidden]=!1),void 0===e[editing]&&(e[editing]=!1)}),this.records.splice(s,r.length,...r),this.fetchPending=!1,this.requestUpdate()})}addRecord(e){e[selected]=!1,e[hidden]=!1,e[index]=this.records.length,this.records.push(e),this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordAdded",{detail:{record:e},bubbles:!0}))}updateRecord(e,t){let s=!1,i=this.records.find(t=>t===e);if(i||void 0===e[index]||(i=this.records[e[index]]),Object.keys(t).forEach(e=>{i.hasOwnProperty(e)&&(i[e]=t[e],s=!0)}),s){const e=(this.currentPage-1)*this.pageSize,t=e+this.pageSize;(!this.enablePages||i[index]>=e&&i[index]<t)&&this.requestUpdate()}}deleteRecord(e){let t=this.records.find(t=>t===e);const s=this.getTotalPages();if(t||void 0===e[index]||(t=this.records[e[index]]),!t)return;const i=()=>{const e=this.records.indexOf(t);this.records.splice(e,1),this.records.forEach((e,t)=>{e[index]=t}),this.requestUpdate(),this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0})),this.dispatchEvent(new CustomEvent("recordDeleted",{detail:{index:e},bubbles:!0}));const i=this.getTotalPages();this.currentPage>i&&this.setPage(i),i!==s&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:i},bubbles:!0}))};if(this.requestDelete){const e=this.shadowRoot.querySelector(`.record[data-index="${t[index]}"]`);e?.classList.add("pending");const s=()=>{e?.classList.remove("pending"),i()},r=()=>{e?.classList.remove("pending")};this.dispatchEvent(new CustomEvent("requestDelete",{detail:{records:[t],approve:s,reject:r},bubbles:!0}))}else i()}deleteSelected(){const e=this.getTotalPages(),t=this.getSelectedRecords().map(e=>this.records.find(t=>t===e)??(void 0!==e[index]?this.records[e[index]]:null)).filter(Boolean);if(!t.length)return;const s=()=>{t.forEach(e=>{const t=this.records.indexOf(e);-1!==t&&this.records.splice(t,1)}),this.records.forEach((e,t)=>{e[index]=t}),this.requestUpdate();const s=this.getTotalPages();this.currentPage>s&&this.setPage(s),s!==e&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:s},bubbles:!0})),this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0}))};if(this.requestDelete){const e=t.map(e=>this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`)).filter(Boolean);e.forEach(e=>e.classList.add("pending"));const i=()=>{e.forEach(e=>e.classList.remove("pending")),s()},r=()=>{e.forEach(e=>e.classList.remove("pending"))};this.dispatchEvent(new CustomEvent("requestDelete",{detail:{records:t,approve:i,reject:r},bubbles:!0}))}else s()}getSelectedRecords(){return this.records.filter(e=>e[selected])}selectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let s=e;s<t;s++)this.records[s][selected]=!0;this.requestUpdate(),setTimeout(()=>{this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0}))},0)}deselectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let s=e;s<t;s++)this.records[s][selected]=!1;this.requestUpdate(),setTimeout(()=>{this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0}))},0)}allOnPageSelected(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let s=e;s<t;s++)if(!this.records[s][selected])return!1;return!0}sortBy(e,t=!0){this.sort=this.sort.filter(t=>t.name!==e),this.sort.push({name:e,asc:t}),this.requestUpdate()}hideRecord(e){let t=this.records.find(t=>t===e);t||void 0===e[index]||(t=this.records[e[index]]),t&&(t[hidden]=!0,this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordHidden",{bubbles:!0})))}showRecord(e){let t=this.records.find(t=>t===e);t||void 0===e[index]||(t=this.records[e[index]]),t&&(t[hidden]=!1,this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordShown",{bubbles:!0})))}showAllRecords(){this.records.forEach(e=>{e[hidden]=!1}),this.filters.length&&(this.filters=[],this.dispatchEvent(new CustomEvent("filterRemoved",{bubbles:!0})),this.dispatchEvent(new CustomEvent("filterChange",{bubbles:!0}))),this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordShown",{bubbles:!0})),this.dispatchEvent(new CustomEvent("allRecordsShown",{bubbles:!0}))}addFilter(e,t,s){this.filters.push({field:e,condition:t,value:s}),this.dispatchEvent(new CustomEvent("filterAdded",{bubbles:!0})),this.dispatchEvent(new CustomEvent("filterChange",{bubbles:!0})),this.requestUpdate()}removeFilter(e,t,s,i=!0){const r=this.filters.findIndex(i=>i.field===e&&i.condition===t&&i.value===s);-1!==r&&(this.records.forEach(i=>{this.testFilter(i,e,t,s)||(i[hidden]=!1)}),this.filters.splice(r,1),this.dispatchEvent(new CustomEvent("filterRemoved",{bubbles:!0})),this.dispatchEvent(new CustomEvent("filterChange",{bubbles:!0})),i&&this.requestUpdate())}testFilter(e,t,s,i){let r=e[t],o=i;switch(this.caseSensitiveFilters||"string"!=typeof r||"string"!=typeof i||(r=r.toLowerCase(),o=i.toLowerCase()),s){case"equals":return r===o;case"not-equals":return r!==o;case"contains":return r.includes(o);case"not-contains":return!r.includes(o);case"greater-than":return r>o;case"less-than":return r<o;case"greater-than-or-equal":return r>=o;case"less-than-or-equal":return r<=o;default:return!0}}removeAllFilters(){this.filters.length&&([...this.filters].forEach(({field:e,condition:t,value:s})=>{this.removeFilter(e,t,s,!1)}),this.requestUpdate())}search(e){const t=e.trim().toLowerCase();let s=!1;this.records.forEach(e=>{if(e[hidden])return;let i=!1;this.fields.forEach(({name:s})=>{(e[s]?.toString().toLowerCase()||"").includes(t)&&(i=!0)}),e[hidden]!==!i&&(e[hidden]=!i,s=!0)}),s&&(this.dispatchEvent(new CustomEvent("recordHidden",{bubbles:!0})),this.requestUpdate()),this.dispatchEvent(new CustomEvent("search",{detail:{term:e},bubbles:!0}))}getDisplayedRecords(){this.filters.forEach(({field:e,condition:t,value:s})=>{this.records.forEach(i=>{null!==i&&(this.testFilter(i,e,t,s)||(i[hidden]=!0))})});let e=this.records.filter(e=>null===e||!e[hidden]);return this.sort.forEach(({name:t,asc:s})=>{e.sort((e,i)=>null===e||null===i?0:e[t]<i[t]?s?-1:1:e[t]>i[t]?s?1:-1:0)}),e}getHiddenRecords(){return this.records.filter(e=>e[hidden])}calculateColumnSizes(){const e=Array.from(this.querySelectorAll('[slot="before"]')),t=Array.from(this.querySelectorAll('[slot="after"]')),s={beforeControls:e.reduce((e,t)=>e+(t.maxWidth||40),0),afterControls:t.reduce((e,t)=>e+(t.maxWidth||40),0)},i=[...e,...t].some(e=>void 0===e.maxWidth);return JSON.stringify(this.columnSizes)!==JSON.stringify(s)&&(this.columnSizes=s),i&&setTimeout(()=>this.calculateColumnSizes(),0),this.columnSizes}setFieldHiddenState(e,t){const s=this.fields.find(t=>t.name===e);s&&(s.hidden=t,this.calculateColumnSizes(),this.requestUpdate(),this.dispatchEvent(new CustomEvent("fieldVisibilityChanged",{detail:{field:s},bubbles:!0})),this.dispatchEvent(new CustomEvent(t?"fieldHidden":"fieldShown",{detail:{field:s},bubbles:!0})))}hideField(e){this.setFieldHiddenState(e,!0)}showField(e){this.setFieldHiddenState(e,!1)}reorderFields(e){const t=[];e.forEach(e=>{const s=this.fields.find(t=>t.name===e);s&&t.push(s)}),this.fields=t,this.requestUpdate()}render(){return this.records&&this.fields?(this.calculateColumnSizes(),this.hasTopControls()?this.setAttribute("top-controls","true"):this.removeAttribute("top-controls"),this.hasBottomControls()?this.setAttribute("bottom-controls","true"):this.removeAttribute("bottom-controls"),html`
|
|
43
|
+
`}hasBeforeControls(){return!!this.querySelector('[slot="before"]')}hasAfterControls(){return!!this.querySelector('[slot="after"]')}hasTopControls(){return!!this.querySelector('[slot="top"]')}hasBottomControls(){return!!this.querySelector(":scope > :not([slot])")}editRecord(e){e[editing]=!0;const t=this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`);t&&(t.classList.add("editing"),t.setAttribute("editing","true"),t.querySelectorAll(".cell[data-field]").forEach(t=>{const s=t.dataset.field,i=this.fields.find(e=>e.name===s);if(i){if(!1===i.editable)return;const r=e[s]||"";if(t.innerHTML="",i.calculator){const s=document.createElement("input");s.disabled=!0,s.value=i.calculator(e,this),t.appendChild(s)}else if(i.editor)t.appendChild(i.editor(r));else{const e=i.type||typeof r,s=Table.editors[e]||Table.editors.string;t.appendChild(s(r))}}})),this.dispatchEvent(new CustomEvent("editingChange",{detail:{record:e,editing:!0},bubbles:!0}))}saveEditedRecord(e){const t=this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`),s={};t&&t.querySelectorAll(".cell[data-field]").forEach(e=>{const t=e.dataset.field,i=this.fields.find(e=>e.name===t);if(i&&!i.calculator){const i=e.querySelector("input, select");i&&(s[t]=i.value)}});const i=()=>{Object.assign(e,s),e[editing]=!1,t&&(t.classList.remove("editing"),t.removeAttribute("editing"),t.querySelectorAll(".cell[data-field]").forEach(t=>{const s=t.dataset.field,i=this.fields.find(e=>e.name===s);if(i){const r=e[s]||"";i.calculator?t.textContent=i.calculator(e,this):i.formatter?t.innerHTML=i.formatter(r):t.textContent=r}})),this.dispatchEvent(new CustomEvent("editingChange",{detail:{record:e,editing:!1},bubbles:!0}))};if(Object.keys(s).some(t=>String(e[t]??"")!==s[t]))if(this.requestEdit){t?.classList.add("pending");const r=()=>{t?.classList.remove("pending"),i()},o=()=>{t?.classList.remove("pending")};this.dispatchEvent(new CustomEvent("requestSave",{detail:{record:e,newData:s,approve:r,reject:o},bubbles:!0}))}else i();else this.cancelEditedRecord(e)}cancelEditedRecord(e){e[editing]=!1;const t=this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`);t&&(t.classList.remove("editing"),t.removeAttribute("editing"),t.querySelectorAll(".cell[data-field]").forEach(t=>{const s=t.dataset.field,i=this.fields.find(e=>e.name===s);if(i){const r=e[s]||"";i.calculator?t.textContent=i.calculator(e,this):i.formatter?t.innerHTML=i.formatter(r):t.textContent=r}})),this.dispatchEvent(new CustomEvent("editingChange",{detail:{record:e,editing:!1},bubbles:!0}))}recordIsEditing(e){return e[editing]}getCurrentPage(){return this.currentPage}getTotalPages(){return Math.ceil(this.getDisplayedRecords().length/this.pageSize)}setPage(e){e<1||e>this.getTotalPages()||(this.currentPage=e,this.requestUpdate(),this.dispatchEvent(new CustomEvent("pageChange",{bubbles:!0})))}firstPage(){1!==this.currentPage&&this.setPage(1)}nextPage(){this.currentPage<this.getTotalPages()&&this.setPage(this.currentPage+1)}prevPage(){this.currentPage>1&&this.setPage(this.currentPage-1)}lastPage(){this.currentPage!==this.getTotalPages()&&this.setPage(this.getTotalPages())}setPageSize(e){this.pageSize=e,this.currentPage=1,this.requestUpdate(),this.dispatchEvent(new CustomEvent("pageSizeChange",{bubbles:!0}))}getPageSize(){return this.pageSize}getPageSizeOptions(){return this.pageSizeOptions}getFieldLabel(e){const t=this.fields.find(t=>t.name===e);return t?t.label:toTitleCase(e)}setPageSizeOptions(e){this.pageSizeOptions=e,this.requestUpdate()}setData({records:e=!1,fields:t=!1,pageSize:s=!1,pageSizeOptions:i=!1,currentPage:r=!1,enableSelection:o}={}){let n=!1,l=this.getTotalPages(),a=this.currentPage;e&&(this.records=e.map(e=>({...e})),this.records.forEach((e,t)=>{e[index]=t,e[selected]=!1,e[hidden]=!1,e[editing]=!1}),this.fields=t||Table.extractFieldsFromRecords(this.records),n=!0),s&&(this.pageSize=s,n=!0),i&&(this.pageSizeOptions=i),r&&(this.currentPage=r,n=!0),void 0!==o&&(this.enableSelection=o,n=!0),n&&this.requestUpdate();const d=this.getTotalPages();d!==l&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:this.getTotalPages()},bubbles:!0})),a>d&&this.setPage(d)}setRecords(e,t){let s=this.getTotalPages(),i=this.currentPage;this.records=e.map(e=>({...e})),this.records.forEach((e,t)=>{e[index]=t,e[selected]=!1,e[hidden]=!1,e[editing]=!1}),this.fields=t||Table.extractFieldsFromRecords(this.records),this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordsSet",{detail:{records:e},bubbles:!0}));const r=this.getTotalPages();r!==s&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:this.getTotalPages()},bubbles:!0})),i>r&&this.setPage(r)}setupFetchRecords(e,t){const s=this.records.length,i=this.getTotalPages();if(s<e){this.records.length=e,this.records.fill(null,s),this.requestUpdate();const t=this.getTotalPages();t!==i&&setTimeout(()=>{this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:t},bubbles:!0}))},0)}this.addEventListener("fetchRecords",async e=>{if(this.fetchPending)return;this.fetchPending=!0;const{start:s,count:i}=e.detail,r=await t(s,i);r.forEach((e,t)=>{e[index]=s+t,void 0===e[selected]&&(e[selected]=!1),void 0===e[hidden]&&(e[hidden]=!1),void 0===e[editing]&&(e[editing]=!1)}),this.records.splice(s,r.length,...r),this.fetchPending=!1,this.requestUpdate()})}addRecord(e){e[selected]=!1,e[hidden]=!1,e[index]=this.records.length,this.records.push(e),this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordAdded",{detail:{record:e},bubbles:!0}))}updateRecord(e,t){let s=!1,i=this.records.find(t=>t===e);if(i||void 0===e[index]||(i=this.records[e[index]]),Object.keys(t).forEach(e=>{i.hasOwnProperty(e)&&(i[e]=t[e],s=!0)}),s){const e=(this.currentPage-1)*this.pageSize,t=e+this.pageSize;(!this.enablePages||i[index]>=e&&i[index]<t)&&this.requestUpdate()}}deleteRecord(e){let t=this.records.find(t=>t===e);const s=this.getTotalPages();if(t||void 0===e[index]||(t=this.records[e[index]]),!t)return;const i=()=>{const e=this.records.indexOf(t);this.records.splice(e,1),this.records.forEach((e,t)=>{e[index]=t}),this.requestUpdate(),this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0})),this.dispatchEvent(new CustomEvent("recordDeleted",{detail:{index:e},bubbles:!0}));const i=this.getTotalPages();this.currentPage>i&&this.setPage(i),i!==s&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:i},bubbles:!0}))};if(this.requestDelete){const e=this.shadowRoot.querySelector(`.record[data-index="${t[index]}"]`);e?.classList.add("pending");const s=()=>{e?.classList.remove("pending"),i()},r=()=>{e?.classList.remove("pending")};this.dispatchEvent(new CustomEvent("requestDelete",{detail:{records:[t],approve:s,reject:r},bubbles:!0}))}else i()}deleteSelected(){const e=this.getTotalPages(),t=this.getSelectedRecords().map(e=>this.records.find(t=>t===e)??(void 0!==e[index]?this.records[e[index]]:null)).filter(Boolean);if(!t.length)return;const s=()=>{t.forEach(e=>{const t=this.records.indexOf(e);-1!==t&&this.records.splice(t,1)}),this.records.forEach((e,t)=>{e[index]=t}),this.requestUpdate();const s=this.getTotalPages();this.currentPage>s&&this.setPage(s),s!==e&&this.dispatchEvent(new CustomEvent("pageCountChanged",{detail:{totalPages:s},bubbles:!0})),this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0}))};if(this.requestDelete){const e=t.map(e=>this.shadowRoot.querySelector(`.record[data-index="${e[index]}"]`)).filter(Boolean);e.forEach(e=>e.classList.add("pending"));const i=()=>{e.forEach(e=>e.classList.remove("pending")),s()},r=()=>{e.forEach(e=>e.classList.remove("pending"))};this.dispatchEvent(new CustomEvent("requestDelete",{detail:{records:t,approve:i,reject:r},bubbles:!0}))}else s()}getSelectedRecords(){return this.records.filter(e=>e[selected])}selectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let s=e;s<t;s++)this.records[s][selected]=!0;this.requestUpdate(),setTimeout(()=>{this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0}))},0)}deselectAllOnPage(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let s=e;s<t;s++)this.records[s][selected]=!1;this.requestUpdate(),setTimeout(()=>{this.dispatchEvent(new CustomEvent("selectionChange",{bubbles:!0}))},0)}allOnPageSelected(){const e=(this.currentPage-1)*this.pageSize,t=Math.min(e+this.pageSize,this.records.length);for(let s=e;s<t;s++)if(!this.records[s][selected])return!1;return!0}sortBy(e,t=!0){this.sort=this.sort.filter(t=>t.name!==e),this.sort.push({name:e,asc:t}),this.requestUpdate()}hideRecord(e){let t=this.records.find(t=>t===e);t||void 0===e[index]||(t=this.records[e[index]]),t&&(t[hidden]=!0,this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordHidden",{bubbles:!0})))}showRecord(e){let t=this.records.find(t=>t===e);t||void 0===e[index]||(t=this.records[e[index]]),t&&(t[hidden]=!1,this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordShown",{bubbles:!0})))}showAllRecords(){this.records.forEach(e=>{e[hidden]=!1}),this.filters.length&&(this.filters=[],this.dispatchEvent(new CustomEvent("filterRemoved",{bubbles:!0})),this.dispatchEvent(new CustomEvent("filterChange",{bubbles:!0}))),this.requestUpdate(),this.dispatchEvent(new CustomEvent("recordShown",{bubbles:!0})),this.dispatchEvent(new CustomEvent("allRecordsShown",{bubbles:!0}))}addFilter(e,t,s){this.filters.push({field:e,condition:t,value:s}),this.dispatchEvent(new CustomEvent("filterAdded",{bubbles:!0})),this.dispatchEvent(new CustomEvent("filterChange",{bubbles:!0})),this.requestUpdate()}removeFilter(e,t,s,i=!0){const r=this.filters.findIndex(i=>i.field===e&&i.condition===t&&i.value===s);-1!==r&&(this.records.forEach(i=>{this.testFilter(i,e,t,s)||(i[hidden]=!1)}),this.filters.splice(r,1),this.dispatchEvent(new CustomEvent("filterRemoved",{bubbles:!0})),this.dispatchEvent(new CustomEvent("filterChange",{bubbles:!0})),i&&this.requestUpdate())}testFilter(e,t,s,i){let r=e[t],o=i;switch(this.caseSensitiveFilters||"string"!=typeof r||"string"!=typeof i||(r=r.toLowerCase(),o=i.toLowerCase()),s){case"equals":return r===o;case"not-equals":return r!==o;case"contains":return r.includes(o);case"not-contains":return!r.includes(o);case"greater-than":return r>o;case"less-than":return r<o;case"greater-than-or-equal":return r>=o;case"less-than-or-equal":return r<=o;default:return!0}}removeAllFilters(){this.filters.length&&([...this.filters].forEach(({field:e,condition:t,value:s})=>{this.removeFilter(e,t,s,!1)}),this.requestUpdate())}search(e){const t=e.trim().toLowerCase();let s=!1;this.records.forEach(e=>{if(e[hidden])return;let i=!1;this.fields.forEach(({name:s})=>{(e[s]?.toString().toLowerCase()||"").includes(t)&&(i=!0)}),e[hidden]!==!i&&(e[hidden]=!i,s=!0)}),s&&(this.dispatchEvent(new CustomEvent("recordHidden",{bubbles:!0})),this.requestUpdate()),this.dispatchEvent(new CustomEvent("search",{detail:{term:e},bubbles:!0}))}getDisplayedRecords(){this.filters.forEach(({field:e,condition:t,value:s})=>{this.records.forEach(i=>{null!==i&&(this.testFilter(i,e,t,s)||(i[hidden]=!0))})});let e=this.records.filter(e=>null===e||!e[hidden]);return this.sort.forEach(({name:t,asc:s})=>{e.sort((e,i)=>null===e||null===i?0:e[t]<i[t]?s?-1:1:e[t]>i[t]?s?1:-1:0)}),e}getHiddenRecords(){return this.records.filter(e=>e[hidden])}calculateColumnSizes(){const e=Array.from(this.querySelectorAll('[slot="before"]')),t=Array.from(this.querySelectorAll('[slot="after"]')),s={beforeControls:e.reduce((e,t)=>e+(t.maxWidth||40),0),afterControls:t.reduce((e,t)=>e+(t.maxWidth||40),0)},i=[...e,...t].some(e=>void 0===e.maxWidth);return JSON.stringify(this.columnSizes)!==JSON.stringify(s)&&(this.columnSizes=s),i&&setTimeout(()=>this.calculateColumnSizes(),0),this.columnSizes}setFieldHiddenState(e,t){const s=this.fields.find(t=>t.name===e);s&&(s.hidden=t,this.calculateColumnSizes(),this.requestUpdate(),this.dispatchEvent(new CustomEvent("fieldVisibilityChanged",{detail:{field:s},bubbles:!0})),this.dispatchEvent(new CustomEvent(t?"fieldHidden":"fieldShown",{detail:{field:s},bubbles:!0})))}hideField(e){this.setFieldHiddenState(e,!0)}showField(e){this.setFieldHiddenState(e,!1)}reorderFields(e){const t=[];e.forEach(e=>{const s=this.fields.find(t=>t.name===e);s&&t.push(s)}),this.fields=t,this.requestUpdate()}render(){return this.records&&this.fields?(this.calculateColumnSizes(),this.hasTopControls()?this.setAttribute("top-controls","true"):this.removeAttribute("top-controls"),this.hasBottomControls()?this.setAttribute("bottom-controls","true"):this.removeAttribute("bottom-controls"),html`
|
|
44
44
|
<div id="wrapper">
|
|
45
45
|
<div id="top"><slot name="top"></slot></div>
|
|
46
46
|
<div id="table-container">
|
|
@@ -122,7 +122,8 @@ import{html,css,unsafeStatic,literal}from"../lit-all.min.js";import ShadowCompon
|
|
|
122
122
|
tbody tr:last-child td {
|
|
123
123
|
border-bottom: none;
|
|
124
124
|
}
|
|
125
|
-
tr.editing td.cell[data-field]
|
|
125
|
+
tr.editing td.cell[data-field]:has(input),
|
|
126
|
+
tr.editing td.cell[data-field]:has(select) {
|
|
126
127
|
padding: 0;
|
|
127
128
|
}
|
|
128
129
|
tr.editing td.cell[data-field] input,
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
</ul>
|
|
51
51
|
|
|
52
52
|
<h3 id="levels"><a href="#levels" class="no-link">Elevation Levels</a></h3>
|
|
53
|
-
<
|
|
53
|
+
<div class="table-wrapper mb">
|
|
54
|
+
<table>
|
|
54
55
|
<thead>
|
|
55
56
|
<tr>
|
|
56
57
|
<th>Level</th>
|
|
@@ -72,10 +73,12 @@
|
|
|
72
73
|
<tr><td>10</td><td>100</td><td><em>Reserved — use only when absolutely necessary</em></td></tr>
|
|
73
74
|
</tbody>
|
|
74
75
|
</table>
|
|
76
|
+
</div>
|
|
75
77
|
|
|
76
78
|
<h3 id="components"><a href="#components" class="no-link">Component Assignments</a></h3>
|
|
77
79
|
<p>Every Kempo UI component that uses <code>position: fixed</code> is assigned an elevation level:</p>
|
|
78
|
-
<
|
|
80
|
+
<div class="table-wrapper mb">
|
|
81
|
+
<table>
|
|
79
82
|
<thead>
|
|
80
83
|
<tr>
|
|
81
84
|
<th>Level</th>
|
|
@@ -123,6 +126,7 @@
|
|
|
123
126
|
</tr>
|
|
124
127
|
</tbody>
|
|
125
128
|
</table>
|
|
129
|
+
</div>
|
|
126
130
|
<p>
|
|
127
131
|
The <strong>Aside</strong> component uses two different levels depending on its <code>main</code> attribute.
|
|
128
132
|
When <code>main="push"</code>, it shifts the page layout and should sit <em>below</em> your site navbar (level 3).
|
package/icons/npm.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z"/></svg>
|
package/llm.txt
CHANGED
|
@@ -57,6 +57,7 @@ import { html, css, LitElement } from 'kempo-ui/src/lit-all.min.js';
|
|
|
57
57
|
| `<k-card>` | `Card.js` | Bordered container; optional `label` attribute | [card.html](https://dustinpoissant.github.io/kempo-ui/components/card.html) |
|
|
58
58
|
| `<k-color-picker>` | `ColorPicker.js` | Full color picker (hex, rgb, hsl, hsv, alpha); `value` property | [color-picker.html](https://dustinpoissant.github.io/kempo-ui/components/color-picker.html) |
|
|
59
59
|
| `<k-content-slider>` | `ContentSlider.js` | Swipeable carousel | [content-slider.html](https://dustinpoissant.github.io/kempo-ui/components/content-slider.html) |
|
|
60
|
+
| `<k-context>` | `Context.js` | Non-rendering state container; `set(key,value)`, `get(key)`, `delete(key)`, `clear()`, `getData()`; fires `context:create`, `context:set`, `context:delete` | [context.html](https://dustinpoissant.github.io/kempo-ui/components/context.html) |
|
|
60
61
|
| `<k-dialog>` | `Dialog.js` | Modal dialog with focus trapping; call `.open()` / `.close()` | [dialog.html](https://dustinpoissant.github.io/kempo-ui/components/dialog.html) |
|
|
61
62
|
| `<k-dropdown>` | `Dropdown.js` | Action menu with keyboard navigation | [dropdown.html](https://dustinpoissant.github.io/kempo-ui/components/dropdown.html) |
|
|
62
63
|
| `<k-filter-list>` `<k-filter-item>` | `FilterList.js` `FilterItem.js` | Filter/search list; items have `filter` attribute with keywords | [filter-list.html](https://dustinpoissant.github.io/kempo-ui/components/filter-list.html) |
|
package/package.json
CHANGED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Context Component
|
|
3
|
+
|
|
4
|
+
A non-rendering state container for sharing data between sibling and descendant
|
|
5
|
+
components, similar in purpose to React's useContext. Place it as an ancestor
|
|
6
|
+
of components that need shared state; children locate it via closest('k-context').
|
|
7
|
+
*/
|
|
8
|
+
import { html } from '../lit-all.min.js';
|
|
9
|
+
import LightComponent from './LightComponent.js';
|
|
10
|
+
|
|
11
|
+
export default class Context extends LightComponent {
|
|
12
|
+
static properties = {
|
|
13
|
+
data: { type: String, reflect: true }
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.data = '{}';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
Lifecycle Callbacks
|
|
23
|
+
*/
|
|
24
|
+
connectedCallback() {
|
|
25
|
+
super.connectedCallback();
|
|
26
|
+
this.style.display = 'contents';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
Public Methods
|
|
31
|
+
*/
|
|
32
|
+
set(key, value) {
|
|
33
|
+
const obj = JSON.parse(this.data || '{}');
|
|
34
|
+
const isNew = !(key in obj);
|
|
35
|
+
const oldValue = obj[key];
|
|
36
|
+
obj[key] = value;
|
|
37
|
+
this.data = JSON.stringify(obj);
|
|
38
|
+
this.dispatchEvent(new CustomEvent(isNew ? 'context:create' : 'context:set', {
|
|
39
|
+
detail: isNew ? { key, value } : { key, value, oldValue },
|
|
40
|
+
bubbles: true,
|
|
41
|
+
composed: true
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get(key) {
|
|
46
|
+
return JSON.parse(this.data || '{}')[key];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
has(key) {
|
|
50
|
+
return key in JSON.parse(this.data || '{}');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
delete(key) {
|
|
54
|
+
const obj = JSON.parse(this.data || '{}');
|
|
55
|
+
if(!(key in obj)) return;
|
|
56
|
+
const value = obj[key];
|
|
57
|
+
delete obj[key];
|
|
58
|
+
this.data = JSON.stringify(obj);
|
|
59
|
+
this.dispatchEvent(new CustomEvent('context:delete', {
|
|
60
|
+
detail: { key, value },
|
|
61
|
+
bubbles: true,
|
|
62
|
+
composed: true
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
clear() {
|
|
67
|
+
for(const key of Object.keys(JSON.parse(this.data || '{}'))){
|
|
68
|
+
this.delete(key);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getData() {
|
|
73
|
+
return JSON.parse(this.data || '{}');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
Rendering
|
|
78
|
+
*/
|
|
79
|
+
renderLightDom() {
|
|
80
|
+
return html``;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
customElements.define('k-context', Context);
|
package/src/components/Table.js
CHANGED
|
@@ -209,12 +209,12 @@ export default class Table extends ShadowComponent {
|
|
|
209
209
|
recordCells.push(this.renderBeforeControlsTemplate());
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
this.fields.forEach(({ name, formatter, calculator, type, editor, hidden }) => {
|
|
212
|
+
this.fields.forEach(({ name, formatter, calculator, type, editor, hidden, editable }) => {
|
|
213
213
|
if(hidden) return;
|
|
214
214
|
let value = record[name] || '';
|
|
215
215
|
recordCells.push(html`
|
|
216
216
|
<td class="cell" data-field=${name}>
|
|
217
|
-
${record[editing] ? this.renderEditingCell(record, name, value, calculator, editor, type) : this.renderDisplayCell(record, name, value, calculator, formatter)}
|
|
217
|
+
${record[editing] ? this.renderEditingCell(record, name, value, calculator, editor, type, editable) : this.renderDisplayCell(record, name, value, calculator, formatter)}
|
|
218
218
|
</td>
|
|
219
219
|
`);
|
|
220
220
|
});
|
|
@@ -230,7 +230,8 @@ export default class Table extends ShadowComponent {
|
|
|
230
230
|
`;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
renderEditingCell(record, name, value, calculator, editor, type) {
|
|
233
|
+
renderEditingCell(record, name, value, calculator, editor, type, editable) {
|
|
234
|
+
if(editable === false) return this.renderDisplayCell(record, name, value, calculator, null);
|
|
234
235
|
if (calculator) {
|
|
235
236
|
return html`<input disabled .value=${calculator(record, this)} />`;
|
|
236
237
|
} else if (editor) {
|
|
@@ -337,6 +338,7 @@ export default class Table extends ShadowComponent {
|
|
|
337
338
|
const field = $cell.dataset.field;
|
|
338
339
|
const fieldDef = this.fields.find(f => f.name === field);
|
|
339
340
|
if(fieldDef){
|
|
341
|
+
if(fieldDef.editable === false) return;
|
|
340
342
|
const value = record[field] || '';
|
|
341
343
|
$cell.innerHTML = '';
|
|
342
344
|
if(fieldDef.calculator){
|
|
@@ -1099,7 +1101,8 @@ export default class Table extends ShadowComponent {
|
|
|
1099
1101
|
tbody tr:last-child td {
|
|
1100
1102
|
border-bottom: none;
|
|
1101
1103
|
}
|
|
1102
|
-
tr.editing td.cell[data-field]
|
|
1104
|
+
tr.editing td.cell[data-field]:has(input),
|
|
1105
|
+
tr.editing td.cell[data-field]:has(select) {
|
|
1103
1106
|
padding: 0;
|
|
1104
1107
|
}
|
|
1105
1108
|
tr.editing td.cell[data-field] input,
|