@flusys/ng-ui 1.2.0-rc.1

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 ADDED
@@ -0,0 +1,1300 @@
1
+ # @flusys/ng-ui
2
+
3
+ Native Angular 21 UI component library for the FLUSYS platform — signal-based, standalone, zoneless-compatible, and Tailwind-friendly. No PrimeNG dependency; every component below is implemented natively in this package.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@flusys/ng-ui.svg)](https://www.npmjs.com/package/@flusys/ng-ui)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ---
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @flusys/ng-ui @flusys/ng-core
14
+ ```
15
+
16
+ All components/directives are standalone — import them individually, or import `UiModule` for the full set (useful in non-standalone contexts or quick prototyping).
17
+
18
+ ---
19
+
20
+ ## Setup
21
+
22
+ Register the theme initializer once in `app.config.ts`:
23
+
24
+ ```typescript
25
+ import { ApplicationConfig } from "@angular/core";
26
+ import { provideNgUI } from "@flusys/ng-ui";
27
+
28
+ export const appConfig: ApplicationConfig = {
29
+ providers: [
30
+ provideNgUI({
31
+ theme: {
32
+ preset: { preset: "violet", options: { darkModeSelector: ".app-dark" } },
33
+ },
34
+ translation: {
35
+ accept: "Yes",
36
+ reject: "No",
37
+ },
38
+ }),
39
+ ],
40
+ };
41
+ ```
42
+
43
+ `provideNgUI(options?: ProvideNgUIOptions)` registers:
44
+
45
+ - `NgUIConfig` — holds the translation/localization strings consumed internally by components (dialog buttons, date picker labels, upload labels, etc.). Override via the `translation` option.
46
+ - An `APP_INITIALIZER` that applies the CSS custom-property theme on bootstrap and re-applies dark/light semantics whenever `.app-dark` is toggled on `<html>` (via `MutationObserver`).
47
+
48
+ `ProvideNgUIOptions`:
49
+
50
+ ```typescript
51
+ interface ProvideNgUIOptions {
52
+ theme?: {
53
+ preset?: ApplyThemeOptions | { preset: ApplyThemeOptions; options: { darkModeSelector?: string } };
54
+ options?: { darkModeSelector?: string };
55
+ };
56
+ translation?: NgUITranslationConfig;
57
+ ripple?: boolean;
58
+ }
59
+ ```
60
+
61
+ Two core services are provided at root and used implicitly by `ToastComponent`/`ConfirmDialog`:
62
+
63
+ ```typescript
64
+ import { MessageService, ConfirmationService } from "@flusys/ng-ui";
65
+
66
+ const messageService = inject(MessageService);
67
+ messageService.add({ severity: "success", summary: "Saved", detail: "Record updated." });
68
+
69
+ const confirmationService = inject(ConfirmationService);
70
+ confirmationService.confirm({
71
+ message: "Delete this record?",
72
+ header: "Confirm",
73
+ icon: "alert-triangle",
74
+ accept: () => doDelete(),
75
+ });
76
+ ```
77
+
78
+ Place `<f-toast />` and `<f-confirmdialog />` once near the root of your app shell to render messages/confirmations raised from anywhere via these services.
79
+
80
+ ---
81
+
82
+ ## Theming
83
+
84
+ Theming is CSS-custom-property based (`--f-*` variables) — no SCSS recompilation needed to switch colors.
85
+
86
+ ### `applyTheme`
87
+
88
+ ```typescript
89
+ import { applyTheme } from "@flusys/ng-ui";
90
+
91
+ applyTheme({
92
+ preset: "Aura", // 'Aura' | 'Lara' | 'Nora'
93
+ primary: "violet", // any key of PRIMARY_PALETTES, or 'noir'
94
+ surface: "slate", // any key of SURFACE_PALETTES, or null for light/dark default
95
+ darkTheme: false,
96
+ });
97
+ ```
98
+
99
+ Lower-level appliers are also exported for partial updates: `applyPrimaryPalette(palette, isDark?, root?)`, `applySurfacePalette(palette, root?)`, `applyPreset(preset, root?)`, `applyLightSemantics(root?)`, `applyDarkSemantics(root?)`.
100
+
101
+ ### Presets
102
+
103
+ ```typescript
104
+ import { PRESETS, PRESET_NAMES, AURA_PRESET, LARA_PRESET, NORA_PRESET } from "@flusys/ng-ui";
105
+ import type { PresetName, ThemePreset } from "@flusys/ng-ui";
106
+
107
+ PRESET_NAMES; // ['Aura', 'Lara', 'Nora']
108
+ PRESETS["Nora"]; // ThemePreset — border radius, shadows, focus ring, card + select-button tokens
109
+ ```
110
+
111
+ Each `ThemePreset` controls border radius scale, shadow scale, transition duration, focus ring style, card tokens, and select-button tokens. `Aura` is soft/rounded, `Lara` is Bootstrap-like, `Nora` is sharp/high-contrast with solid highlights.
112
+
113
+ ### Palettes
114
+
115
+ ```typescript
116
+ import { PRIMARY_PALETTES, SURFACE_PALETTES, NOIR_PRIMARY } from "@flusys/ng-ui";
117
+ import type { ColorPalette, SurfacePalette } from "@flusys/ng-ui";
118
+
119
+ PRIMARY_PALETTES["emerald"]; // { '50': '#ecfdf5', ..., '950': '#022c22' }
120
+ SURFACE_PALETTES["zinc"]; // { 0: '#ffffff', '50': ..., '950': '#09090b' }
121
+ ```
122
+
123
+ `PRIMARY_PALETTES` ships all 16 Tailwind color ramps (`emerald`, `green`, `lime`, `orange`, `amber`, `yellow`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`) plus the special `NOIR_PRIMARY` (grayscale primary that maps onto the active surface palette). `SURFACE_PALETTES` ships `slate`, `gray`, `zinc`, `neutral`, `stone`, `soho`, `viva`, `ocean`.
124
+
125
+ ### Bootstrap helper
126
+
127
+ ```typescript
128
+ import { buildBootstrapPreset } from "@flusys/ng-ui";
129
+
130
+ const options = buildBootstrapPreset({ preset: "Aura", primary: "violet", surface: null });
131
+ // Reads `flusys.layout.config` from localStorage when isMemorable !== false
132
+ ```
133
+
134
+ ---
135
+
136
+ ## UiModule
137
+
138
+ ```typescript
139
+ import { UiModule } from "@flusys/ng-ui";
140
+
141
+ @Component({
142
+ imports: [UiModule],
143
+ // ...
144
+ })
145
+ export class SomePage {}
146
+ ```
147
+
148
+ `UiModule` re-exports every component/directive documented below plus `FormsModule`. Prefer importing individual standalone components in new code; `UiModule` exists for bulk-import convenience.
149
+
150
+ ---
151
+
152
+ ## Buttons & Actions
153
+
154
+ ### ButtonComponent
155
+
156
+ Standard button with severity, icon, and loading states. Selector: `f-button`.
157
+
158
+ ```html
159
+ <f-button [label]="'shared.save' | translate" icon="check" severity="primary" [loading]="isSaving()" (onClick)="save()" />
160
+ ```
161
+
162
+ Key inputs: `label`, `icon`, `iconPos`, `severity` (`primary | secondary | success | info | warn | danger | contrast | help`), `disabled`, `loading`, `text`, `link`, `outlined`, `raised`, `rounded`, `fluid`, `size` (`small | large | null`). Output: `onClick`.
163
+
164
+ ### FButtonDirective
165
+
166
+ Attribute-directive version of the button — apply button styling to a native `<button>` or `<a>`. Selector: `[fButton]`.
167
+
168
+ ```html
169
+ <a fButton severity="secondary" outlined label="Cancel"></a>
170
+ ```
171
+
172
+ Key inputs: `severity`, `text`, `outlined`, `link`, `rounded`, `raised`, `fluid`, `disabled`, `loading`, `size`, `label`, `icon`, `iconPos`, `ariaLabel`, `plain`.
173
+
174
+ ### SplitButtonComponent
175
+
176
+ Primary action button with an attached dropdown menu. Selector: `f-splitbutton`.
177
+
178
+ ```html
179
+ <f-splitbutton [label]="'shared.export' | translate" icon="download" [model]="exportMenu" severity="primary" (onClick)="exportDefault()" />
180
+ ```
181
+
182
+ Key inputs: `label`, `icon`, `model` (`MenuItem[]`), `severity`, `disabled`, `loading`, `appendTo`. Outputs: `onClick`, `onDropdownClick`.
183
+
184
+ ### ButtonGroupComponent
185
+
186
+ Groups adjacent buttons with connected borders via content projection. Selector: `f-buttongroup`.
187
+
188
+ ```html
189
+ <f-buttongroup>
190
+ <f-button label="Left" />
191
+ <f-button label="Right" />
192
+ </f-buttongroup>
193
+ ```
194
+
195
+ ### SpeedDialComponent
196
+
197
+ Floating action button that expands into a radial/linear menu. Selector: `f-speeddial`.
198
+
199
+ ```html
200
+ <f-speeddial [model]="actions" icon="plus" direction="up" type="linear" [radius]="80" />
201
+ ```
202
+
203
+ Key inputs: `model` (`MenuItem[]`), `icon`, `direction` (`up | down | left | right`), `rotate`, `type` (`linear | circle`), `radius`.
204
+
205
+ ---
206
+
207
+ ## Form Inputs
208
+
209
+ ### InputTextDirective
210
+
211
+ Applies text-input styling to native `<input>`. Selector: `[fInputText]`.
212
+
213
+ ```html
214
+ <input fInputText type="text" [invalid]="form.controls.name.invalid && form.controls.name.touched" [placeholder]="'form.namePlaceholder' | translate" />
215
+ ```
216
+
217
+ Key inputs: `invalid`, `touched` (defaults `true`; gates red invalid styling on `invalid && touched`).
218
+
219
+ ### InputPasswordDirective
220
+
221
+ Password-input styling with optional native masking. Selector: `[fInputPassword]`.
222
+
223
+ ```html
224
+ <input fInputPassword type="password" [mask]="true" />
225
+ ```
226
+
227
+ Key input: `mask` (default `true`).
228
+
229
+ ### TextareaDirective
230
+
231
+ Applies textarea styling. Selector: `[fTextarea]`.
232
+
233
+ ```html
234
+ <textarea fTextarea rows="4" [invalid]="control.invalid"></textarea>
235
+ ```
236
+
237
+ Key inputs: `invalid`, `touched`.
238
+
239
+ ### SelectComponent
240
+
241
+ Native single-select dropdown with filtering. Selector: `f-select`.
242
+
243
+ ```html
244
+ <f-select [options]="countries" optionLabel="name" optionValue="code" [(ngModel)]="selectedCountry" [filter]="true" [placeholder]="'form.selectCountry' | translate" />
245
+ ```
246
+
247
+ Key inputs: `options`, `optionLabel`, `optionValue`, `placeholder`, `disabled`, `filter`, `showClear`, `loading`, `invalid`, `touched`, `editable`. Outputs: `onFilter`, `onChange`, `onShow`, `onHide`, `onBlur`. Supports `fTemplate="selectedItem"` / `fTemplate="item"` content templates.
248
+
249
+ ### MultiSelectComponent
250
+
251
+ Multi-value select with chip/comma display. Selector: `f-multiselect`.
252
+
253
+ ```html
254
+ <f-multiselect [options]="roles" optionLabel="name" [(ngModel)]="selectedRoles" display="chip" [showToggleAll]="true" />
255
+ ```
256
+
257
+ Key inputs: `options`, `optionLabel`, `optionValue`, `placeholder`, `filter`, `display` (`comma | chip`), `maxSelectedLabels`, `selectionLimit`, `showToggleAll`, `invalid`, `touched`.
258
+
259
+ ### CheckboxComponent
260
+
261
+ Binary or value-bound checkbox. Selector: `f-checkbox`.
262
+
263
+ ```html
264
+ <f-checkbox [(checked)]="acceptedTerms" [label]="'auth.acceptTerms' | translate" [binary]="true" />
265
+ ```
266
+
267
+ Key inputs: `label`, `binary`, `disabled`, `invalid`, `indeterminate`, `touched`. Model: `checked`. Outputs: `onChange` (`CheckboxChangeEvent`), `onBlur`.
268
+
269
+ ### ToggleSwitchComponent
270
+
271
+ On/off switch with `ControlValueAccessor` support. Selector: `f-toggleswitch`.
272
+
273
+ ```html
274
+ <f-toggleswitch formControlName="isActive" [trueValue]="true" [falseValue]="false" />
275
+ ```
276
+
277
+ Key inputs: `disabled`, `readonly`, `invalid`, `trueValue`, `falseValue`, `ariaLabel`.
278
+
279
+ ### ToggleButtonComponent
280
+
281
+ Two-state button toggle with distinct on/off labels and icons. Selector: `f-togglebutton`.
282
+
283
+ ```html
284
+ <f-togglebutton [(ngModel)]="isPublic" [onLabel]="'shared.public' | translate" [offLabel]="'shared.private' | translate" />
285
+ ```
286
+
287
+ Key inputs: `onLabel`, `offLabel`, `onIcon`, `offIcon`, `disabled`, `invalid`.
288
+
289
+ ### SelectButtonComponent
290
+
291
+ Single/multi-choice segmented control. Selector: `f-selectbutton`.
292
+
293
+ ```html
294
+ <f-selectbutton [options]="viewModes" optionLabel="label" [(ngModel)]="currentView" />
295
+ ```
296
+
297
+ Key inputs: `options`, `optionLabel`, `optionValue`, `multiple`, `disabled`, `allowEmpty`, `size`. Output: `onChange`.
298
+
299
+ ### PasswordComponent
300
+
301
+ Password field with strength feedback and reveal toggle. Selector: `f-password`.
302
+
303
+ ```html
304
+ <f-password [(ngModel)]="password" [feedback]="true" [toggleMask]="true" [placeholder]="'auth.passwordPlaceholder' | translate" />
305
+ ```
306
+
307
+ Key inputs: `toggleMask`, `feedback`, `disabled`, `placeholder`, `invalid`, `touched`. Output: `onBlur`.
308
+
309
+ ### InputNumberComponent
310
+
311
+ Numeric input with optional increment/decrement buttons, prefix/suffix, and grouping. Selector: `f-inputnumber`.
312
+
313
+ ```html
314
+ <f-inputnumber [(ngModel)]="quantity" [min]="0" [max]="100" [showButtons]="true" suffix=" kg" />
315
+ ```
316
+
317
+ Key inputs: `min`, `max`, `step`, `showButtons`, `disabled`, `invalid`, `prefix`, `suffix`, `useGrouping`, `buttonLayout` (`stacked | horizontal`). Output: `onBlur`.
318
+
319
+ ### RadioButtonComponent
320
+
321
+ Single radio input within a shared `name` group. Selector: `f-radiobutton`.
322
+
323
+ ```html
324
+ <f-radiobutton name="plan" value="pro" [(ngModel)]="selectedPlan" [label]="'billing.proPlan' | translate" />
325
+ ```
326
+
327
+ Key inputs: `name`, `value`, `label`, `disabled`, `invalid`. Outputs: `onClick` (`RadioButtonClickEvent`), `onBlur`.
328
+
329
+ ### RatingComponent
330
+
331
+ Star rating input. Selector: `f-rating`.
332
+
333
+ ```html
334
+ <f-rating [(ngModel)]="rating" [stars]="5" [cancel]="true" (onRate)="onRatingChange($event)" />
335
+ ```
336
+
337
+ Key inputs: `stars`, `cancel`, `readonly`, `disabled`, `invalid`, `iconOn`, `iconOff`. Outputs: `onRate`, `onBlur`.
338
+
339
+ ### DatePickerComponent
340
+
341
+ Calendar/date input with single, range, and multiple selection modes. Selector: `f-datepicker`.
342
+
343
+ ```html
344
+ <f-datepicker [(ngModel)]="eventDate" selectionMode="single" [showIcon]="true" [minDate]="today" [placeholder]="'form.selectDate' | translate" />
345
+ ```
346
+
347
+ Key inputs: `placeholder`, `dateFormat`, `disabled`, `showTime`, `selectionMode` (`single | range | multiple`), `minDate`, `maxDate`, `invalid`, `touched`, `showClear`, `showIcon`, `showButtonBar`, `appendTo`. Output: `onBlur`.
348
+
349
+ ### FileUploadComponent
350
+
351
+ File upload with drag-drop, auto-upload, and progress. Selector: `f-fileupload`.
352
+
353
+ ```html
354
+ <f-fileupload accept="image/*" [maxFileSize]="2000000" [multiple]="true" (onSelect)="onFilesSelected($event)" (onError)="onUploadError($event)" />
355
+ ```
356
+
357
+ Key inputs: `name`, `accept`, `multiple`, `auto`, `maxFileSize`, `fileLimit`, `disabled`, `url`, `customUpload`, `chooseLabel`, `mode` (`advanced | basic`). Outputs: `onSelect` (`FileSelectEvent`), `onRemove` (`FileRemoveEvent`), `onClear`, `onError` (`FileErrorEvent[]`).
358
+
359
+ ### AutoCompleteComponent
360
+
361
+ Type-ahead input backed by an async or static suggestion list. Selector: `f-autocomplete`.
362
+
363
+ ```html
364
+ <f-autocomplete [suggestions]="filteredUsers()" field="name" [(ngModel)]="selectedUser" (completeMethod)="search($event.query)" />
365
+ ```
366
+
367
+ Key inputs: `suggestions`, `field`, `placeholder`, `disabled`, `dropdown`, `forceSelection`, `multiple`, `delay`, `minLength`, `invalid`, `touched`. Outputs: `completeMethod` (`AutoCompleteCompleteEvent`), `onSelect` (`AutoCompleteSelectEvent`), `onUnselect`, `onClear`, `onChange`.
368
+
369
+ ### ColorPickerComponent
370
+
371
+ Inline or overlay color picker. Selector: `f-colorpicker`.
372
+
373
+ ```html
374
+ <f-colorpicker [(ngModel)]="brandColor" format="hex" [inline]="false" (onChange)="onColorChange($event)" />
375
+ ```
376
+
377
+ Key inputs: `format` (`hex | rgb | hsb`), `inline`, `disabled`, `invalid`. Output: `onChange` (`ColorPickerChangeEvent`).
378
+
379
+ ### ListboxComponent
380
+
381
+ Scrollable option list with optional filter and multi-select. Selector: `f-listbox`.
382
+
383
+ ```html
384
+ <f-listbox [options]="statuses" optionLabel="label" [(ngModel)]="selectedStatus" [filter]="true" />
385
+ ```
386
+
387
+ Key inputs: `options`, `optionLabel`, `optionValue`, `multiple`, `filter`, `filterPlaceholder`, `disabled`, `metaKeySelection`, `emptyMessage`. Output: `onChange` (`ListboxChangeEvent`).
388
+
389
+ ### InputMaskDirective
390
+
391
+ Applies a slotted input mask to a native `<input>`. Selector: `[fInputMask]`.
392
+
393
+ ```html
394
+ <input fInputMask="(999) 999-9999" slotChar="_" [placeholder]="'form.phonePlaceholder' | translate" />
395
+ ```
396
+
397
+ Key inputs: `fInputMask` (mask pattern), `slotChar`.
398
+
399
+ ### InputOtpComponent
400
+
401
+ Segmented one-time-passcode input. Selector: `f-inputotp`.
402
+
403
+ ```html
404
+ <f-inputotp [(ngModel)]="otpCode" [length]="6" [integerOnly]="true" [mask]="false" />
405
+ ```
406
+
407
+ Key inputs: `length`, `mask`, `disabled`, `integerOnly`, `invalid`.
408
+
409
+ ### SliderComponent
410
+
411
+ Range slider input, single or dual-handle. Selector: `f-slider`.
412
+
413
+ ```html
414
+ <f-slider [(ngModel)]="priceRange" [min]="0" [max]="1000" [range]="true" />
415
+ ```
416
+
417
+ Key inputs: `min`, `max`, `step`, `range`, `disabled`.
418
+
419
+ ### KnobComponent
420
+
421
+ Circular dial numeric input. Selector: `f-knob`.
422
+
423
+ ```html
424
+ <f-knob [(ngModel)]="volume" [min]="0" [max]="100" [size]="100" valueColor="var(--f-primary-500)" />
425
+ ```
426
+
427
+ Key inputs: `size`, `min`, `max`, `step`, `strokeWidth`, `showValue`, `disabled`, `readonly`, `valueColor`, `rangeColor`, `textColor`.
428
+
429
+ ### CascadeSelectComponent
430
+
431
+ Hierarchical dependent-option selector (e.g. country → state → city). Selector: `f-cascadeselect`.
432
+
433
+ ```html
434
+ <f-cascadeselect [options]="locations" optionLabel="label" optionChildren="children" [(ngModel)]="selectedLocation" />
435
+ ```
436
+
437
+ Key inputs: `options`, `optionLabel`, `optionValue`, `optionChildren`, `placeholder`, `disabled`, `invalid`, `touched`.
438
+
439
+ ### KeyFilterDirective
440
+
441
+ Restricts keystrokes on a native input to a preset or custom pattern. Selector: `[fKeyFilter]`.
442
+
443
+ ```html
444
+ <input fInputText [fKeyFilter]="'num'" />
445
+ ```
446
+
447
+ Key input: `fKeyFilter` (`'int' | 'pint' | 'num' | 'pnum' | 'money' | 'alpha' | 'alphanum' | 'email' | RegExp | null`).
448
+
449
+ ### TreeSelectComponent
450
+
451
+ Select input backed by a hierarchical tree of options. Selector: `f-treeselect`.
452
+
453
+ ```html
454
+ <f-treeselect [options]="orgTree" [(ngModel)]="selectedNode" selectionMode="checkbox" [filter]="true" />
455
+ ```
456
+
457
+ Key inputs: `options` (`TreeNode[]`), `placeholder`, `disabled`, `filter`, `selectionMode` (`single | multiple | checkbox`), `invalid`, `touched`.
458
+
459
+ ### IconFieldComponent / InputIconComponent
460
+
461
+ Positions an icon inside a text input (search boxes, etc.) via content projection. Selectors: `f-iconfield`, `f-inputicon`.
462
+
463
+ ```html
464
+ <f-iconfield>
465
+ <f-inputicon><ui-icon name="search" /></f-inputicon>
466
+ <input fInputText [placeholder]="'shared.search' | translate" />
467
+ </f-iconfield>
468
+ ```
469
+
470
+ ### FloatLabelComponent
471
+
472
+ Floats a `<label>` above the input on focus/fill. Selector: `f-floatlabel`.
473
+
474
+ ```html
475
+ <f-floatlabel variant="over">
476
+ <input fInputText id="email" />
477
+ <label for="email">{{ 'form.email' | translate }}</label>
478
+ </f-floatlabel>
479
+ ```
480
+
481
+ Key input: `variant` (`over | in | on`).
482
+
483
+ ### IftaLabelComponent
484
+
485
+ "In-the-field" label layout, pairing a persistent inline label with the input. Selector: `f-iftalabel`.
486
+
487
+ ```html
488
+ <f-iftalabel>
489
+ <input fInputText id="username" />
490
+ <label for="username">{{ 'form.username' | translate }}</label>
491
+ </f-iftalabel>
492
+ ```
493
+
494
+ ### InputGroupComponent / InputGroupAddonComponent
495
+
496
+ Groups an input with leading/trailing addons (currency symbols, buttons). Selectors: `f-inputgroup`, `f-inputgroupaddon`.
497
+
498
+ ```html
499
+ <f-inputgroup>
500
+ <f-inputgroupaddon>$</f-inputgroupaddon>
501
+ <input fInputText type="number" />
502
+ </f-inputgroup>
503
+ ```
504
+
505
+ ### FluidComponent
506
+
507
+ Stretches all descendant form controls to full width. Selector: `f-fluid`.
508
+
509
+ ```html
510
+ <f-fluid>
511
+ <f-select [options]="items" />
512
+ </f-fluid>
513
+ ```
514
+
515
+ ---
516
+
517
+ ## Data Display & Tables
518
+
519
+ ### TableComponent
520
+
521
+ Full-featured data table — sorting, pagination, lazy loading, scrollable body. Selector: `f-table`.
522
+
523
+ ```html
524
+ <f-table [value]="rows()" [lazy]="true" [loading]="loading()" [totalRecords]="total()" [rows]="pageSize" [paginator]="true" (onLazyLoad)="loadPage($event)">
525
+ <ng-template fTemplate="header">
526
+ <th fSortableColumn="name">{{ 'shared.name' | translate }} <f-sorticon field="name" /></th>
527
+ </ng-template>
528
+ <ng-template fTemplate="body" let-row>
529
+ <td>{{ row.name }}</td>
530
+ </ng-template>
531
+ </f-table>
532
+ ```
533
+
534
+ Key inputs: `value`, `lazy`, `loading`, `rows`, `totalRecords`, `rowHover`, `dataKey`, `scrollable`, `paginator`, `first`, `rowsPerPageOptions`, `tableStyle`, `globalFilterFields`. Models: `sortField`, `sortOrder`. Outputs: `onLazyLoad` (`TableLazyLoadEvent`), `onSort` (`TableSortEvent`). Supports `fTemplate="header" | "body" | "emptymessage"`.
535
+
536
+ ### SortIconComponent / SortableColumnDirective
537
+
538
+ Sort indicator and clickable sortable-column host, used inside `f-table` headers. Selectors: `f-sorticon`, `[fSortableColumn]`.
539
+
540
+ ```html
541
+ <th fSortableColumn="createdAt">{{ 'shared.createdAt' | translate }} <f-sorticon field="createdAt" /></th>
542
+ ```
543
+
544
+ Key input: `fSortableColumn` / `field` — the field name to sort by.
545
+
546
+ ### PaginatorComponent
547
+
548
+ Standalone pagination control (also used internally by `f-table`/`f-dataview`). Selector: `f-paginator`.
549
+
550
+ ```html
551
+ <f-paginator [first]="first" [rows]="10" [totalRecords]="total" (onPageChange)="onPage($event)" />
552
+ ```
553
+
554
+ Key inputs: `first`, `rows`, `totalRecords`, `rowsPerPageOptions`, `showCurrentPageReport`, `currentPageReportTemplate`. Output: `onPageChange` (`PaginatorState`).
555
+
556
+ ### TreeTableComponent
557
+
558
+ Hierarchical table combining tree expand/collapse with tabular columns. Selector: `f-treetable`.
559
+
560
+ ```html
561
+ <f-treetable [value]="orgNodes" [loading]="loading()" dataKey="id">
562
+ <ng-template fTemplate="header">
563
+ <th>{{ 'shared.name' | translate }}</th>
564
+ </ng-template>
565
+ <ng-template fTemplate="body" let-rowNode>
566
+ <td><f-treetabletoggler [rowNode]="rowNode" /> {{ rowNode.node.label }}</td>
567
+ </ng-template>
568
+ </f-treetable>
569
+ ```
570
+
571
+ Key inputs: `value` (`TreeNode[]`), `loading`, `dataKey`, `scrollable`, `tableStyle`. `TreeTableTogglerComponent` (`f-treetabletoggler`) requires `rowNode: input.required<TreeTableNode>()`. `TreeTableService` exposes an `expanded` signal and `toggle(key, node)` for custom expand/collapse UIs.
572
+
573
+ ### TreeComponent
574
+
575
+ Hierarchical tree view with selection and filtering. Selector: `f-tree`.
576
+
577
+ ```html
578
+ <f-tree [value]="categoryTree" selectionMode="checkbox" [filter]="true" (selectionChange)="onSelect($event)" />
579
+ ```
580
+
581
+ Key inputs: `value` (`TreeNode[]`), `selectionMode` (`single | multiple | checkbox | null`), `filter`, `loading`, `emptyMessage`. Outputs: `selectionChange`, `nodeExpand`, `nodeCollapse`.
582
+
583
+ ### DataViewComponent
584
+
585
+ List/grid toggleable data view with built-in pagination. Selector: `f-dataview`.
586
+
587
+ ```html
588
+ <f-dataview [value]="products()" [paginator]="true" [rows]="12" [(layout)]="viewLayout" (onPageChange)="onPage($event)">
589
+ <ng-template let-item>
590
+ <div>{{ item.name }}</div>
591
+ </ng-template>
592
+ </f-dataview>
593
+ ```
594
+
595
+ Key inputs: `value`, `showLayoutToggle`, `paginator`, `rows`, `totalRecords`, `first`, `loading`. Model: `layout` (`'list' | 'grid'`). Output: `onPageChange`.
596
+
597
+ ### OrganizationChartComponent
598
+
599
+ Renders a `TreeNode` hierarchy as a top-down org chart. Selector: `f-organizationchart`.
600
+
601
+ ```html
602
+ <f-organizationchart [value]="ceoNode">
603
+ <ng-template let-node>{{ node.label }}</ng-template>
604
+ </f-organizationchart>
605
+ ```
606
+
607
+ Key input: `value` (`TreeNode | null`).
608
+
609
+ ### PickListComponent
610
+
611
+ Dual-list source/target transfer control. Selector: `f-picklist`.
612
+
613
+ ```html
614
+ <f-picklist [(source)]="available" [(target)]="assigned" [sourceHeader]="'shared.available' | translate" [targetHeader]="'shared.assigned' | translate" />
615
+ ```
616
+
617
+ Key inputs/models: `source`, `target` (models), `sourceHeader`, `targetHeader`. Outputs: `onMoveToTarget`, `onMoveToSource`.
618
+
619
+ ### OrderListComponent
620
+
621
+ Reorderable single-list control with up/down/top/bottom controls. Selector: `f-orderlist`.
622
+
623
+ ```html
624
+ <f-orderlist [(value)]="steps" [header]="'shared.steps' | translate" (onReorder)="onReorder($event)" />
625
+ ```
626
+
627
+ Key inputs: `value` (model), `header`, `selected` (model). Output: `onReorder`.
628
+
629
+ ### ScrollerComponent
630
+
631
+ Virtual scroller for large flat lists. Selector: `f-scroller`.
632
+
633
+ ```html
634
+ <f-scroller [items]="bigList()" [itemSize]="40" scrollHeight="20rem">
635
+ <ng-template let-item>{{ item.label }}</ng-template>
636
+ </f-scroller>
637
+ ```
638
+
639
+ Key inputs: `items`, `itemSize`, `scrollHeight`.
640
+
641
+ ### TimelineComponent
642
+
643
+ Vertical/horizontal timeline of events. Selector: `f-timeline`.
644
+
645
+ ```html
646
+ <f-timeline [value]="events()" align="alternate" layout="vertical">
647
+ <ng-template let-event>{{ event.status }}</ng-template>
648
+ </f-timeline>
649
+ ```
650
+
651
+ Key inputs: `value`, `align` (`left | right | alternate`), `layout` (`vertical | horizontal`).
652
+
653
+ ### ChartComponent
654
+
655
+ Canvas-based chart wrapper (bar/line/pie/etc.). Selector: `f-chart`.
656
+
657
+ ```html
658
+ <f-chart type="bar" [data]="chartData" [options]="chartOptions" height="300" />
659
+ ```
660
+
661
+ Key inputs: `type`, `data`, `options`, `width`, `height`.
662
+
663
+ ### MeterGroupComponent
664
+
665
+ Segmented meter/progress bar for showing proportional values. Selector: `f-metergroup`.
666
+
667
+ ```html
668
+ <f-metergroup [values]="[{ label: 'Used', value: 65, color: 'var(--f-primary-500)' }]" [max]="100" />
669
+ ```
670
+
671
+ Key inputs: `values` (`MeterItem[]`), `min`, `max`.
672
+
673
+ ---
674
+
675
+ ## Overlays & Dialogs
676
+
677
+ ### DialogComponent
678
+
679
+ Modal dialog with header, footer template, and resizing. Selector: `f-dialog`.
680
+
681
+ ```html
682
+ <f-dialog [(visible)]="showDialog" [header]="'shared.editUser' | translate" [modal]="true" [closable]="true">
683
+ <p>Content</p>
684
+ <ng-template #footer>
685
+ <f-button [label]="'shared.close' | translate" (onClick)="showDialog.set(false)" />
686
+ </ng-template>
687
+ </f-dialog>
688
+ ```
689
+
690
+ Key inputs: `header`, `modal`, `closable`, `dismissableMask`, `resizable`, `style`, `breakpoints`. Model: `visible`. Outputs: `onShow`, `onHide`. Supports `#footer` template ref and `fTemplate` content children.
691
+
692
+ ### DrawerComponent
693
+
694
+ Slide-in panel from any edge of the viewport. Selector: `f-drawer`.
695
+
696
+ ```html
697
+ <f-drawer [(visible)]="showDrawer" position="right" [header]="'shared.filters' | translate">
698
+ <p>Filter controls</p>
699
+ </f-drawer>
700
+ ```
701
+
702
+ Key inputs: `header`, `position` (`left | right | top | bottom`), `fullScreen`, `modal`, `closable`, `closeOnEscape`. Model: `visible`. Output: `onHide`.
703
+
704
+ ### PopoverComponent
705
+
706
+ Anchored overlay panel triggered programmatically. Selector: `f-popover`.
707
+
708
+ ```html
709
+ <f-popover #op [dismissable]="true">
710
+ <p>Popover content</p>
711
+ </f-popover>
712
+ <f-button label="Show" (onClick)="op.toggle($event)" />
713
+ ```
714
+
715
+ Key input: `dismissable`.
716
+
717
+ ### ConfirmDialog
718
+
719
+ Global confirmation modal driven by `ConfirmationService.confirm()`. Selector: `f-confirmdialog`. Place once in the app shell; supports multiple independent instances via the `key` input matched against `ConfirmationService.confirm({ key })`.
720
+
721
+ ```html
722
+ <f-confirmdialog />
723
+ ```
724
+
725
+ ### ConfirmPopupComponent
726
+
727
+ Anchored (non-modal) confirmation popup, also driven by `ConfirmationService`. Selector: `f-confirmpopup`.
728
+
729
+ ```html
730
+ <f-confirmpopup />
731
+ <f-button label="Delete" (onClick)="confirmationService.confirm({ target: $event.target, message: 'Sure?', accept: onDelete })" />
732
+ ```
733
+
734
+ Key input: `key`.
735
+
736
+ ### DynamicDialogComponent / DynamicDialogService
737
+
738
+ Renders arbitrary components inside a dialog shell opened imperatively. Selector: `f-dynamicdialog`.
739
+
740
+ ```html
741
+ <f-dynamicdialog />
742
+ ```
743
+
744
+ ```typescript
745
+ import { DynamicDialogService, DYNAMIC_DIALOG_DATA, DYNAMIC_DIALOG_REF } from "@flusys/ng-ui";
746
+
747
+ const dialogService = inject(DynamicDialogService);
748
+ const ref = dialogService.open(UserFormComponent, { header: "Edit User", width: "32rem", data: { id: userId } });
749
+ ref.onClose.subscribe((result) => reloadList());
750
+
751
+ // Inside UserFormComponent:
752
+ private readonly data = inject(DYNAMIC_DIALOG_DATA);
753
+ private readonly ref = inject(DYNAMIC_DIALOG_REF);
754
+ this.ref.close(updatedUser);
755
+ ```
756
+
757
+ `DynamicDialogConfig`: `header`, `width`, `height`, `closable`, `closeOnEscape`, `dismissableMask`, `footer`, `data`.
758
+
759
+ ### BlockUiComponent
760
+
761
+ Overlays a blocking mask + spinner over its projected content. Selector: `f-blockui`.
762
+
763
+ ```html
764
+ <f-blockui [blocked]="isSaving()">
765
+ <form>...</form>
766
+ </f-blockui>
767
+ ```
768
+
769
+ Key inputs: `blocked`, `hasCustomTemplate` (set `true` when projecting a custom `[block-template]` node instead of the default spinner).
770
+
771
+ ### ToastComponent
772
+
773
+ Renders queued messages from `MessageService`. Selector: `f-toast`.
774
+
775
+ ```html
776
+ <f-toast position="top-right" key="main" />
777
+ ```
778
+
779
+ Key inputs: `key`, `position` (`top-right | top-left | top-center | bottom-right | bottom-left | bottom-center | center`).
780
+
781
+ ---
782
+
783
+ ## Navigation & Menus
784
+
785
+ ### MenuComponent
786
+
787
+ Flat or popup vertical menu. Selector: `f-menu`.
788
+
789
+ ```html
790
+ <f-menu #menu [model]="actions" [popup]="true" />
791
+ <f-button icon="ellipsis" (onClick)="menu.toggle($event)" />
792
+ ```
793
+
794
+ Key inputs: `model` (`MenuItem[]`), `popup`.
795
+
796
+ ### MenubarComponent
797
+
798
+ Horizontal top-level navigation bar with nested submenus. Selector: `f-menubar`.
799
+
800
+ ```html
801
+ <f-menubar [model]="navItems" />
802
+ ```
803
+
804
+ Key input: `model` (`MenuItem[]`).
805
+
806
+ ### TieredMenuComponent
807
+
808
+ Multi-level flyout menu (hover/click cascading submenus). Selector: `f-tieredmenu`.
809
+
810
+ ```html
811
+ <f-tieredmenu [model]="menuItems" [popup]="false" />
812
+ ```
813
+
814
+ Key inputs: `model`, `popup`.
815
+
816
+ ### ContextMenuComponent
817
+
818
+ Right-click context menu bound to a target selector. Selector: `f-contextmenu`.
819
+
820
+ ```html
821
+ <f-contextmenu [model]="rowActions" target=".table-row" />
822
+ ```
823
+
824
+ Key inputs: `model`, `target`.
825
+
826
+ ### MegaMenuComponent
827
+
828
+ Multi-column dropdown navigation (site-wide mega menus). Selector: `f-megamenu`.
829
+
830
+ ```html
831
+ <f-megamenu [model]="megaMenuItems" />
832
+ ```
833
+
834
+ Key input: `model` (`MenuItem[]`, each top item's `items` render as columns).
835
+
836
+ ### PanelMenuComponent
837
+
838
+ Accordion-style vertical menu with nested expand/collapse. Selector: `f-panelmenu`.
839
+
840
+ ```html
841
+ <f-panelmenu [model]="sidebarItems" [multiple]="true" />
842
+ ```
843
+
844
+ Key inputs: `model`, `multiple` (allow more than one root panel expanded at once, default `true`).
845
+
846
+ ### BreadcrumbComponent
847
+
848
+ Horizontal breadcrumb trail. Selector: `f-breadcrumb`.
849
+
850
+ ```html
851
+ <f-breadcrumb [model]="crumbs" [home]="{ icon: 'home', routerLink: '/' }" />
852
+ ```
853
+
854
+ Key inputs: `model` (`MenuItem[]`), `home`.
855
+
856
+ ### DockComponent
857
+
858
+ macOS-dock-style icon launcher with magnification. Selector: `f-dock`.
859
+
860
+ ```html
861
+ <f-dock [model]="appShortcuts" position="bottom" />
862
+ ```
863
+
864
+ Key inputs: `model` (`MenuItem[]`), `position` (`DockPosition`).
865
+
866
+ ### StepsComponent
867
+
868
+ Linear step/wizard indicator. Selector: `f-steps`.
869
+
870
+ ```html
871
+ <f-steps [model]="wizardSteps" [activeIndex]="currentStep()" (onActiveIndexChange)="currentStep.set($event)" />
872
+ ```
873
+
874
+ Key inputs: `model` (`StepsMenuItem[]`, alias of `MenuItem[]`), `activeIndex`, `readonly`. Output: `onActiveIndexChange`.
875
+
876
+ ### TabsComponent family
877
+
878
+ Composable tabs: `TabsComponent` (`f-tabs`), `TabListComponent` (`f-tablist`), `TabComponent` (`f-tab`), `TabPanelsComponent` (`f-tabpanels`), `TabPanelComponent` (`f-tabpanel`).
879
+
880
+ ```html
881
+ <f-tabs [(value)]="activeTab">
882
+ <f-tablist>
883
+ <f-tab value="general">{{ 'shared.general' | translate }}</f-tab>
884
+ <f-tab value="security">{{ 'shared.security' | translate }}</f-tab>
885
+ </f-tablist>
886
+ <f-tabpanels>
887
+ <f-tabpanel value="general">General content</f-tabpanel>
888
+ <f-tabpanel value="security">Security content</f-tabpanel>
889
+ </f-tabpanels>
890
+ </f-tabs>
891
+ ```
892
+
893
+ `f-tabs` model: `value`; input `scrollable`; output `onTabChange`. `f-tab` inputs: `value`, `disabled`. `TabsContext` is the internal `@Injectable()` DI context `f-tabs` provides for its children to read active/scrollable state — not instantiated directly by consumers.
894
+
895
+ ---
896
+
897
+ ## Media
898
+
899
+ ### ImageComponent
900
+
901
+ Image with optional full-screen preview overlay. Selector: `f-image`.
902
+
903
+ ```html
904
+ <f-image [src]="avatarUrl()" [alt]="user.name" [preview]="true" width="120" />
905
+ ```
906
+
907
+ Key inputs: `src`, `alt`, `width`, `height`, `preview`. Outputs: `onShow`, `onHide`.
908
+
909
+ ### GalleriaComponent
910
+
911
+ Image gallery with thumbnail strip. Selector: `f-galleria`.
912
+
913
+ ```html
914
+ <f-galleria [value]="photos" [showThumbnails]="true" height="24rem" />
915
+ ```
916
+
917
+ Key inputs: `value` (`GalleriaItem[]` — `itemImageSrc`, `thumbnailImageSrc?`, `alt?`), `showThumbnails`, `height`.
918
+
919
+ ### CarouselComponent
920
+
921
+ Sliding item carousel with configurable visible-item count and autoplay. Selector: `f-carousel`.
922
+
923
+ ```html
924
+ <f-carousel [value]="banners()" [numVisible]="1" [autoplayInterval]="5000" (onPage)="onPageChange($event)">
925
+ <ng-template let-item>{{ item.title }}</ng-template>
926
+ </f-carousel>
927
+ ```
928
+
929
+ Key inputs: `value`, `numVisible`, `showIndicators`, `circular`, `autoplayInterval`. Output: `onPage`.
930
+
931
+ ### ImageCompareComponent
932
+
933
+ Before/after image slider comparison. Selector: `f-imagecompare`.
934
+
935
+ ```html
936
+ <f-imagecompare [imageBeforeSrc]="before" [imageAfterSrc]="after" height="20rem" />
937
+ ```
938
+
939
+ Key inputs: `imageBeforeSrc`, `imageAfterSrc`, `altBefore`, `altAfter`, `height`.
940
+
941
+ ### AvatarComponent / AvatarGroupComponent
942
+
943
+ User avatar (image, initials, or icon) and stacked group wrapper. Selectors: `f-avatar`, `f-avatar-group`.
944
+
945
+ ```html
946
+ <f-avatar-group>
947
+ <f-avatar image="/user1.png" shape="circle" size="large" />
948
+ <f-avatar label="JD" shape="circle" />
949
+ </f-avatar-group>
950
+ ```
951
+
952
+ Key inputs (`f-avatar`): `label`, `icon`, `image`, `shape` (`square | circle`), `size` (`normal | large | xlarge`), `color`, `styleClass`.
953
+
954
+ ---
955
+
956
+ ## Feedback & Status
957
+
958
+ ### TagComponent
959
+
960
+ Small inline status label. Selector: `f-tag`.
961
+
962
+ ```html
963
+ <f-tag [value]="'shared.active' | translate" severity="success" icon="check" [rounded]="true" />
964
+ ```
965
+
966
+ Key inputs: `value`, `severity` (`success | info | warn | danger | secondary | contrast | null`), `icon`, `rounded`, `color`.
967
+
968
+ ### BadgeComponent
969
+
970
+ Small numeric/status indicator, standalone or attached to an element. Selector: `f-badge`.
971
+
972
+ ```html
973
+ <f-badge [value]="unreadCount()" severity="danger" size="small" />
974
+ ```
975
+
976
+ Key inputs: `value`, `severity` (`BadgeSeverity`), `size` (`small | large | xlarge | null`).
977
+
978
+ ### OverlayBadgeComponent
979
+
980
+ Positions a badge in the corner of its projected content (e.g. bell icon with unread count). Selector: `f-overlaybadge`.
981
+
982
+ ```html
983
+ <f-overlaybadge [value]="notificationCount()" severity="danger">
984
+ <ui-icon name="bell" />
985
+ </f-overlaybadge>
986
+ ```
987
+
988
+ Key inputs: `value`, `severity`, `size`.
989
+
990
+ ### MessageComponent
991
+
992
+ Inline severity-styled message banner. Selector: `f-message`.
993
+
994
+ ```html
995
+ <f-message severity="warn" [text]="'form.unsavedChanges' | translate" icon="alert-triangle" />
996
+ ```
997
+
998
+ Key inputs: `severity` (`success | info | warn | error`), `text`, `icon`.
999
+
1000
+ ### ProgressbarComponent
1001
+
1002
+ Horizontal progress indicator. Selector: `f-progressbar`.
1003
+
1004
+ ```html
1005
+ <f-progressbar [value]="uploadProgress()" mode="determinate" [showValue]="true" />
1006
+ ```
1007
+
1008
+ Key inputs: `value`, `mode` (`determinate | indeterminate`), `showValue`.
1009
+
1010
+ ### ProgressSpinnerComponent
1011
+
1012
+ Circular loading spinner. Selector: `f-progressspinner`.
1013
+
1014
+ ```html
1015
+ <f-progressspinner [size]="40" [strokeWidth]="4" />
1016
+ ```
1017
+
1018
+ Key inputs: `size`, `strokeWidth`.
1019
+
1020
+ ### SkeletonComponent
1021
+
1022
+ Loading placeholder block. Selector: `f-skeleton`.
1023
+
1024
+ ```html
1025
+ <f-skeleton width="100%" height="1.5rem" shape="rectangle" />
1026
+ ```
1027
+
1028
+ Key inputs: `width`, `height`, `borderRadius`, `shape` (`rectangle | circle`).
1029
+
1030
+ ### ChipComponent
1031
+
1032
+ Removable label chip. Selector: `f-chip`.
1033
+
1034
+ ```html
1035
+ <f-chip [label]="tag.name" [removable]="true" (onRemove)="removeTag(tag)" />
1036
+ ```
1037
+
1038
+ Key inputs: `label`, `icon`, `removable`. Output: `onRemove`.
1039
+
1040
+ ---
1041
+
1042
+ ## Layout
1043
+
1044
+ ### CardComponent
1045
+
1046
+ Content card with optional header/footer templates. Selector: `f-card`.
1047
+
1048
+ ```html
1049
+ <f-card [header]="'shared.summary' | translate" styleClass="mb-4">
1050
+ <p>Body content</p>
1051
+ <ng-template #footer><f-button label="Details" text /></ng-template>
1052
+ </f-card>
1053
+ ```
1054
+
1055
+ Key inputs: `header`, `subheader`, `styleClass`. Content templates: `#header`, `#footer`.
1056
+
1057
+ ### PanelComponent
1058
+
1059
+ Collapsible titled panel. Selector: `f-panel`.
1060
+
1061
+ ```html
1062
+ <f-panel [header]="'shared.advanced' | translate" [toggleable]="true" [(collapsed)]="advancedCollapsed">
1063
+ <p>Advanced settings</p>
1064
+ </f-panel>
1065
+ ```
1066
+
1067
+ Key inputs: `header`, `toggleable`. Model: `collapsed`.
1068
+
1069
+ ### FieldsetComponent
1070
+
1071
+ Bordered/legend-labeled grouping, optionally collapsible. Selector: `f-fieldset`.
1072
+
1073
+ ```html
1074
+ <f-fieldset [legend]="'shared.contactInfo' | translate" [toggleable]="true" [(collapsed)]="contactCollapsed">
1075
+ <p>Fields</p>
1076
+ </f-fieldset>
1077
+ ```
1078
+
1079
+ Key inputs: `legend`, `toggleable`. Model: `collapsed`.
1080
+
1081
+ ### AccordionComponent family
1082
+
1083
+ Composable accordion: `AccordionComponent` (`f-accordion`), `AccordionPanelComponent` (`f-accordion-panel`), `AccordionHeaderComponent` (`f-accordion-header`), `AccordionContentComponent` (`f-accordion-content`).
1084
+
1085
+ ```html
1086
+ <f-accordion [multiple]="false" [(value)]="activePanel">
1087
+ <f-accordion-panel value="0">
1088
+ <f-accordion-header>{{ 'shared.section1' | translate }}</f-accordion-header>
1089
+ <f-accordion-content>Content 1</f-accordion-content>
1090
+ </f-accordion-panel>
1091
+ </f-accordion>
1092
+ ```
1093
+
1094
+ `f-accordion` input: `multiple`; model: `value`; outputs: `onOpen`, `onClose`. `f-accordion-panel` inputs: `value`, `disabled`. `AccordionContext` is the internal `@Injectable()` DI context `f-accordion` provides for its panels — not instantiated directly by consumers.
1095
+
1096
+ ### SplitterComponent
1097
+
1098
+ Resizable multi-pane layout via draggable gutters. `SplitterComponent` selector: `f-splitter`; panels use `SplitterPanelComponent`, selector: `f-splitter-panel`.
1099
+
1100
+ ```html
1101
+ <f-splitter layout="horizontal" [panelSizes]="[30, 70]">
1102
+ <f-splitter-panel>Sidebar</f-splitter-panel>
1103
+ <f-splitter-panel>Content</f-splitter-panel>
1104
+ </f-splitter>
1105
+ ```
1106
+
1107
+ Key inputs: `layout` (`horizontal | vertical`), `panelSizes`, `minSizes`, `styleClass`.
1108
+
1109
+ ### ToolbarComponent
1110
+
1111
+ Header/action toolbar with start/center/end projection slots. Selector: `f-toolbar`.
1112
+
1113
+ ```html
1114
+ <f-toolbar>
1115
+ <ng-template fTemplate="start"><h2>{{ 'shared.title' | translate }}</h2></ng-template>
1116
+ <ng-template fTemplate="end"><f-button label="New" /></ng-template>
1117
+ </f-toolbar>
1118
+ ```
1119
+
1120
+ Key input: `styleClass`.
1121
+
1122
+ ### DividerComponent
1123
+
1124
+ Horizontal/vertical separator, optionally with centered content/label. Selector: `f-divider`.
1125
+
1126
+ ```html
1127
+ <f-divider layout="horizontal" type="dashed" align="center">{{ 'shared.or' | translate }}</f-divider>
1128
+ ```
1129
+
1130
+ Key inputs: `layout` (`horizontal | vertical`), `type` (`solid | dashed | dotted`), `align` (`left | center | right`).
1131
+
1132
+ ### ScrollPanelComponent
1133
+
1134
+ Custom-styled scrollable container. Selector: `f-scrollpanel`.
1135
+
1136
+ ```html
1137
+ <f-scrollpanel maxHeight="20rem">
1138
+ <p>Long content...</p>
1139
+ </f-scrollpanel>
1140
+ ```
1141
+
1142
+ Key inputs: `maxHeight`, `maxWidth`.
1143
+
1144
+ ### ScrollTopComponent
1145
+
1146
+ Floating "scroll to top" button, appears after a scroll threshold. Selector: `f-scrolltop`.
1147
+
1148
+ ```html
1149
+ <f-scrolltop [threshold]="400" target="window" [buttonAriaLabel]="'shared.scrollToTop' | translate" />
1150
+ ```
1151
+
1152
+ Key inputs: `threshold`, `behavior` (`ScrollBehavior`), `target` (`window | parent`), `buttonAriaLabel`.
1153
+
1154
+ ### InplaceComponent
1155
+
1156
+ Toggles between a display view and an editable/expanded view in place. Selector: `f-inplace`.
1157
+
1158
+ ```html
1159
+ <f-inplace [(active)]="isEditing">
1160
+ <ng-template #display>{{ value() }}</ng-template>
1161
+ <ng-template #content><input fInputText [(ngModel)]="value" /></ng-template>
1162
+ </f-inplace>
1163
+ ```
1164
+
1165
+ Key input: `disabled`. Model: `active`. Outputs: `onActivate`, `onDeactivate`.
1166
+
1167
+ ---
1168
+
1169
+ ## Directives & Utilities
1170
+
1171
+ ### TooltipDirective
1172
+
1173
+ Attaches a hover/focus tooltip to any element. Selector: `[fTooltip]`.
1174
+
1175
+ ```html
1176
+ <button [fTooltip]="'shared.deleteHint' | translate" tooltipPosition="top"></button>
1177
+ ```
1178
+
1179
+ Key inputs: `fTooltip` (text), `tooltipPosition` (`top | bottom | left | right`), `tooltipStyleClass`, `disabled`, `tooltipEvent` (`hover | focus | both`), `showDelay`, `hideDelay`.
1180
+
1181
+ ### StyleClassDirective
1182
+
1183
+ Toggles CSS classes on a target element with enter/leave transition class support (accordion/dropdown-style show/hide). Selector: `[fStyleClass]`.
1184
+
1185
+ ```html
1186
+ <button [fStyleClass]="'#panel'" enterFromClass="hidden" enterActiveClass="animate-fade-in" leaveToClass="hidden"></button>
1187
+ ```
1188
+
1189
+ Key inputs: `fStyleClass` (target selector), `enterFromClass`, `enterActiveClass`, `enterToClass`, `leaveFromClass`, `leaveActiveClass`, `leaveToClass`, `hideOnOutsideClick`, `toggleClass`.
1190
+
1191
+ ### AnimateOnScrollDirective
1192
+
1193
+ Adds an enter animation class when the host scrolls into the viewport. Selector: `[fAnimateOnScroll]`.
1194
+
1195
+ ```html
1196
+ <div fAnimateOnScroll enterClass="animate-fade-in" [once]="true" [threshold]="0.15">Content</div>
1197
+ ```
1198
+
1199
+ Key inputs: `enterClass`, `leaveClass`, `once`, `threshold`.
1200
+
1201
+ ### AutoFocusDirective
1202
+
1203
+ Focuses the host element on init when enabled. Selector: `[fAutoFocus]`.
1204
+
1205
+ ```html
1206
+ <input fInputText [fAutoFocus]="true" />
1207
+ ```
1208
+
1209
+ Key input: `fAutoFocus`.
1210
+
1211
+ ### RippleDirective
1212
+
1213
+ Adds a Material-style ripple feedback effect on click. Selector: `[fRipple]`.
1214
+
1215
+ ```html
1216
+ <button fButton fRipple label="Click me"></button>
1217
+ ```
1218
+
1219
+ `KeyFilterDirective` and `InputMaskDirective` are documented under [Form Inputs](#form-inputs) above.
1220
+
1221
+ ### FTemplateDirective
1222
+
1223
+ Marks an `ng-template` as a named content slot consumed by host components (table headers/body, toolbar start/end, dialog footer, etc.). Selector: `ng-template[fTemplate]`.
1224
+
1225
+ ```html
1226
+ <ng-template fTemplate="body" let-row>{{ row.name }}</ng-template>
1227
+ ```
1228
+
1229
+ Key input: `fTemplate` (slot name).
1230
+
1231
+ ### UiIconComponent
1232
+
1233
+ Renders a Lucide icon by name, with PrimeIcons-style aliases mapped internally for drop-in compatibility. Selector: `ui-icon`.
1234
+
1235
+ ```html
1236
+ <ui-icon name="check-circle" [size]="20" [spin]="false" />
1237
+ ```
1238
+
1239
+ Key inputs: `name`, `size` (default `16`), `spin`, `fill`.
1240
+
1241
+ ### EditorComponent
1242
+
1243
+ Rich-text editor with `ControlValueAccessor` support. Selector: `f-editor`.
1244
+
1245
+ ```html
1246
+ <f-editor [(ngModel)]="htmlContent" [placeholder]="'form.writeHere' | translate" />
1247
+ ```
1248
+
1249
+ Key input: `placeholder`.
1250
+
1251
+ ### TerminalComponent
1252
+
1253
+ Interactive command-line-style output panel. Selector: `f-terminal`.
1254
+
1255
+ ```html
1256
+ <f-terminal [welcomeMessage]="'Welcome to FLUSYS CLI'" prompt="$" (onCommand)="runCommand($event.command)" />
1257
+ ```
1258
+
1259
+ Key inputs: `welcomeMessage`, `prompt`, `height`. Output: `onCommand` (`TerminalCommandEvent`).
1260
+
1261
+ ---
1262
+
1263
+ ## Interfaces
1264
+
1265
+ ```typescript
1266
+ import type { MenuItem, MenuItemCommandEvent, TreeNode } from "@flusys/ng-ui";
1267
+
1268
+ interface MenuItem {
1269
+ label?: string;
1270
+ icon?: string;
1271
+ command?: (event: MenuItemCommandEvent) => void;
1272
+ url?: string;
1273
+ routerLink?: string | string[];
1274
+ items?: MenuItem[];
1275
+ disabled?: boolean;
1276
+ visible?: boolean;
1277
+ separator?: boolean;
1278
+ selected?: boolean;
1279
+ badge?: string;
1280
+ // ...
1281
+ }
1282
+
1283
+ interface TreeNode<T = unknown> {
1284
+ data?: T;
1285
+ children?: TreeNode<T>[];
1286
+ expanded?: boolean;
1287
+ leaf?: boolean;
1288
+ label?: string;
1289
+ icon?: string;
1290
+ key?: string;
1291
+ selectable?: boolean;
1292
+ // ...
1293
+ }
1294
+ ```
1295
+
1296
+ `MenuItem` drives every menu-family component (`f-menu`, `f-menubar`, `f-tieredmenu`, `f-contextmenu`, `f-megamenu`, `f-panelmenu`, `f-breadcrumb`, `f-dock`, `f-steps`, `f-speeddial`, `f-splitbutton`). `TreeNode` drives `f-tree`, `f-treeselect`, `f-treetable`, and `f-organizationchart`.
1297
+
1298
+ ## License
1299
+
1300
+ MIT © FLUSYS