@foxeltech/angular-ui 0.7.124 → 0.7.131

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": "@foxeltech/angular-ui",
3
- "version": "0.7.124",
3
+ "version": "0.7.131",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -361,11 +361,12 @@ input[type='password'] {
361
361
  inset 0 0 0 1px rgb(0 0 0 / 0.08),
362
362
  0 1px 2px rgb(0 0 0 / 0.12);
363
363
  }
364
- /* Icon-only button (no label): square h-8 × w-8, no side padding, so the
365
- glyph sits dead-centre (anh Tú 04/09). Consumers may still size it with
366
- utilities (`w-9 h-9`) those win in the utilities layer. */
364
+ /* Icon-only button (no label): square, no side padding, so the glyph sits
365
+ dead-centre (anh Tú 04/09). The width tracks `btn-common`'s height — 27px
366
+ since 17/09so it stays square; consumers may still size it with
367
+ utilities (`w-9 h-9`), which win in the utilities layer. */
367
368
  .fx-btn--icon {
368
- width: 2rem;
369
+ width: 27px;
369
370
  padding-left: 0;
370
371
  padding-right: 0;
371
372
  }
@@ -8,10 +8,15 @@
8
8
  }
9
9
 
10
10
  @utility btn-common {
11
- /* Compact size (anh Tú 29/08): h-8 + 13px label the pre-V2 h-10 read too
12
- large against the V2 density. leading-none: arbitrary text-[13px] inherits
13
- lh 1.5 and Archivo's uneven leading floats the ink ~1px above center. */
14
- @apply flex text-[13px] leading-none h-8 font-semibold px-large py-small items-center justify-center rounded-lg shadow-sm transition-all duration-200 disabled:opacity-50 disabled:pointer-events-none disabled:cursor-not-allowed;
11
+ /* The demo's `.og-button--sm` (anh Tú 17/09: compact như New Analysis)
12
+ 27px tall, 11.5px at weight 400, 12px sides, 7px radius. MEASURED off the
13
+ reference's own `.og-button--sm.bi-newbtn`, which is the topbar CTA: it
14
+ wore this shape through `!` overrides because the shared button was a size
15
+ above it. The h-8 / 13px / 600 this replaces was itself a step down from
16
+ pre-V2 h-10 (29/08); against V2 panel density it still read one notch
17
+ heavy. leading-none: an arbitrary font-size inherits lh 1.5 and Archivo's
18
+ uneven leading floats the ink ~1px above centre. */
19
+ @apply flex text-[length:var(--og-fs-xs)] leading-none h-[27px] font-normal px-[12px] py-[4px] items-center justify-center rounded-control shadow-sm transition-all duration-200 disabled:opacity-50 disabled:pointer-events-none disabled:cursor-not-allowed;
15
20
  }
16
21
 
17
22
  @utility btn-menu-common {
@@ -14,229 +14,41 @@
14
14
  [disabled]="disabled() || loading()"
15
15
  (click)="onClick()"
16
16
  >
17
- @if (loading()) {
18
- <div class="flex w-full items-center justify-center" aria-hidden="true">
19
- <svg
20
- [attr.fill]="
21
- buttonVariant() !== 'alternative' ? 'rgb(var(--text-primary))' : 'rgb(var(--primary))'
22
- "
23
- width="16"
24
- height="16"
25
- viewBox="0 0 24 24"
26
- xmlns="http://www.w3.org/2000/svg"
27
- >
28
- <circle cx="4" cy="12" r="0">
29
- <animate
30
- begin="0;spinner_z0Or.end"
31
- attributeName="r"
32
- calcMode="spline"
33
- dur="0.5s"
34
- keySplines=".36,.6,.31,1"
35
- values="0;3"
36
- fill="freeze"
37
- />
38
- <animate
39
- begin="spinner_OLMs.end"
40
- attributeName="cx"
41
- calcMode="spline"
42
- dur="0.5s"
43
- keySplines=".36,.6,.31,1"
44
- values="4;12"
45
- fill="freeze"
46
- />
47
- <animate
48
- begin="spinner_UHR2.end"
49
- attributeName="cx"
50
- calcMode="spline"
51
- dur="0.5s"
52
- keySplines=".36,.6,.31,1"
53
- values="12;20"
54
- fill="freeze"
55
- />
56
- <animate
57
- id="spinner_lo66"
58
- begin="spinner_Aguh.end"
59
- attributeName="r"
60
- calcMode="spline"
61
- dur="0.5s"
62
- keySplines=".36,.6,.31,1"
63
- values="3;0"
64
- fill="freeze"
65
- />
66
- <animate
67
- id="spinner_z0Or"
68
- begin="spinner_lo66.end"
69
- attributeName="cx"
70
- dur="0.001s"
71
- values="20;4"
72
- fill="freeze"
73
- />
74
- </circle>
75
- <circle cx="4" cy="12" r="3">
76
- <animate
77
- begin="0;spinner_z0Or.end"
78
- attributeName="cx"
79
- calcMode="spline"
80
- dur="0.5s"
81
- keySplines=".36,.6,.31,1"
82
- values="4;12"
83
- fill="freeze"
84
- />
85
- <animate
86
- begin="spinner_OLMs.end"
87
- attributeName="cx"
88
- calcMode="spline"
89
- dur="0.5s"
90
- keySplines=".36,.6,.31,1"
91
- values="12;20"
92
- fill="freeze"
93
- />
94
- <animate
95
- id="spinner_JsnR"
96
- begin="spinner_UHR2.end"
97
- attributeName="r"
98
- calcMode="spline"
99
- dur="0.5s"
100
- keySplines=".36,.6,.31,1"
101
- values="3;0"
102
- fill="freeze"
103
- />
104
- <animate
105
- id="spinner_Aguh"
106
- begin="spinner_JsnR.end"
107
- attributeName="cx"
108
- dur="0.001s"
109
- values="20;4"
110
- fill="freeze"
111
- />
112
- <animate
113
- begin="spinner_Aguh.end"
114
- attributeName="r"
115
- calcMode="spline"
116
- dur="0.5s"
117
- keySplines=".36,.6,.31,1"
118
- values="0;3"
119
- fill="freeze"
120
- />
121
- </circle>
122
- <circle cx="12" cy="12" r="3">
123
- <animate
124
- begin="0;spinner_z0Or.end"
125
- attributeName="cx"
126
- calcMode="spline"
127
- dur="0.5s"
128
- keySplines=".36,.6,.31,1"
129
- values="12;20"
130
- fill="freeze"
131
- />
132
- <animate
133
- id="spinner_hSjk"
134
- begin="spinner_OLMs.end"
135
- attributeName="r"
136
- calcMode="spline"
137
- dur="0.5s"
138
- keySplines=".36,.6,.31,1"
139
- values="3;0"
140
- fill="freeze"
141
- />
142
- <animate
143
- id="spinner_UHR2"
144
- begin="spinner_hSjk.end"
145
- attributeName="cx"
146
- dur="0.001s"
147
- values="20;4"
148
- fill="freeze"
149
- />
150
- <animate
151
- begin="spinner_UHR2.end"
152
- attributeName="r"
153
- calcMode="spline"
154
- dur="0.5s"
155
- keySplines=".36,.6,.31,1"
156
- values="0;3"
157
- fill="freeze"
158
- />
159
- <animate
160
- begin="spinner_Aguh.end"
161
- attributeName="cx"
162
- calcMode="spline"
163
- dur="0.5s"
164
- keySplines=".36,.6,.31,1"
165
- values="4;12"
166
- fill="freeze"
167
- />
168
- </circle>
169
- <circle cx="20" cy="12" r="3">
170
- <animate
171
- id="spinner_4v5M"
172
- begin="0;spinner_z0Or.end"
173
- attributeName="r"
174
- calcMode="spline"
175
- dur="0.5s"
176
- keySplines=".36,.6,.31,1"
177
- values="3;0"
178
- fill="freeze"
179
- />
180
- <animate
181
- id="spinner_OLMs"
182
- begin="spinner_4v5M.end"
183
- attributeName="cx"
184
- dur="0.001s"
185
- values="20;4"
186
- fill="freeze"
187
- />
188
- <animate
189
- begin="spinner_OLMs.end"
190
- attributeName="r"
191
- calcMode="spline"
192
- dur="0.5s"
193
- keySplines=".36,.6,.31,1"
194
- values="0;3"
195
- fill="freeze"
196
- />
197
- <animate
198
- begin="spinner_UHR2.end"
199
- attributeName="cx"
200
- calcMode="spline"
201
- dur="0.5s"
202
- keySplines=".36,.6,.31,1"
203
- values="4;12"
204
- fill="freeze"
205
- />
206
- <animate
207
- begin="spinner_Aguh.end"
208
- attributeName="cx"
209
- calcMode="spline"
210
- dur="0.5s"
211
- keySplines=".36,.6,.31,1"
212
- values="12;20"
213
- fill="freeze"
214
- />
215
- </circle>
216
- </svg>
217
- </div>
218
- } @else {
219
- <ng-container>
220
- <div class="flex items-center justify-center gap-small">
221
- @if (icon) {
222
- <fx-ui-hero-icon
223
- [icon]="icon"
224
- [size]="16"
225
- class="flex"
226
- [ngClass]="{
227
- 'text-text-inverse': buttonVariant() === 'default',
228
- 'text-text-primary': buttonVariant() === 'alternative',
229
- 'text-accent-contrast': buttonVariant() === 'primary',
230
- 'text-surface': buttonVariant() === 'success',
231
- 'text-white': buttonVariant() === 'cta',
232
- }"
233
- ></fx-ui-hero-icon>
234
- }
235
- @if (label) {
236
- <!-- text-box: optical centering — Archivo's leading floats ink up otherwise -->
237
- <div class="[text-box:trim-both_cap_alphabetic]">{{ label }}</div>
238
- }
239
- </div>
240
- </ng-container>
241
- }
17
+ <!-- Loading keeps the LABEL, as the sign-in button does: a button that
18
+ swaps its text for a spinner collapses to a stub, and the row jumps.
19
+ The ring is that button's `.li-spin`, in the foreground the variant
20
+ already uses for its icon so it reads on a coloured ground. -->
21
+ <!-- 6px, the reference button's own gap; `gap-small` is 4px. -->
22
+ <div class="flex items-center justify-center gap-[6px]">
23
+ @if (loading()) {
24
+ <span
25
+ class="fx-btn__spin"
26
+ aria-hidden="true"
27
+ [ngClass]="{
28
+ 'text-text-inverse': buttonVariant() === 'default',
29
+ 'text-text-primary': buttonVariant() === 'alternative',
30
+ 'text-accent-contrast': buttonVariant() === 'primary',
31
+ 'text-surface': buttonVariant() === 'success',
32
+ 'text-white': buttonVariant() === 'cta',
33
+ }"
34
+ ></span>
35
+ } @else if (icon) {
36
+ <fx-ui-hero-icon
37
+ [icon]="icon"
38
+ [size]="13"
39
+ class="flex"
40
+ [ngClass]="{
41
+ 'text-text-inverse': buttonVariant() === 'default',
42
+ 'text-text-primary': buttonVariant() === 'alternative',
43
+ 'text-accent-contrast': buttonVariant() === 'primary',
44
+ 'text-surface': buttonVariant() === 'success',
45
+ 'text-white': buttonVariant() === 'cta',
46
+ }"
47
+ ></fx-ui-hero-icon>
48
+ }
49
+ @if (label) {
50
+ <!-- text-box: optical centering — Archivo's leading floats ink up otherwise -->
51
+ <div class="[text-box:trim-both_cap_alphabetic]">{{ label }}</div>
52
+ }
53
+ </div>
242
54
  </button>
@@ -0,0 +1,30 @@
1
+
2
+
3
+ /* Loading ring — the sign-in button's `.li-spin`, sized to sit beside a label.
4
+ `currentColor` so the variant's own foreground class colours it. */
5
+ .fx-btn__spin {
6
+ display: inline-block;
7
+ /* 12px, matching the button's 13px icon — 14 crowded the 27px box. */
8
+ width: 12px;
9
+ height: 12px;
10
+ flex: 0 0 auto;
11
+ border-radius: 50%;
12
+ border: 2px solid currentColor;
13
+ border-top-color: transparent;
14
+ opacity: 0.9;
15
+ animation: fx-btn-spin 0.8s linear infinite;
16
+ }
17
+
18
+ @keyframes fx-btn-spin {
19
+ to {
20
+ transform: rotate(360deg);
21
+ }
22
+ }
23
+
24
+ /* A ring that has stopped still marks the button as busy, and `aria-busy`
25
+ carries the state regardless. */
26
+ @media (prefers-reduced-motion: reduce) {
27
+ .fx-btn__spin {
28
+ animation: none;
29
+ }
30
+ }
@@ -73,9 +73,21 @@
73
73
  min-height: 420px;
74
74
  }
75
75
 
76
- /* Panes CO GIÃN: facets/list nhường chỗ để cụm detail luôn sàn 400px.
77
- `--fx-md-list-width` (input `listWidth`) giờ bề rộng MONG MUỐN kiêm
78
- tối đa của cụm list, không còn con số cứng. */
76
+ /* Track widths are the DESIGN'S own: every three-column screen in the demo
77
+ bundle is `204px minmax(0,1fr) 340px` measured on Results, License and
78
+ Relationships, 17/09. So the rail and the DETAIL are the fixed tracks and
79
+ the LIST takes what is left.
80
+
81
+ It used to be the other way round: the list was capped at 420px and the
82
+ detail was `flex: 1 1 360px`, so every pixel of a wide window went to the
83
+ reading pane — ~930px of it at 1920, against a list that never grew past
84
+ 420 (anh Tú 17/09: kéo rộng cột list ra và thu nhỏ cột detail lại).
85
+
86
+ All three still SHRINK below their track (`flex-basis` + a floor, not a
87
+ hard width): with the rail open the three floors add up past the 720px
88
+ where this query starts, and a pane that refuses to give way would push
89
+ the frame into a horizontal scrollbar instead. Collapsed, the rail is
90
+ 40px and 40 + 260 + 300 fits. */
79
91
  /* Hairline to the RIGHT of rail and list instead of below. */
80
92
  .fx-md-facets,
81
93
  .fx-md-list {
@@ -91,10 +103,10 @@
91
103
  max-width: 40px;
92
104
  }
93
105
  .fx-md-facets--open {
94
- flex: 0 1 230px;
106
+ flex: 0 1 204px;
95
107
  width: auto;
96
- min-width: 200px;
97
- max-width: 260px;
108
+ min-width: 180px;
109
+ max-width: 204px;
98
110
  }
99
111
  .fx-md-rail-toggle {
100
112
  height: 100%;
@@ -109,14 +121,30 @@
109
121
 
110
122
  .fx-md-list {
111
123
  width: auto;
112
- flex: 0 1 var(--fx-md-list-width, 420px);
124
+ flex: 1 1 0;
113
125
  min-width: 260px;
114
- max-width: var(--fx-md-list-width, 420px);
126
+ /* Uncapped unless a caller asks for one — see the `listWidth` input. */
127
+ max-width: var(--fx-md-list-width, none);
115
128
  }
116
129
 
117
130
  .fx-md-detail {
131
+ width: auto;
132
+ flex: 0 1 var(--fx-md-detail-width, 340px);
133
+ min-width: 300px;
134
+ max-width: var(--fx-md-detail-width, 340px);
135
+ }
136
+
137
+ /* `detailWidth="auto"`: the pre-0.7.130 split, kept for the panes that need
138
+ the room (Binaries, Remediation — anh Tú 17/09). The detail takes the
139
+ spare width and the LIST goes back to being the capped one. */
140
+ .fx-md-row--detail-fluid .fx-md-list {
141
+ flex: 0 1 var(--fx-md-list-width, 420px);
142
+ max-width: var(--fx-md-list-width, 420px);
143
+ }
144
+ .fx-md-row--detail-fluid .fx-md-detail {
118
145
  flex: 1 1 360px;
119
146
  min-width: 360px;
147
+ max-width: none;
120
148
  }
121
149
  }
122
150
 
@@ -6,6 +6,8 @@
6
6
  class="fx-md-row flex flex-col items-stretch"
7
7
  [class.fx-md-row--rail-open]="railOpen()"
8
8
  [style.--fx-md-list-width]="listWidth()"
9
+ [class.fx-md-row--detail-fluid]="detailFluid()"
10
+ [style.--fx-md-detail-width]="detailFluid() ? null : detailWidth()"
9
11
  [style.--fx-md-pane-h]="paneHeight()"
10
12
  >
11
13
  <!-- Facets rail — collapsible (» / «), collapsed = 40px strip with the label
@@ -108,7 +110,7 @@
108
110
  <div class="flex gap-small">
109
111
  <button
110
112
  type="button"
111
- class="btn-alternative !h-8 !px-semi text-sm"
113
+ class="btn-alternative"
112
114
  [disabled]="!paginator().hasPreviousPage()"
113
115
  (click)="paginator().previousPage()"
114
116
  >
@@ -116,7 +118,7 @@
116
118
  </button>
117
119
  <button
118
120
  type="button"
119
- class="btn-alternative !h-8 !px-semi text-sm"
121
+ class="btn-alternative"
120
122
  [disabled]="!paginator().hasNextPage()"
121
123
  (click)="paginator().nextPage()"
122
124
  >
@@ -51,14 +51,36 @@ declare class FlowCanvasComponent {
51
51
  readonly height: _angular_core.InputSignal<string>;
52
52
  /** Caller-translated hint shown when the graph is empty. */
53
53
  readonly emptyText: _angular_core.InputSignal<string>;
54
+ /**
55
+ * Work is running against this chain — validation, typically.
56
+ *
57
+ * The edges become a travelling dashed line ("marching ants") so the canvas
58
+ * says something is in flight without a spinner sitting on top of the graph.
59
+ * Purely presentational: the caller owns what "busy" means and when it ends.
60
+ */
61
+ readonly busy: _angular_core.InputSignal<boolean>;
54
62
  readonly nodeClick: _angular_core.OutputEmitterRef<string>;
55
63
  private readonly flow;
56
64
  private readonly host;
57
65
  private readonly destroyRef;
58
66
  constructor();
59
67
  private fitHandle;
60
- /** Coalesces fit requests into one frame after vflow has measured its nodes. */
68
+ /**
69
+ * Coalesces fit requests, then fits TWICE — one frame apart.
70
+ *
71
+ * vflow frames the graph from `getNodesBounds`, which sums each node's
72
+ * `point()` and its `size()`. For an html-template node that size is the
73
+ * MEASURED box and is still 0 on the frame the nodes are created, so the
74
+ * first fit sees a bounds box running origin-to-origin: five 176px cards
75
+ * measured 864px instead of 1040px, and the graph was framed 88px — half a
76
+ * card — too far right, clipping the last one (MEASURED 16/09).
77
+ *
78
+ * The second pass runs once the cards have been laid out and measured, and
79
+ * is what actually frames them. The first is kept so a slow frame still
80
+ * shows something sensible rather than the graph pinned top-left.
81
+ */
61
82
  private scheduleFit;
83
+ private fit;
62
84
  /** Column index per node: pinned value, else longest path from a source. */
63
85
  private readonly columns;
64
86
  /** ngx-vflow nodes: html-template cards positioned by the derived layout. */
@@ -86,7 +108,7 @@ declare class FlowCanvasComponent {
86
108
  isEdgeActive(edge: Edge): boolean;
87
109
  isEdgeDimmed(edge: Edge): boolean;
88
110
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlowCanvasComponent, never>;
89
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlowCanvasComponent, "fx-ui-flow-canvas", never, { "nodes": { "alias": "nodes"; "required": false; "isSignal": true; }; "edges": { "alias": "edges"; "required": false; "isSignal": true; }; "activeId": { "alias": "activeId"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; }, { "nodeClick": "nodeClick"; }, never, never, true, never>;
111
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlowCanvasComponent, "fx-ui-flow-canvas", never, { "nodes": { "alias": "nodes"; "required": false; "isSignal": true; }; "edges": { "alias": "edges"; "required": false; "isSignal": true; }; "activeId": { "alias": "activeId"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "busy": { "alias": "busy"; "required": false; "isSignal": true; }; }, { "nodeClick": "nodeClick"; }, never, never, true, never>;
90
112
  }
91
113
 
92
114
  declare class FlowConnection {
@@ -2097,8 +2097,27 @@ declare class MasterDetailComponent implements AfterViewInit, AfterContentInit {
2097
2097
  /** True when the host projected a [mdFacets] block — switches to 3 columns. */
2098
2098
  hasFacets: boolean;
2099
2099
  table: BaseMasterDetailComponent<any>;
2100
- /** Fixed list-pane width on lg+ viewports (stacked full-width below). */
2101
- readonly listWidth: _angular_core.InputSignal<string>;
2100
+ /**
2101
+ * Optional CAP on the list pane.
2102
+ *
2103
+ * The list is the flexible track now (the design's `204px 1fr 340px`), so it
2104
+ * takes whatever the rail and the detail leave. Set this only for a screen
2105
+ * whose rows genuinely stop reading better past some width; left unset the
2106
+ * property is not emitted at all and the pane simply fills.
2107
+ */
2108
+ readonly listWidth: _angular_core.InputSignal<string | null>;
2109
+ /**
2110
+ * The detail pane's fixed track — the design's own 340px, and 450px on the
2111
+ * screens anh Tú widened (17/09).
2112
+ *
2113
+ * Pass `'auto'` (or null) to give the detail the SPARE width instead and cap
2114
+ * the list at `listWidth` — the pre-0.7.130 behaviour, which Binaries and
2115
+ * Remediation keep because their panes carry header blocks, metric grids and
2116
+ * step lists that a narrow track cannot hold.
2117
+ */
2118
+ readonly detailWidth: _angular_core.InputSignal<string | null>;
2119
+ /** true = detail takes the spare width; false = it is a fixed track. */
2120
+ protected detailFluid(): boolean;
2102
2121
  /**
2103
2122
  * Chiều cao CHUNG của cả ba cụm (facets / list / detail). Mặc định trừ phần
2104
2123
  * chrome phía trên (topbar + tab strip + context line) khỏi viewport để
@@ -2144,7 +2163,7 @@ declare class MasterDetailComponent implements AfterViewInit, AfterContentInit {
2144
2163
  optionId(index: number): string;
2145
2164
  onKeydown(event: KeyboardEvent, index: number): void;
2146
2165
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MasterDetailComponent, never>;
2147
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MasterDetailComponent, "fx-ui-master-detail", never, { "table": { "alias": "table"; "required": false; }; "listWidth": { "alias": "listWidth"; "required": false; "isSignal": true; }; "paneHeight": { "alias": "paneHeight"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "listLabel": { "alias": "listLabel"; "required": false; "isSignal": true; }; "skeletonCards": { "alias": "skeletonCards"; "required": false; "isSignal": true; }; "paginationStyle": { "alias": "paginationStyle"; "required": false; "isSignal": true; }; "prevLabel": { "alias": "prevLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; "pageLabel": { "alias": "pageLabel"; "required": false; "isSignal": true; }; "ofLabel": { "alias": "ofLabel"; "required": false; "isSignal": true; }; "facetsOpen": { "alias": "facetsOpen"; "required": false; "isSignal": true; }; "facetsLabel": { "alias": "facetsLabel"; "required": false; "isSignal": true; }; "expandFacetsLabel": { "alias": "expandFacetsLabel"; "required": false; "isSignal": true; }; "collapseFacetsLabel": { "alias": "collapseFacetsLabel"; "required": false; "isSignal": true; }; }, {}, ["rowTemplate", "detailTemplate"], ["[mdFacets]", "[mdHeader]", "[mdFilters]"], true, never>;
2166
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MasterDetailComponent, "fx-ui-master-detail", never, { "table": { "alias": "table"; "required": false; }; "listWidth": { "alias": "listWidth"; "required": false; "isSignal": true; }; "detailWidth": { "alias": "detailWidth"; "required": false; "isSignal": true; }; "paneHeight": { "alias": "paneHeight"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "listLabel": { "alias": "listLabel"; "required": false; "isSignal": true; }; "skeletonCards": { "alias": "skeletonCards"; "required": false; "isSignal": true; }; "paginationStyle": { "alias": "paginationStyle"; "required": false; "isSignal": true; }; "prevLabel": { "alias": "prevLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; "pageLabel": { "alias": "pageLabel"; "required": false; "isSignal": true; }; "ofLabel": { "alias": "ofLabel"; "required": false; "isSignal": true; }; "facetsOpen": { "alias": "facetsOpen"; "required": false; "isSignal": true; }; "facetsLabel": { "alias": "facetsLabel"; "required": false; "isSignal": true; }; "expandFacetsLabel": { "alias": "expandFacetsLabel"; "required": false; "isSignal": true; }; "collapseFacetsLabel": { "alias": "collapseFacetsLabel"; "required": false; "isSignal": true; }; }, {}, ["rowTemplate", "detailTemplate"], ["[mdFacets]", "[mdHeader]", "[mdFilters]"], true, never>;
2148
2167
  }
2149
2168
 
2150
2169
  interface FxMenuItem {
package/utilities.css CHANGED
@@ -8,10 +8,15 @@
8
8
  }
9
9
 
10
10
  @utility btn-common {
11
- /* Compact size (anh Tú 29/08): h-8 + 13px label the pre-V2 h-10 read too
12
- large against the V2 density. leading-none: arbitrary text-[13px] inherits
13
- lh 1.5 and Archivo's uneven leading floats the ink ~1px above center. */
14
- @apply flex text-[13px] leading-none h-8 font-semibold px-large py-small items-center justify-center rounded-lg shadow-sm transition-all duration-200 disabled:opacity-50 disabled:pointer-events-none disabled:cursor-not-allowed;
11
+ /* The demo's `.og-button--sm` (anh Tú 17/09: compact như New Analysis)
12
+ 27px tall, 11.5px at weight 400, 12px sides, 7px radius. MEASURED off the
13
+ reference's own `.og-button--sm.bi-newbtn`, which is the topbar CTA: it
14
+ wore this shape through `!` overrides because the shared button was a size
15
+ above it. The h-8 / 13px / 600 this replaces was itself a step down from
16
+ pre-V2 h-10 (29/08); against V2 panel density it still read one notch
17
+ heavy. leading-none: an arbitrary font-size inherits lh 1.5 and Archivo's
18
+ uneven leading floats the ink ~1px above centre. */
19
+ @apply flex text-[length:var(--og-fs-xs)] leading-none h-[27px] font-normal px-[12px] py-[4px] items-center justify-center rounded-control shadow-sm transition-all duration-200 disabled:opacity-50 disabled:pointer-events-none disabled:cursor-not-allowed;
15
20
  }
16
21
 
17
22
  @utility btn-menu-common {