@keenmate/pure-admin-core 2.3.6 → 2.5.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/README.md +23 -29
- package/dist/css/main.css +68 -148
- package/package.json +1 -5
- package/snippets/AUDIT.md +94 -0
- package/snippets/alerts.html +264 -89
- package/snippets/badges.html +193 -61
- package/snippets/buttons.html +178 -0
- package/snippets/callouts.html +210 -129
- package/snippets/cards.html +383 -200
- package/snippets/checkbox-lists.html +199 -65
- package/snippets/code.html +55 -11
- package/snippets/command-palette.html +401 -111
- package/snippets/comparison.html +144 -93
- package/snippets/customization.html +311 -104
- package/snippets/data-display.html +584 -0
- package/snippets/detail-panel.html +470 -138
- package/snippets/filter-card.html +246 -0
- package/snippets/forms.html +408 -308
- package/snippets/grid.html +253 -141
- package/snippets/layout.html +379 -480
- package/snippets/lists.html +144 -47
- package/snippets/loaders.html +64 -39
- package/snippets/manifest.json +330 -280
- package/snippets/modal-dialogs.html +137 -64
- package/snippets/modals.html +221 -151
- package/snippets/notifications.html +285 -0
- package/snippets/popconfirm.html +213 -19
- package/snippets/profile.html +290 -330
- package/snippets/statistics.html +247 -0
- package/snippets/tables.html +359 -150
- package/snippets/tabs.html +129 -45
- package/snippets/timeline.html +123 -56
- package/snippets/toasts.html +179 -31
- package/snippets/tooltips.html +199 -81
- package/snippets/typography.html +183 -58
- package/snippets/utilities.html +511 -415
- package/snippets/virtual-scroll.html +201 -75
- package/snippets/web-daterangepicker.html +369 -189
- package/snippets/web-multiselect.html +360 -124
- package/src/scss/core-components/_alerts.scss +51 -12
- package/src/scss/core-components/_pagers.scss +1 -1
- package/src/scss/core-components/_popconfirm.scss +35 -13
- package/src/scss/core-components/_profile.scss +18 -8
- package/src/scss/core-components/_statistics.scss +12 -12
- package/src/scss/core-components/_tables.scss +2 -134
- package/src/scss/variables/_components.scss +17 -2
- package/scripts/download-themes.js +0 -351
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
|
|
1
|
+
<!-- ================================
|
|
2
|
+
VIRTUAL SCROLL & INFINITE SCROLL
|
|
3
|
+
Pure Admin Visual Framework
|
|
4
|
+
|
|
5
|
+
Two strategies for rendering large datasets without melting the
|
|
6
|
+
DOM. The framework provides a small JS helper class
|
|
7
|
+
(VirtualScroll) plus a CSS shell for grid-based virtual tables
|
|
8
|
+
(.pa-virtual-table — see _tables.scss). Infinite scroll is pure
|
|
9
|
+
pattern, no helper required.
|
|
10
|
+
================================ -->
|
|
3
11
|
|
|
4
12
|
<!-- ========================================
|
|
5
13
|
Virtual Scroll (True Virtualization)
|
|
@@ -75,9 +83,12 @@ renderTimelineItems();
|
|
|
75
83
|
Preserves table structure
|
|
76
84
|
======================================== -->
|
|
77
85
|
|
|
86
|
+
<!-- Sticky header positioning is the only inline style needed — the
|
|
87
|
+
.pa-table thead th rule already paints the header with
|
|
88
|
+
var(--pa-table-header-bg). -->
|
|
78
89
|
<div id="table-virtual-container" style="height: 400px; overflow-y: auto;">
|
|
79
90
|
<table class="pa-table pa-table--striped">
|
|
80
|
-
<thead style="position: sticky; top: 0;
|
|
91
|
+
<thead style="position: sticky; top: 0; z-index: 10;">
|
|
81
92
|
<tr>
|
|
82
93
|
<th>#</th>
|
|
83
94
|
<th>Name</th>
|
|
@@ -157,13 +168,12 @@ renderTableRows();
|
|
|
157
168
|
<div class="pa-timeline__scroll-container" id="infinite-scroll-container" style="max-height: 400px; overflow-y: auto;">
|
|
158
169
|
<ul class="pa-timeline pa-timeline--feed" id="infinite-scroll-timeline"></ul>
|
|
159
170
|
</div>
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
<div class="pa-
|
|
165
|
-
|
|
166
|
-
</div>
|
|
171
|
+
<!-- pa-timeline__loader is a centred wrapper from _timeline.scss; the
|
|
172
|
+
real loader visual is just .pa-spinner. There's no .pa-loader /
|
|
173
|
+
--sm class — the wrapper provides centring + padding. -->
|
|
174
|
+
<div class="pa-timeline__loader d-none" id="infinite-scroll-loader">
|
|
175
|
+
<div class="pa-spinner pa-spinner--primary"></div>
|
|
176
|
+
<div class="pa-timeline__loader-text">Loading more entries…</div>
|
|
167
177
|
</div>
|
|
168
178
|
|
|
169
179
|
<script>
|
|
@@ -171,8 +181,7 @@ let infinitePage = 0;
|
|
|
171
181
|
let isLoadingInfinite = false;
|
|
172
182
|
const infiniteContainer = document.getElementById('infinite-scroll-container');
|
|
173
183
|
const infiniteTimeline = document.getElementById('infinite-scroll-timeline');
|
|
174
|
-
const
|
|
175
|
-
const infiniteText = document.getElementById('infinite-scroll-text');
|
|
184
|
+
const infiniteLoader = document.getElementById('infinite-scroll-loader');
|
|
176
185
|
|
|
177
186
|
function loadInfiniteItems() {
|
|
178
187
|
if (isLoadingInfinite || infinitePage >= 100) {
|
|
@@ -180,8 +189,7 @@ function loadInfiniteItems() {
|
|
|
180
189
|
}
|
|
181
190
|
|
|
182
191
|
isLoadingInfinite = true;
|
|
183
|
-
|
|
184
|
-
infiniteText.style.display = 'block';
|
|
192
|
+
infiniteLoader.classList.remove('d-none');
|
|
185
193
|
|
|
186
194
|
// Simulate async data loading
|
|
187
195
|
setTimeout(() => {
|
|
@@ -203,8 +211,7 @@ function loadInfiniteItems() {
|
|
|
203
211
|
}
|
|
204
212
|
|
|
205
213
|
infinitePage++;
|
|
206
|
-
|
|
207
|
-
infiniteText.style.display = 'none';
|
|
214
|
+
infiniteLoader.classList.add('d-none');
|
|
208
215
|
isLoadingInfinite = false;
|
|
209
216
|
}, 500);
|
|
210
217
|
}
|
|
@@ -225,6 +232,57 @@ infiniteContainer.addEventListener('scroll', () => {
|
|
|
225
232
|
});
|
|
226
233
|
</script>
|
|
227
234
|
|
|
235
|
+
<!-- ========================================
|
|
236
|
+
CSS Shell: .pa-virtual-table
|
|
237
|
+
A grid-based virtual table component shipped in _tables.scss.
|
|
238
|
+
Use when you'd rather not roll your own <table>+spacer markup.
|
|
239
|
+
The shell is purely presentational — render the visible window
|
|
240
|
+
yourself (same loop as the table example above), then absolutely
|
|
241
|
+
position rows inside __body. The grid columns are themed via
|
|
242
|
+
CSS variables; the snippet shows a 6-column dashboard preset,
|
|
243
|
+
but you can override grid-template-columns inline.
|
|
244
|
+
======================================== -->
|
|
245
|
+
|
|
246
|
+
<div class="pa-virtual-table" id="vt-container">
|
|
247
|
+
<div class="pa-virtual-table__header">
|
|
248
|
+
<div class="pa-virtual-table__header-cell">#</div>
|
|
249
|
+
<div class="pa-virtual-table__header-cell">Name</div>
|
|
250
|
+
<div class="pa-virtual-table__header-cell">Email</div>
|
|
251
|
+
<div class="pa-virtual-table__header-cell">Role</div>
|
|
252
|
+
<div class="pa-virtual-table__header-cell">Status</div>
|
|
253
|
+
<div class="pa-virtual-table__header-cell">Updated</div>
|
|
254
|
+
</div>
|
|
255
|
+
<div class="pa-virtual-table__body" id="vt-body" style="height: 600000px; position: relative;">
|
|
256
|
+
<!-- Rows added by your virtual scroll loop:
|
|
257
|
+
<div class="pa-virtual-table__row" style="position: absolute; top: 0;">
|
|
258
|
+
<div class="pa-virtual-table__cell">1</div>
|
|
259
|
+
<div class="pa-virtual-table__cell">John Doe</div>
|
|
260
|
+
...
|
|
261
|
+
</div>
|
|
262
|
+
-->
|
|
263
|
+
</div>
|
|
264
|
+
</div>
|
|
265
|
+
|
|
266
|
+
<!--
|
|
267
|
+
Sub-elements:
|
|
268
|
+
.pa-virtual-table border + radius shell, sticky header,
|
|
269
|
+
internal scroll
|
|
270
|
+
.pa-virtual-table__header sticky-positioned grid row
|
|
271
|
+
.pa-virtual-table__header-cell single header cell with end border
|
|
272
|
+
.pa-virtual-table__body positioning context for absolute rows
|
|
273
|
+
.pa-virtual-table__row grid row; even rows get table stripe;
|
|
274
|
+
hover applies the same accent border
|
|
275
|
+
inline-start as .pa-table
|
|
276
|
+
.pa-virtual-table__cell grid cell with ellipsis overflow
|
|
277
|
+
|
|
278
|
+
Default grid template (6 columns) lives in _tables.scss; override
|
|
279
|
+
inline if your dataset has different column counts:
|
|
280
|
+
|
|
281
|
+
<div class="pa-virtual-table__header"
|
|
282
|
+
style="grid-template-columns: 8rem 1fr 1fr 12rem;">
|
|
283
|
+
-->
|
|
284
|
+
|
|
285
|
+
|
|
228
286
|
<!-- ========================================
|
|
229
287
|
Using VirtualScroll Class (General Purpose)
|
|
230
288
|
======================================== -->
|
|
@@ -258,65 +316,133 @@ const range = vs.getVisibleRange(); // Get current visible range
|
|
|
258
316
|
vs.destroy(); // Cleanup
|
|
259
317
|
</script>
|
|
260
318
|
|
|
261
|
-
<!--
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
<!--
|
|
265
|
-
VIRTUAL SCROLL (Constant DOM):
|
|
266
|
-
- DOM size: ~20-30 elements regardless of dataset
|
|
267
|
-
- Performance: Handles millions of items smoothly
|
|
268
|
-
- Requirements: Fixed item heights, uniform layout
|
|
269
|
-
- Best for: Tables, logs, file lists, data grids
|
|
270
|
-
- Strategy: Items added/removed dynamically as you scroll
|
|
271
|
-
|
|
272
|
-
INFINITE SCROLL (Growing DOM):
|
|
273
|
-
- DOM size: Grows with each load (e.g., 2000 elements for 2000 items)
|
|
274
|
-
- Performance: Good for hundreds/low thousands
|
|
275
|
-
- Requirements: Works with variable heights
|
|
276
|
-
- Best for: Social feeds, news lists, image galleries
|
|
277
|
-
- Strategy: Items appended, never removed
|
|
278
|
-
|
|
279
|
-
WHEN TO USE WHAT:
|
|
280
|
-
- 10,000+ uniform items → Virtual Scroll
|
|
281
|
-
- Rich variable content → Infinite Scroll
|
|
282
|
-
- Complex nested layouts → Infinite Scroll
|
|
283
|
-
- Simple repeating rows → Virtual Scroll
|
|
284
|
-
-->
|
|
319
|
+
<!-- ================================
|
|
320
|
+
COMPONENT REFERENCE
|
|
321
|
+
================================ -->
|
|
285
322
|
|
|
286
|
-
<!-- ========================================
|
|
287
|
-
Configuration Guidelines
|
|
288
|
-
======================================== -->
|
|
289
323
|
<!--
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
-
|
|
321
|
-
|
|
324
|
+
TWO STRATEGIES:
|
|
325
|
+
|
|
326
|
+
VIRTUAL SCROLL (constant DOM)
|
|
327
|
+
Render only the items inside the viewport (+ a small buffer);
|
|
328
|
+
add/remove rows on scroll. DOM stays at ~20-30 elements no matter
|
|
329
|
+
how big the dataset is.
|
|
330
|
+
Best for: tables, logs, file lists, data grids — anything with
|
|
331
|
+
fixed-height uniform rows.
|
|
332
|
+
Requires: known + consistent itemHeight.
|
|
333
|
+
|
|
334
|
+
INFINITE SCROLL (growing DOM)
|
|
335
|
+
Append more items as the user nears the bottom; never remove.
|
|
336
|
+
DOM grows with each page load.
|
|
337
|
+
Best for: social feeds, news lists, image galleries — variable
|
|
338
|
+
heights and rich nested layouts.
|
|
339
|
+
Requires: nothing; just a scroll listener + a loader element.
|
|
340
|
+
|
|
341
|
+
Rule of thumb:
|
|
342
|
+
10,000+ uniform items → Virtual
|
|
343
|
+
Rich / variable content → Infinite
|
|
344
|
+
Complex nested layouts → Infinite
|
|
345
|
+
Simple repeating rows → Virtual
|
|
346
|
+
|
|
347
|
+
CSS SHELL — .pa-virtual-table (in _tables.scss):
|
|
348
|
+
|
|
349
|
+
Use this when you want a grid-based virtual table without rolling
|
|
350
|
+
your own <table>+spacer markup. The shell is purely presentational —
|
|
351
|
+
you still own the visible-window loop and absolute positioning.
|
|
352
|
+
|
|
353
|
+
Sub-elements:
|
|
354
|
+
.pa-virtual-table Border + radius + sticky-header
|
|
355
|
+
shell. Internal scroll, fixed
|
|
356
|
+
$chart-height, --pa-table-bg.
|
|
357
|
+
.pa-virtual-table__header Sticky grid row at the top.
|
|
358
|
+
.pa-virtual-table__header-cell Single header cell with
|
|
359
|
+
border-inline-end (RTL-safe).
|
|
360
|
+
.pa-virtual-table__body Positioning context for absolute
|
|
361
|
+
rows (you set its height to
|
|
362
|
+
totalItems × rowHeight).
|
|
363
|
+
.pa-virtual-table__row Grid row; striped via :nth-child(even);
|
|
364
|
+
hover applies the same accent
|
|
365
|
+
border-inline-start as .pa-table.
|
|
366
|
+
.pa-virtual-table__cell Grid cell with ellipsis overflow.
|
|
367
|
+
|
|
368
|
+
Default grid template is 6-column (dashboard preset). Override
|
|
369
|
+
inline if your dataset shape differs:
|
|
370
|
+
<div class="pa-virtual-table__header"
|
|
371
|
+
style="grid-template-columns: 8rem 1fr 1fr 12rem;">
|
|
372
|
+
<div class="pa-virtual-table__row"
|
|
373
|
+
style="grid-template-columns: 8rem 1fr 1fr 12rem;">
|
|
374
|
+
Both header and rows must use the same template.
|
|
375
|
+
|
|
376
|
+
VirtualScroll CLASS API (/dist/js/virtual-scroll.js):
|
|
377
|
+
|
|
378
|
+
new VirtualScroll({
|
|
379
|
+
container, // scroll container element (required)
|
|
380
|
+
itemHeight, // px, exact + consistent (required)
|
|
381
|
+
totalItems, // dataset size (required)
|
|
382
|
+
bufferSize, // extra items above/below viewport (default: 10)
|
|
383
|
+
renderItem, // (index) => HTMLElement (required)
|
|
384
|
+
onScroll, // (scrollTop) => void (optional)
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
Methods:
|
|
388
|
+
.setTotalItems(n) Update total; re-renders.
|
|
389
|
+
.scrollToItem(i) Programmatic scroll.
|
|
390
|
+
.getVisibleRange() Returns { start, end } for current viewport.
|
|
391
|
+
.destroy() Detach scroll listener; cleanup.
|
|
392
|
+
|
|
393
|
+
INFINITE SCROLL LOADER:
|
|
394
|
+
|
|
395
|
+
Wrap the spinner in .pa-timeline__loader (centred wrapper from
|
|
396
|
+
_timeline.scss) — the loader visual is just .pa-spinner. There is
|
|
397
|
+
no .pa-loader / .pa-loader--sm class.
|
|
398
|
+
|
|
399
|
+
<div class="pa-timeline__loader d-none" id="loader">
|
|
400
|
+
<div class="pa-spinner pa-spinner--primary"></div>
|
|
401
|
+
<div class="pa-timeline__loader-text">Loading more…</div>
|
|
402
|
+
</div>
|
|
403
|
+
|
|
404
|
+
Toggle visibility with classList.add/remove('d-none') — keep the
|
|
405
|
+
show/hide path uniform; don't mix d-none with style.display = 'none'.
|
|
406
|
+
|
|
407
|
+
CONFIGURATION GUIDELINES:
|
|
408
|
+
|
|
409
|
+
Virtual scroll
|
|
410
|
+
itemHeight Must be exact. Measure with element.offsetHeight.
|
|
411
|
+
Examples: timeline ~50px, table row ~38px, list ~44px.
|
|
412
|
+
bufferSize 5-15 items. Larger = smoother but more DOM.
|
|
413
|
+
totalItems Can change at runtime via vs.setTotalItems(n).
|
|
414
|
+
|
|
415
|
+
Infinite scroll
|
|
416
|
+
Threshold 50-100px from bottom — trigger early for smoothness.
|
|
417
|
+
Page size 20-50 items — balance request count vs. UX.
|
|
418
|
+
Max pages Cap to keep DOM bounded (e.g. 100 pages × 20 = 2000).
|
|
419
|
+
|
|
420
|
+
STRUCTURE PATTERNS:
|
|
421
|
+
|
|
422
|
+
1. Roll-your-own virtual list (timeline / custom layout):
|
|
423
|
+
scroll listener → compute visible range → innerHTML='' → append
|
|
424
|
+
visible items with absolute top offsets → set list height to
|
|
425
|
+
totalItems × itemHeight to preserve scroll.
|
|
426
|
+
|
|
427
|
+
2. Roll-your-own virtual table (top + bottom spacer rows):
|
|
428
|
+
same loop, but instead of absolute positioning, emit a single
|
|
429
|
+
spacer <tr> above (height = visibleStart × rowHeight) and below
|
|
430
|
+
(height = remaining × rowHeight) the visible rows. Preserves
|
|
431
|
+
<thead>/<tbody> semantics; sticky header just works.
|
|
432
|
+
|
|
433
|
+
3. .pa-virtual-table grid shell:
|
|
434
|
+
same loop as #1, but render rows as .pa-virtual-table__row +
|
|
435
|
+
.pa-virtual-table__cell inside the grid shell. Lets you skip
|
|
436
|
+
<table> markup entirely; gives you striping + hover accent for
|
|
437
|
+
free.
|
|
438
|
+
|
|
439
|
+
4. VirtualScroll class:
|
|
440
|
+
pass renderItem callback; the helper handles scroll listening,
|
|
441
|
+
range math, and DOM diffing for you.
|
|
442
|
+
|
|
443
|
+
5. Infinite scroll:
|
|
444
|
+
append-only. Listen for scroll near bottom (scrollTop +
|
|
445
|
+
clientHeight >= scrollHeight - threshold), guard with
|
|
446
|
+
isLoading flag, increment a page cursor, append items, toggle
|
|
447
|
+
loader d-none.
|
|
322
448
|
-->
|