@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.
Files changed (47) hide show
  1. package/README.md +23 -29
  2. package/dist/css/main.css +68 -148
  3. package/package.json +1 -5
  4. package/snippets/AUDIT.md +94 -0
  5. package/snippets/alerts.html +264 -89
  6. package/snippets/badges.html +193 -61
  7. package/snippets/buttons.html +178 -0
  8. package/snippets/callouts.html +210 -129
  9. package/snippets/cards.html +383 -200
  10. package/snippets/checkbox-lists.html +199 -65
  11. package/snippets/code.html +55 -11
  12. package/snippets/command-palette.html +401 -111
  13. package/snippets/comparison.html +144 -93
  14. package/snippets/customization.html +311 -104
  15. package/snippets/data-display.html +584 -0
  16. package/snippets/detail-panel.html +470 -138
  17. package/snippets/filter-card.html +246 -0
  18. package/snippets/forms.html +408 -308
  19. package/snippets/grid.html +253 -141
  20. package/snippets/layout.html +379 -480
  21. package/snippets/lists.html +144 -47
  22. package/snippets/loaders.html +64 -39
  23. package/snippets/manifest.json +330 -280
  24. package/snippets/modal-dialogs.html +137 -64
  25. package/snippets/modals.html +221 -151
  26. package/snippets/notifications.html +285 -0
  27. package/snippets/popconfirm.html +213 -19
  28. package/snippets/profile.html +290 -330
  29. package/snippets/statistics.html +247 -0
  30. package/snippets/tables.html +359 -150
  31. package/snippets/tabs.html +129 -45
  32. package/snippets/timeline.html +123 -56
  33. package/snippets/toasts.html +179 -31
  34. package/snippets/tooltips.html +199 -81
  35. package/snippets/typography.html +183 -58
  36. package/snippets/utilities.html +511 -415
  37. package/snippets/virtual-scroll.html +201 -75
  38. package/snippets/web-daterangepicker.html +369 -189
  39. package/snippets/web-multiselect.html +360 -124
  40. package/src/scss/core-components/_alerts.scss +51 -12
  41. package/src/scss/core-components/_pagers.scss +1 -1
  42. package/src/scss/core-components/_popconfirm.scss +35 -13
  43. package/src/scss/core-components/_profile.scss +18 -8
  44. package/src/scss/core-components/_statistics.scss +12 -12
  45. package/src/scss/core-components/_tables.scss +2 -134
  46. package/src/scss/variables/_components.scss +17 -2
  47. package/scripts/download-themes.js +0 -351
@@ -1,5 +1,13 @@
1
- <!-- Virtual Scroll & Infinite Scroll Snippets -->
2
- <!-- Clean HTML and JavaScript examples for efficient large dataset rendering -->
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; background: var(--base-primary-bg); z-index: 10;">
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
- <div class="pa-timeline__loader" id="infinite-scroll-loader">
161
- <div class="pa-loader pa-loader--sm d-none" id="infinite-scroll-spinner">
162
- <div class="pa-spinner"></div>
163
- </div>
164
- <div class="pa-timeline__loader-text d-none" id="infinite-scroll-text">
165
- Loading more entries...
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 infiniteSpinner = document.getElementById('infinite-scroll-spinner');
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
- infiniteSpinner.style.display = 'block';
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
- infiniteSpinner.style.display = 'none';
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
- Performance Comparison
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
- VIRTUAL SCROLL SETTINGS:
291
-
292
- itemHeight:
293
- - Must be exact and consistent
294
- - Measure with: element.offsetHeight
295
- - Examples:
296
- - Timeline item: 50px
297
- - Table row: 38px
298
- - List item: 44px
299
-
300
- bufferSize:
301
- - Recommended: 5-15 items
302
- - Larger = smoother scroll, more DOM
303
- - Smaller = less DOM, potential flicker
304
-
305
- totalItems:
306
- - Can be updated dynamically
307
- - Example: vs.setTotalItems(newCount)
308
-
309
- INFINITE SCROLL SETTINGS:
310
-
311
- Threshold:
312
- - Recommended: 50-100px from bottom
313
- - Trigger early for smooth experience
314
-
315
- Page size:
316
- - Recommended: 20-50 items per load
317
- - Balance between requests and UX
318
-
319
- Max pages:
320
- - Set a limit to prevent memory issues
321
- - Example: 100 pages = 2000 items max
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
  -->