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

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 (35) hide show
  1. package/README.md +55 -13
  2. package/dist/css/main.css +554 -7
  3. package/package.json +3 -1
  4. package/snippets/buttons.html +51 -0
  5. package/snippets/cards.html +132 -47
  6. package/snippets/comparison.html +26 -22
  7. package/snippets/manifest.json +180 -115
  8. package/snippets/range-group.html +125 -0
  9. package/snippets/splitter.html +44 -38
  10. package/snippets/statistics.html +31 -0
  11. package/src/js/btn-split-auto-absorb.js +327 -0
  12. package/src/js/command-palette.js +472 -0
  13. package/src/js/file-selector.js +1275 -0
  14. package/src/js/internal/logging.js +121 -0
  15. package/src/js/logic-tree-renderer.js +303 -0
  16. package/src/js/modal-dialogs.js +460 -0
  17. package/src/js/overflow.js +371 -0
  18. package/src/js/pa-stat-fit.js +184 -0
  19. package/src/js/range-group.js +663 -0
  20. package/src/js/search-autocomplete-v2.js +907 -0
  21. package/src/js/search-autocomplete.js +434 -0
  22. package/src/js/settings-panel.js +245 -0
  23. package/src/js/split-button.js +141 -0
  24. package/src/js/splitter.js +1323 -0
  25. package/src/js/toast-service.js +302 -0
  26. package/src/js/tooltips-popovers.js +275 -0
  27. package/src/js/virtual-scroll.js +143 -0
  28. package/src/js/virtual-textbox.js +803 -0
  29. package/src/scss/_core.scss +7 -0
  30. package/src/scss/core-components/_buttons.scss +44 -0
  31. package/src/scss/core-components/_cards.scss +95 -6
  32. package/src/scss/core-components/_overflow.scss +50 -0
  33. package/src/scss/core-components/_range-group.scss +474 -0
  34. package/src/scss/core-components/_statistics.scss +163 -0
  35. package/src/scss/variables/_components.scss +41 -2
@@ -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
 
@@ -114,6 +117,10 @@
114
117
  // Splitter (resizable two-pane container)
115
118
  @use 'core-components/splitter' as *;
116
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
+
117
124
  // Data Display (read-only fields)
118
125
  @use 'core-components/data-display' as *;
119
126
 
@@ -492,6 +492,18 @@
492
492
  border-end-start-radius: 0;
493
493
  }
494
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
+
495
507
  // Toggle button (chevron) - fixed square width
496
508
  &__toggle {
497
509
  border-inline-start: $border-width-base solid rgba(255, 255, 255, 0.25);
@@ -597,3 +609,35 @@
597
609
  }
598
610
  }
599
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
+
@@ -83,8 +83,11 @@
83
83
  white-space: nowrap;
84
84
  }
85
85
 
86
- // Description paragraphs - flexible middle, truncate with ellipsis
87
- > p {
86
+ // Description - flexible middle, truncate with ellipsis.
87
+ // `.pa-card__description` is the canonical element; bare `> p` is kept as
88
+ // legacy tolerance so hand-written markup doesn't break.
89
+ > p,
90
+ > .pa-card__description {
88
91
  flex: 1;
89
92
  min-width: 0;
90
93
  overflow: hidden;
@@ -92,6 +95,12 @@
92
95
  white-space: nowrap;
93
96
  color: var(--pa-text-color-2);
94
97
  font-size: $font-size-sm;
98
+ // Nudge the smaller description onto the title's baseline (see
99
+ // $card-description-offset-y). `position: relative` keeps it in flow —
100
+ // truncation/flex sizing are unaffected — it only shifts the paint.
101
+ // Font-metric dependent, so themes can retune via the CSS variable.
102
+ position: relative;
103
+ top: var(--pa-card-description-offset-y, #{$card-description-offset-y});
95
104
  }
96
105
 
97
106
  // Actions container - fixed, doesn't shrink
@@ -118,6 +127,42 @@
118
127
  min-width: 6rem;
119
128
  }
120
129
 
130
+ // Auto-absorb button toolbar (btn-split-auto-absorb.js) hosted in a header,
131
+ // nested inside `.pa-card__actions`: prioritise the ACTIONS over the title.
132
+ // The toolbar must stay shrinkable so the JS can read `scrollWidth >
133
+ // clientWidth` and decide what to fold — but the title has to yield FIRST.
134
+ // Otherwise a long title and the toolbar share the deficit by proportional
135
+ // flex-shrink (weighted by the title's *natural* width), so the toolbar is
136
+ // allocated less width than its content even while the rendered title
137
+ // truncates and leaves a visible gap — and the split button folds all the
138
+ // way down to a lone toggle. A large shrink factor makes the title absorb
139
+ // nearly all the deficit (truncating to the min-width floor) so the toolbar
140
+ // keeps its buttons; siblings only begin folding once the title bottoms out
141
+ // at the floor. Matched as a descendant (not `> `) because the toolbar sits
142
+ // one level down, inside `.pa-card__actions`.
143
+ &:has(.pa-btn-toolbar) > h1,
144
+ &:has(.pa-btn-toolbar) > h2,
145
+ &:has(.pa-btn-toolbar) > h3,
146
+ &:has(.pa-btn-toolbar) > h4,
147
+ &:has(.pa-btn-toolbar) > h5,
148
+ &:has(.pa-btn-toolbar) > h6,
149
+ &:has(.pa-btn-toolbar) > .pa-card__title {
150
+ flex-shrink: 9999;
151
+ min-width: 8rem;
152
+ }
153
+
154
+ // The actions wrapper hosting the toolbar must itself be shrinkable.
155
+ // `.pa-card__actions` defaults to `flex-shrink: 0` (above) so it holds its
156
+ // natural width — which would keep the toolbar inside at natural width too,
157
+ // and the `scrollWidth > clientWidth` signal would never fire. Let it
158
+ // shrink (`min-width: 0`) so the deficit propagates down to the toolbar,
159
+ // which keeps the `overflow: hidden` clip. `:has()` scopes this so ordinary
160
+ // action wrappers stay fixed-width.
161
+ .pa-card__actions:has(> .pa-btn-toolbar) {
162
+ flex-shrink: 1;
163
+ min-width: 0;
164
+ }
165
+
121
166
  // Buttons in card headers - negative margin to prevent header height growth
122
167
  .pa-btn {
123
168
  margin-top: -0.25rem;
@@ -125,6 +170,27 @@
125
170
  flex-shrink: 0;
126
171
  }
127
172
 
173
+ // …but any actions wrapper that CLIPS its overflow — the auto-absorb
174
+ // button toolbar and the progressive-overflow actions container both
175
+ // set `overflow: hidden` so the JS can read `scrollWidth > clientWidth` —
176
+ // would shave the top/bottom borders off those buttons: the -0.25rem
177
+ // block margin above pushes each button past the wrapper's content box,
178
+ // and the clip lands right on the border. Re-parent the compaction onto
179
+ // the wrapper so its clip edge is flush with the button box; the header
180
+ // still gets the same height reduction, borders survive. Scoped under
181
+ // `&__header` so a standalone `.pa-btn-toolbar` (used outside a card
182
+ // header) is untouched.
183
+ .pa-btn-toolbar,
184
+ .pa-card__actions--overflow {
185
+ margin-top: -0.25rem;
186
+ margin-bottom: -0.25rem;
187
+
188
+ .pa-btn {
189
+ margin-top: 0;
190
+ margin-bottom: 0;
191
+ }
192
+ }
193
+
128
194
  // Underline modifier - accent border under heading inside card header
129
195
  &--underlined {
130
196
  h1, h2, h3, h4, h5, h6 {
@@ -186,13 +252,18 @@
186
252
  &--wrap {
187
253
  flex-wrap: wrap;
188
254
 
189
- > h1, > h2, > h3, > h4, > h5, > h6 {
255
+ // Un-truncate both the bare-heading shorthand AND the canonical
256
+ // `.pa-card__title` > `.pa-card__title-text` so titles wrap (not
257
+ // ellipsis) in wrap mode regardless of which header shape is used.
258
+ > h1, > h2, > h3, > h4, > h5, > h6,
259
+ > .pa-card__title .pa-card__title-text {
190
260
  white-space: normal;
191
261
  overflow: visible;
192
262
  text-overflow: clip;
193
263
  }
194
264
 
195
- > p {
265
+ > p,
266
+ > .pa-card__description {
196
267
  white-space: normal;
197
268
  flex-basis: 100%;
198
269
  order: 1;
@@ -206,7 +277,11 @@
206
277
  align-items: center;
207
278
  gap: $spacing-sm;
208
279
  min-width: 0; // Enable text truncation
209
- flex: 1;
280
+ // Natural width (like a bare heading), shrinkable, no grow — so a sibling
281
+ // `.pa-card__description` gets the free space instead of the title hogging
282
+ // half the row. `justify-content: space-between` on the header still pins
283
+ // `.pa-card__actions` to the right.
284
+ flex: 0 1 auto;
210
285
 
211
286
  &-icon {
212
287
  flex-shrink: 0;
@@ -222,7 +297,9 @@
222
297
  color: var(--pa-text-color-1);
223
298
  font-size: $font-size-base;
224
299
  font-weight: $font-weight-semibold;
225
- line-height: 1;
300
+ // Not `1` — line-height 1 clips glyph descenders (g, y, p) under
301
+ // `overflow: hidden`. Matches the room bare headings already leave.
302
+ line-height: 1.4;
226
303
  }
227
304
  }
228
305
 
@@ -249,6 +326,18 @@
249
326
  display: flex;
250
327
  justify-content: space-between;
251
328
  align-items: center;
329
+ gap: $spacing-sm;
330
+
331
+ // Canonical footer content model (mirrors the header): optional leading
332
+ // content on the left — text or `.pa-card__meta` — plus `.pa-card__actions`
333
+ // on the right. The auto inline-start margin pins the actions slot to the
334
+ // trailing edge whether or not there's leading content, so an actions-only
335
+ // footer no longer needs an empty spacer `<div>` to fight `space-between`.
336
+ // Buttons live inside `.pa-card__actions` (the same slot as the header) so
337
+ // they never scatter to opposite corners the way bare footer buttons do.
338
+ .pa-card__actions {
339
+ margin-inline-start: auto;
340
+ }
252
341
  }
253
342
 
254
343
  &__actions {
@@ -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
+ }