@elasticias/ui 1.0.43 → 1.0.45

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elasticias/ui",
3
- "version": "1.0.43",
3
+ "version": "1.0.45",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^21.0.0",
6
6
  "@angular/core": "^21.0.0",
@@ -115,6 +115,15 @@
115
115
  --hit-touch: 48px; /* POS / mobile primary actions */
116
116
  --hit-pos: 64px; /* POS number pad, big totals */
117
117
 
118
+ /* ── Layers ──────────────────────────────────────────────────── */
119
+ /* Toasts sit above every modal and overlay. PrimeNG numbers its layers
120
+ at runtime (ZIndexUtils): each new layer takes the last one's value
121
+ plus 1, plus the base of its own kind when the kind changes (modal
122
+ 1100, overlay 1000). A dialog is 1101, a select opened inside it
123
+ 2102, a dialog opened over that 3203, so no value near PrimeNG's
124
+ bases stays on top. 100000 is about ninety mixed layers away. */
125
+ --z-toast: 100000;
126
+
118
127
  /* ── Motion ──────────────────────────────────────────────────── */
119
128
  --t-fast: 140ms;
120
129
  --t-base: 260ms;
@@ -1048,11 +1048,20 @@
1048
1048
 
1049
1049
  /* ──────────── PAGER ─────────────────────────────────────────────── */
1050
1050
 
1051
+ /* Both halves wrap and can shrink. A row of controls has an intrinsic
1052
+ min-content width, so a pager that cannot wrap is as wide as its
1053
+ lines-per-page block plus every page button, and the card clips the
1054
+ rest: on a 390px phone, or in a narrow card on a tablet with the side
1055
+ panel open, "next" and the last page were cut off. When the two halves
1056
+ no longer fit on one line the page buttons take their own line, still
1057
+ at the end. */
1051
1058
  .pager {
1052
1059
  display: flex;
1060
+ flex-wrap: wrap;
1053
1061
  justify-content: space-between;
1054
1062
  align-items: center;
1055
1063
  gap: var(--s-3);
1064
+ min-width: 0;
1056
1065
  padding: var(--s-3) var(--s-5);
1057
1066
  border-top: 1px solid var(--rule);
1058
1067
  background: var(--paper-alt);
@@ -1060,8 +1069,21 @@
1060
1069
 
1061
1070
  .pager .pages {
1062
1071
  display: flex;
1072
+ flex-wrap: wrap;
1063
1073
  align-items: center;
1064
1074
  gap: 4px;
1075
+ min-width: 0;
1076
+ margin-inline-start: auto;
1077
+ }
1078
+
1079
+ /* The phone pager's "5 sur 20", between previous and next. */
1080
+ .pager .pg-status {
1081
+ padding: 0 8px;
1082
+ font-size: 12.5px;
1083
+ font-weight: 600;
1084
+ color: var(--text);
1085
+ font-variant-numeric: tabular-nums;
1086
+ white-space: nowrap;
1065
1087
  }
1066
1088
 
1067
1089
  .pager .pg {
@@ -1090,7 +1112,9 @@
1090
1112
 
1091
1113
  .pager .size {
1092
1114
  display: flex;
1115
+ flex-wrap: wrap;
1093
1116
  align-items: center;
1117
+ min-width: 0;
1094
1118
  gap: 8px;
1095
1119
  font-size: 12.5px;
1096
1120
  color: var(--text-mute);
@@ -1515,11 +1539,17 @@
1515
1539
  }
1516
1540
 
1517
1541
  .row-actions__trigger {
1542
+ /* Read again by the touch tier, which reserves the 48px footprint
1543
+ around this box. */
1544
+ --ef-row-trigger-w: 34px;
1545
+ --ef-row-trigger-h: 28px;
1518
1546
  appearance: none;
1519
1547
  background: var(--paper-alt);
1520
1548
  border: 1px solid var(--rule);
1521
- width: 34px;
1522
- height: 28px;
1549
+ box-sizing: border-box;
1550
+ width: var(--ef-row-trigger-w);
1551
+ height: var(--ef-row-trigger-h);
1552
+ flex-shrink: 0;
1523
1553
  border-radius: var(--r-pill);
1524
1554
  display: inline-grid;
1525
1555
  place-items: center;
@@ -2219,6 +2249,15 @@
2219
2249
  line-height: 1;
2220
2250
  }
2221
2251
 
2252
+ /* The back and month arrows are icon-font glyphs, which bidi never
2253
+ mirrors. In Arabic the header runs right to left, so "previous" sits on
2254
+ the right and must point right. (Text arrows such as the pager's
2255
+ ‹ › « » are Bidi_Mirrored and already flip on their own.) */
2256
+ [dir='rtl'] .dp__back i,
2257
+ [dir='rtl'] .dp__cal-nav i {
2258
+ transform: scaleX(-1);
2259
+ }
2260
+
2222
2261
  .dp__cal-title {
2223
2262
  display: inline-flex;
2224
2263
  align-items: center;
@@ -2495,7 +2534,10 @@
2495
2534
  position: fixed;
2496
2535
  top: var(--s-4);
2497
2536
  inset-inline-end: var(--s-4);
2498
- z-index: 1000;
2537
+ /* Above every PrimeNG modal mask and overlay, so an error raised by a
2538
+ dialog's save is readable and its ✕ clickable while the dialog is
2539
+ open. The token explains the number. */
2540
+ z-index: var(--z-toast);
2499
2541
  display: grid;
2500
2542
  gap: var(--s-2);
2501
2543
  align-content: start;
@@ -3569,6 +3611,9 @@ input.ef-input[type='number'] {
3569
3611
 
3570
3612
  .es.p-select,
3571
3613
  .es.p-multiselect {
3614
+ /* The gap between label, clear ✕ and caret. The touch tier reads it to
3615
+ keep the ✕'s 48px target between the label and the caret. */
3616
+ --es-gap: 10px;
3572
3617
  width: 100%;
3573
3618
  min-width: 200px;
3574
3619
  background: var(--paper-alt);
@@ -3578,7 +3623,7 @@ input.ef-input[type='number'] {
3578
3623
  padding: 0 10px 0 14px;
3579
3624
  display: inline-flex;
3580
3625
  align-items: center;
3581
- gap: 10px;
3626
+ gap: var(--es-gap);
3582
3627
  color: var(--text);
3583
3628
  font-size: 14px;
3584
3629
  cursor: pointer;
@@ -3662,11 +3707,14 @@ input.ef-input[type='number'] {
3662
3707
  clearable control (input, number, select, typeahead) is identical. */
3663
3708
  .ef-clear,
3664
3709
  .es .es-clear {
3710
+ /* One size, read again by the touch tier below to size the target and
3711
+ the space it reserves, so the two cannot drift apart. */
3712
+ --ef-clear-size: 22px;
3665
3713
  display: inline-grid;
3666
3714
  place-items: center;
3667
3715
  box-sizing: border-box;
3668
- width: 22px;
3669
- height: 22px;
3716
+ width: var(--ef-clear-size);
3717
+ height: var(--ef-clear-size);
3670
3718
  border: 0;
3671
3719
  padding: 0;
3672
3720
  background: transparent;
@@ -4585,10 +4633,75 @@ input.ef-input[type='number'] {
4585
4633
  min-inline-size: var(--hit-touch);
4586
4634
  }
4587
4635
 
4636
+ /* The row ⋯ trigger and the clear ✕ draw at their desktop size (34x28
4637
+ pill, 22px circle) and reach the 48px tier through an invisible
4638
+ overhang, like the top-bar icons. Growing the painted box instead
4639
+ turned every row's ⋯ into a 48px bordered circle.
4640
+
4641
+ The margin reserves the same 48x48 the old rule laid out, so rows,
4642
+ cards and inputs keep their height and spacing, and the overhang
4643
+ never leaves that box: two triggers in adjacent compact rows cannot
4644
+ overlap, because each target is the footprint its own row already
4645
+ made room for. The trigger's overhang adds its 1px border, since an
4646
+ absolute box is measured from the padding edge. */
4588
4647
  .row-actions__trigger,
4589
4648
  .ef-clear,
4590
- .pg {
4591
- inline-size: var(--hit-touch);
4649
+ .es .es-clear {
4650
+ position: relative;
4651
+ }
4652
+
4653
+ .row-actions__trigger {
4654
+ margin-block: calc((var(--hit-touch) - var(--ef-row-trigger-h)) / 2);
4655
+ margin-inline: calc((var(--hit-touch) - var(--ef-row-trigger-w)) / 2);
4656
+ }
4657
+
4658
+ .ef-clear {
4659
+ margin: calc((var(--hit-touch) - var(--ef-clear-size)) / 2);
4660
+ }
4661
+
4662
+ /* The select / multiselect ✕ sits in the trigger's flex row, between the
4663
+ label and the caret, 10px (--es-gap) from each. It reserves only the
4664
+ inline room its 48px target still lacks after that gap, so the target
4665
+ ends exactly at the label's edge and at the caret's, and a tap on the
4666
+ caret opens the panel instead of clearing the value. No block margin:
4667
+ the trigger is 40px whether it holds a value or not, and the target's
4668
+ extra 4px above and below overhangs the trigger the way the input ✕
4669
+ does. */
4670
+ .es .es-clear {
4671
+ margin-inline: calc((var(--hit-touch) - var(--ef-clear-size)) / 2 - var(--es-gap));
4672
+ }
4673
+
4674
+ .row-actions__trigger::after,
4675
+ .ef-clear::after,
4676
+ .es .es-clear::after {
4677
+ content: '';
4678
+ position: absolute;
4679
+ }
4680
+
4681
+ /* A fixed 48px box centred on the trigger, not an inset derived from
4682
+ its size. The inset version measured from the padding edge and from
4683
+ whatever size the row laid the trigger out at, and a phone row drew a
4684
+ 47.75px-wide target. The centred box is 48x48 whatever the painted
4685
+ size, border or sub-pixel layout. */
4686
+ .row-actions__trigger::after {
4687
+ top: 50%;
4688
+ left: 50%;
4689
+ width: max(var(--hit-touch), 100%);
4690
+ height: max(var(--hit-touch), 100%);
4691
+ transform: translate(-50%, -50%);
4692
+ }
4693
+
4694
+ .ef-clear::after,
4695
+ .es .es-clear::after {
4696
+ inset: calc((var(--hit-touch) - var(--ef-clear-size)) / -2);
4697
+ }
4698
+
4699
+ /* Written as `.pager .pg` to match the base rule's specificity: a bare
4700
+ `.pg` lost to its `height: 32px`, so page buttons drew 48px wide but
4701
+ 32px tall on every touch screen. A floor rather than a fixed width,
4702
+ so a four-digit page number is not squeezed. */
4703
+ .pager .pg {
4704
+ min-inline-size: var(--hit-touch);
4592
4705
  block-size: var(--hit-touch);
4593
4706
  }
4594
4707
 
@@ -5194,6 +5194,13 @@ interface PageBtn {
5194
5194
  *
5195
5195
  * Renders a windowed page list (first / current ±1 / last with
5196
5196
  * ellipsis) for total > 7 pages. Below 7 pages all buttons show.
5197
+ *
5198
+ * On a phone (`EfViewportService.isMobile`) the window becomes
5199
+ * first · previous · "5 of 20" · next · last. The window is up to nine
5200
+ * 48px touch targets (about 464px) and a 390px phone has about 316px
5201
+ * inside a card, so it ran off the edge. The compact set still reaches
5202
+ * every page the window offered: its numbered neighbours are one step
5203
+ * away, and the first and the last page are one tap.
5197
5204
  */
5198
5205
  declare class EfPagerComponent {
5199
5206
  readonly pageNumber: _angular_core.InputSignal<number>;
@@ -5205,10 +5212,14 @@ declare class EfPagerComponent {
5205
5212
  readonly ofLabelKey: _angular_core.InputSignal<string>;
5206
5213
  readonly prevLabelKey: _angular_core.InputSignal<string>;
5207
5214
  readonly nextLabelKey: _angular_core.InputSignal<string>;
5215
+ readonly firstLabelKey: _angular_core.InputSignal<string>;
5216
+ readonly lastLabelKey: _angular_core.InputSignal<string>;
5208
5217
  /** Hide the lines-per-page selector + range when only paging is wanted. */
5209
5218
  readonly hideSize: _angular_core.InputSignal<boolean>;
5210
5219
  readonly pageChange: _angular_core.OutputEmitterRef<number>;
5211
5220
  readonly pageSizeChange: _angular_core.OutputEmitterRef<number>;
5221
+ /** Phone layout: first · prev · "n of N" · next · last. */
5222
+ readonly compact: _angular_core.Signal<boolean>;
5212
5223
  /** Falls back to the first configured option if the value ever goes empty. */
5213
5224
  private get defaultSize();
5214
5225
  /** `pageSizeOptions` shaped for `ef-select`, which reads a label and a
@@ -5228,7 +5239,7 @@ declare class EfPagerComponent {
5228
5239
  onSizeChange(value: number | string | null): void;
5229
5240
  trackBtn(index: number, btn: PageBtn): string;
5230
5241
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EfPagerComponent, never>;
5231
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPagerComponent, "ef-pager", never, { "pageNumber": { "alias": "pageNumber"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "linesPerPageLabelKey": { "alias": "linesPerPageLabelKey"; "required": false; "isSignal": true; }; "ofLabelKey": { "alias": "ofLabelKey"; "required": false; "isSignal": true; }; "prevLabelKey": { "alias": "prevLabelKey"; "required": false; "isSignal": true; }; "nextLabelKey": { "alias": "nextLabelKey"; "required": false; "isSignal": true; }; "hideSize": { "alias": "hideSize"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; }, never, never, true, never>;
5242
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EfPagerComponent, "ef-pager", never, { "pageNumber": { "alias": "pageNumber"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "linesPerPageLabelKey": { "alias": "linesPerPageLabelKey"; "required": false; "isSignal": true; }; "ofLabelKey": { "alias": "ofLabelKey"; "required": false; "isSignal": true; }; "prevLabelKey": { "alias": "prevLabelKey"; "required": false; "isSignal": true; }; "nextLabelKey": { "alias": "nextLabelKey"; "required": false; "isSignal": true; }; "firstLabelKey": { "alias": "firstLabelKey"; "required": false; "isSignal": true; }; "lastLabelKey": { "alias": "lastLabelKey"; "required": false; "isSignal": true; }; "hideSize": { "alias": "hideSize"; "required": false; "isSignal": true; }; }, { "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; }, never, never, true, never>;
5232
5243
  }
5233
5244
 
5234
5245
  /**