@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
package/README.md CHANGED
@@ -2,15 +2,20 @@
2
2
 
3
3
  Lightweight, data-focused CSS/SCSS admin framework with Corporate theme as default.
4
4
 
5
- ## What's New in 2.3.6
5
+ ## What's New in 2.5.0
6
6
 
7
- - **Responsive font sizing** — `pa-font-responsive` class on `<html>` for automatic mobile scaling (10px desktop, 12px mobile). Granular `pa-font-base-*` / `pa-font-mobile-*` classes for full control. No JS, no FOUC.
8
- - **Getting Started page** — New demo page covering installation, theme management via CLI, responsive sizing, RTL, and BEM reference
7
+ - **Form Demo showcase page** (`/showcases/form-demo`) Vanilla-JS CRUD form mirroring the LiveView form demo from `keen-pure-admin`: inline validation slots, edit/update flow, optimistic delete with toast-undo, and a `simulateServerSave()` failure path so error states are exercisable without any tooling.
8
+ - **Alert system overhaul** — `pa-alert__heading` is now the single heading element (compact default + new `--lg` modifier for punchy presentation), default alignment flipped to `align-items: center` so icons sit nicely with single-line content (new `pa-alert--multiline` opt-out for icon + multi-line stacks), real size scale on `--sm` / `--lg` (both padding *and* font now step in 0.25rem / 0.2rem increments), and `__actions` renders with a toast-style separator. Multi-element layouts (heading + list + actions) stack reliably now via `flex-basis: 100%` on structural children.
9
+ - **Snippets audit + gap pass** — Every snippet under `snippets/` cross-checked against its SCSS source (27 audit commits, tracked in `snippets/AUDIT.md`). Wrong attribute names, dead classes, and structural omissions corrected across the board. Four new gap-pass snippets: `filter-card`, `statistics`, `notifications`, `data-display`.
10
+ - **Popconfirm position classes renamed (Breaking)** — `pa-popconfirm--right` / `--left` → `pa-popconfirm--end` / `--start`. SCSS uses logical properties so the popconfirm and its arrow mirror in `dir="rtl"`. No backwards-compatibility aliases — update markup directly.
11
+ - **`pa-alert__heading` size now opt-in (Breaking)** — Was hardcoded `font-size-lg`; defaults to the alert's body font-size now. Add `pa-alert__heading--lg` on existing alerts to keep the previous bigger treatment.
9
12
 
10
- ## What's New in 2.3.5
13
+ ## What's New in 2.4.0
11
14
 
12
- - **Navbar alignment fix** — `__end` section pushed to right edge via `margin-inline-start: auto`, works without `__center` spacer
13
- - **Scroll-lock fix** — Panel/modal open no longer hides scrollbar (`overflow-y: scroll` instead of `hidden`)
15
+ - **`download-themes` bin removed** — Theme management now lives in the [`pureadmin` CLI](https://www.npmjs.com/package/@keenmate/pureadmin) (`npx pureadmin themes add/update/list`). README's Theme Setup section rewritten to match.
16
+ - **Theme-aware charts** — Demo dashboard chart rewritten to source colors and fonts from Pure Admin CSS custom properties (`--pa-accent`, `--pa-text-color-*`, `--base-font-family`). Establishes the canonical pattern for SVG charts tracking the active theme.
17
+ - **KPI square stats theme correctly** — `pa-stat--square` color variants now route through `--pa-accent` / `--pa-success-bg` / etc. instead of raw SCSS vars that resolved to Bootstrap defaults in every theme.
18
+ - **Profile panel readable on colored headers** — Name, email, role badge, and tab icons now use `--pa-header-profile-name-color` (guaranteed to contrast with header bg) instead of body text vars, with opacity/color-mix for hierarchy.
14
19
 
15
20
  ## Installation
16
21
 
@@ -109,40 +114,29 @@ Themes are maintained in the separate [`pure-admin-themes`](https://github.com/K
109
114
 
110
115
  ### Theme Setup
111
116
 
112
- Themes are configured via `themes.json` (base config) and `.themes.json` (local overrides, gitignored). Each entry is a theme name mapped to an options object:
113
-
114
- ```json
115
- {
116
- "themes": {
117
- "audi": {},
118
- "corporate": { "path": "../pure-admin-themes/corporate" },
119
- "custom": { "url": "https://my-server.com/themes/custom.zip" }
120
- }
121
- }
122
- ```
123
-
124
- - **`{}`** — downloaded from pureadmin.io bundle
125
- - **`{ "path": "..." }`** — use a local directory (must contain `dist/{name}.css`)
126
- - **`{ "url": "..." }`** — downloaded from a custom URL
127
-
128
- Then run:
117
+ Themes are managed via the [`pureadmin` CLI](https://www.npmjs.com/package/@keenmate/pureadmin):
129
118
 
130
119
  ```bash
131
- npx download-themes
120
+ npm install -D @keenmate/pureadmin
121
+
122
+ npx pureadmin themes list # browse all themes available on pureadmin.io
123
+ npx pureadmin themes add audi corporate # download + register themes in this project
124
+ npx pureadmin themes update # re-download only themes whose content changed
125
+ npx pureadmin themes list --local # show themes configured in this project
132
126
  ```
133
127
 
134
- Or add to your `package.json` scripts:
128
+ The CLI extracts theme ZIPs into `static/themes/{name}/` (configurable via `--dir`) and tracks each one in `pureadmin.json` with version + content hash for change detection. See `npx pureadmin help themes` for the full subcommand reference.
129
+
130
+ For local development against a sibling theme repo, you can hand-edit `.pureadmin.json` (gitignored) and point a slug at a filesystem path:
135
131
 
136
132
  ```json
137
133
  {
138
- "scripts": {
139
- "download-themes": "download-themes"
134
+ "themes": {
135
+ "corporate": "../pure-admin-themes/corporate"
140
136
  }
141
137
  }
142
138
  ```
143
139
 
144
- This fetches all remote themes into `./themes/{name}/` and leaves local paths unchanged. Config files are never modified.
145
-
146
140
  ### pureadmin.io Theme API
147
141
 
148
142
  - `GET /api/theme/{name}` — download a specific theme (e.g. `/api/theme/audi`)
package/dist/css/main.css CHANGED
@@ -6414,28 +6414,28 @@ a.pa-card p {
6414
6414
  white-space: nowrap;
6415
6415
  }
6416
6416
  .pa-stat--square.pa-stat--primary {
6417
- background-color: #007bff;
6418
- color: #ffffff;
6417
+ background-color: var(--pa-accent);
6418
+ color: var(--pa-btn-primary-text);
6419
6419
  }
6420
6420
  .pa-stat--square.pa-stat--success {
6421
- background-color: #28a745;
6422
- color: #ffffff;
6421
+ background-color: var(--pa-success-bg);
6422
+ color: var(--pa-btn-success-text);
6423
6423
  }
6424
6424
  .pa-stat--square.pa-stat--info {
6425
- background-color: #17a2b8;
6426
- color: #ffffff;
6425
+ background-color: var(--pa-info-bg);
6426
+ color: var(--pa-btn-info-text);
6427
6427
  }
6428
6428
  .pa-stat--square.pa-stat--warning {
6429
- background-color: #ffc107;
6430
- color: #212529;
6429
+ background-color: var(--pa-warning-bg);
6430
+ color: var(--pa-btn-warning-text);
6431
6431
  }
6432
6432
  .pa-stat--square.pa-stat--danger {
6433
- background-color: #dc3545;
6434
- color: #ffffff;
6433
+ background-color: var(--pa-danger-bg);
6434
+ color: var(--pa-btn-danger-text);
6435
6435
  }
6436
6436
  .pa-stat--square.pa-stat--secondary {
6437
6437
  background-color: var(--pa-text-color-2);
6438
- color: #ffffff;
6438
+ color: var(--pa-btn-primary-text);
6439
6439
  }
6440
6440
 
6441
6441
  .pa-kpi-grid {
@@ -8762,14 +8762,14 @@ a.pa-card p {
8762
8762
  ======================================== */
8763
8763
  .pa-alert {
8764
8764
  position: relative;
8765
- padding: 1.2rem 1rem;
8765
+ padding: 1.2rem 1.25rem;
8766
8766
  margin-bottom: 1.6rem;
8767
8767
  border: 1px solid transparent;
8768
8768
  border-radius: var(--pa-border-radius);
8769
8769
  font-size: 1.4rem;
8770
8770
  display: flex;
8771
8771
  flex-wrap: wrap;
8772
- align-items: flex-start;
8772
+ align-items: center;
8773
8773
  }
8774
8774
  .pa-card__body .pa-alert:first-child {
8775
8775
  margin-top: 0;
@@ -8937,16 +8937,19 @@ a.pa-card p {
8937
8937
  background-color: transparent;
8938
8938
  }
8939
8939
  .pa-alert--sm {
8940
- padding: 1.2rem 1rem;
8941
- font-size: 1.4rem;
8940
+ padding: 0.8rem 1.6rem;
8941
+ font-size: 1.2rem;
8942
8942
  }
8943
8943
  .pa-alert--lg {
8944
- padding: 1.2rem 1rem;
8944
+ padding: 1.6rem 2.4rem;
8945
8945
  font-size: 1.6rem;
8946
8946
  }
8947
8947
  .pa-alert--dismissible {
8948
8948
  padding-inline-end: 4.8rem;
8949
8949
  }
8950
+ .pa-alert--multiline {
8951
+ align-items: flex-start;
8952
+ }
8950
8953
  .pa-alert__icon {
8951
8954
  flex-shrink: 0;
8952
8955
  font-size: 1.6rem;
@@ -8954,28 +8957,39 @@ a.pa-card p {
8954
8957
  }
8955
8958
  .pa-alert__content {
8956
8959
  flex: 1;
8960
+ min-width: 0;
8961
+ }
8962
+ .pa-alert__heading, .pa-alert__list, .pa-alert__actions,
8963
+ .pa-alert > p,
8964
+ .pa-alert > hr {
8965
+ flex-basis: 100%;
8957
8966
  }
8958
8967
  .pa-alert__heading {
8959
- margin: 0 0 0.8rem 0;
8968
+ margin: 0;
8960
8969
  color: inherit;
8961
- font-size: 1.8rem;
8962
8970
  font-weight: 600;
8963
8971
  }
8972
+ .pa-alert__heading--lg {
8973
+ font-size: 1.8rem;
8974
+ }
8964
8975
  .pa-alert__list {
8965
- margin: 0.8rem 0;
8976
+ margin: 0;
8966
8977
  padding-inline-start: 2.4rem;
8967
8978
  }
8968
8979
  .pa-alert__actions {
8969
- margin-top: 1.2rem;
8980
+ margin-top: 0;
8981
+ padding-top: 1.6rem;
8982
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
8970
8983
  display: flex;
8971
8984
  gap: 0.8rem;
8985
+ flex-wrap: wrap;
8972
8986
  }
8973
8987
  .pa-alert__close {
8974
8988
  position: absolute;
8975
8989
  top: 0;
8976
8990
  inset-inline-end: 0;
8977
8991
  z-index: 2px;
8978
- padding: 1.2rem 1rem;
8992
+ padding: 1.2rem 1.25rem;
8979
8993
  background: none;
8980
8994
  border: none;
8981
8995
  font-size: 2rem;
@@ -11469,115 +11483,6 @@ web-multiselect {
11469
11483
  white-space: nowrap;
11470
11484
  }
11471
11485
 
11472
- .pa-pager {
11473
- display: flex;
11474
- margin: 1.6rem 0;
11475
- }
11476
- .pa-card__body .pa-pager:first-child {
11477
- margin-top: 0;
11478
- }
11479
- .pa-card__body .pa-pager:last-child {
11480
- margin-bottom: 0;
11481
- }
11482
- .pa-pager {
11483
- justify-content: center;
11484
- }
11485
- .pa-pager--start {
11486
- justify-content: flex-start;
11487
- }
11488
- .pa-pager--center {
11489
- justify-content: center;
11490
- }
11491
- .pa-pager--end {
11492
- justify-content: flex-end;
11493
- }
11494
- .pa-pager__container {
11495
- display: flex;
11496
- align-items: center;
11497
- gap: 0.8rem;
11498
- white-space: nowrap;
11499
- }
11500
- .pa-pager__controls {
11501
- display: flex;
11502
- gap: 0.4rem;
11503
- }
11504
- .pa-pager__info {
11505
- display: flex;
11506
- align-items: center;
11507
- gap: 0.8rem;
11508
- }
11509
- .pa-pager__input {
11510
- width: 6.4rem !important;
11511
- text-align: center;
11512
- }
11513
- .pa-pager__text {
11514
- color: var(--pa-text-color-2);
11515
- font-size: 1.4rem;
11516
- }
11517
-
11518
- .pa-load-more {
11519
- display: flex;
11520
- margin: 1.6rem 0;
11521
- }
11522
- .pa-card__body .pa-load-more:first-child {
11523
- margin-top: 0;
11524
- }
11525
- .pa-card__body .pa-load-more:last-child {
11526
- margin-bottom: 0;
11527
- }
11528
- .pa-load-more {
11529
- justify-content: center;
11530
- }
11531
- .pa-load-more--start {
11532
- justify-content: flex-start;
11533
- }
11534
- .pa-load-more--center {
11535
- justify-content: center;
11536
- }
11537
- .pa-load-more--end {
11538
- justify-content: flex-end;
11539
- }
11540
- .pa-load-more__button {
11541
- display: flex;
11542
- align-items: center;
11543
- gap: 0.8rem;
11544
- padding: 0.8rem 1.2rem;
11545
- background-color: transparent;
11546
- border: 1px solid var(--pa-border-color);
11547
- border-radius: var(--pa-border-radius);
11548
- color: var(--pa-text-color-1);
11549
- font-size: 1.4rem;
11550
- cursor: pointer;
11551
- transition: all 0.1s ease-out;
11552
- }
11553
- .pa-load-more__button:hover {
11554
- border-color: var(--pa-accent);
11555
- color: var(--pa-accent);
11556
- background-color: var(--pa-accent-light);
11557
- }
11558
- .pa-load-more__button--loading {
11559
- pointer-events: none;
11560
- opacity: 0.7;
11561
- }
11562
- .pa-load-more__button--loading .pa-load-more__spinner {
11563
- animation: pa-spin 1s linear infinite;
11564
- }
11565
- .pa-load-more__spinner {
11566
- width: 1.6rem;
11567
- height: 1.6rem;
11568
- border: 2px solid var(--pa-border-color);
11569
- border-top: 2px solid var(--pa-accent);
11570
- border-radius: 50%;
11571
- }
11572
- .pa-load-more__text {
11573
- color: inherit;
11574
- }
11575
- .pa-load-more__count {
11576
- color: var(--pa-text-color-2);
11577
- font-size: 1.2rem;
11578
- margin-inline-start: 0.4rem;
11579
- }
11580
-
11581
11486
  .pa-virtual-table {
11582
11487
  border: 1px solid var(--pa-border-color);
11583
11488
  border-radius: var(--pa-border-radius);
@@ -12194,7 +12099,7 @@ code {
12194
12099
  width: 1.6rem;
12195
12100
  height: 1.6rem;
12196
12101
  border: 2px solid var(--pa-border-color);
12197
- border-top: 2px solid #007bff;
12102
+ border-top: 2px solid var(--pa-accent);
12198
12103
  border-radius: 50%;
12199
12104
  }
12200
12105
  .pa-load-more__text {
@@ -12325,7 +12230,7 @@ code {
12325
12230
  margin: 0 0 0.4rem 0;
12326
12231
  font-size: 1.8rem;
12327
12232
  font-weight: 600;
12328
- color: var(--pa-text-color-1);
12233
+ color: var(--pa-header-profile-name-color);
12329
12234
  overflow: hidden;
12330
12235
  text-overflow: ellipsis;
12331
12236
  white-space: nowrap;
@@ -12333,7 +12238,8 @@ code {
12333
12238
  .pa-profile-panel__email {
12334
12239
  margin: 0 0 0.8rem 0;
12335
12240
  font-size: 1.4rem;
12336
- color: var(--pa-text-color-2);
12241
+ color: var(--pa-header-profile-name-color);
12242
+ opacity: 0.75;
12337
12243
  overflow: hidden;
12338
12244
  text-overflow: ellipsis;
12339
12245
  white-space: nowrap;
@@ -12342,7 +12248,8 @@ code {
12342
12248
  display: inline-block;
12343
12249
  padding: 0.8rem 1.2rem;
12344
12250
  background-color: var(--pa-accent-light);
12345
- color: var(--pa-accent);
12251
+ background-color: color-mix(in srgb, var(--pa-header-profile-name-color) 15%, transparent);
12252
+ color: var(--pa-header-profile-name-color);
12346
12253
  font-size: 1.2rem;
12347
12254
  font-weight: 500;
12348
12255
  border-radius: var(--pa-border-radius);
@@ -12442,15 +12349,16 @@ code {
12442
12349
  margin-bottom: 0;
12443
12350
  }
12444
12351
  .pa-profile-panel__tabs .pa-tabs__item {
12445
- color: var(--pa-header-text-secondary);
12352
+ color: var(--pa-header-profile-name-color);
12353
+ opacity: 0.6;
12446
12354
  border-bottom-color: transparent;
12447
12355
  }
12448
12356
  .pa-profile-panel__tabs .pa-tabs__item:hover {
12449
- color: var(--pa-header-text);
12450
- background-color: var(--pa-accent-light);
12357
+ opacity: 0.85;
12358
+ background-color: color-mix(in srgb, var(--pa-header-profile-name-color) 10%, transparent);
12451
12359
  }
12452
12360
  .pa-profile-panel__tabs .pa-tabs__item--active {
12453
- color: var(--pa-header-text);
12361
+ opacity: 1;
12454
12362
  border-bottom-color: var(--pa-accent);
12455
12363
  }
12456
12364
  .pa-profile-panel__tabs--icon-only .pa-profile-panel__tab-text {
@@ -14806,44 +14714,56 @@ code {
14806
14714
  }
14807
14715
  .pa-popconfirm--bottom .pa-popconfirm__arrow {
14808
14716
  top: -0.64rem;
14809
- left: 50%;
14717
+ inset-inline-start: 50%;
14810
14718
  transform: translateX(-50%) rotate(45deg);
14811
14719
  border-right: none;
14812
14720
  border-bottom: none;
14813
14721
  }
14722
+ [dir=rtl] .pa-popconfirm--bottom .pa-popconfirm__arrow {
14723
+ transform: translateX(50%) rotate(45deg);
14724
+ }
14814
14725
 
14815
14726
  .pa-popconfirm--top {
14816
14727
  margin-bottom: 0.8rem;
14817
14728
  }
14818
14729
  .pa-popconfirm--top .pa-popconfirm__arrow {
14819
14730
  bottom: -0.64rem;
14820
- left: 50%;
14731
+ inset-inline-start: 50%;
14821
14732
  transform: translateX(-50%) rotate(45deg);
14822
14733
  border-left: none;
14823
14734
  border-top: none;
14824
14735
  }
14736
+ [dir=rtl] .pa-popconfirm--top .pa-popconfirm__arrow {
14737
+ transform: translateX(50%) rotate(45deg);
14738
+ }
14825
14739
 
14826
- .pa-popconfirm--right {
14827
- margin-left: 0.8rem;
14740
+ .pa-popconfirm--end {
14741
+ margin-inline-start: 0.8rem;
14828
14742
  }
14829
- .pa-popconfirm--right .pa-popconfirm__arrow {
14830
- left: -0.64rem;
14743
+ .pa-popconfirm--end .pa-popconfirm__arrow {
14744
+ inset-inline-start: -0.64rem;
14831
14745
  top: 50%;
14832
14746
  transform: translateY(-50%) rotate(45deg);
14833
14747
  border-top: none;
14834
14748
  border-right: none;
14835
14749
  }
14750
+ [dir=rtl] .pa-popconfirm--end .pa-popconfirm__arrow {
14751
+ transform: translateY(-50%) rotate(45deg) scaleX(-1);
14752
+ }
14836
14753
 
14837
- .pa-popconfirm--left {
14838
- margin-right: 0.8rem;
14754
+ .pa-popconfirm--start {
14755
+ margin-inline-end: 0.8rem;
14839
14756
  }
14840
- .pa-popconfirm--left .pa-popconfirm__arrow {
14841
- right: -0.64rem;
14757
+ .pa-popconfirm--start .pa-popconfirm__arrow {
14758
+ inset-inline-end: -0.64rem;
14842
14759
  top: 50%;
14843
14760
  transform: translateY(-50%) rotate(45deg);
14844
14761
  border-bottom: none;
14845
14762
  border-left: none;
14846
14763
  }
14764
+ [dir=rtl] .pa-popconfirm--start .pa-popconfirm__arrow {
14765
+ transform: translateY(-50%) rotate(45deg) scaleX(-1);
14766
+ }
14847
14767
 
14848
14768
  .pa-popconfirm--compact {
14849
14769
  min-width: 19.2rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keenmate/pure-admin-core",
3
- "version": "2.3.6",
3
+ "version": "2.5.0",
4
4
  "description": "Lightweight, data-focused HTML/CSS admin framework built with PureCSS foundation and comprehensive component system",
5
5
  "style": "dist/css/main.css",
6
6
  "exports": {
@@ -16,7 +16,6 @@
16
16
  "src/scss/",
17
17
  "schemas/",
18
18
  "scripts/pack-theme.js",
19
- "scripts/download-themes.js",
20
19
  "snippets/",
21
20
  "README.md",
22
21
  "LICENSE"
@@ -40,9 +39,6 @@
40
39
  "components",
41
40
  "ui-kit"
42
41
  ],
43
- "bin": {
44
- "download-themes": "./scripts/download-themes.js"
45
- },
46
42
  "author": "KeenMate",
47
43
  "license": "MIT",
48
44
  "peerDependencies": {
@@ -0,0 +1,94 @@
1
+ # Snippets Audit Log
2
+
3
+ Tracks which snippets have been cross-checked against their SCSS source and when. Paired with `manifest.json` (which records file hashes for downstream framework wrappers), this file answers *has anyone verified this is still accurate*.
4
+
5
+ **Process.** An audit reads the corresponding SCSS surface, compares it against the snippet (base class, modifiers, BEM elements, child styling, sizes, variants), triangulates with usage in `demo/views/*.mustache`, and fixes drift in-place. One snippet per commit.
6
+
7
+ **Legend.**
8
+ - ✅ audited — snippet reviewed and brought in line with SCSS as of the listed commit
9
+ - ⏳ pending — not yet touched in this pass
10
+ - 🆕 missing — component exists in SCSS but has no snippet
11
+
12
+ ## Audited
13
+
14
+ | Snippet | Audited | SCSS verified against | Commit |
15
+ |---|---|---|---|
16
+ | `callouts.html` | 2026-04-24 | `core-components/_callouts.scss` | [6ea28e8](../../../commit/6ea28e8) |
17
+ | `code.html` | 2026-04-24 | `core-components/_code.scss`, `variables/_colors.scss` | [cd2e51b](../../../commit/cd2e51b) |
18
+ | `loaders.html` | 2026-04-24 | `core-components/_loaders.scss`, `core-components/_buttons.scss` (loading state), `variables/_components.scss` | [6a4682d](../../../commit/6a4682d) |
19
+ | `toasts.html` | 2026-04-24 | `core-components/_toasts.scss` | [4056fa9](../../../commit/4056fa9) |
20
+ | `popconfirm.html` | 2026-04-24 | `core-components/_popconfirm.scss` | [d8e7f7c](../../../commit/d8e7f7c) |
21
+ | `typography.html` | 2026-04-24 | `core-components/_base.scss`, `core-components/_utilities.scss` (.pa-text), `utilities.scss` (.text-*), `_fonts.scss`, `variables/_typography.scss` | [12f1281](../../../commit/12f1281) |
22
+ | `alerts.html` | 2026-04-25 | `core-components/_alerts.scss`, `variables/_components.scss` (alert padding + font-size scales) | [512ef3c](../../../commit/512ef3c), revised [dd7a096](../../../commit/dd7a096) (toast-style `__actions` separator), [f824000](../../../commit/f824000) (flex-wrap layout fix: structural children get `flex-basis: 100%`), [514d67d](../../../commit/514d67d) (heading unification: `__heading` defaults to body size, `--lg` opt-in for punchy), [f25700d](../../../commit/f25700d) (introduced `$alert-padding-{sm,lg}-{v,h}` and `$alert-font-size-{sm,lg}` so `--sm` / `--lg` actually differ from default), [d2b27ea](../../../commit/d2b27ea) (default `$alert-padding-{v,h}` decoupled from `$card-footer-padding-{v,h}`: 0.75rem / 1.25rem, so default sits inside the V 0.5 → 0.75 → 1 / H 1 → 1.25 → 1.5 scale instead of outside it), and _(this commit)_ (default `align-items: center` so icon + single-line content centres; new `pa-alert--multiline` modifier opts back to `flex-start` for icon + multi-line `__content`) |
23
+ | `badges.html` | 2026-04-24 | `core-components/badges/_badge-base.scss`, `_composite-badge.scss`, `_composite-badge-variants.scss`, `_badge-group.scss`, `_labels.scss` | [517f6bf](../../../commit/517f6bf) |
24
+ | `buttons.html` | 2026-04-24 | `core-components/_buttons.scss` | [43a9a42](../../../commit/43a9a42) |
25
+ | `tables.html` | 2026-04-24 | `core-components/_tables.scss` (covers `.pa-table`, `.pa-table-container`, `.pa-table-card`), `core-components/_pagers.scss` (covers `.pa-pager`, `.pa-load-more`) | [e34ca85](../../../commit/e34ca85) |
26
+ | `lists.html` | 2026-04-24 | `core-components/_lists.scss` | [894b0dd](../../../commit/894b0dd) |
27
+ | `tooltips.html` | 2026-04-24 | `core-components/_tooltips.scss` | [b2d196b](../../../commit/b2d196b) |
28
+ | `grid.html` | 2026-04-24 | `core-components/_grid.scss`, `utilities.scss` (.pa-cq), `variables/_spacing.scss` ($grid-breakpoints) | [0bd9f16](../../../commit/0bd9f16) |
29
+ | `utilities.html` | 2026-04-24 | `utilities.scss` (main utilities), `core-components/_utilities.scss` (components-adjacent helpers), `variables/_spacing.scss` (spacing scale) | [20df758](../../../commit/20df758) |
30
+ | `cards.html` | 2026-04-24 | `core-components/_cards.scss` | [4a67018](../../../commit/4a67018) |
31
+ | `forms.html` | 2026-04-24 | `core-components/forms/` (all 7 files: _form-layout, _form-inputs, _form-states, _input-groups, _input-wrapper, _checkboxes-radios, _query-editor) | [272f141](../../../commit/272f141) |
32
+ | `layout.html` | 2026-04-24 | `core-components/layout/` (all 6 files: _layout-container, _navbar, _navbar-elements, _sidebar, _sidebar-states, _layout-responsive), `variables/_layout.scss` (container widths) | [9762492](../../../commit/9762492) |
33
+ | `profile.html` | 2026-04-24 | `core-components/_profile.scss` | [2b70e27](../../../commit/2b70e27) |
34
+ | `tabs.html` | 2026-04-24 | `core-components/_tabs.scss` | [35f5f16](../../../commit/35f5f16) |
35
+ | `timeline.html` | 2026-04-24 | `core-components/_timeline.scss` | [eaa5ad9](../../../commit/eaa5ad9) |
36
+ | `checkbox-lists.html` | 2026-04-24 | `core-components/_checkbox-lists.scss`, `core-components/forms/_checkboxes-radios.scss` (pa-checkbox component reference) | [e2bb951](../../../commit/e2bb951) |
37
+ | `command-palette.html` | 2026-04-24 | `core-components/_command-palette.scss` (covers `.pa-command-palette`, `.pa-navbar-search`, `.pa-shortcut-help`) | [a9b4fe3](../../../commit/a9b4fe3) |
38
+ | `comparison.html` | 2026-04-24 | `core-components/_comparison.scss` | [e4f1cd6](../../../commit/e4f1cd6) |
39
+ | `modals.html` | 2026-04-24 | `core-components/_modals.scss`, `variables/_components.scss` ($modal-*-width + $modal-body-scrollable-max-height) | [795856e](../../../commit/795856e) |
40
+ | `modal-dialogs.html` | 2026-04-24 | `src/js/modal-dialogs.js` (PureAdmin.confirm / alert / prompt / custom API); DOM produced matches `_modals.scss` | [e5eba00](../../../commit/e5eba00) |
41
+ | `detail-panel.html` | 2026-04-24 | `core-components/_detail-panel.scss`, `variables/_components.scss` (panel width + z-index) | [c1dc6ff](../../../commit/c1dc6ff) |
42
+ | `customization.html` | 2026-04-25 | `_base-css-variables.scss`, `_variables.scss`, theme-system pattern (mirrors `pure-admin-themes` repo) | [0a8950e](../../../commit/0a8950e) |
43
+ | `virtual-scroll.html` | 2026-04-25 | `core-components/_tables.scss` (`.pa-virtual-table` shell, lines 477-552), `core-components/_timeline.scss` (`.pa-timeline__loader`), `src/js/virtual-scroll.js` (VirtualScroll class API) | [85db533](../../../commit/85db533) |
44
+ | `web-daterangepicker.html` | 2026-04-25 | `../../web-daterangepicker/src/web-component.ts` (observedAttributes), `../../web-daterangepicker/src/types.ts` (DatePickerOptions, DateInfo, disabledDatesHandling), `../../web-daterangepicker/API.md`, `core-components/_web-components-theme.scss` (--base-* bridge) | [7cbad56](../../../commit/7cbad56) |
45
+ | `web-multiselect.html` | 2026-04-25 | `../../web-multiselect/src/web-component.ts` (observedAttributes), `../../web-multiselect/src/types.ts` (BadgesDisplayMode, BadgesPosition, SearchMode, ValueFormat etc.), `../../web-multiselect/src/css/_variables.css` (--ms-* surface), `core-components/_web-components-theme.scss` | [95cf062](../../../commit/95cf062) |
46
+ | `filter-card.html` | 2026-04-25 | `core-components/_filter-card.scss` (whole file — only BEM elements + 2 state modifiers, no base block) | [b65ec2b](../../../commit/b65ec2b) |
47
+ | `statistics.html` | 2026-04-25 | `core-components/_statistics.scss` (whole file — `.pa-stat`, `--hero`, `--hero-compact`, `--square` + 6 colour variants, `.pa-kpi-grid`) | [5de0ce8](../../../commit/5de0ce8) |
48
+ | `notifications.html` | 2026-04-25 | `core-components/_notifications.scss` (whole file — bell + dropdown panel, item states, page-view modifier, hover-revealed actions) | [0d7bb15](../../../commit/0d7bb15) |
49
+ | `data-display.html` | 2026-04-25 | `core-components/_data-display.scss` (whole file — 7 components: `.pa-field` + `.pa-fields` (15+ layout modifiers), `.pa-field-group`, `.pa-desc-table`, `.pa-prop-card`, `.pa-banded`, `.pa-accent-grid`, `.pa-dot-leaders`; shared copy-pattern modifiers across all) | [39cc6bd](../../../commit/39cc6bd) |
50
+
51
+ ## Pending
52
+
53
+ _None — both audit and gap passes complete._
54
+
55
+ Run `npm run generate-hashes -w @keenmate/pure-admin-core` to refresh `snippets/manifest.json` whenever any of the snippet files change.
56
+
57
+ ## Gaps — SCSS without a snippet
58
+
59
+ These components exist in `src/scss/core-components/` but downstream consumers have no snippet to crib from. Decide per-entry whether to add a snippet or mark as demo-internal.
60
+
61
+ | Component | SCSS file | Notes |
62
+ |---|---|---|
63
+ | pagers | `_pagers.scss` | Covered inside `tables.html` audit (same family; pager/load-more only meaningful alongside tables). |
64
+ | ~~notifications~~ | ~~`_notifications.scss`~~ | ~~Public — snippet worth adding~~ → done in `notifications.html` |
65
+ | ~~statistics~~ | ~~`_statistics.scss`~~ | ~~Public — snippet worth adding~~ → done in `statistics.html` |
66
+ | file-selector | `_file-selector.scss` | **Deferred** — component is not yet finished. Revisit once the API stabilizes; snippet would chase a moving target. |
67
+ | ~~filter-card~~ | ~~`_filter-card.scss`~~ | ~~Public — snippet worth adding~~ → done in `filter-card.html` |
68
+ | logic-tree | `_logic-tree.scss` | **Deferred** — component is not yet finished. Revisit once the API stabilizes. |
69
+ | ~~data-display~~ | ~~`_data-display.scss`~~ | ~~Public — snippet worth adding~~ → done in `data-display.html` |
70
+ | smart-filters (aka query-editor) | `core-components/forms/_query-editor.scss` | **Deferred** — component is not yet finished. SCSS file is named `_query-editor.scss` but the demo calls it "Smart Filters" (`demo/views/smart-filters.mustache` + `demo/js/search-autocomplete*.js`, `virtual-textbox.js`). Briefly cross-referenced from forms.html; revisit once the API stabilizes. |
71
+ | data-viz | `_data-viz.scss` | D3-driven — snippet would be thin; defer |
72
+ | scrollbars | `_scrollbars.scss` | Global utility styling; no snippet needed |
73
+ | settings-panel | `_settings-panel.scss` | Demo-internal; no snippet needed |
74
+ | web-components-theme | `_web-components-theme.scss` | CSS custom properties bridge; no snippet needed |
75
+ | base | `_base.scss` | Reset/base styles; covered by `typography.html` |
76
+
77
+ ## Known issues flagged during audits (not in scope to fix here)
78
+
79
+ - **`demo/views/code.mustache`** reference block lists several accent colors that don't match `variables/_colors.scss`: JSON → "Green" (actual amber), bash → "Gray" (actual green), SQL → "Purple" (actual teal), keyword → "purple, bold" (actual blue + medium), function → "blue" (actual purple), property → "cyan" (actual pink-red). Fix in a later demo pass.
80
+ - **`.pa-spinner` ghost size modifiers.** `_loaders.scss` only defines `--xs`; the demo page (`demo/views/loaders.mustache`) and the previous snippet both showed `--sm`, `--md`, `--lg`, `--xl`, `--2xl` with fabricated size labels (1rem → 4rem). All render at the default 16px because the modifiers don't exist. Snippet fixed in loaders commit; demo page still broken — either remove the ghost sizes from the demo, or add them to SCSS. Decision to be made in a future framework pass.
81
+ - ~~**Popconfirm is physical-only; toasts are logical.**~~ Fixed in the popconfirm logical-rename commit: `--left`/`--right` → `--start`/`--end`, SCSS switched to `inset-inline-*` + `margin-inline-*`, arrow gets `scaleX(-1)` under `[dir="rtl"]`. See Unreleased section of CHANGELOG.
82
+ - **Composite badge missing `--btn-danger` variant.** All other button-section colour overrides exist (`--btn-primary`, `--btn-secondary`, `--btn-success`, `--btn-warning`, `--btn-info`, `--btn-light`, `--btn-dark`) but not `--btn-danger`. The base `.pa-composite-badge__button` defaults to danger colours, so adding `--btn-danger` would be a no-op in practice, but the gap is inconsistent with `--label-danger` (which does exist) and makes "what overrides are available" harder to predict. Snippet flags the omission; actual fix is a single block in `_composite-badge-variants.scss`.
83
+ - ~~**Pager/load-more definitions are duplicated** between `_tables.scss` (lines 475-608) and `_pagers.scss`.~~ Fixed: duplicate block removed from `_tables.scss`, and the `var(--pa-accent)` upgrade on the load-more spinner ported into `_pagers.scss` (it was using the raw SCSS `$accent-color` before). See Unreleased CHANGELOG entry.
84
+ - **Timeline `--alternating` uses physical `left`/`right` throughout.** `_timeline.scss` mixes its RTL handling: `--simple` and `--feed` use logical properties (`inset-inline-*`, `margin-inline-*`, `padding-inline-*`, `border-inline-*`) and mirror correctly in RTL. But `--alternating` and its modifiers (`--start`, `--end`, `--keep-layout`, `--single-column`) use physical `left`/`right` positions for the centre line, dots, connector arms, dates, icons, and content offsets. Result: in RTL, the alternating timeline doesn't mirror — items stay on the same physical sides, the dates don't flip to the inline-start of each item, and `--start`/`--end` are locked to physical left/right. Fix would need `inset-inline-start/end` + `border-inline-*` substitutions throughout the alternating block, plus probably a `[dir="rtl"] &` flip for the nth-child offset origin. Framework scope; snippet documents the current physical behaviour accurately.
85
+
86
+ ## Rehash
87
+
88
+ At the end of the audit (or whenever snippets settle), run:
89
+
90
+ ```bash
91
+ npm run generate-hashes -w @keenmate/pure-admin-core
92
+ ```
93
+
94
+ to refresh `snippets/manifest.json` so downstream framework wrappers see the new hashes.