@keenmate/pure-admin-core 2.8.0 → 2.9.0-rc03

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 CHANGED
@@ -2,21 +2,22 @@
2
2
 
3
3
  Lightweight, data-focused CSS/SCSS admin framework with Corporate theme as default.
4
4
 
5
- ## What's New in 2.8.0
6
-
7
- - **CSS variable defaults now ship at `:root` in `dist/css/main.css`.** The unthemed bundle previously had no `--pa-*` / `--base-*` values they were emitted only by theme stylesheets, so consuming `@keenmate/pure-admin-core/css` standalone (or any page before its theme link resolved) left tokens unresolved and components rendered with broken fallbacks (KPI sparklines and deltas in near-black via inherited text colour, web components reverting to hardcoded literals). `main.scss` now emits `output-base-css-variables`, `output-pa-css-variables`, and `output-pa-alert-variables-light` at `:root` for a complete neutral default. Themes are unaffected they emit their own `:root` from their theme file and all 15 themes rebuild byte-identical. Supersedes the partial 2.7.1-era sentiment-scale fallback patch.
8
- - **KPI layout modifiers and CSS-variable knobs across four showcases.** `.pa-kpi-spark-list--no-delta` drops the Δ% column (with track widths now lifted to local SCSS variables for one source of truth); `.pa-kpi-hero-list__layout--hero-2-3` / `--hero-3-4` shift the hero/rail split off the locked 50/50; `.pa-kpi-bento__grid--hero-right` mirrors the default and `--5-tile` swaps to a five-tile composition, plus a new `--pa-kpi-bento-row-height` variable for tuning row height per instance.
9
- - **KPI grids redesigned as cell-min-driven auto-fit (Visual breaking).** `.pa-kpi-gauge-list__grid` and `.pa-kpi-edit__grid` swap fixed `repeat(N, 1fr)` + `@container` breakpoints for `repeat(auto-fit, minmax(var(--pa-kpi-X-cell-min, …), 1fr))` intrinsic responsive cascade, no `@container` queries on the grids. Five new cap-at-N modifiers (`--max-2` through `--max-6`) constrain column count without forcing it; a `--2col` modifier forces a deterministic 2×N rhythm. Migration: bare grids with fixed item counts may produce uneven rows at widths that fit 4+ columns add the appropriate `--max-N` to preserve a fixed rhythm.
10
- - **`.pa-kpi-terminal` view-mode toggle generalised to a tab strip (Visual breaking).** `__viewtoggle`/`__viewbtn` renamed to `__tabs`/`__tab`; `data-view` attribute on the root is gone in favour of `data-tab` on tabs and panes; the per-tile `__value[data-mode]` triple-value mechanism is removed. Each tab now swaps in a separate `__pane` with its own tile set and grid layout authors can put a different number of tiles (and a different grid modifier) behind each tab. JS contract: `initTerminalViewToggle` → `initTerminalTabs`.
11
- - **`.pa-kpi-strip` column toggles extended to a composable 2–5 column family.** Three independently composable toggle modifiers (`--no-prev`, `--no-delta`, `--no-target`) replace the previous fixed 4/5-col shapes, yielding eight visible-column combinations. Per-column header classes (`__head--metric`/`--now`/`--prev`/`--delta`/`--target`) keep the header row in sync with the data rows. Track widths lifted to local SCSS variables so the eight precomputed templates share one source of truth.
12
-
13
- ## What's New in 2.7.1
14
-
15
- - **KPI showcases promoted to permanent core components.** The seven showcase designs (terminal grid, sparkline list, comparison gauges, hero + supporting, bento, numeric strip, editorial minimal) graduate from demo-inline `<style>`/`<script>` blocks into framework components — ~500 lines of CSS and ~350 lines of JS now live in shared sources instead of duplicated inline blocks.
16
- - **Eight new core SCSS partials** under `core-components/`. `_kpi-base.scss` carries the chrome shared across all seven designs (`pa-kpi-header`, `pa-kpi-live` + pulse animation, `pa-kpi-footer`, `pa-kpi-detail` hover popover, `pa-kpi-spark-dot`/`-spark-wrap`, `pa-kpi-sectionhead`); seven design-specific files carry per-design layout + typography. All wired into `_core.scss` after `data-viz`.
17
- - **All `kpi-*` classes renamed to `pa-kpi-*`** to match the framework's BEM prefix rule. Element (`__header`, `__live`, `__footer`, `__detail`) and modifier (`--positive`, `--negative`, `--neutral`, `--up-strong`, `--down-strong`) structures preserved 1:1.
18
- - **Per-component cascade variables namespace-prefixed.** `--kpi-accent` `--pa-kpi-accent`, `--kpi-bar-color` `--pa-kpi-bar-color`. Gauge tick knobs (`--pa-kpi-gauge-tick-pos`, `--pa-kpi-gauge-tick-color`) keep their gauge-specific names.
19
- - **No new framework tokens.** All sentiment, popover-chrome, sparkline-geometry, contrast-tier, and surface tokens were already emitted by `_base-css-variables.scss` from the 2.6.0 consolidation this release reuses them.
5
+ ## What's New in 2.9.0-rc03
6
+
7
+ - **`.pa-splitter` drag model reworked to "rebalance-on-drag".** Each gutter now resizes only its primary neighbour (edge-closer side, LTR/RTL tiebreaker on ties); the matching delta is absorbed by the immediate adjacent non-rail pane (classic boundary feel), or when the adjacent pane is rail tunnels through the rail wall to the contiguous non-rail block beyond. Eliminates the "boundary locks when both sides are rail" deadlock from the prior model drag-from-rail with a railed neighbour now grows the primary by pulling room from the next section.
8
+ - **Middle panes can now minimize to rail** (previously first / last only). Any pane with `data-pa-splitter-minimize` collapses on toggle / dblclick / drag-snap regardless of position. Snap-into-rail enforces an "at least one expanded pane" invariant you can't drag the last visible pane to rail and end up with nothing to grab.
9
+ - **Restoring a minimized pane reclaims layout gaps cleanly.** When a prior minimize hit an absorber's `max` cap and left empty space in the layout, restoring the pane now reaches its remembered size by drawing from the gap (not just from other panes' shrink headroom) fixes the "restored pane stuck at min width" surprise. Conversely, restoring no longer aggressively inflates a sibling pane to fill remaining gap empty space stays as empty space and gets consumed as more panes restore. No more "sibling pane suddenly jumps" UX.
10
+ - **Rail width in `--pa-splitter-rail-size` now correctly resolves `rem` / non-px units.** Previously `parseFloat("4rem")` returned `4` and snapped rail panes to 4px-wide strips; rebuilt via a hidden probe element so the browser does the unit resolution. The three-step fallback chain (per-instance attribute CSS var literal 40) still applies.
11
+ - **Gutter highlighting now isolates the dragged gutter only.** During a drag, the splitter `--dragging` modifier suppresses `:hover` / `:focus-visible` on sibling gutters so they don't light up as the cursor passes over them or as a stale focus ring lingers only the active gutter carries the highlight.
12
+ - **Splitter padding subtracted from available space.** Flex children sit inside the splitter's content box but `clientWidth` includes padding — without subtracting it the last pane's `flex-basis` overflowed and got clipped by `overflow: hidden`. Visible in the N-pane demo where the rightmost rail's right edge touched the splitter border.
13
+
14
+ ## What's New in 2.9.0-rc02
15
+
16
+ - **`.pa-splitter` resizable container with optional collapse-to-rail.** Vanilla JS + SCSS, two orientations (`--horizontal` / `--vertical`), per-instance constraints (`min-start` / `max-start` accept px or %), and `localStorage` persistence via `data-pa-splitter-id`. Pointer-event drag (mouse / touch / pen), `gap`-aware constraint math, keyboard a11y on the gutter (`role="separator"`, arrow keys, `Home`/`End`, `Enter`/`Space` to toggle), and a `ResizeObserver`-driven re-clamp on container resize. Opt-in `data-pa-splitter-minimize="start" | "end"` collapses a pane to a thin sideways-rotated header rail; dragging past a snap threshold commits, dragging back outward restores.
17
+ - **`.pa-splitter` N-pane mode (3+ panes).** `init()` is now a dispatcher: the legacy 2-pane path (selected by `pane--start` + `pane--end` markup) is preserved byte-identical; everything else goes through `initNPane()`. Per-pane API: `data-pa-splitter-size="240px|30%"` for initial sizing, `-min` / `-max` for per-pane clamps, `data-pa-splitter-minimize` as presence marker (first / last pane only — middle-pane rail rotation has nowhere clean to dock). Drag math is per-gutter stop-at-min (Split.js basic-mode semantics). Container-resize redistributes proportionally to unminimized panes; minimized panes stay pinned to rail. Storage shape versioned under the same `pa-splitter:<id>` key.
18
+ - **`pa-card__actions--responsive` CSS-only collapse to a split button when the header runs out of space.** Render both forms inline (`pa-card__actions-full` + `pa-card__actions-collapsed`, the latter hosting a `pa-btn-split`); a container query on `.pa-card__header:has(> .pa-card__actions--responsive)` swaps which is visible. Threshold lives in one SCSS variable (`$card-actions-collapse-at`, default `28rem`). No JS, no `ResizeObserver` — but action data is duplicated in the DOM.
19
+ - **`pa-card__actions--overflow` JS-driven progressive collapse into a "..." menu.** Complement to `--responsive`: walks buttons into an overflow menu one at a time as space shrinks, restoring them in original DOM order as it grows. `data-pa-actions-overflow-from="end" | "start"` controls drop direction; `data-pa-actions-priority="N"` per button pins primary actions. Menu reuses `pa-btn-split__menu` styling (one menu source across split-button and overflow). Positioning via Floating UI (`computePosition` + `offset` + `flip` + `shift` + `autoUpdate`), with a hand-rolled fallback when `FloatingUIDOM` isn't loaded. Auto-closes on any wrapper resize or when the trigger goes `display: none` (e.g. splitter rail mode).
20
+ - **`pa-btn--ghost` variant defined in core.** Previously referenced by demo files (`alerts`, `notifications`, `splitter`) but had no SCSS rule — every usage silently rendered as a base `.pa-btn`. Now defined in `_buttons.scss`: transparent background and border, `var(--pa-text-secondary)` text, hover snaps to `var(--pa-surface-hover)` + `--pa-text-color-1`. No new tokens introduced; themes need a rebuild to pick up the variant.
20
21
 
21
22
  ## Installation
22
23
 
package/dist/css/main.css CHANGED
@@ -5425,8 +5425,6 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5425
5425
  .pa-card__header {
5426
5426
  padding: 0.5rem 1rem;
5427
5427
  min-height: 4rem;
5428
- border-top-left-radius: 8px;
5429
- border-top-right-radius: 8px;
5430
5428
  border-bottom: 1px solid var(--pa-border-color);
5431
5429
  background: var(--pa-card-header-bg);
5432
5430
  display: flex;
@@ -5486,6 +5484,12 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5486
5484
  .pa-card__header .pa-btn-group {
5487
5485
  flex-shrink: 0;
5488
5486
  }
5487
+ .pa-card__header .pa-card__actions--overflow {
5488
+ flex-shrink: 1;
5489
+ }
5490
+ .pa-card__header:has(> .pa-card__actions--overflow) > .pa-card__title {
5491
+ min-width: 6rem;
5492
+ }
5489
5493
  .pa-card__header .pa-btn {
5490
5494
  margin-top: -0.25rem;
5491
5495
  margin-bottom: -0.25rem;
@@ -5595,6 +5599,25 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5595
5599
  gap: 0.8rem;
5596
5600
  align-items: center;
5597
5601
  }
5602
+ .pa-card__actions--responsive > .pa-card__actions-full {
5603
+ display: flex;
5604
+ gap: 0.8rem;
5605
+ align-items: center;
5606
+ }
5607
+ .pa-card__actions--responsive > .pa-card__actions-collapsed {
5608
+ display: none;
5609
+ }
5610
+ .pa-card__actions--overflow {
5611
+ min-width: 0;
5612
+ overflow: hidden;
5613
+ }
5614
+ .pa-card__actions--overflow > * {
5615
+ flex-shrink: 0;
5616
+ }
5617
+ .pa-card__header:has(> .pa-card__actions--responsive) {
5618
+ container-type: inline-size;
5619
+ container-name: pa-card-header;
5620
+ }
5598
5621
  .pa-card__meta {
5599
5622
  color: var(--pa-text-color-2);
5600
5623
  font-size: 1.4rem;
@@ -5604,6 +5627,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5604
5627
  }
5605
5628
  .pa-card--primary .pa-card__header {
5606
5629
  background-color: var(--pa-accent);
5630
+ border-bottom-color: var(--pa-accent);
5607
5631
  color: var(--pa-btn-primary-text);
5608
5632
  }
5609
5633
  .pa-card--primary .pa-card__header h1,
@@ -5619,6 +5643,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5619
5643
  }
5620
5644
  .pa-card--success .pa-card__header {
5621
5645
  background-color: var(--pa-success-bg);
5646
+ border-bottom-color: var(--pa-success-bg);
5622
5647
  color: var(--pa-btn-success-text);
5623
5648
  }
5624
5649
  .pa-card--success .pa-card__header h1,
@@ -5634,6 +5659,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5634
5659
  }
5635
5660
  .pa-card--warning .pa-card__header {
5636
5661
  background-color: var(--pa-warning-bg);
5662
+ border-bottom-color: var(--pa-warning-bg);
5637
5663
  color: var(--pa-btn-warning-text);
5638
5664
  }
5639
5665
  .pa-card--warning .pa-card__header h1,
@@ -5649,6 +5675,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5649
5675
  }
5650
5676
  .pa-card--danger .pa-card__header {
5651
5677
  background-color: var(--pa-danger-bg);
5678
+ border-bottom-color: var(--pa-danger-bg);
5652
5679
  color: var(--pa-btn-danger-text);
5653
5680
  }
5654
5681
  .pa-card--danger .pa-card__header h1,
@@ -5695,6 +5722,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5695
5722
  }
5696
5723
  .pa-card--color-1 .pa-card__header {
5697
5724
  background-color: var(--pa-color-1);
5725
+ border-bottom-color: var(--pa-color-1);
5698
5726
  color: var(--pa-color-1-text);
5699
5727
  }
5700
5728
  .pa-card--color-1 .pa-card__header h1,
@@ -5710,6 +5738,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5710
5738
  }
5711
5739
  .pa-card--color-2 .pa-card__header {
5712
5740
  background-color: var(--pa-color-2);
5741
+ border-bottom-color: var(--pa-color-2);
5713
5742
  color: var(--pa-color-2-text);
5714
5743
  }
5715
5744
  .pa-card--color-2 .pa-card__header h1,
@@ -5725,6 +5754,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5725
5754
  }
5726
5755
  .pa-card--color-3 .pa-card__header {
5727
5756
  background-color: var(--pa-color-3);
5757
+ border-bottom-color: var(--pa-color-3);
5728
5758
  color: var(--pa-color-3-text);
5729
5759
  }
5730
5760
  .pa-card--color-3 .pa-card__header h1,
@@ -5740,6 +5770,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5740
5770
  }
5741
5771
  .pa-card--color-4 .pa-card__header {
5742
5772
  background-color: var(--pa-color-4);
5773
+ border-bottom-color: var(--pa-color-4);
5743
5774
  color: var(--pa-color-4-text);
5744
5775
  }
5745
5776
  .pa-card--color-4 .pa-card__header h1,
@@ -5755,6 +5786,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5755
5786
  }
5756
5787
  .pa-card--color-5 .pa-card__header {
5757
5788
  background-color: var(--pa-color-5);
5789
+ border-bottom-color: var(--pa-color-5);
5758
5790
  color: var(--pa-color-5-text);
5759
5791
  }
5760
5792
  .pa-card--color-5 .pa-card__header h1,
@@ -5770,6 +5802,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5770
5802
  }
5771
5803
  .pa-card--color-6 .pa-card__header {
5772
5804
  background-color: var(--pa-color-6);
5805
+ border-bottom-color: var(--pa-color-6);
5773
5806
  color: var(--pa-color-6-text);
5774
5807
  }
5775
5808
  .pa-card--color-6 .pa-card__header h1,
@@ -5785,6 +5818,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5785
5818
  }
5786
5819
  .pa-card--color-7 .pa-card__header {
5787
5820
  background-color: var(--pa-color-7);
5821
+ border-bottom-color: var(--pa-color-7);
5788
5822
  color: var(--pa-color-7-text);
5789
5823
  }
5790
5824
  .pa-card--color-7 .pa-card__header h1,
@@ -5800,6 +5834,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5800
5834
  }
5801
5835
  .pa-card--color-8 .pa-card__header {
5802
5836
  background-color: var(--pa-color-8);
5837
+ border-bottom-color: var(--pa-color-8);
5803
5838
  color: var(--pa-color-8-text);
5804
5839
  }
5805
5840
  .pa-card--color-8 .pa-card__header h1,
@@ -5815,6 +5850,7 @@ body:not(.sidebar-hidden) .pa-layout__sidebar--icon-collapse .pa-sidebar__icon {
5815
5850
  }
5816
5851
  .pa-card--color-9 .pa-card__header {
5817
5852
  background-color: var(--pa-color-9);
5853
+ border-bottom-color: var(--pa-color-9);
5818
5854
  color: var(--pa-color-9-text);
5819
5855
  }
5820
5856
  .pa-card--color-9 .pa-card__header h1,
@@ -5911,6 +5947,48 @@ a.pa-card p {
5911
5947
  padding-bottom: 0.8rem;
5912
5948
  }
5913
5949
 
5950
+ @container pa-card-header (max-width: 28rem) {
5951
+ .pa-card__actions--responsive > .pa-card__actions-full {
5952
+ display: none;
5953
+ }
5954
+ .pa-card__actions--responsive > .pa-card__actions-collapsed {
5955
+ display: flex;
5956
+ align-items: center;
5957
+ }
5958
+ }
5959
+ .pa-splitter__pane--minimized > .pa-card {
5960
+ height: 100%;
5961
+ display: flex;
5962
+ flex-direction: column;
5963
+ margin: 0;
5964
+ }
5965
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__body,
5966
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__footer {
5967
+ display: none;
5968
+ }
5969
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header {
5970
+ flex: 1 1 auto;
5971
+ justify-content: flex-start;
5972
+ writing-mode: sideways-rl;
5973
+ }
5974
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header i,
5975
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header svg {
5976
+ writing-mode: initial;
5977
+ }
5978
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header .pa-card__title {
5979
+ padding-top: calc((4rem - 1.6rem) / 2 - 0.5rem);
5980
+ }
5981
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header .pa-btn,
5982
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header .pa-btn-group,
5983
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header button,
5984
+ .pa-splitter__pane--minimized > .pa-card > .pa-card__header input {
5985
+ display: none;
5986
+ }
5987
+
5988
+ .pa-splitter--minimize-mirror .pa-splitter__pane--minimized > .pa-card > .pa-card__header :is(h1, h2, h3, h4, h5, h6) {
5989
+ transform: scale(-1, -1);
5990
+ }
5991
+
5914
5992
  /* ========================================
5915
5993
  Tabs Component
5916
5994
  Standalone tabs for organizing content into separate sections
@@ -7295,6 +7373,15 @@ a.pa-card p {
7295
7373
  background-color: var(--pa-main-bg);
7296
7374
  border-color: var(--pa-accent);
7297
7375
  }
7376
+ .pa-btn--ghost {
7377
+ background-color: transparent;
7378
+ border-color: transparent;
7379
+ color: var(--pa-text-secondary);
7380
+ }
7381
+ .pa-btn--ghost:hover {
7382
+ background-color: var(--pa-surface-hover);
7383
+ color: var(--pa-text-color-1);
7384
+ }
7298
7385
  .pa-btn--xs {
7299
7386
  height: 3.1rem;
7300
7387
  padding: 0.6rem 0.8rem;
@@ -12264,18 +12351,6 @@ code {
12264
12351
  text-overflow: ellipsis;
12265
12352
  white-space: nowrap;
12266
12353
  }
12267
- .pa-profile-panel__role {
12268
- display: inline-block;
12269
- padding: 0.8rem 1.2rem;
12270
- background-color: var(--pa-accent-light);
12271
- background-color: color-mix(in srgb, var(--pa-header-profile-name-color) 15%, transparent);
12272
- color: var(--pa-header-profile-name-color);
12273
- font-size: 1.2rem;
12274
- font-weight: 500;
12275
- border-radius: var(--pa-border-radius);
12276
- text-transform: uppercase;
12277
- letter-spacing: 0.5px;
12278
- }
12279
12354
  .pa-profile-panel__close {
12280
12355
  position: absolute;
12281
12356
  top: 1.6rem;
@@ -15243,6 +15318,138 @@ code {
15243
15318
  transform: rotate(180deg);
15244
15319
  }
15245
15320
 
15321
+ /* ========================================
15322
+ Splitter Component
15323
+ Resizable container with draggable gutters (2 or more panes).
15324
+ Modifiers:
15325
+ --horizontal panes side-by-side, vertical gutter (default)
15326
+ --vertical panes stacked, horizontal gutter
15327
+ --dragging applied to root while user is dragging
15328
+ --collapsed start pane has been collapsed to 0
15329
+ --minimize-mirror flip rail-title text 180° (bottom-to-top reading)
15330
+
15331
+ Rail mode is fully decoupled from any specific component. The splitter
15332
+ only rotates elements marked `[data-pa-splitter-rail-title]` inside a
15333
+ minimized pane; per-component adaptation (e.g. card body / footer
15334
+ hiding) lives in that component's SCSS, keyed off
15335
+ `.pa-splitter__pane--minimized > .pa-foo`. Card integration is in
15336
+ `_cards.scss`.
15337
+ ======================================== */
15338
+ :root {
15339
+ --pa-splitter-rail-size: 4rem;
15340
+ }
15341
+
15342
+ .pa-splitter {
15343
+ display: flex;
15344
+ width: 100%;
15345
+ height: 100%;
15346
+ min-width: 0;
15347
+ min-height: 0;
15348
+ overflow: hidden;
15349
+ }
15350
+ .pa-splitter--horizontal {
15351
+ flex-direction: row;
15352
+ }
15353
+ .pa-splitter--horizontal > .pa-splitter__gutter {
15354
+ cursor: col-resize;
15355
+ width: var(--pa-splitter-gutter-size, 0.6rem);
15356
+ height: auto;
15357
+ align-self: stretch;
15358
+ }
15359
+ .pa-splitter--horizontal > .pa-splitter__gutter::before {
15360
+ width: 2px;
15361
+ height: 2.4rem;
15362
+ }
15363
+ .pa-splitter--vertical {
15364
+ flex-direction: column;
15365
+ }
15366
+ .pa-splitter--vertical > .pa-splitter__gutter {
15367
+ cursor: row-resize;
15368
+ width: auto;
15369
+ height: var(--pa-splitter-gutter-size, 0.6rem);
15370
+ align-self: stretch;
15371
+ }
15372
+ .pa-splitter--vertical > .pa-splitter__gutter::before {
15373
+ width: 2.4rem;
15374
+ height: 2px;
15375
+ }
15376
+ .pa-splitter--dragging {
15377
+ user-select: none;
15378
+ }
15379
+ .pa-splitter--dragging > .pa-splitter__pane {
15380
+ pointer-events: none;
15381
+ }
15382
+ .pa-splitter--dragging > .pa-splitter__gutter:not(.pa-splitter__gutter--active) {
15383
+ pointer-events: none;
15384
+ }
15385
+ .pa-splitter--dragging > .pa-splitter__gutter:not(.pa-splitter__gutter--active):focus-visible {
15386
+ box-shadow: none;
15387
+ }
15388
+ .pa-splitter--dragging > .pa-splitter__gutter:not(.pa-splitter__gutter--active):focus-visible::before {
15389
+ background-color: rgba(128, 128, 128, 0.45);
15390
+ }
15391
+ .pa-splitter__gutter--active {
15392
+ background-color: rgba(0, 123, 255, 0.35);
15393
+ }
15394
+ .pa-splitter__gutter--active::before {
15395
+ background-color: #007bff;
15396
+ }
15397
+ .pa-splitter__pane {
15398
+ overflow: auto;
15399
+ min-width: 0;
15400
+ min-height: 0;
15401
+ }
15402
+ .pa-splitter__pane--start {
15403
+ flex: 0 0 auto;
15404
+ }
15405
+ .pa-splitter__pane--end {
15406
+ flex: 1 1 0;
15407
+ }
15408
+ .pa-splitter__pane--minimized {
15409
+ cursor: pointer;
15410
+ overflow: hidden;
15411
+ }
15412
+ .pa-splitter__pane--minimized [data-pa-splitter-rail-title] {
15413
+ writing-mode: sideways-rl;
15414
+ }
15415
+ .pa-splitter__pane--minimized [data-pa-splitter-rail-title] i,
15416
+ .pa-splitter__pane--minimized [data-pa-splitter-rail-title] svg {
15417
+ writing-mode: initial;
15418
+ }
15419
+ .pa-splitter--minimize-mirror .pa-splitter__pane--minimized [data-pa-splitter-rail-title] :is(h1, h2, h3, h4, h5, h6) {
15420
+ transform: scale(-1, -1);
15421
+ }
15422
+ .pa-splitter__gutter {
15423
+ position: relative;
15424
+ flex: 0 0 auto;
15425
+ background-color: rgba(128, 128, 128, 0.08);
15426
+ transition: background-color 0.15s ease;
15427
+ touch-action: none;
15428
+ outline: none;
15429
+ }
15430
+ .pa-splitter__gutter::before {
15431
+ content: "";
15432
+ position: absolute;
15433
+ top: 50%;
15434
+ left: 50%;
15435
+ transform: translate(-50%, -50%);
15436
+ background-color: rgba(128, 128, 128, 0.45);
15437
+ border-radius: 2px;
15438
+ transition: background-color 0.15s ease;
15439
+ }
15440
+ .pa-splitter__gutter:hover {
15441
+ background-color: rgba(128, 128, 128, 0.18);
15442
+ }
15443
+ .pa-splitter__gutter:hover::before {
15444
+ background-color: #007bff;
15445
+ }
15446
+ .pa-splitter__gutter:focus-visible {
15447
+ box-shadow: inset 0 0 0 2px rgba(0, 123, 255, 0.4);
15448
+ }
15449
+ .pa-splitter__gutter:focus-visible::before {
15450
+ background-color: #007bff;
15451
+ }
15452
+
15246
15453
  /* ========================================
15247
15454
  Data Display Components
15248
15455
  Read-only label-value field pairs
@@ -19321,12 +19528,6 @@ html.pa-font-base-12 {
19321
19528
  --base-active-bg: rgb(218.2368421053, 223.25, 228.2631578947);
19322
19529
  --base-disabled-bg: #e9ecef;
19323
19530
  --base-elevated-bg: #f5f5f5;
19324
- --base-surface-1: #ffffff;
19325
- --base-surface-2: #f8f9fa;
19326
- --base-surface-3: #e9ecef;
19327
- --base-surface-inverse: #2c3e50;
19328
- --base-primary-bg: #ffffff;
19329
- --base-primary-bg-hover: rgb(242.25, 242.25, 242.25);
19330
19531
  --base-border-color: #e1e5e9;
19331
19532
  --base-border: 1px solid #e1e5e9;
19332
19533
  --base-input-bg: #ffffff;
@@ -19401,6 +19602,7 @@ html.pa-font-base-12 {
19401
19602
  --base-border-radius-sm: 0.4;
19402
19603
  --base-border-radius-md: 0.6;
19403
19604
  --base-border-radius-lg: 0.8;
19605
+ color-scheme: light;
19404
19606
  --pa-main-bg: #f8f9fa;
19405
19607
  --pa-page-bg: #f8f9fa;
19406
19608
  --pa-subtle-bg: #ffffff;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keenmate/pure-admin-core",
3
- "version": "2.8.0",
3
+ "version": "2.9.0-rc03",
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": {
@@ -58,7 +58,7 @@ to save horizontal space in the navbar.
58
58
  <!-- title= attrs give a tooltip when the text truncates with ellipsis -->
59
59
  <h3 class="pa-profile-panel__name" title="John Doe">John Doe</h3>
60
60
  <p class="pa-profile-panel__email" title="john.doe@company.com">john.doe@company.com</p>
61
- <span class="pa-profile-panel__role">Administrator</span>
61
+ <span class="pa-badge">Administrator</span>
62
62
  </div>
63
63
  <button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
64
64
 
@@ -124,7 +124,7 @@ to save horizontal space in the navbar.
124
124
  <div class="pa-profile-panel__info">
125
125
  <h3 class="pa-profile-panel__name">John Doe</h3>
126
126
  <p class="pa-profile-panel__email">john.doe@company.com</p>
127
- <span class="pa-profile-panel__role">Administrator</span>
127
+ <span class="pa-badge">Administrator</span>
128
128
  </div>
129
129
  <button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">✕</button>
130
130
  </div>
@@ -170,7 +170,7 @@ to save horizontal space in the navbar.
170
170
  <div class="pa-profile-panel__info">
171
171
  <h3 class="pa-profile-panel__name">Jane Smith</h3>
172
172
  <p class="pa-profile-panel__email">jane.smith@corp.example</p>
173
- <span class="pa-profile-panel__role">Analyst</span>
173
+ <span class="pa-badge">Analyst</span>
174
174
  </div>
175
175
  <button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">✕</button>
176
176
  </div>
@@ -207,7 +207,7 @@ to save horizontal space in the navbar.
207
207
  <div class="pa-profile-panel__info">
208
208
  <h3 class="pa-profile-panel__name">John Doe</h3>
209
209
  <p class="pa-profile-panel__email">john.doe@company.com</p>
210
- <span class="pa-profile-panel__role">Administrator</span>
210
+ <span class="pa-badge">Administrator</span>
211
211
  </div>
212
212
  <button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">✕</button>
213
213
  </div>
@@ -425,7 +425,10 @@ HEADER:
425
425
  - .pa-profile-panel__info Text column (name + email + role).
426
426
  - .pa-profile-panel__name User name (ellipsis on overflow).
427
427
  - .pa-profile-panel__email Email (ellipsis on overflow).
428
- - .pa-profile-panel__role Role badge (uppercase, tinted bg).
428
+ - .pa-badge Role chip (standard badge component;
429
+ add `.pa-badge--primary` / `--info` /
430
+ `--success` / `--warning` / `--danger`
431
+ / `--light` for variant styling).
429
432
  - .pa-profile-panel__close Close button (top-end corner).
430
433
 
431
434
  Theme-colour design choices (why they're like this):
@@ -433,11 +436,13 @@ Theme-colour design choices (why they're like this):
433
436
  colour the header uses for the user's name. This guarantees contrast
434
437
  against dark / coloured header backgrounds across all themes (body
435
438
  text colours would read wrong on a dark header).
436
- - __role paints its background with color-mix(in srgb,
437
- var(--pa-header-profile-name-color) 15%, transparent) so the tint is
438
- derived from the header colour and works on any theme. An older
439
- --pa-accent-light fallback is declared first for browsers without
440
- color-mix.
439
+ - Role uses the standard `.pa-badge` component (var(--pa-btn-secondary-bg)
440
+ / -text by default), which themes already tune for both light and dark
441
+ modes. Previously this was a custom `.pa-profile-panel__role` element
442
+ coupled to --pa-header-profile-name-color that token is sized for the
443
+ header (e.g. black on yellow in Express) and went invisible on dark
444
+ panel bodies. Migrated to `.pa-badge` in 2.9.0; older snippet markup
445
+ using `pa-profile-panel__role` needs the class swap.
441
446
 
442
447
  TABS (optional — sits between __header and __body):
443
448
  - .pa-profile-panel__tabs Tabs container (border-bottom + header-bg).