@lukfel/ng-scaffold 22.1.13 → 22.2.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 +645 -643
- package/fesm2022/lukfel-ng-scaffold.mjs +32 -10
- package/fesm2022/lukfel-ng-scaffold.mjs.map +1 -1
- package/package.json +1 -1
- package/schematics/ng-add/add-styles.d.ts +2 -1
- package/schematics/ng-add/add-styles.js +52 -27
- package/schematics/ng-add/add-styles.js.map +1 -1
- package/schematics/ng-add/index.d.ts +2 -1
- package/schematics/ng-add/index.js +2 -2
- package/schematics/ng-add/index.js.map +1 -1
- package/schematics/ng-add/schema.d.ts +5 -0
- package/schematics/ng-add/schema.js +3 -0
- package/schematics/ng-add/schema.js.map +1 -0
- package/schematics/ng-add/schema.json +22 -7
- package/schematics/package.json +3 -0
- package/styles/_theme.scss +28 -2
- package/styles/_variables.scss +76 -75
- package/types/lukfel-ng-scaffold.d.ts +21 -16
package/README.md
CHANGED
|
@@ -1,644 +1,646 @@
|
|
|
1
|
-
# Documentation
|
|
2
|
-
## Introduction
|
|
3
|
-
|
|
4
|
-
This Angular library provides a foundational scaffold for modern web and mobile applications. It includes essential UI elements such as a header, sidebar, drawer, footer, floating button, and built-in services for theme switching, language switching, snackbar notifications, dialog management, and breakpoint detection. Simply wrap your `router-outlet` with the `lf-scaffold` element and configure the `ScaffoldConfig` within the `ScaffoldService`.
|
|
5
|
-
|
|
6
|
-
- **NPM**: [@lukfel/ng-scaffold](https://www.npmjs.com/package/@lukfel/ng-scaffold)
|
|
7
|
-
- **Demo**: [lukfel.github.io/ng-scaffold](https://lukfel.github.io/ng-scaffold)
|
|
8
|
-
- **Examples**: [Uglygotchi](https://www.uglygotchi.at), [What a Waste](https://www.what-a-waste.at), [Create a Tournament](https://www.create-a-tournament.com), [Wowen](https://www.wowen.at)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
Install the package using `npm install` or `ng add` (with experimental Angular schematics):
|
|
15
|
-
|
|
16
|
-
```sh
|
|
17
|
-
npm install @lukfel/ng-scaffold
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
```sh
|
|
21
|
-
ng add @lukfel/ng-scaffold
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The ng add command will additionally try to perform the following actions:
|
|
25
|
-
* Import `ScaffoldComponent` in root
|
|
26
|
-
* Inject `ScaffoldService` and initialize `ScaffoldConfig`
|
|
27
|
-
* Wrap template with `<lf-scaffold>`
|
|
28
|
-
* Include styles
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
## Component
|
|
32
|
-
Import the `ScaffoldComponent` into your `app.module.ts` or `app.component.ts` (standalone).
|
|
33
|
-
|
|
34
|
-
```ts
|
|
35
|
-
import { ScaffoldComponent } from '@lukfel/ng-scaffold';
|
|
36
|
-
|
|
37
|
-
...
|
|
38
|
-
imports: [
|
|
39
|
-
ScaffoldComponent
|
|
40
|
-
]
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### (Optional) Provider
|
|
44
|
-
The library uses the built-in logging service `Logger` to log debugging events when a `ScaffoldLibraryConfig` is provided and `debugging` is set to `true`. Logging is automatically disabled in production mode when `production` is set to `true`.
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
import { provideScaffold } from '@lukfel/ng-scaffold';
|
|
48
|
-
import { isDevMode } from '@angular/core';
|
|
49
|
-
|
|
50
|
-
...
|
|
51
|
-
providers: [
|
|
52
|
-
provideScaffold({
|
|
53
|
-
production: !isDevMode(),
|
|
54
|
-
debugging: isDevMode()
|
|
55
|
-
})
|
|
56
|
-
]
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
## Configuration
|
|
63
|
-
Import the `ScaffoldService` in `app.component.ts` to manage the `ScaffoldConfig`.
|
|
64
|
-
|
|
65
|
-
```ts
|
|
66
|
-
import { ScaffoldService } from '@lukfel/ng-scaffold';
|
|
67
|
-
|
|
68
|
-
export class AppComponent {
|
|
69
|
-
|
|
70
|
-
private scaffoldService = inject(ScaffoldService);
|
|
71
|
-
|
|
72
|
-
private scaffoldConfig: ScaffoldConfig = {
|
|
73
|
-
// Create your own config or generate it at https://lukfel.github.io/ng-scaffold
|
|
74
|
-
headerConfig: { enable: true, title: 'Scaffold works!' }
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
constructor() {
|
|
78
|
-
this.scaffoldService.scaffoldConfig = this.scaffoldConfig;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### (Optional) Update Configuration
|
|
84
|
-
The `ScaffoldService` provides `updateScaffoldProperty()` to partially update the `ScaffoldConfig` in a type-safe way. It performs an immutable update, creating a new configuration object with the updated property and emits the new state.
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
import { ScaffoldService, DrawerConfig, HeaderConfig, MenuButton } from '@lukfel/ng-scaffold';
|
|
88
|
-
|
|
89
|
-
export class AppComponent {
|
|
90
|
-
|
|
91
|
-
...
|
|
92
|
-
|
|
93
|
-
// Example #1: Toggle the drawer open state
|
|
94
|
-
public toggleDrawer(): void {
|
|
95
|
-
const open: boolean = this.scaffoldService?.scaffoldConfig?.drawerConfig?.open || false;
|
|
96
|
-
this.scaffoldService.updateScaffoldProperty('drawerConfig', { open: !open });
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Example #2: Enable the header input field
|
|
100
|
-
public enableHeaderInput(): void {
|
|
101
|
-
this.scaffoldService.updateScaffoldProperty('headerConfig', inputConfig: { enable: true });
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Example #2: Add new button to navbar
|
|
105
|
-
public addNavbarButton(button: MenuButton): void {
|
|
106
|
-
const currentNavbarConfig: NavbarConfig = this.scaffoldService.scaffoldConfig.navbarConfig;
|
|
107
|
-
this.scaffoldService.updateScaffoldProperty('navbarConfig', { menuButtons: [...currentNavbarConfig.menuButtons, button] });
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
## Template
|
|
116
|
-
Wrap your application’s content inside the `lf-scaffold` component in `app.component.html`.
|
|
117
|
-
|
|
118
|
-
```html
|
|
119
|
-
<lf-scaffold>
|
|
120
|
-
<ng-container drawerContent></ng-container> <!-- (Optional) content projection for drawer -->
|
|
121
|
-
<router-outlet></router-outlet>
|
|
122
|
-
</lf-scaffold>
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
## Styling
|
|
129
|
-
Import the styles in your `styles.scss` and apply the default theme.
|
|
130
|
-
|
|
131
|
-
* **Note:** The library’s styles include Material icons and Roboto font styles.
|
|
132
|
-
|
|
133
|
-
```scss
|
|
134
|
-
@use "@lukfel/ng-scaffold/styles" as lf;
|
|
135
|
-
@include lf.scaffold-theme();
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
@use
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
$theme2: (
|
|
174
|
-
primary: mat
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
// Include themes (use ThemeService to switch between themes)
|
|
180
|
-
@include lf.scaffold-theme($base-theme);
|
|
181
|
-
@include lf.scaffold-colors($theme2, 'theme2');
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### (Optional) Custom Typography
|
|
185
|
-
To change the default typography from Roboto, pass an additional parameter ``font-family`` in the theme map.
|
|
186
|
-
|
|
187
|
-
* **Note:** Don't forget to also import and set the font-family in the styles.
|
|
188
|
-
|
|
189
|
-
```scss
|
|
190
|
-
@use "@lukfel/ng-scaffold/styles" as lf;
|
|
191
|
-
@use '@angular/material' as mat;
|
|
192
|
-
|
|
193
|
-
$base-theme: (
|
|
194
|
-
primary: mat
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
- **`
|
|
278
|
-
- **`
|
|
279
|
-
- **`
|
|
280
|
-
- **`
|
|
281
|
-
- **`
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
...
|
|
372
|
-
} else if (result.breakpoints[Breakpoints.
|
|
373
|
-
...
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
{ id:
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
[
|
|
519
|
-
[
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
(
|
|
523
|
-
(
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
1
|
+
# Documentation
|
|
2
|
+
## Introduction
|
|
3
|
+
|
|
4
|
+
This Angular library provides a foundational scaffold for modern web and mobile applications. It includes essential UI elements such as a header, sidebar, drawer, footer, floating button, and built-in services for theme switching, language switching, snackbar notifications, dialog management, and breakpoint detection. Simply wrap your `router-outlet` with the `lf-scaffold` element and configure the `ScaffoldConfig` within the `ScaffoldService`.
|
|
5
|
+
|
|
6
|
+
- **NPM**: [@lukfel/ng-scaffold](https://www.npmjs.com/package/@lukfel/ng-scaffold)
|
|
7
|
+
- **Demo**: [lukfel.github.io/ng-scaffold](https://lukfel.github.io/ng-scaffold)
|
|
8
|
+
- **Examples**: [Uglygotchi](https://www.uglygotchi.at), [What a Waste](https://www.what-a-waste.at), [Create a Tournament](https://www.create-a-tournament.com), [Wowen](https://www.wowen.at)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
Install the package using `npm install` or `ng add` (with experimental Angular schematics):
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install @lukfel/ng-scaffold
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
ng add @lukfel/ng-scaffold
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The ng add command will additionally try to perform the following actions:
|
|
25
|
+
* Import `ScaffoldComponent` in root
|
|
26
|
+
* Inject `ScaffoldService` and initialize `ScaffoldConfig`
|
|
27
|
+
* Wrap template with `<lf-scaffold>`
|
|
28
|
+
* Include styles
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Component
|
|
32
|
+
Import the `ScaffoldComponent` into your `app.module.ts` or `app.component.ts` (standalone).
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { ScaffoldComponent } from '@lukfel/ng-scaffold';
|
|
36
|
+
|
|
37
|
+
...
|
|
38
|
+
imports: [
|
|
39
|
+
ScaffoldComponent
|
|
40
|
+
]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### (Optional) Provider
|
|
44
|
+
The library uses the built-in logging service `Logger` to log debugging events when a `ScaffoldLibraryConfig` is provided and `debugging` is set to `true`. Logging is automatically disabled in production mode when `production` is set to `true`.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { provideScaffold } from '@lukfel/ng-scaffold';
|
|
48
|
+
import { isDevMode } from '@angular/core';
|
|
49
|
+
|
|
50
|
+
...
|
|
51
|
+
providers: [
|
|
52
|
+
provideScaffold({
|
|
53
|
+
production: !isDevMode(),
|
|
54
|
+
debugging: isDevMode()
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## Configuration
|
|
63
|
+
Import the `ScaffoldService` in `app.component.ts` to manage the `ScaffoldConfig`.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { ScaffoldService } from '@lukfel/ng-scaffold';
|
|
67
|
+
|
|
68
|
+
export class AppComponent {
|
|
69
|
+
|
|
70
|
+
private scaffoldService = inject(ScaffoldService);
|
|
71
|
+
|
|
72
|
+
private scaffoldConfig: ScaffoldConfig = {
|
|
73
|
+
// Create your own config or generate it at https://lukfel.github.io/ng-scaffold
|
|
74
|
+
headerConfig: { enable: true, title: 'Scaffold works!' }
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
constructor() {
|
|
78
|
+
this.scaffoldService.scaffoldConfig = this.scaffoldConfig;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### (Optional) Update Configuration
|
|
84
|
+
The `ScaffoldService` provides `updateScaffoldProperty()` to partially update the `ScaffoldConfig` in a type-safe way. It performs an immutable update, creating a new configuration object with the updated property and emits the new state.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { ScaffoldService, DrawerConfig, HeaderConfig, MenuButton } from '@lukfel/ng-scaffold';
|
|
88
|
+
|
|
89
|
+
export class AppComponent {
|
|
90
|
+
|
|
91
|
+
...
|
|
92
|
+
|
|
93
|
+
// Example #1: Toggle the drawer open state
|
|
94
|
+
public toggleDrawer(): void {
|
|
95
|
+
const open: boolean = this.scaffoldService?.scaffoldConfig?.drawerConfig?.open || false;
|
|
96
|
+
this.scaffoldService.updateScaffoldProperty('drawerConfig', { open: !open });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Example #2: Enable the header input field
|
|
100
|
+
public enableHeaderInput(): void {
|
|
101
|
+
this.scaffoldService.updateScaffoldProperty('headerConfig', inputConfig: { enable: true });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Example #2: Add new button to navbar
|
|
105
|
+
public addNavbarButton(button: MenuButton): void {
|
|
106
|
+
const currentNavbarConfig: NavbarConfig = this.scaffoldService.scaffoldConfig.navbarConfig;
|
|
107
|
+
this.scaffoldService.updateScaffoldProperty('navbarConfig', { menuButtons: [...currentNavbarConfig.menuButtons, button] });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
## Template
|
|
116
|
+
Wrap your application’s content inside the `lf-scaffold` component in `app.component.html`.
|
|
117
|
+
|
|
118
|
+
```html
|
|
119
|
+
<lf-scaffold>
|
|
120
|
+
<ng-container drawerContent></ng-container> <!-- (Optional) content projection for drawer -->
|
|
121
|
+
<router-outlet></router-outlet>
|
|
122
|
+
</lf-scaffold>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
## Styling
|
|
129
|
+
Import the styles in your `styles.scss` and apply the default theme.
|
|
130
|
+
|
|
131
|
+
* **Note:** The library’s styles include Material icons and Roboto font styles.
|
|
132
|
+
|
|
133
|
+
```scss
|
|
134
|
+
@use "@lukfel/ng-scaffold/styles" as lf;
|
|
135
|
+
@include lf.scaffold-theme-m3(); // Include default theme
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
* **Note:** `ng add` sets this up for you and can generate the Material 2 variant instead.
|
|
139
|
+
|
|
140
|
+
### (Optional) Custom Themes
|
|
141
|
+
To customize the default theme, define a new theme map specifying `primary` and `tertiary` colors using Material palettes. `theme-type` takes `light`, `dark` or `color-scheme` (follows the OS setting). Pass your custom theme to `lf.scaffold-theme-m3($my-theme)`.
|
|
142
|
+
|
|
143
|
+
```scss
|
|
144
|
+
@use "@lukfel/ng-scaffold/styles" as lf;
|
|
145
|
+
@use '@angular/material' as mat;
|
|
146
|
+
|
|
147
|
+
// Define theme (use Material palettes or create your own)
|
|
148
|
+
$base-theme: (
|
|
149
|
+
primary: mat.$rose-palette,
|
|
150
|
+
tertiary: mat.$blue-palette,
|
|
151
|
+
theme-type: light
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
@include lf.scaffold-theme-m3($base-theme);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### (Optional) Multiple Themes
|
|
158
|
+
To switch between multiple themes dynamically, define additional themes using `lf.scaffold-colors-m3($theme, 'theme-class')`, then apply the class to the `<body class="theme-class">` tag.
|
|
159
|
+
|
|
160
|
+
* **Note:** The `ThemeService` allows dynamic theme switching.
|
|
161
|
+
|
|
162
|
+
```scss
|
|
163
|
+
@use "@lukfel/ng-scaffold/styles" as lf;
|
|
164
|
+
@use '@angular/material' as mat;
|
|
165
|
+
|
|
166
|
+
// Define themes (use Material palettes or create your own)
|
|
167
|
+
$base-theme: (
|
|
168
|
+
primary: mat.$rose-palette,
|
|
169
|
+
tertiary: mat.$blue-palette,
|
|
170
|
+
theme-type: light
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
$theme2: (
|
|
174
|
+
primary: mat.$rose-palette,
|
|
175
|
+
tertiary: mat.$blue-palette,
|
|
176
|
+
theme-type: dark
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// Include themes (use ThemeService to switch between themes)
|
|
180
|
+
@include lf.scaffold-theme-m3($base-theme);
|
|
181
|
+
@include lf.scaffold-colors-m3($theme2, 'theme2');
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### (Optional) Custom Typography
|
|
185
|
+
To change the default typography from Roboto, pass an additional parameter ``font-family`` in the theme map.
|
|
186
|
+
|
|
187
|
+
* **Note:** Don't forget to also import and set the font-family in the styles.
|
|
188
|
+
|
|
189
|
+
```scss
|
|
190
|
+
@use "@lukfel/ng-scaffold/styles" as lf;
|
|
191
|
+
@use '@angular/material' as mat;
|
|
192
|
+
|
|
193
|
+
$base-theme: (
|
|
194
|
+
primary: mat.$rose-palette,
|
|
195
|
+
tertiary: mat.$blue-palette,
|
|
196
|
+
theme-type: light,
|
|
197
|
+
font-family: 'Comic Sans'
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
@include lf.scaffold-theme-m3($base-theme);
|
|
201
|
+
|
|
202
|
+
body {
|
|
203
|
+
font-family: "Comic Sans MS" !important;
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### (Optional) Material 2 Theming
|
|
208
|
+
Material 2 is still supported through `lf.scaffold-theme-m2($theme)` and `lf.scaffold-colors-m2($theme, 'theme-class')`. Its theme map uses `primary`, `accent`, `warn` and `dark`, with palettes from `mat.m2-define-palette()`. Use one API or the other, not both.
|
|
209
|
+
|
|
210
|
+
* **Note:** To keep the exact colors of an existing Material 2 theme after moving to Material 3, pass the same M2 palettes as `m2-compat` to `lf.scaffold-theme-m3()`.
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
## Events
|
|
216
|
+
There are two ways to listen to scaffold user events (button clicks, input changes, ...):
|
|
217
|
+
|
|
218
|
+
### (Recommended) Option 1 – Subscribe to Event Observables
|
|
219
|
+
Subscribe to the event Observables and listen to changes
|
|
220
|
+
```ts
|
|
221
|
+
private scaffoldService = inject(ScaffoldService);
|
|
222
|
+
private router = inject(Router);
|
|
223
|
+
|
|
224
|
+
constructor() {
|
|
225
|
+
// Listen to click events (header menu and navbar buttons - click)
|
|
226
|
+
this.scaffoldService.buttonClickEventValue$.subscribe((id: string) => {
|
|
227
|
+
this.router.navigate([id]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Listen to header input change events (header input field - change)
|
|
231
|
+
this.scaffoldService.headerInputChangeValue$.subscribe((value: string) => {
|
|
232
|
+
...
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Option 2 – Use Output Events
|
|
238
|
+
Specify the needed output events and call custom methods
|
|
239
|
+
```html
|
|
240
|
+
<lf-scaffold
|
|
241
|
+
(headerButtonClickEvent)="headerButtonClickEvent($event)"
|
|
242
|
+
(headerInputSubmitEvent)="headerInputSubmitEvent($event)"
|
|
243
|
+
(headerInputChangeEvent)="headerInputChangeEvent($event)"
|
|
244
|
+
(navbarButtonClickEvent)="navbarButtonClickEvent($event)">
|
|
245
|
+
<router-outlet></router-outlet>
|
|
246
|
+
</lf-scaffold>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
// Listen to header click events (header menu buttons - click)
|
|
251
|
+
public headerButtonClickEvent(id: string): void {
|
|
252
|
+
this.router.navigate([id]);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Listen to header input submit events (header input field - submit)
|
|
256
|
+
public headerInputSubmitEvent(value: string): void {
|
|
257
|
+
...
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Listen to header input change events (header input field - change)
|
|
261
|
+
public headerInputChangeEvent(value: string): void {
|
|
262
|
+
...
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Listen to navbar click events (navbar menu buttons - click)
|
|
266
|
+
public navbarButtonClickEvent(id: string): void {
|
|
267
|
+
this.router.navigate([id]);
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
## (Optional) Additional Services
|
|
275
|
+
This library includes several utility services:
|
|
276
|
+
|
|
277
|
+
- **`Logger`** – Development-only logging
|
|
278
|
+
- **`SnackbarService`** – Display snackbar notifications
|
|
279
|
+
- **`DialogService`** – Display custom dialogs
|
|
280
|
+
- **`BreakpointService`** – Detect screen breakpoints
|
|
281
|
+
- **`ThemeService`** – Manage themes dynamically
|
|
282
|
+
- **`RouterService`** – Track route changes and retrieve route history
|
|
283
|
+
- **`SeoService`** – Manage meta tags
|
|
284
|
+
- **`LocalStorageService`** – Handle local storage
|
|
285
|
+
- **`TranslationService`** – Switch languages at runtime with per-locale JSON files
|
|
286
|
+
|
|
287
|
+
### Logger
|
|
288
|
+
Logs information during development and hides all logs during production.
|
|
289
|
+
|
|
290
|
+
* **Note:** Use the provoder `provideScaffold({ production: !isDevMode() })` to disable logs in production
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
import { Logger } from '@lukfel/ng-scaffold';
|
|
294
|
+
|
|
295
|
+
export class AppComponent {
|
|
296
|
+
|
|
297
|
+
private logger = inject(Logger);
|
|
298
|
+
|
|
299
|
+
// Generic api call with logging
|
|
300
|
+
public apiCallWithLogging(): void {
|
|
301
|
+
this.apiService.apiCall().then(result => {
|
|
302
|
+
this.logger.log(result);
|
|
303
|
+
}).catch(error => {
|
|
304
|
+
this.logger.error(error);
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### SnackbarService
|
|
311
|
+
Provides basic methods to display simple snackbar notifications with or without actions.
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
import { SnackbarService } from '@lukfel/ng-scaffold';
|
|
315
|
+
|
|
316
|
+
export class AppComponent {
|
|
317
|
+
|
|
318
|
+
private snackbarService = inject(SnackbarService);
|
|
319
|
+
|
|
320
|
+
// Generic api call with snackbar response
|
|
321
|
+
public apiCallWithSnackbarResponse(): void {
|
|
322
|
+
this.apiService.apiCall().then(result => {
|
|
323
|
+
this.snackbarService.openSnackbar('Call was successful');
|
|
324
|
+
}).catch(error => {
|
|
325
|
+
this.snackbarService.openSnackbar('Call was not successful');
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### DialogService
|
|
332
|
+
Includes a basic confirmation dialog thar returns a `Promise`. Use the method `openCustomDialog` to pass your own dialog template and config.
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
import { DialogService } from '@lukfel/ng-scaffold';
|
|
336
|
+
|
|
337
|
+
export class AppComponent {
|
|
338
|
+
|
|
339
|
+
private dialogService = inject(DialogService);
|
|
340
|
+
|
|
341
|
+
// Generic api call with a subsequent confirmation dialog
|
|
342
|
+
public apiCallWithDialogConfirmation(): void {
|
|
343
|
+
this.dialogService.openConfirmDialog('Do you really want to make this api call?').then(response => {
|
|
344
|
+
// If the user confirmed the dialog, go through with the api call
|
|
345
|
+
if(response === true) {
|
|
346
|
+
this.apiService.apiCall().then(result => {
|
|
347
|
+
...
|
|
348
|
+
}).catch(error => {
|
|
349
|
+
...
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### BreakpointService
|
|
358
|
+
Allows you to subscribe to breakpoint changes.
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
import { BreakpointService } from '@lukfel/ng-scaffold';
|
|
362
|
+
|
|
363
|
+
export class AppComponent {
|
|
364
|
+
|
|
365
|
+
private breakpointService = inject(BreakpointService);
|
|
366
|
+
|
|
367
|
+
constructor() {
|
|
368
|
+
this.breakpointService.breakpoint$.subscribe((result: BreakpointState) => {
|
|
369
|
+
// Check which breakpoint is active
|
|
370
|
+
if (result.breakpoints[Breakpoints.XSmall]) {
|
|
371
|
+
...
|
|
372
|
+
} else if (result.breakpoints[Breakpoints.Small]) {
|
|
373
|
+
...
|
|
374
|
+
} else if (result.breakpoints[Breakpoints.Medium]) {
|
|
375
|
+
...
|
|
376
|
+
} else if (result.breakpoints[Breakpoints.Large]) {
|
|
377
|
+
...
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### ThemeService
|
|
385
|
+
Dynamically change between your defined themes.
|
|
386
|
+
|
|
387
|
+
* **Note:** The theme must be defined and included in your styles
|
|
388
|
+
|
|
389
|
+
```ts
|
|
390
|
+
import { ThemeService } from '@lukfel/ng-scaffold';
|
|
391
|
+
|
|
392
|
+
export class AppComponent {
|
|
393
|
+
|
|
394
|
+
constructor(private themeService: ThemeService) {
|
|
395
|
+
this.themeService.setTheme('my-theme2', true); // set theme and store in local storage (using the built in LocalStorageService)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### TranslationService
|
|
401
|
+
Switches the application language at runtime by loading a separate JSON file per locale (e.g. `de.json`, `en.json`) that share the same keys. Keys missing from a locale are automatically resolved from the `fallbackLocale`.
|
|
402
|
+
|
|
403
|
+
* **Note:** Configure the available locales in the `provideScaffold` provider and serve the `<locale>.json` files from the configured `path` (default `assets/i18n/`)
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
import { provideScaffold } from '@lukfel/ng-scaffold';
|
|
407
|
+
|
|
408
|
+
...
|
|
409
|
+
providers: [
|
|
410
|
+
provideScaffold({
|
|
411
|
+
language: {
|
|
412
|
+
locales: ['de', 'en'], // available locales (also drives a language picker)
|
|
413
|
+
fallbackLocale: 'en', // used when a locale is unknown or a key is missing
|
|
414
|
+
path: 'assets/i18n/', // (Optional) base path of the <locale>.json files
|
|
415
|
+
persist: true // (Optional) store the active locale in local storage
|
|
416
|
+
}
|
|
417
|
+
})
|
|
418
|
+
]
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Inject the `TranslationService` to read the translations and switch the locale. Each app keeps its own strongly-typed `TransMap` interface and reads the labels through the typed accessors.
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
import { TranslationService } from '@lukfel/ng-scaffold';
|
|
425
|
+
|
|
426
|
+
export class AppComponent {
|
|
427
|
+
|
|
428
|
+
private translationService = inject(TranslationService);
|
|
429
|
+
|
|
430
|
+
// Typed signal of the active translations (empty until the first load)
|
|
431
|
+
public transMap = this.translationService.transMapAs<TransMap>();
|
|
432
|
+
|
|
433
|
+
// Active locale and all configured locales (e.g. for a language picker)
|
|
434
|
+
public locale = this.translationService.locale;
|
|
435
|
+
public locales = this.translationService.locales;
|
|
436
|
+
|
|
437
|
+
// Switch the active language (persisted according to the config)
|
|
438
|
+
public changeLanguage(locale: string): void {
|
|
439
|
+
this.translationService.setLocale(locale);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
* **Note:** For observable consumers use `locale$` and `transMap$` (or the typed `transMapStream<TransMap>()`, which only emits once translations are loaded). Track the loading state with the `loading` signal or `loading$`.
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
## (Optional) Standalone Components
|
|
450
|
+
In addition to the scaffold components provided by default by the the `ScaffoldComponent` there are several standalone components that can be utilized.
|
|
451
|
+
|
|
452
|
+
* **Note:** Standalone components must be imported manually and are not part of the `ScaffoldComponent` import
|
|
453
|
+
|
|
454
|
+
### List
|
|
455
|
+
A standalone Material Design inspired list and table hybrid component for displaying structured
|
|
456
|
+
collections of items. It supports avatars, titles, subtitles, actions, selections and dragging —
|
|
457
|
+
making it ideal for dashboards, inventories, and administrative views.
|
|
458
|
+
|
|
459
|
+
```ts
|
|
460
|
+
import { ListComponent } from '@lukfel/ng-scaffold';
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
import { Button, ListConfig, ListHeader, ListItem } from '@lukfel/ng-scaffold';
|
|
465
|
+
|
|
466
|
+
public listConfig = signal<ListConfig>({ // (Optional) list config
|
|
467
|
+
enableSelection: true,
|
|
468
|
+
enableDragging: true,
|
|
469
|
+
initialSortToken: 'title',
|
|
470
|
+
initialSortAsc: true,
|
|
471
|
+
showDividers: true
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
public listHeader = signal<ListHeader>({ // (Optional) list header
|
|
475
|
+
matIcon: 'sort',
|
|
476
|
+
items: [
|
|
477
|
+
{ title: 'Items', sortToken: 'title' }
|
|
478
|
+
]
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
public listItems = signal<ListItem[]>([
|
|
482
|
+
{ id: 1, svgIcon: 'logo', title: 'Item 2', subtitle: 'I am disabled', disabled: true },
|
|
483
|
+
{ id: 0, avatar: 'img/logos/ic_launcher-web.png', title: 'Item 1', subtitle: 'I am clickable', clickable: true },
|
|
484
|
+
{ id: 2, matIcon: 'person', title: 'Item 3', subtitle: 'I have no edit buton', hiddenButtonIds: ['edit'] },
|
|
485
|
+
]);
|
|
486
|
+
|
|
487
|
+
public listButtons = signal<Button[]>([ // (Optional) list buttons
|
|
488
|
+
{ id: 'edit', matIcon: 'edit' },
|
|
489
|
+
{ id: 'delete', matIcon: 'delete', cssClass: 'warn' }
|
|
490
|
+
]);
|
|
491
|
+
|
|
492
|
+
// (Optional) Handle sort events
|
|
493
|
+
public onListSortChange(event: { sortToken: string, sortAsc: boolean }): void {
|
|
494
|
+
if (event?.sortToken === 'title') {
|
|
495
|
+
this.listItems().sort((a, b) => {
|
|
496
|
+
if (!a.title || !b.title) return 0;
|
|
497
|
+
if (event.sortAsc) return a.title.localeCompare(b.title);
|
|
498
|
+
return b.title.localeCompare(a.title);
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
public onListSelectionChange(items: ListItem[]): void {
|
|
504
|
+
// handle selection change
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
public onListButtonClick(event: { buttonId: string, item: ListItem }): void {
|
|
508
|
+
// handle button click
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
public onListItemClick(item: ListItem): void {
|
|
512
|
+
// handle item click
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
```html
|
|
517
|
+
<lf-list
|
|
518
|
+
[config]="listConfig()"
|
|
519
|
+
[header]="listHeader()"
|
|
520
|
+
[items]="listItems()"
|
|
521
|
+
[buttons]="listButtons()"
|
|
522
|
+
(sortChangeEvent)="onListSortChange($event)"
|
|
523
|
+
(selectionChangeEvent)="onListSelectionChange()"
|
|
524
|
+
(buttonClickEvent)="onListButtonClick($event)"
|
|
525
|
+
(itemClickEvent)="onListItemClick($event)"></lf-list>
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### File-Upload
|
|
529
|
+
A standalone Material Design styled button for selecting and uploading files. It wraps a hidden
|
|
530
|
+
native file input and exposes a simple, customizable interface with built-in icon, tooltip, and
|
|
531
|
+
state management.
|
|
532
|
+
|
|
533
|
+
```ts
|
|
534
|
+
import { FileUploadComponent } from '@lukfel/ng-scaffold';
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
```ts
|
|
538
|
+
public onFileChange(file: File): void {
|
|
539
|
+
// handle file upload
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
```html
|
|
544
|
+
<lf-file-upload
|
|
545
|
+
color="accent"
|
|
546
|
+
label="Upload File"
|
|
547
|
+
matIcon="upload"
|
|
548
|
+
accept="*"
|
|
549
|
+
(fileChangeEvent)="onFileChange($event)"></lf-file-upload>
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Color-Picker
|
|
553
|
+
A standalone Material Design styled button for picking colors (uses native design on Safari). It wraps a hidden native color
|
|
554
|
+
input and exposes a simple, customizable interface with built-in icon, tooltip, and state
|
|
555
|
+
management.
|
|
556
|
+
|
|
557
|
+
```ts
|
|
558
|
+
import { ColorPickerComponent } from '@lukfel/ng-scaffold';
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
```ts
|
|
562
|
+
public onColorChange(color: string): void {
|
|
563
|
+
// handle color pick
|
|
564
|
+
}
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
```html
|
|
568
|
+
<lf-color-picker
|
|
569
|
+
color="accent"
|
|
570
|
+
label="Pick Color"
|
|
571
|
+
matIcon="color_lens"
|
|
572
|
+
(colorChangeEvent)="onColorChange($event)"></lf-color-picker>
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Placeholder
|
|
576
|
+
A standalone UI component designed to display an informative placeholder or empty state when no
|
|
577
|
+
data is available. It provides a structured layout for an icon, heading, message, and optional
|
|
578
|
+
action — helping guide users toward the next step.
|
|
579
|
+
|
|
580
|
+
```ts
|
|
581
|
+
import { PlaceholderComponent } from '@lukfel/ng-scaffold';
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
```ts
|
|
585
|
+
import { PlaceholderConfig } from '@lukfel/ng-scaffold';
|
|
586
|
+
|
|
587
|
+
public placeholderConfig = signal<PlaceholderConfig>({
|
|
588
|
+
matIcon: 'widgets',
|
|
589
|
+
title: 'Title',
|
|
590
|
+
message: 'This is a placeholder message.',
|
|
591
|
+
button: {
|
|
592
|
+
id: 'placeholder',
|
|
593
|
+
label: 'ACTION'
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
public onPlaceholderButtonClick(): void {
|
|
598
|
+
// handle placeholder click
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
```html
|
|
603
|
+
<lf-placeholder
|
|
604
|
+
[placeholderConfig]="placeholderConfig()"
|
|
605
|
+
(buttonClickEvent)="onPlaceholderButtonClick()"></lf-placeholder>
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### Notification
|
|
609
|
+
A standalone standalone Material Design inspired notification component for displaying transient
|
|
610
|
+
messages to users. It supports different severity levels (primary, accent, warn), optional
|
|
611
|
+
icons, optional actions, and links.
|
|
612
|
+
|
|
613
|
+
```ts
|
|
614
|
+
import { NotificationComponent } from '@lukfel/ng-scaffold';
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
```html
|
|
618
|
+
<lf-notification
|
|
619
|
+
[static]="true"
|
|
620
|
+
color="accent"
|
|
621
|
+
message="This is an info notification with action."
|
|
622
|
+
matIcon="info"
|
|
623
|
+
action="Action"
|
|
624
|
+
(clickEvent)="onNotificationClick()"></lf-notification>
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
## (Optional) Interceptors
|
|
631
|
+
Intercept HTTP Calls and automatically show a loading spinner.
|
|
632
|
+
|
|
633
|
+
* **Note:** The loading spinner can also be manually shown by udpating the value for `scaffoldConfig.loading` in the `ScaffoldService`
|
|
634
|
+
|
|
635
|
+
```ts
|
|
636
|
+
import { ScaffoldLoadingInterceptor } from '@lukfel/ng-scaffold';
|
|
637
|
+
|
|
638
|
+
...
|
|
639
|
+
providers: [
|
|
640
|
+
{
|
|
641
|
+
provide: HTTP_INTERCEPTORS,
|
|
642
|
+
useClass: ScaffoldLoadingInterceptor,
|
|
643
|
+
multi: true
|
|
644
|
+
}
|
|
645
|
+
]
|
|
644
646
|
```
|