@geosdi/ngx-ui 0.0.0-stage → 1.1.0

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
@@ -1,3 +1,816 @@
1
- # Temporary Holding Version
1
+ # @geosdi/ngx-ui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Standalone Angular components and directives for forms, dialogs, notifications, navigation and
4
+ tables. The library uses signals, Angular CDK overlays and local SVG icons. Its `ml-*` selectors
5
+ and `--ml-*` theme tokens can be used in any Angular application; it has no runtime dependency on
6
+ Maplite, PrimeNG, PrimeIcons or PrimeFlex.
7
+
8
+ ## Installation
9
+
10
+ ```sh
11
+ npm i @geosdi/ngx-ui --save
12
+ ```
13
+
14
+ Peer dependencies:
15
+
16
+ ```json
17
+ {
18
+ "@angular/common": ">=22.0.0",
19
+ "@angular/core": ">=22.0.0",
20
+ "@angular/cdk": ">=22.0.0",
21
+ "@angular/forms": ">=22.0.0",
22
+ "rxjs": ">=7.8.0"
23
+ }
24
+ ```
25
+
26
+ The initial implementation is verified with Angular 22. The package also depends on `tslib`.
27
+ No Angular animations provider is required: visual animations use CSS. The package must be built
28
+ and published before the installation command is available from npm.
29
+
30
+ ## Usage
31
+
32
+ Import the standalone components and directives used by each consuming component. There is no
33
+ module to register and the services are provided in root.
34
+
35
+ ```typescript
36
+ import { Component } from "@angular/core";
37
+ import { FormsModule } from "@angular/forms";
38
+ import {
39
+ ButtonDirective,
40
+ InputTextDirective,
41
+ SelectComponent,
42
+ ToastComponent,
43
+ TooltipDirective,
44
+ } from "@geosdi/ngx-ui";
45
+
46
+ @Component({
47
+ selector: "app-example",
48
+ imports: [
49
+ FormsModule,
50
+ ButtonDirective,
51
+ InputTextDirective,
52
+ SelectComponent,
53
+ ToastComponent,
54
+ TooltipDirective,
55
+ ],
56
+ template: `
57
+ <label for="name">Name</label>
58
+ <input id="name" mlInputText [(ngModel)]="name" />
59
+ <ml-select
60
+ [options]="cities"
61
+ optionLabel="label"
62
+ optionValue="id"
63
+ [(ngModel)]="city"
64
+ ariaLabel="City"
65
+ />
66
+ <button mlButton severity="success" [mlTooltip]="'Save changes'">
67
+ Save
68
+ </button>
69
+ <ml-toast />
70
+ `,
71
+ })
72
+ export class ExampleComponent {
73
+ name = "";
74
+ city: number | null = null;
75
+ cities = [
76
+ { id: 1, label: "Rome" },
77
+ { id: 2, label: "Milan" },
78
+ ];
79
+ }
80
+ ```
81
+
82
+ Place one `ml-toast` host in the application shell if notifications are needed. Form controls
83
+ implement `ControlValueAccessor`: import `FormsModule` for `ngModel` or `ReactiveFormsModule`
84
+ for `formControl` / `formControlName`. Plain directives such as `mlInputText` keep the native
85
+ input behavior. The examples do not require layout utility classes.
86
+
87
+ ## Styles and theme
88
+
89
+ Include both global styles in the application's SCSS entry point:
90
+
91
+ ```scss
92
+ @use "@angular/cdk/overlay-prebuilt.css";
93
+ @use "@geosdi/ngx-ui/styles/index";
94
+
95
+ // Overrides must follow the imports.
96
+ :root {
97
+ --ml-primary: #7c3aed;
98
+ --ml-primary-hover: #6d28d9;
99
+ --ml-on-primary: #fff;
100
+ --ml-font-family: Arial, sans-serif;
101
+ --ml-radius: 8px;
102
+ --ml-control-height: 2.75rem;
103
+ }
104
+ ```
105
+
106
+ `styles/index` includes the default theme, a box-sizing reset scoped to `ml-*` classes, SVG
107
+ icons and component styles. The individual `styles/theme`, `styles/base`, `styles/icons` and
108
+ `styles/ui` entry points are also available. Import either the complete entry point or the
109
+ individual files, to avoid emitting the styles twice. No fonts or styles are downloaded at runtime.
110
+
111
+ The default theme is light. The public tokens and their defaults are listed below. Changing
112
+ `--ml-success`, for example, changes the status color; its hover and subtle tokens remain separately
113
+ configurable. Internal variables (`--ml-bg`, `--ml-bg-hover`, `--ml-fg`, `--ml-soft`, `--ml-toast`
114
+ and `--ml-slider-fill`) are implementation details, not theme API.
115
+
116
+ | Token | Default |
117
+ | ------------------------------ | ---------------------------- |
118
+ | `--ml-overlay-z-index` | `1102` |
119
+ | `--ml-toast-z-index` | `1103` |
120
+ | `--ml-primary` | `#06c` |
121
+ | `--ml-primary-hover` | `#004d99` |
122
+ | `--ml-on-primary` | `#fff` |
123
+ | `--ml-info` | `#0059b3` |
124
+ | `--ml-info-hover` | `#004080` |
125
+ | `--ml-surface` | `#fff` |
126
+ | `--ml-surface-muted` | `#f0f3f7` |
127
+ | `--ml-text` | `#19191a` |
128
+ | `--ml-text-secondary` | `#5c6f82` |
129
+ | `--ml-text-heading` | `#17324d` |
130
+ | `--ml-text-muted` | `#768594` |
131
+ | `--ml-control-border` | `#b1b1b3` |
132
+ | `--ml-divider` | `#e3e4e6` |
133
+ | `--ml-focus-color` | `#f90` |
134
+ | `--ml-focus-shadow-color` | `rgb(23 50 77 / 10%)` |
135
+ | `--ml-selection-background` | `rgb(0 102 204 / 6%)` |
136
+ | `--ml-success` | `#008758` |
137
+ | `--ml-warning` | `#a66300` |
138
+ | `--ml-danger` | `#d9364f` |
139
+ | `--ml-radius` | `4px` |
140
+ | `--ml-shadow` | `0 2px 20px rgb(0 0 0 / 7%)` |
141
+ | `--ml-font-family` | `system-ui, sans-serif` |
142
+ | `--ml-secondary-hover` | `#17324d` |
143
+ | `--ml-secondary-subtle` | `rgb(92 111 130 / 8%)` |
144
+ | `--ml-success-hover` | `#006b46` |
145
+ | `--ml-success-subtle` | `rgb(0 135 88 / 8%)` |
146
+ | `--ml-warning-hover` | `#855000` |
147
+ | `--ml-warning-subtle` | `rgb(166 99 0 / 8%)` |
148
+ | `--ml-danger-hover` | `#b72a40` |
149
+ | `--ml-danger-subtle` | `rgb(217 54 79 / 8%)` |
150
+ | `--ml-control-height` | `2.5rem` |
151
+ | `--ml-control-height-small` | `2rem` |
152
+ | `--ml-control-font-size-small` | `0.875rem` |
153
+ | `--ml-button-padding` | `0.5rem 1rem` |
154
+ | `--ml-button-padding-small` | `0.375rem 0.75rem` |
155
+ | `--ml-input-padding` | `0.5rem 0.75rem` |
156
+ | `--ml-toast-enter-duration` | `450ms` |
157
+
158
+ ### Global and runtime themes
159
+
160
+ Apply theme overrides on `:root` or on an ancestor shared by the application and the CDK overlay
161
+ container. Dialogs, tooltips and dropdown panels are mounted outside their triggering component;
162
+ variables set only on that component do not reach the overlay. Independent themes on separate
163
+ subtrees are not supported in this version.
164
+
165
+ A global runtime switch can use a class on `html` without an Angular theme service:
166
+
167
+ ```scss
168
+ :root.brand-violet {
169
+ --ml-primary: #7c3aed;
170
+ --ml-primary-hover: #6d28d9;
171
+ --ml-info: #7c3aed;
172
+ --ml-info-hover: #6d28d9;
173
+ }
174
+ ```
175
+
176
+ Add or remove `brand-violet` on `document.documentElement` in browser code. A dark theme requires
177
+ a complete palette, including surfaces, text, focus and state variants; changing the primary
178
+ color alone does not create a dark theme. A packaged dark preset is not included.
179
+
180
+ ### Application layout
181
+
182
+ Application header heights, map layers and page-specific widths do not belong to the theme.
183
+ For example, an application with a 64px header can place notifications below it:
184
+
185
+ ```scss
186
+ .ml-toast-stack {
187
+ top: calc(64px + 1rem + env(safe-area-inset-top, 0px));
188
+ }
189
+ ```
190
+
191
+ Use `--ml-overlay-z-index` and `--ml-toast-z-index` when integrating overlays with an application's
192
+ stacking order. The default toast stack sits at the top right with a safe-area-aware 1rem offset.
193
+ Keep the CDK overlay stylesheet global; component-encapsulated styles cannot style detached panels.
194
+
195
+ ## Components and directives
196
+
197
+ | Selector | Export |
198
+ | ------------------------------------------- | ---------------------------------------------------------------------------- |
199
+ | `ml-accordion` | [`AccordionComponent`](src/lib/accordion/accordion.component.ts) |
200
+ | `ml-accordion-panel` | [`AccordionPanelComponent`](src/lib/accordion/accordion.component.ts) |
201
+ | `ml-accordion-header` | [`AccordionHeaderComponent`](src/lib/accordion/accordion.component.ts) |
202
+ | `ml-accordion-content` | [`AccordionContentComponent`](src/lib/accordion/accordion.component.ts) |
203
+ | `ml-autocomplete` | [`AutocompleteComponent`](src/lib/autocomplete/autocomplete.component.ts) |
204
+ | `button[mlButton], a[mlButton]` | [`ButtonDirective`](src/lib/button/button.directive.ts) |
205
+ | `ml-cascadeselect` | [`CascadeSelectComponent`](src/lib/cascadeselect/cascadeselect.component.ts) |
206
+ | `ml-checkbox` | [`CheckboxComponent`](src/lib/checkbox/checkbox.component.ts) |
207
+ | `ml-confirm` | [`ConfirmComponent`](src/lib/confirm/confirm.service.ts) |
208
+ | `ml-datepicker` | [`DatePickerComponent`](src/lib/datepicker/datepicker.component.ts) |
209
+ | `ml-dialog-container` | [`DialogContainerComponent`](src/lib/dialog/dialog-container.component.ts) |
210
+ | `ml-dialog` | [`DialogComponent`](src/lib/dialog/dialog.component.ts) |
211
+ | `ml-drawer` | [`DrawerComponent`](src/lib/drawer/drawer.component.ts) |
212
+ | `ml-floatlabel` | [`FloatLabelComponent`](src/lib/floatlabel/floatlabel.component.ts) |
213
+ | `input[mlInputText], textarea[mlInputText]` | [`InputTextDirective`](src/lib/input-text/input-text.directive.ts) |
214
+ | `ml-inputnumber` | [`InputNumberComponent`](src/lib/inputnumber/inputnumber.component.ts) |
215
+ | `ml-paginator` | [`PaginatorComponent`](src/lib/paginator/paginator.component.ts) |
216
+ | `ml-popover` | [`PopoverComponent`](src/lib/popover/popover.component.ts) |
217
+ | `ml-radiobutton` | [`RadioButtonComponent`](src/lib/radiobutton/radiobutton.component.ts) |
218
+ | `ml-select` | [`SelectComponent`](src/lib/select/select.component.ts) |
219
+ | `ml-selectbutton` | [`SelectButtonComponent`](src/lib/selectbutton/selectbutton.component.ts) |
220
+ | `ml-slider` | [`SliderComponent`](src/lib/slider/slider.component.ts) |
221
+ | `ml-spinner` | [`SpinnerComponent`](src/lib/spinner/spinner.component.ts) |
222
+ | `ml-table` | [`TableComponent`](src/lib/table/table.component.ts) |
223
+ | `ml-table-checkbox` | [`TableCheckboxComponent`](src/lib/table/table.component.ts) |
224
+ | `th[mlResizableColumn]` | [`ResizableColumnDirective`](src/lib/table/table.component.ts) |
225
+ | `ml-column-filter` | [`ColumnFilterComponent`](src/lib/table/table.component.ts) |
226
+ | `ml-tabs` | [`TabsComponent`](src/lib/tabs/tabs.component.ts) |
227
+ | `ml-tablist` | [`TabListComponent`](src/lib/tabs/tabs.component.ts) |
228
+ | `ml-tab` | [`TabComponent`](src/lib/tabs/tabs.component.ts) |
229
+ | `ml-tabpanels` | [`TabPanelsComponent`](src/lib/tabs/tabs.component.ts) |
230
+ | `ml-tabpanel` | [`TabPanelComponent`](src/lib/tabs/tabs.component.ts) |
231
+ | `ml-toast` | [`ToastComponent`](src/lib/toast/toast.component.ts) |
232
+ | `ml-toggleswitch` | [`ToggleSwitchComponent`](src/lib/toggleswitch/toggleswitch.component.ts) |
233
+ | `ml-tooltip-bubble` | [`TooltipBubbleComponent`](src/lib/tooltip/tooltip.directive.ts) |
234
+ | `[mlTooltip]` | [`TooltipDirective`](src/lib/tooltip/tooltip.directive.ts) |
235
+ | `ml-tree` | [`TreeComponent`](src/lib/tree/tree.component.ts) |
236
+
237
+ The selector prefix and the package name are independent: imports use `@geosdi/ngx-ui`, while
238
+ HTML uses `ml-*`. The former `maplite-*` selectors and `mapliteButton`-style directives are not aliases.
239
+
240
+ ### Buttons, inputs and tooltips
241
+
242
+ ```html
243
+ <button mlButton severity="primary">Save</button>
244
+ <button mlButton severity="secondary" outlined>Cancel</button>
245
+ <button mlButton severity="danger" [disabled]="busy">Delete</button>
246
+ <button mlButton size="small" [mlTooltip]="'More information'">Help</button>
247
+ <textarea mlInputText aria-label="Notes"></textarea>
248
+ ```
249
+
250
+ Button severities are `primary`, `secondary`, `success`, `info`, `warn` and `danger`. Use
251
+ `iconOnly`, `rounded`, `outlined` or `text` for the corresponding variants. Give icon-only buttons
252
+ an accessible label. Tooltips support `tooltipPosition`, `tooltipDisabled`, `autoHide` and
253
+ `showOnEllipsis`; with `autoHide` false a touch opens the tooltip until the next touch elsewhere.
254
+ Do not use a tooltip as the only accessible label for a control.
255
+
256
+ ### Notifications
257
+
258
+ ```typescript
259
+ import { inject } from "@angular/core";
260
+ import { ToastStore } from "@geosdi/ngx-ui";
261
+
262
+ // In a component or service:
263
+ private readonly toasts = inject(ToastStore);
264
+
265
+ saved(): void {
266
+ this.toasts.add("success", "Changes saved");
267
+ }
268
+ ```
269
+
270
+ `ToastStore.add(severity, detail, life?)` supports `success`, `info`, `warn` and `error` and returns
271
+ void. The default lifetime is 3000ms. `messages()` exposes the current messages (including their
272
+ numeric ids); `remove(id)` dismisses a message. The `ml-toast` host renders the messages and close
273
+ buttons. Opening lasts 450ms by default, configurable with `--ml-toast-enter-duration`. Reduced
274
+ motion preferences disable the entrance animation. Content is rendered as text, not HTML.
275
+
276
+ ### Confirmation dialogs
277
+
278
+ ```typescript
279
+ import { inject } from "@angular/core";
280
+ import { ConfirmService } from "@geosdi/ngx-ui";
281
+
282
+ private readonly confirms = inject(ConfirmService);
283
+
284
+ askToDelete(): void {
285
+ this.confirms.confirm({
286
+ header: "Delete item",
287
+ message: "Do you want to delete this item?",
288
+ acceptLabel: "Delete",
289
+ rejectLabel: "Cancel",
290
+ accept: () => this.deleteItem(),
291
+ reject: () => {},
292
+ });
293
+ }
294
+ ```
295
+
296
+ `ConfirmOptions` contains `message`, `header`, `acceptLabel`, `rejectLabel`, `accept` and `reject`.
297
+ Reject is also called when the dialog is closed with X or Escape. Confirmation content is plain
298
+ text. Defaults are Italian (`Conferma`, `Sì`, `No`); provide labels for another language.
299
+
300
+ ### Dynamic dialogs
301
+
302
+ ```typescript
303
+ import { Component, inject } from "@angular/core";
304
+ import {
305
+ DialogConfig,
306
+ DialogRef,
307
+ DialogService,
308
+ ButtonDirective,
309
+ } from "@geosdi/ngx-ui";
310
+
311
+ @Component({
312
+ selector: "app-edit-item",
313
+ imports: [ButtonDirective],
314
+ template: `<p>{{ data.name }}</p>
315
+ <button mlButton (click)="ref.close(true)">Save</button>`,
316
+ })
317
+ export class EditItemComponent {
318
+ readonly data = inject<DialogConfig<{ name: string }>>(DialogConfig).data!;
319
+ readonly ref = inject<DialogRef<boolean>>(DialogRef);
320
+ }
321
+
322
+ // In a component or service:
323
+ const ref = inject(DialogService).open<EditItemComponent, boolean>(
324
+ EditItemComponent,
325
+ {
326
+ header: "Edit item",
327
+ width: "36rem",
328
+ breakpoints: { "767px": "95vw" },
329
+ data: { name: "Example" },
330
+ },
331
+ );
332
+ ref.onClose.subscribe((saved) => {
333
+ /* true, false or undefined */
334
+ });
335
+ ```
336
+
337
+ Call `inject` only in an Angular injection context. `DialogService.open` returns a `DialogRef`;
338
+ `close(result?)` closes it, `destroy()` closes without a result, and `onClose` emits the result.
339
+ `DialogService.closeAll()` closes its open dialogs.
340
+
341
+ `DialogOptions` accepts `header`, `showHeader`, `closable`, `closeOnEscape`, `dismissableMask`,
342
+ `width`, `height`, `style`, `styleClass`, `breakpoints` and `data`. Defaults: header and close
343
+ button visible, Escape closes, backdrop clicks do not close. Breakpoints select the first maximum
344
+ viewport width that matches. `ml-dialog` is also available for a dialog declared in a template;
345
+ its API is listed below.
346
+
347
+ ### Selects and other form controls
348
+
349
+ `ml-select` supports primitive or object options, `optionLabel` / `optionValue`, filtering,
350
+ multiple selection, editable values, grouped options and item templates. `ml-autocomplete`
351
+ requests suggestions with `(complete)` and receives them through `[suggestions]`.
352
+ `ml-cascadeselect` navigates nested groups with `optionGroupChildren`.
353
+
354
+ The remaining form controls are `ml-checkbox`, `ml-radiobutton`, `ml-toggleswitch`, `ml-slider`,
355
+ `ml-inputnumber`, `ml-selectbutton` and `ml-datepicker`. Use labels or their accessible-name
356
+ inputs. Date values are JavaScript `Date` objects; range mode uses a date array. Number entry
357
+ accepts temporary empty values and clamps to `min` / `max` on blur.
358
+
359
+ ### Tabs, accordion and tables
360
+
361
+ Tabs use `ml-tabs`, `ml-tablist`, `ml-tab`, `ml-tabpanels` and `ml-tabpanel`. Match `value` between
362
+ each tab and panel. Accordion uses `ml-accordion`, `ml-accordion-panel`, `ml-accordion-header`
363
+ and `ml-accordion-content`. Both preserve closed content in the DOM, so hidden charts may need
364
+ resizing when their panel opens.
365
+
366
+ ```html
367
+ <ml-table [value]="rows">
368
+ <ng-template #header>
369
+ <tr>
370
+ <th>Name</th>
371
+ </tr>
372
+ </ng-template>
373
+ <ng-template #body let-row>
374
+ <tr>
375
+ <td>{{ row.name }}</td>
376
+ </tr>
377
+ </ng-template>
378
+ <ng-template #emptymessage>
379
+ <tr class="table-empty">
380
+ <td>No results</td>
381
+ </tr>
382
+ </ng-template>
383
+ </ml-table>
384
+ ```
385
+
386
+ Import `TableComponent` for the example. Additional templates include `#caption`, `#colgroup` and
387
+ `#footer`. The table provides pagination, selection, filtering support, lazy loading and
388
+ resizable columns through its public API; it does not provide virtual scrolling. Use
389
+ `TableCheckboxComponent`, `ResizableColumnDirective` and `ColumnFilterComponent` when needed.
390
+
391
+ ## API
392
+
393
+ The tables below list Angular inputs, model bindings and outputs declared by each exported
394
+ component/directive. A model supports two-way binding (`[(value)]`, `[(visible)]`, etc.). Signal
395
+ initializers show the defaults and transformation settings; optional inputs have no default.
396
+ Public helper types and functions are exported from `src/index.ts` alongside the components.
397
+
398
+ ### AccordionComponent
399
+
400
+ Selector: `ml-accordion`. [Source](src/lib/accordion/accordion.component.ts).
401
+
402
+ | Binding | Kind | Type | Declaration / default |
403
+ | -------- | ------ | ----------------------- | --------------------- |
404
+ | `value` | model | `ModelSignal<any>` | `model<any>(null)` |
405
+ | `opened` | output | `OutputEmitterRef<any>` | `output<any>()` |
406
+ | `closed` | output | `OutputEmitterRef<any>` | `output<any>()` |
407
+
408
+ ### AccordionPanelComponent
409
+
410
+ Selector: `ml-accordion-panel`. [Source](src/lib/accordion/accordion.component.ts).
411
+
412
+ | Binding | Kind | Type | Declaration / default |
413
+ | ------- | ----- | ---------------------- | --------------------- |
414
+ | `value` | input | `InputSignal<unknown>` | `input<unknown>()` |
415
+
416
+ ### AutocompleteComponent
417
+
418
+ Selector: `ml-autocomplete`. [Source](src/lib/autocomplete/autocomplete.component.ts).
419
+
420
+ | Binding | Kind | Type | Declaration / default |
421
+ | ----------------- | ------ | -------------------------------------------------------------- | ------------------------------------------------------------ |
422
+ | `suggestions` | input | `InputSignal<readonly unknown[] &#124; null &#124; undefined>` | `input<readonly unknown[] &#124; null &#124; undefined>([])` |
423
+ | `optionLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
424
+ | `delay` | input | `InputSignalWithTransform<number, unknown>` | `input(300, { transform: numberAttribute, })` |
425
+ | `minQueryLength` | input | `InputSignalWithTransform<number, unknown>` | `input( 1, { transform: numberAttribute }, )` |
426
+ | `dropdown` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
427
+ | `showClear` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
428
+ | `placeholder` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
429
+ | `emptyMessage` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
430
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
431
+ | `inputId` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
432
+ | `enterKeyHint` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
433
+ | `ariaLabel` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
434
+ | `styleClass` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
435
+ | `panelStyleClass` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
436
+ | `size` | input | `InputSignal<"small" &#124; undefined>` | `input<"small">()` |
437
+ | `autoFocus` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
438
+ | `fluid` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute, })` |
439
+ | `complete` | output | `OutputEmitterRef<string>` | `output<string>()` |
440
+ | `selected` | output | `OutputEmitterRef<any>` | `output<any>()` |
441
+ | `cleared` | output | `OutputEmitterRef<void>` | `output<void>()` |
442
+ | `blurred` | output | `OutputEmitterRef<void>` | `output<void>()` |
443
+
444
+ ### ButtonDirective
445
+
446
+ Selector: `button[mlButton], a[mlButton]`. [Source](src/lib/button/button.directive.ts).
447
+
448
+ | Binding | Kind | Type | Declaration / default |
449
+ | ---------- | ----- | -------------------------------------------- | -------------------------------------------------- |
450
+ | `severity` | input | `InputSignal<ButtonSeverity>` | `input<ButtonSeverity>("primary")` |
451
+ | `outlined` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
452
+ | `text` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute, })` |
453
+ | `rounded` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
454
+ | `iconOnly` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
455
+ | `size` | input | `InputSignal<"small" &#124; "normal">` | `input<"small" &#124; "normal">( "normal", )` |
456
+
457
+ ### CascadeSelectComponent
458
+
459
+ Selector: `ml-cascadeselect`. [Source](src/lib/cascadeselect/cascadeselect.component.ts).
460
+
461
+ | Binding | Kind | Type | Declaration / default |
462
+ | --------------------- | ------ | ----------------------------------------------------------------- | ------------------------------------------------------------ |
463
+ | `options` | input | `InputSignal<readonly unknown[] &#124; null &#124; undefined>` | `input<readonly unknown[] &#124; null &#124; undefined>([])` |
464
+ | `optionLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
465
+ | `optionGroupLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
466
+ | `optionGroupChildren` | input | `InputSignal< string &#124; readonly string[] &#124; undefined >` | `input<string &#124; readonly string[]>()` |
467
+ | `optionDisabled` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
468
+ | `placeholder` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
469
+ | `ariaLabel` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
470
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
471
+ | `keepSelection` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
472
+ | `changed` | output | `OutputEmitterRef<any>` | `output<any>()` |
473
+
474
+ ### CheckboxComponent
475
+
476
+ Selector: `ml-checkbox`. [Source](src/lib/checkbox/checkbox.component.ts).
477
+
478
+ | Binding | Kind | Type | Declaration / default |
479
+ | ----------- | ------ | -------------------------------------------- | -------------------------------------------------- |
480
+ | `inputId` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
481
+ | `ariaLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
482
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
483
+ | `changed` | output | `OutputEmitterRef<boolean>` | `output<boolean>()` |
484
+
485
+ ### DatePickerComponent
486
+
487
+ Selector: `ml-datepicker`. [Source](src/lib/datepicker/datepicker.component.ts).
488
+
489
+ | Binding | Kind | Type | Declaration / default |
490
+ | --------------- | ------ | ------------------------------------------------------- | -------------------------------------------------- |
491
+ | `selectionMode` | input | `InputSignal<"single" &#124; "range" &#124; undefined>` | `input< "single" &#124; "range" >()` |
492
+ | `showTime` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
493
+ | `showClear` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
494
+ | `showIcon` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
495
+ | `touchUI` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
496
+ | `placeholder` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
497
+ | `ariaLabel` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
498
+ | `inputId` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
499
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
500
+ | `locale` | input | `InputSignal<string>` | `input("it-IT")` |
501
+ | `changed` | output | `OutputEmitterRef<any>` | `output<any>()` |
502
+
503
+ ### DialogComponent
504
+
505
+ Selector: `ml-dialog`. [Source](src/lib/dialog/dialog.component.ts).
506
+
507
+ | Binding | Kind | Type | Declaration / default |
508
+ | ----------------- | ------ | ------------------------------------------------------ | ------------------------------------------------- |
509
+ | `visible` | model | `ModelSignal<boolean>` | `model(false)` |
510
+ | `header` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
511
+ | `showHeader` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
512
+ | `closable` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
513
+ | `closeOnEscape` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
514
+ | `dismissableMask` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute })` |
515
+ | `modal` | input | `InputSignalWithTransform<boolean, unknown>` | `input(true, { transform: booleanAttribute, })` |
516
+ | `focusOnShow` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
517
+ | `style` | input | `InputSignal<Record<string, string> &#124; undefined>` | `input<Record<string, string>>()` |
518
+ | `breakpoints` | input | `InputSignal<Record<string, string> &#124; undefined>` | `input<Record<string, string>>()` |
519
+ | `closed` | output | `OutputEmitterRef<void>` | `output<void>()` |
520
+
521
+ ### DrawerComponent
522
+
523
+ Selector: `ml-drawer`. [Source](src/lib/drawer/drawer.component.ts).
524
+
525
+ | Binding | Kind | Type | Declaration / default |
526
+ | ----------- | ------ | -------------------------------------- | ----------------------------------------- |
527
+ | `visible` | model | `ModelSignal<boolean>` | `model(false)` |
528
+ | `position` | input | `InputSignal<"left" &#124; "right">` | `input<"left" &#124; "right">( "left", )` |
529
+ | `ariaLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
530
+ | `closed` | output | `OutputEmitterRef<void>` | `output<void>()` |
531
+
532
+ ### FloatLabelComponent
533
+
534
+ Selector: `ml-floatlabel`. [Source](src/lib/floatlabel/floatlabel.component.ts).
535
+
536
+ | Binding | Kind | Type | Declaration / default |
537
+ | --------- | ----- | --------------------------------- | ----------------------------------- |
538
+ | `variant` | input | `InputSignal<"on" &#124; "over">` | `input<"on" &#124; "over">("over")` |
539
+
540
+ ### InputNumberComponent
541
+
542
+ Selector: `ml-inputnumber`. [Source](src/lib/inputnumber/inputnumber.component.ts).
543
+
544
+ | Binding | Kind | Type | Declaration / default |
545
+ | ------------------- | ----- | -------------------------------------------------------------- | ---------------------------------------------------- |
546
+ | `inputId` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
547
+ | `ariaLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
548
+ | `placeholder` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
549
+ | `min` | input | `InputSignalWithTransform<number &#124; undefined, unknown>` | `input( undefined, { transform: optionalNumber }, )` |
550
+ | `max` | input | `InputSignalWithTransform<number &#124; undefined, unknown>` | `input( undefined, { transform: optionalNumber }, )` |
551
+ | `step` | input | `InputSignalWithTransform<number, unknown>` | `input(1, { transform: numberAttribute, })` |
552
+ | `minFractionDigits` | input | `InputSignalWithTransform< number &#124; undefined, unknown >` | `input(undefined, { transform: optionalNumber })` |
553
+ | `maxFractionDigits` | input | `InputSignalWithTransform< number &#124; undefined, unknown >` | `input(undefined, { transform: optionalNumber })` |
554
+ | `useGrouping` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
555
+ | `locale` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
556
+ | `mode` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
557
+ | `showButtons` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
558
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
559
+
560
+ ### PaginatorComponent
561
+
562
+ Selector: `ml-paginator`. [Source](src/lib/paginator/paginator.component.ts).
563
+
564
+ | Binding | Kind | Type | Declaration / default |
565
+ | -------------- | ------ | ------------------------------------------- | --------------------------------------------- |
566
+ | `first` | input | `InputSignalWithTransform<number, unknown>` | `input(0, { transform: numberAttribute, })` |
567
+ | `rows` | input | `InputSignalWithTransform<number, unknown>` | `input(10, { transform: numberAttribute, })` |
568
+ | `totalRecords` | input | `InputSignalWithTransform<number, unknown>` | `input( 0, { transform: numberAttribute }, )` |
569
+ | `pageChange` | output | `OutputEmitterRef<PageChange>` | `output<PageChange>()` |
570
+
571
+ ### PopoverComponent
572
+
573
+ Selector: `ml-popover`. [Source](src/lib/popover/popover.component.ts).
574
+
575
+ | Binding | Kind | Type | Declaration / default |
576
+ | ------------ | ----- | -------------------------------------- | --------------------- |
577
+ | `styleClass` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
578
+
579
+ ### RadioButtonComponent
580
+
581
+ Selector: `ml-radiobutton`. [Source](src/lib/radiobutton/radiobutton.component.ts).
582
+
583
+ | Binding | Kind | Type | Declaration / default |
584
+ | ---------- | ----- | -------------------------------------------- | -------------------------------------------------- |
585
+ | `value` | input | `InputSignal<unknown>` | `input<unknown>()` |
586
+ | `name` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
587
+ | `inputId` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
588
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
589
+
590
+ ### SelectComponent
591
+
592
+ Selector: `ml-select`. [Source](src/lib/select/select.component.ts).
593
+
594
+ | Binding | Kind | Type | Declaration / default |
595
+ | --------------------- | ------ | -------------------------------------------------------------- | ------------------------------------------------------------ |
596
+ | `options` | input | `InputSignal<readonly unknown[] &#124; null &#124; undefined>` | `input<readonly unknown[] &#124; null &#124; undefined>([])` |
597
+ | `optionLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
598
+ | `optionValue` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
599
+ | `group` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute, })` |
600
+ | `optionGroupLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
601
+ | `optionGroupChildren` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
602
+ | `placeholder` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
603
+ | `showClear` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
604
+ | `filter` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute, })` |
605
+ | `filterBy` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
606
+ | `editable` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
607
+ | `multiple` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
608
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
609
+ | `inputId` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
610
+ | `ariaLabel` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
611
+ | `styleClass` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
612
+ | `panelStyleClass` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
613
+ | `size` | input | `InputSignal<"small" &#124; undefined>` | `input<"small">()` |
614
+ | `fluid` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute, })` |
615
+ | `emptyMessage` | input | `InputSignal<string>` | `input("Nessun risultato")` |
616
+ | `changed` | output | `OutputEmitterRef<any>` | `output<any>()` |
617
+ | `cleared` | output | `OutputEmitterRef<void>` | `output<void>()` |
618
+
619
+ ### SelectButtonComponent
620
+
621
+ Selector: `ml-selectbutton`. [Source](src/lib/selectbutton/selectbutton.component.ts).
622
+
623
+ | Binding | Kind | Type | Declaration / default |
624
+ | ------------- | ----- | -------------------------------------------------------------- | ------------------------------------------------------------ |
625
+ | `options` | input | `InputSignal<readonly unknown[] &#124; null &#124; undefined>` | `input<readonly unknown[] &#124; null &#124; undefined>([])` |
626
+ | `optionLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
627
+ | `optionValue` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
628
+ | `allowEmpty` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
629
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
630
+
631
+ ### SliderComponent
632
+
633
+ Selector: `ml-slider`. [Source](src/lib/slider/slider.component.ts).
634
+
635
+ | Binding | Kind | Type | Declaration / default |
636
+ | ---------------- | ------ | -------------------------------------------- | -------------------------------------------------- |
637
+ | `min` | input | `InputSignalWithTransform<number, unknown>` | `input(0, { transform: numberAttribute, })` |
638
+ | `max` | input | `InputSignalWithTransform<number, unknown>` | `input(100, { transform: numberAttribute, })` |
639
+ | `step` | input | `InputSignalWithTransform<number, unknown>` | `input(1, { transform: numberAttribute, })` |
640
+ | `ariaLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
641
+ | `ariaLabelledBy` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
642
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
643
+ | `changed` | output | `OutputEmitterRef<number>` | `output<number>()` |
644
+
645
+ ### TableComponent
646
+
647
+ Selector: `ml-table`. [Source](src/lib/table/table.component.ts).
648
+
649
+ | Binding | Kind | Type | Declaration / default |
650
+ | -------------- | ------ | -------------------------------------------------------------------- | -------------------------------------------------------------- |
651
+ | `value` | input | `InputSignal<readonly any[] &#124; null &#124; undefined>` | `input< readonly any[] &#124; null &#124; undefined >([])` |
652
+ | `columns` | input | `InputSignal<any[] &#124; null &#124; undefined>` | `input< any[] &#124; null &#124; undefined >()` |
653
+ | `dataKey` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
654
+ | `size` | input | `InputSignal<"small" &#124; undefined>` | `input<"small">()` |
655
+ | `stripedRows` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
656
+ | `rowHover` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
657
+ | `scrollHeight` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >()` |
658
+ | `tableStyle` | input | `InputSignal< Record<string, string> &#124; null &#124; undefined >` | `input<Record<string, string> &#124; null &#124; undefined>()` |
659
+ | `styleClass` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
660
+ | `paginator` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
661
+ | `rows` | input | `InputSignalWithTransform<number, unknown>` | `input(10, { transform: numberAttribute, })` |
662
+ | `totalRecords` | input | `InputSignalWithTransform<number, unknown>` | `input( 0, { transform: numberAttribute }, )` |
663
+ | `first` | input | `InputSignalWithTransform<number, unknown>` | `input(0, { transform: numberAttribute, })` |
664
+ | `lazy` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute, })` |
665
+ | `loading` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
666
+ | `selection` | model | `ModelSignal<any[] &#124; null &#124; undefined>` | `model< any[] &#124; null &#124; undefined >([])` |
667
+ | `rowSelect` | output | `OutputEmitterRef<TableRowEvent>` | `output<TableRowEvent>()` |
668
+ | `rowUnselect` | output | `OutputEmitterRef<TableRowEvent>` | `output<TableRowEvent>()` |
669
+ | `lazyLoad` | output | `OutputEmitterRef<TableLazyLoad>` | `output<TableLazyLoad>()` |
670
+
671
+ ### TableCheckboxComponent
672
+
673
+ Selector: `ml-table-checkbox`. [Source](src/lib/table/table.component.ts).
674
+
675
+ | Binding | Kind | Type | Declaration / default |
676
+ | ------- | ----- | -------------------------------------- | --------------------- |
677
+ | `value` | input | `InputSignal<unknown>` | `input<unknown>()` |
678
+ | `index` | input | `InputSignal<number &#124; undefined>` | `input<number>()` |
679
+
680
+ ### ColumnFilterComponent
681
+
682
+ Selector: `ml-column-filter`. [Source](src/lib/table/table.component.ts).
683
+
684
+ | Binding | Kind | Type | Declaration / default |
685
+ | ----------- | ---------------- | ------------------------------- | ---------------------------------- |
686
+ | `field` | input (required) | `InputSignal<string>` | `input.required<string>()` |
687
+ | `type` | input | `InputSignal<ColumnFilterType>` | `input<ColumnFilterType>("text")` |
688
+ | `matchMode` | input | `InputSignal<ColumnMatchMode>` | `input<ColumnMatchMode>("equals")` |
689
+
690
+ ### TabsComponent
691
+
692
+ Selector: `ml-tabs`. [Source](src/lib/tabs/tabs.component.ts).
693
+
694
+ | Binding | Kind | Type | Declaration / default |
695
+ | --------------------- | ----- | ------------------ | --------------------- |
696
+ | `value` | model | `ModelSignal<any>` | `model<any>()` |
697
+ | `scrollable` | input | boolean (coerced) | `false` |
698
+ | `previousButtonLabel` | input | string | `Previous tabs` |
699
+ | `nextButtonLabel` | input | string | `Next tabs` |
700
+
701
+ ### TabComponent
702
+
703
+ Selector: `ml-tab`. [Source](src/lib/tabs/tabs.component.ts).
704
+
705
+ | Binding | Kind | Type | Declaration / default |
706
+ | ------- | ----- | ---------------------- | --------------------- |
707
+ | `value` | input | `InputSignal<unknown>` | `input<unknown>()` |
708
+
709
+ ### TabPanelComponent
710
+
711
+ Selector: `ml-tabpanel`. [Source](src/lib/tabs/tabs.component.ts).
712
+
713
+ | Binding | Kind | Type | Declaration / default |
714
+ | ------- | ----- | ---------------------- | --------------------- |
715
+ | `value` | input | `InputSignal<unknown>` | `input<unknown>()` |
716
+
717
+ ### ToggleSwitchComponent
718
+
719
+ Selector: `ml-toggleswitch`. [Source](src/lib/toggleswitch/toggleswitch.component.ts).
720
+
721
+ | Binding | Kind | Type | Declaration / default |
722
+ | ----------- | ------ | -------------------------------------------- | -------------------------------------------------- |
723
+ | `inputId` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
724
+ | `ariaLabel` | input | `InputSignal<string &#124; undefined>` | `input<string>()` |
725
+ | `disabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
726
+ | `changed` | output | `OutputEmitterRef<boolean>` | `output<boolean>()` |
727
+
728
+ ### TooltipDirective
729
+
730
+ Selector: `[mlTooltip]`. [Source](src/lib/tooltip/tooltip.directive.ts).
731
+
732
+ | Binding | Kind | Type | Declaration / default |
733
+ | ----------------- | ----- | -------------------------------------------------- | -------------------------------------------------------------------------- |
734
+ | `mlTooltip` | input | `InputSignal<string &#124; null &#124; undefined>` | `input< string &#124; null &#124; undefined >("", { alias: "mlTooltip" })` |
735
+ | `tooltipPosition` | input | `InputSignal<TooltipPosition>` | `input<TooltipPosition>("top")` |
736
+ | `tooltipDisabled` | input | `InputSignalWithTransform<boolean, unknown>` | `input(false, { transform: booleanAttribute })` |
737
+ | `autoHide` | input | `InputSignalWithTransform<boolean, unknown>` | `input( true, { transform: booleanAttribute }, )` |
738
+ | `showOnEllipsis` | input | `InputSignalWithTransform<boolean, unknown>` | `input( false, { transform: booleanAttribute }, )` |
739
+
740
+ ### TreeComponent
741
+
742
+ Selector: `ml-tree`. [Source](src/lib/tree/tree.component.ts).
743
+
744
+ | Binding | Kind | Type | Declaration / default |
745
+ | ------- | ----- | --------------------------------------------------------------- | --------------------------------------------------------------- |
746
+ | `value` | input | `InputSignal<readonly TreeItem[] &#124; null &#124; undefined>` | `input< readonly TreeItem[] &#124; null &#124; undefined >([])` |
747
+
748
+ ## Behavior and limitations
749
+
750
+ - The library expects a browser DOM. Some overlay and viewport code uses `window` and `document`;
751
+ SSR/hydration compatibility has not been validated.
752
+ - Themes are global; isolated themes for separate component subtrees are not supported.
753
+ - The default theme is light, and some component dimensions remain fixed in component styles.
754
+ Buttons and text inputs expose dimensional tokens in this first version.
755
+ - There is no translation service dependency. Some default strings and accessible labels are
756
+ Italian; override exposed labels where available. Not every built-in label is configurable yet.
757
+ - Overlay behavior comes from Angular CDK; dynamic dialogs use CDK focus handling. This does not
758
+ imply a complete accessibility certification. Test keyboard, screen readers and contrast in the
759
+ consuming application, especially after theme overrides.
760
+ - Status SVGs use Font Awesome Free paths (CC BY 4.0); social silhouettes are local. The component
761
+ code is MIT. No Font Awesome Angular package is required at runtime.
762
+ - Utility classes such as `flex` or `w-full` are not shipped. Use the application's layout styles.
763
+ - HTML strings are not accepted by toast and confirmation messages.
764
+
765
+ ## Development
766
+
767
+ From the `angular-libraries` repository root:
768
+
769
+ ```sh
770
+ npm run ngx-ui:build
771
+ npx nx test @geosdi/ngx-ui
772
+ npx nx lint @geosdi/ngx-ui
773
+ ```
774
+
775
+ The build writes `dist/@geosdi/ngx-ui`, including the README, declarations, compiled Angular code
776
+ and `styles/*.scss`. To test without publishing, build and run `npm pack` from that output
777
+ folder, then install the generated tarball in a consumer. Publish only through the repository's
778
+ manual release workflow after committing the versioned source.
779
+
780
+ ## Changes in 1.0.0
781
+
782
+ - Initial extraction of the standalone UI components and tests from Maplite.
783
+ - Independent CSS theme, local SVG icons and public Sass entry points.
784
+ - `ml-*` component selectors, `ml*` directives and `--ml-*` theme tokens.
785
+ - Application header offsets and map-specific stacking rules excluded from the package.
786
+
787
+ ### Scrollable tabs (1.1.0)
788
+
789
+ ```html
790
+ <ml-tabs
791
+ [(value)]="selectedTab"
792
+ [scrollable]="true"
793
+ previousButtonLabel="Previous regions"
794
+ nextButtonLabel="Next regions"
795
+ >
796
+ <ml-tablist>
797
+ @for (region of regions; track region.id) {
798
+ <ml-tab [value]="region.id">{{ region.name }}</ml-tab>
799
+ }
800
+ </ml-tablist>
801
+ <ml-tabpanels><!-- Matching ml-tabpanel elements --></ml-tabpanels>
802
+ </ml-tabs>
803
+ ```
804
+
805
+ `scrollable` defaults to `false`. When enabled, tabs stay on one line, native
806
+ scrollbars are hidden, and previous/next buttons appear only on overflow. Buttons
807
+ are disabled at the corresponding end. Touch and trackpad scrolling remain
808
+ available. The active tab is revealed after selection, including keyboard and
809
+ programmatic changes. Resizing and dynamic labels recalculate overflow. Scrolling
810
+ respects reduced motion and right-to-left layout.
811
+
812
+ `previousButtonLabel` and `nextButtonLabel` customize the accessible button labels
813
+ (defaults: `Previous tabs` and `Next tabs`). Existing theme tokens style the buttons;
814
+ no icon package or application CSS is required. The tablist now contains an internal
815
+ `.ml-tablist__viewport`; custom CSS targeting direct children of `ml-tablist` should
816
+ instead target `.ml-tablist__viewport > ml-tab`.