@keenmate/pure-admin-core 2.9.0-rc01 → 2.9.0-rc04
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 +61 -14
- package/dist/css/main.css +748 -2
- package/package.json +3 -1
- package/snippets/buttons.html +51 -0
- package/snippets/cards.html +34 -4
- package/snippets/comparison.html +26 -22
- package/snippets/manifest.json +180 -115
- package/snippets/range-group.html +125 -0
- package/snippets/splitter.html +216 -0
- package/snippets/statistics.html +31 -0
- package/src/js/btn-split-auto-absorb.js +327 -0
- package/src/js/command-palette.js +472 -0
- package/src/js/file-selector.js +1275 -0
- package/src/js/internal/logging.js +121 -0
- package/src/js/logic-tree-renderer.js +303 -0
- package/src/js/modal-dialogs.js +460 -0
- package/src/js/overflow.js +371 -0
- package/src/js/pa-stat-fit.js +184 -0
- package/src/js/range-group.js +663 -0
- package/src/js/search-autocomplete-v2.js +907 -0
- package/src/js/search-autocomplete.js +434 -0
- package/src/js/settings-panel.js +245 -0
- package/src/js/split-button.js +141 -0
- package/src/js/splitter.js +1323 -0
- package/src/js/toast-service.js +302 -0
- package/src/js/tooltips-popovers.js +275 -0
- package/src/js/virtual-scroll.js +143 -0
- package/src/js/virtual-textbox.js +803 -0
- package/src/scss/_core.scss +10 -0
- package/src/scss/core-components/_buttons.scss +59 -0
- package/src/scss/core-components/_cards.scss +206 -0
- package/src/scss/core-components/_overflow.scss +50 -0
- package/src/scss/core-components/_range-group.scss +474 -0
- package/src/scss/core-components/_splitter.scss +206 -0
- package/src/scss/core-components/_statistics.scss +163 -0
- package/src/scss/variables/_components.scss +56 -2
package/src/scss/_core.scss
CHANGED
|
@@ -72,6 +72,9 @@
|
|
|
72
72
|
// Filter card (expandable table filters)
|
|
73
73
|
@use 'core-components/filter-card' as *;
|
|
74
74
|
|
|
75
|
+
// Range group (compact multi-range filter: slider primitive + floating panel)
|
|
76
|
+
@use 'core-components/range-group' as *;
|
|
77
|
+
|
|
75
78
|
// Comparison tables
|
|
76
79
|
@use 'core-components/comparison' as *;
|
|
77
80
|
|
|
@@ -111,6 +114,13 @@
|
|
|
111
114
|
// Settings Panel
|
|
112
115
|
@use 'core-components/settings-panel' as *;
|
|
113
116
|
|
|
117
|
+
// Splitter (resizable two-pane container)
|
|
118
|
+
@use 'core-components/splitter' as *;
|
|
119
|
+
|
|
120
|
+
// Overflow (progressive-collapse row — generic primitive used by toolbars,
|
|
121
|
+
// breadcrumb rows, chip rows, button bars, plus the card-actions variant)
|
|
122
|
+
@use 'core-components/overflow' as *;
|
|
123
|
+
|
|
114
124
|
// Data Display (read-only fields)
|
|
115
125
|
@use 'core-components/data-display' as *;
|
|
116
126
|
|
|
@@ -44,6 +44,21 @@
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
// Chromeless action button — no fill, no border, just the label / icon.
|
|
48
|
+
// Used for inline affordances inside dense surfaces (card-header actions,
|
|
49
|
+
// notification dismiss, toast close, splitter minimize) where a full button
|
|
50
|
+
// would compete with the content.
|
|
51
|
+
&--ghost {
|
|
52
|
+
background-color: transparent;
|
|
53
|
+
border-color: transparent;
|
|
54
|
+
color: var(--pa-text-secondary);
|
|
55
|
+
|
|
56
|
+
&:hover {
|
|
57
|
+
background-color: var(--pa-surface-hover);
|
|
58
|
+
color: var(--pa-text-color-1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
&--xs {
|
|
48
63
|
height: $btn-height-xs;
|
|
49
64
|
padding: $btn-padding-xs-v $btn-padding-xs-h;
|
|
@@ -477,6 +492,18 @@
|
|
|
477
492
|
border-end-start-radius: 0;
|
|
478
493
|
}
|
|
479
494
|
|
|
495
|
+
// Auto-absorb collapsed state (btn-split-auto-absorb.js): the split
|
|
496
|
+
// button's own primary action has folded into the dropdown, leaving only
|
|
497
|
+
// the toggle. Render the lone toggle as a standalone, fully-rounded button
|
|
498
|
+
// — override the flattened inner corners (the toggle is now :first-child,
|
|
499
|
+
// so it also picks up the primary's flat-end rule) and drop the divider
|
|
500
|
+
// border. `:first-child` keeps specificity at/above the `> .pa-btn:first-child`
|
|
501
|
+
// rule so the all-corner radius wins.
|
|
502
|
+
&--collapsed > .pa-btn-split__toggle:first-child {
|
|
503
|
+
border-radius: var(--pa-border-radius);
|
|
504
|
+
border-inline-start: none;
|
|
505
|
+
}
|
|
506
|
+
|
|
480
507
|
// Toggle button (chevron) - fixed square width
|
|
481
508
|
&__toggle {
|
|
482
509
|
border-inline-start: $border-width-base solid rgba(255, 255, 255, 0.25);
|
|
@@ -582,3 +609,35 @@
|
|
|
582
609
|
}
|
|
583
610
|
}
|
|
584
611
|
|
|
612
|
+
// === Button Toolbar (auto-absorb host) ===
|
|
613
|
+
//
|
|
614
|
+
// Flex row that wraps a `.pa-btn-split.pa-btn-split--auto-absorb` together
|
|
615
|
+
// with the sibling buttons it should absorb when there's no horizontal
|
|
616
|
+
// room. Provides the layout contract `btn-split-auto-absorb.js` needs in
|
|
617
|
+
// order to read a truthful overflow signal:
|
|
618
|
+
//
|
|
619
|
+
// - `min-width: 0` so the row can shrink below its content width
|
|
620
|
+
// - `overflow: hidden` so `scrollWidth > clientWidth` actually goes
|
|
621
|
+
// truthful (without this the row would keep growing past its parent)
|
|
622
|
+
// - children `flex-shrink: 0` so individual buttons don't collapse into
|
|
623
|
+
// unreadable slivers — the JS moves them into the menu instead
|
|
624
|
+
//
|
|
625
|
+
// The split button itself stays put (it's the anchor for the dropdown
|
|
626
|
+
// menu) and never shrinks; siblings get moved into / out of the menu.
|
|
627
|
+
//
|
|
628
|
+
// Standalone (any flex context) or nested inside `.pa-card__actions` when it
|
|
629
|
+
// is a card header's actions — `_cards.scss` makes the actions wrapper
|
|
630
|
+
// shrinkable in that case so the overflow signal still works.
|
|
631
|
+
.pa-btn-toolbar {
|
|
632
|
+
display: flex;
|
|
633
|
+
align-items: center;
|
|
634
|
+
gap: $spacing-sm;
|
|
635
|
+
min-width: 0;
|
|
636
|
+
overflow: hidden;
|
|
637
|
+
flex-shrink: 1;
|
|
638
|
+
|
|
639
|
+
> * {
|
|
640
|
+
flex-shrink: 0;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
@@ -100,6 +100,60 @@
|
|
|
100
100
|
flex-shrink: 0;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
// …unless it's the progressive-overflow variant, which intentionally
|
|
104
|
+
// shrinks below content so the JS can read `scrollWidth > clientWidth`
|
|
105
|
+
// as the "needs overflow" signal. Nested under `&__header` so the
|
|
106
|
+
// selector matches `.pa-card__header .pa-card__actions--overflow` —
|
|
107
|
+
// the same specificity as the rule above, but later in source order
|
|
108
|
+
// and explicit on the modifier.
|
|
109
|
+
.pa-card__actions--overflow {
|
|
110
|
+
flex-shrink: 1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// When the actions wrapper can shrink (overflow variant), give the title
|
|
114
|
+
// a floor so it can't be squeezed to 0 — icon + a few chars + ellipsis
|
|
115
|
+
// stay visible no matter how narrow. `:has()` scopes the override so
|
|
116
|
+
// ordinary cards keep `min-width: 0` and their full ellipsis range.
|
|
117
|
+
&:has(> .pa-card__actions--overflow) > .pa-card__title {
|
|
118
|
+
min-width: 6rem;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Auto-absorb button toolbar (btn-split-auto-absorb.js) hosted in a header,
|
|
122
|
+
// nested inside `.pa-card__actions`: prioritise the ACTIONS over the title.
|
|
123
|
+
// The toolbar must stay shrinkable so the JS can read `scrollWidth >
|
|
124
|
+
// clientWidth` and decide what to fold — but the title has to yield FIRST.
|
|
125
|
+
// Otherwise a long title and the toolbar share the deficit by proportional
|
|
126
|
+
// flex-shrink (weighted by the title's *natural* width), so the toolbar is
|
|
127
|
+
// allocated less width than its content even while the rendered title
|
|
128
|
+
// truncates and leaves a visible gap — and the split button folds all the
|
|
129
|
+
// way down to a lone toggle. A large shrink factor makes the title absorb
|
|
130
|
+
// nearly all the deficit (truncating to the min-width floor) so the toolbar
|
|
131
|
+
// keeps its buttons; siblings only begin folding once the title bottoms out
|
|
132
|
+
// at the floor. Matched as a descendant (not `> `) because the toolbar sits
|
|
133
|
+
// one level down, inside `.pa-card__actions`.
|
|
134
|
+
&:has(.pa-btn-toolbar) > h1,
|
|
135
|
+
&:has(.pa-btn-toolbar) > h2,
|
|
136
|
+
&:has(.pa-btn-toolbar) > h3,
|
|
137
|
+
&:has(.pa-btn-toolbar) > h4,
|
|
138
|
+
&:has(.pa-btn-toolbar) > h5,
|
|
139
|
+
&:has(.pa-btn-toolbar) > h6,
|
|
140
|
+
&:has(.pa-btn-toolbar) > .pa-card__title {
|
|
141
|
+
flex-shrink: 9999;
|
|
142
|
+
min-width: 8rem;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// The actions wrapper hosting the toolbar must itself be shrinkable.
|
|
146
|
+
// `.pa-card__actions` defaults to `flex-shrink: 0` (above) so it holds its
|
|
147
|
+
// natural width — which would keep the toolbar inside at natural width too,
|
|
148
|
+
// and the `scrollWidth > clientWidth` signal would never fire. Let it
|
|
149
|
+
// shrink (`min-width: 0`) so the deficit propagates down to the toolbar,
|
|
150
|
+
// which keeps the `overflow: hidden` clip. `:has()` scopes this so ordinary
|
|
151
|
+
// action wrappers stay fixed-width.
|
|
152
|
+
.pa-card__actions:has(> .pa-btn-toolbar) {
|
|
153
|
+
flex-shrink: 1;
|
|
154
|
+
min-width: 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
103
157
|
// Buttons in card headers - negative margin to prevent header height growth
|
|
104
158
|
.pa-btn {
|
|
105
159
|
margin-top: -0.25rem;
|
|
@@ -107,6 +161,27 @@
|
|
|
107
161
|
flex-shrink: 0;
|
|
108
162
|
}
|
|
109
163
|
|
|
164
|
+
// …but any actions wrapper that CLIPS its overflow — the auto-absorb
|
|
165
|
+
// button toolbar and the progressive-overflow actions container both
|
|
166
|
+
// set `overflow: hidden` so the JS can read `scrollWidth > clientWidth` —
|
|
167
|
+
// would shave the top/bottom borders off those buttons: the -0.25rem
|
|
168
|
+
// block margin above pushes each button past the wrapper's content box,
|
|
169
|
+
// and the clip lands right on the border. Re-parent the compaction onto
|
|
170
|
+
// the wrapper so its clip edge is flush with the button box; the header
|
|
171
|
+
// still gets the same height reduction, borders survive. Scoped under
|
|
172
|
+
// `&__header` so a standalone `.pa-btn-toolbar` (used outside a card
|
|
173
|
+
// header) is untouched.
|
|
174
|
+
.pa-btn-toolbar,
|
|
175
|
+
.pa-card__actions--overflow {
|
|
176
|
+
margin-top: -0.25rem;
|
|
177
|
+
margin-bottom: -0.25rem;
|
|
178
|
+
|
|
179
|
+
.pa-btn {
|
|
180
|
+
margin-top: 0;
|
|
181
|
+
margin-bottom: 0;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
110
185
|
// Underline modifier - accent border under heading inside card header
|
|
111
186
|
&--underlined {
|
|
112
187
|
h1, h2, h3, h4, h5, h6 {
|
|
@@ -237,6 +312,61 @@
|
|
|
237
312
|
display: flex;
|
|
238
313
|
gap: $spacing-sm;
|
|
239
314
|
align-items: center;
|
|
315
|
+
|
|
316
|
+
// Responsive actions — render both the spread button list AND a
|
|
317
|
+
// collapsed split-button form; a container query on the header swaps
|
|
318
|
+
// which is visible. Stays CSS-only (no ResizeObserver / layout reads)
|
|
319
|
+
// but the markup carries both forms.
|
|
320
|
+
//
|
|
321
|
+
// <div class="pa-card__header">
|
|
322
|
+
// <div class="pa-card__title">…</div>
|
|
323
|
+
// <div class="pa-card__actions pa-card__actions--responsive">
|
|
324
|
+
// <div class="pa-card__actions-full">
|
|
325
|
+
// …spread buttons…
|
|
326
|
+
// </div>
|
|
327
|
+
// <div class="pa-card__actions-collapsed">
|
|
328
|
+
// <div class="pa-btn-split">…same actions as a menu…</div>
|
|
329
|
+
// </div>
|
|
330
|
+
// </div>
|
|
331
|
+
// </div>
|
|
332
|
+
//
|
|
333
|
+
// Container is the header; threshold is $card-actions-collapse-at.
|
|
334
|
+
// Wired up via :has() (Baseline 2023) so authors don't need a second
|
|
335
|
+
// modifier on the header.
|
|
336
|
+
&--responsive {
|
|
337
|
+
> .pa-card__actions-full {
|
|
338
|
+
display: flex;
|
|
339
|
+
gap: $spacing-sm;
|
|
340
|
+
align-items: center;
|
|
341
|
+
}
|
|
342
|
+
> .pa-card__actions-collapsed {
|
|
343
|
+
display: none;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Progressive overflow variant — driven by card-actions-overflow.js.
|
|
348
|
+
// `min-width: 0` lets flex shrink the wrapper below its content; with
|
|
349
|
+
// `overflow: hidden` the wrapper clips its children when narrow, which
|
|
350
|
+
// is what makes `scrollWidth > clientWidth` a reliable overflow signal
|
|
351
|
+
// for the JS. Buttons themselves get `flex-shrink: 0` so they don't
|
|
352
|
+
// squeeze to fit — they either fit fully or get moved to the menu.
|
|
353
|
+
&--overflow {
|
|
354
|
+
min-width: 0;
|
|
355
|
+
overflow: hidden;
|
|
356
|
+
|
|
357
|
+
> * {
|
|
358
|
+
flex-shrink: 0;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Enable the container query on any header that contains a responsive
|
|
364
|
+
// actions wrapper. Container query rule itself is emitted at the bottom
|
|
365
|
+
// of this file (outside the .pa-card block) since `@container` can't
|
|
366
|
+
// hide inside an arbitrarily-nested selector cleanly.
|
|
367
|
+
&__header:has(> .pa-card__actions--responsive) {
|
|
368
|
+
container-type: inline-size;
|
|
369
|
+
container-name: pa-card-header;
|
|
240
370
|
}
|
|
241
371
|
|
|
242
372
|
&__meta {
|
|
@@ -499,3 +629,79 @@ a.pa-card {
|
|
|
499
629
|
border-bottom: $border-width-medium solid var(--pa-accent);
|
|
500
630
|
padding-bottom: $spacing-sm;
|
|
501
631
|
}
|
|
632
|
+
|
|
633
|
+
// Responsive card actions — container query for the spread/collapsed swap.
|
|
634
|
+
// Container context set by `.pa-card__header:has(> .pa-card__actions--responsive)`
|
|
635
|
+
// above. Threshold needs explicit interpolation in `@container` (the Sass
|
|
636
|
+
// auto-interpolation that works in `@media` doesn't apply here).
|
|
637
|
+
@container pa-card-header (max-width: #{$card-actions-collapse-at}) {
|
|
638
|
+
.pa-card__actions--responsive {
|
|
639
|
+
> .pa-card__actions-full {
|
|
640
|
+
display: none;
|
|
641
|
+
}
|
|
642
|
+
> .pa-card__actions-collapsed {
|
|
643
|
+
display: flex;
|
|
644
|
+
align-items: center;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Card adaptation inside a minimized splitter pane.
|
|
650
|
+
// Lives here (not in `_splitter.scss`) so the splitter stays unaware of card
|
|
651
|
+
// internals — the rotation hook on the splitter side is `[data-pa-splitter-rail-title]`
|
|
652
|
+
// and this rule applies that attribute's contract to the card header.
|
|
653
|
+
//
|
|
654
|
+
// Layout: pa-card already has `height: 100%` etc., we just hide body/footer,
|
|
655
|
+
// promote the header to fill the rail, and pin the title to the top.
|
|
656
|
+
.pa-splitter__pane--minimized > .pa-card {
|
|
657
|
+
height: 100%;
|
|
658
|
+
display: flex;
|
|
659
|
+
flex-direction: column;
|
|
660
|
+
margin: 0;
|
|
661
|
+
|
|
662
|
+
> .pa-card__body,
|
|
663
|
+
> .pa-card__footer {
|
|
664
|
+
display: none;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
> .pa-card__header {
|
|
668
|
+
flex: 1 1 auto;
|
|
669
|
+
// Pin title to the rail's top (inline-start in sideways-rl writing mode).
|
|
670
|
+
justify-content: flex-start;
|
|
671
|
+
writing-mode: sideways-rl;
|
|
672
|
+
|
|
673
|
+
// Icons reset to natural orientation (descendant combinator covers both
|
|
674
|
+
// flat markup and the BEM `pa-card__title > i` nesting).
|
|
675
|
+
i,
|
|
676
|
+
svg {
|
|
677
|
+
writing-mode: initial;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Vertically align the icon between expanded and minimized states.
|
|
681
|
+
// In expanded mode, `align-items: center` centers the title vertically
|
|
682
|
+
// (icon center at header-min-height / 2 from top). In minimized mode,
|
|
683
|
+
// `justify-content: flex-start` pins the title to the rail's top edge.
|
|
684
|
+
// Push the title down by the difference so the icon sits at the same
|
|
685
|
+
// visual y-position in both states — no "jump" when toggling.
|
|
686
|
+
.pa-card__title {
|
|
687
|
+
padding-top: calc((#{$card-header-min-height} - #{$font-size-base}) / 2 - #{$card-header-padding-v});
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Hide interactive controls inside the header — they'd be sideways and
|
|
691
|
+
// unreadable. The list here is intentional: cards know their own header
|
|
692
|
+
// contents better than the splitter ever could.
|
|
693
|
+
.pa-btn,
|
|
694
|
+
.pa-btn-group,
|
|
695
|
+
button,
|
|
696
|
+
input {
|
|
697
|
+
display: none;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Mirror modifier — when the splitter root carries `pa-splitter--minimize-mirror`,
|
|
703
|
+
// the card heading flips 180° (matches the generic mirror behaviour, scoped
|
|
704
|
+
// to the card title heading).
|
|
705
|
+
.pa-splitter--minimize-mirror .pa-splitter__pane--minimized > .pa-card > .pa-card__header :is(h1, h2, h3, h4, h5, h6) {
|
|
706
|
+
transform: scale(-1, -1);
|
|
707
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* ========================================
|
|
2
|
+
Overflow (progressive-collapse row)
|
|
3
|
+
|
|
4
|
+
Generic primitive: a horizontal flex row whose children get walked into
|
|
5
|
+
a "more" menu when the row can't fit, driven by `overflow.js`. Use
|
|
6
|
+
anywhere you want a button toolbar, breadcrumb row, chip row, or tab bar
|
|
7
|
+
to collapse gracefully on narrow widths.
|
|
8
|
+
|
|
9
|
+
<div class="pa-overflow" data-pa-actions-overflow-from="end">
|
|
10
|
+
<button class="pa-btn pa-btn--xs">Save</button>
|
|
11
|
+
<button class="pa-btn pa-btn--xs" data-pa-actions-priority="10">Run</button>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
The card-flavoured alias `pa-card__actions--overflow` carries equivalent
|
|
15
|
+
rules under `.pa-card__header` (see `_cards.scss`); both wire into the
|
|
16
|
+
same JS module. ======================================== */
|
|
17
|
+
@use '../variables' as *;
|
|
18
|
+
|
|
19
|
+
.pa-overflow {
|
|
20
|
+
// Flex row by default. The JS pulls children out and appends a trigger
|
|
21
|
+
// button at the end; both the row and the trigger inherit normal flex
|
|
22
|
+
// layout from this block. Consumers override gap / alignment per-instance
|
|
23
|
+
// via inline style or a local class.
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
gap: $spacing-sm;
|
|
27
|
+
|
|
28
|
+
// Layout contract for the truthful-overflow signal: the wrapper has to
|
|
29
|
+
// shrink below its content (`min-width: 0`) and clip when it does
|
|
30
|
+
// (`overflow: hidden`) so `scrollWidth > clientWidth` reliably means
|
|
31
|
+
// "the row doesn't fit". Without these, modern flex defaults keep the
|
|
32
|
+
// wrapper at intrinsic content width and the JS sees no overflow.
|
|
33
|
+
// `flex-shrink: 1` so a parent flex layout can compress the row.
|
|
34
|
+
min-width: 0;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
flex-shrink: 1;
|
|
37
|
+
|
|
38
|
+
// Items themselves stay at intrinsic width — they either fit fully or
|
|
39
|
+
// get moved to the menu. Without this they'd squeeze unevenly as the
|
|
40
|
+
// wrapper narrows, defeating the "drop one at a time" UX.
|
|
41
|
+
> * {
|
|
42
|
+
flex-shrink: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Trigger button has no dedicated styling here — it ships with
|
|
46
|
+
// `pa-btn pa-btn--xs pa-btn--ghost` so it picks up the ghost button
|
|
47
|
+
// appearance automatically. The `__trigger` element class is set by
|
|
48
|
+
// the JS as a stable hook for consumers who want to retheme it
|
|
49
|
+
// (e.g. swap the ellipsis icon, change padding).
|
|
50
|
+
}
|