@foxeltech/angular-ui 0.3.1 → 0.4.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/fesm2022/foxeltech-angular-ui-chart.mjs +392 -0
- package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -0
- package/fesm2022/foxeltech-angular-ui-flow.mjs +38 -0
- package/fesm2022/foxeltech-angular-ui-flow.mjs.map +1 -0
- package/fesm2022/foxeltech-angular-ui-rich-text.mjs +156 -0
- package/fesm2022/foxeltech-angular-ui-rich-text.mjs.map +1 -0
- package/fesm2022/foxeltech-angular-ui.mjs +773 -1382
- package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
- package/fx-icons.svg +97 -0
- package/package.json +14 -8
- package/src/lib/styles/tailwind.css +0 -1
- package/src/lib/ui/components/button/button.component.html +14 -14
- package/src/lib/ui/components/checkbox/checkbox.component.html +2 -2
- package/src/lib/ui/components/circle-progress-bar/circle-progress-bar.component.html +2 -2
- package/src/lib/ui/components/datetime-picker/datetime-picker.component.html +49 -27
- package/src/lib/ui/components/datetime-picker/datetime-picker.component.scss +25 -137
- package/src/lib/ui/components/dnd-upload/dnd-upload.component.html +3 -3
- package/src/lib/ui/components/drawer/drawer.component.html +1 -1
- package/src/lib/ui/components/empty-state/empty-state.component.html +2 -2
- package/src/lib/ui/components/hero-icon/hero-icon.component.html +10 -9
- package/src/lib/ui/components/info-field/info-field.component.html +1 -1
- package/src/lib/ui/components/input/input.component.html +6 -6
- package/src/lib/ui/components/kanban-board/kanban-board.component.html +1 -1
- package/src/lib/ui/components/loading-panel/loading-panel.component.html +1 -1
- package/src/lib/ui/components/master-detail/master-detail.component.html +9 -9
- package/src/lib/ui/components/menu/menu.component.html +27 -0
- package/src/lib/ui/components/radio-button/radio-button.component.html +3 -3
- package/src/lib/ui/components/radio-button-toggle/radio-button-toggle.component.html +3 -3
- package/src/lib/ui/components/search-bar/search-bar.component.html +1 -1
- package/src/lib/ui/components/section-card/section-card.component.html +1 -1
- package/src/lib/ui/components/select/select.component.html +6 -6
- package/src/lib/ui/components/skeleton-detail/skeleton-detail.component.html +2 -2
- package/src/lib/ui/components/skeleton-list/skeleton-list.component.html +1 -1
- package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.html +5 -5
- package/src/lib/ui/components/slider/slider.component.html +7 -7
- package/src/lib/ui/components/stat-cards/stat-cards.component.html +1 -1
- package/src/lib/ui/components/switch/switch.component.html +1 -1
- package/src/lib/ui/components/tab-group/tab-group.component.html +4 -4
- package/src/lib/ui/components/table-cell/table-cell.component.html +2 -2
- package/src/lib/ui/components/tag/tag.component.html +4 -4
- package/src/lib/ui/components/toast/toast.component.html +7 -7
- package/src/lib/ui/components/toast-container/toast-container.component.html +1 -0
- package/src/lib/ui/components/tree-diagram/tree-diagram.component.html +2 -2
- package/tailwind.css +0 -1
- package/types/foxeltech-angular-ui-chart.d.ts +53 -0
- package/types/foxeltech-angular-ui-flow.d.ts +14 -0
- package/types/foxeltech-angular-ui-rich-text.d.ts +35 -0
- package/types/foxeltech-angular-ui.d.ts +394 -387
- package/src/lib/ui/components/chart/chart.component.html +0 -20
- package/src/lib/ui/components/chart/chart.component.scss +0 -49
- package/src/lib/ui/components/flow-connection/flow-connection.component.html +0 -10
- package/src/lib/ui/components/flow-connection/flow-connection.component.scss +0 -0
- package/src/lib/ui/components/rich-text-area/rich-text-area.component.html +0 -3
- package/src/lib/ui/components/rich-text-area/rich-text-area.component.scss +0 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foxeltech/angular-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -13,19 +13,13 @@
|
|
|
13
13
|
"@angular/forms": "^20.3.0 || ^21.0.0",
|
|
14
14
|
"@angular/material": "^20.2.7 || ^21.0.0",
|
|
15
15
|
"@angular/cdk": "^20.2.7 || ^21.0.0",
|
|
16
|
-
"lodash": "^4.17.21",
|
|
17
16
|
"@ngx-translate/core": "^14.0.0",
|
|
18
|
-
"@ngx-translate/http-loader": "^7.0.0"
|
|
19
|
-
"moment": "^2.30.1"
|
|
17
|
+
"@ngx-translate/http-loader": "^7.0.0"
|
|
20
18
|
},
|
|
21
19
|
"dependencies": {
|
|
22
20
|
"tslib": "^2.3.0",
|
|
23
|
-
"@danielmoncada/angular-datetime-picker": "^21.0.0",
|
|
24
|
-
"@danielmoncada/angular-datetime-picker-moment-adapter": "^8.0.0",
|
|
25
21
|
"echarts": "^6.0.0",
|
|
26
22
|
"ngx-echarts": "^20.0.2",
|
|
27
|
-
"d3": "^7.9.0",
|
|
28
|
-
"@dimaslz/ng-heroicons": "^1.19.1",
|
|
29
23
|
"quill": "^2.0.3",
|
|
30
24
|
"ngx-vflow": "^1.16.2",
|
|
31
25
|
"@microsoft/signalr": "^10.0.0"
|
|
@@ -45,6 +39,18 @@
|
|
|
45
39
|
".": {
|
|
46
40
|
"types": "./types/foxeltech-angular-ui.d.ts",
|
|
47
41
|
"default": "./fesm2022/foxeltech-angular-ui.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./chart": {
|
|
44
|
+
"types": "./types/foxeltech-angular-ui-chart.d.ts",
|
|
45
|
+
"default": "./fesm2022/foxeltech-angular-ui-chart.mjs"
|
|
46
|
+
},
|
|
47
|
+
"./flow": {
|
|
48
|
+
"types": "./types/foxeltech-angular-ui-flow.d.ts",
|
|
49
|
+
"default": "./fesm2022/foxeltech-angular-ui-flow.mjs"
|
|
50
|
+
},
|
|
51
|
+
"./rich-text": {
|
|
52
|
+
"types": "./types/foxeltech-angular-ui-rich-text.d.ts",
|
|
53
|
+
"default": "./fesm2022/foxeltech-angular-ui-rich-text.mjs"
|
|
48
54
|
}
|
|
49
55
|
},
|
|
50
56
|
"sideEffects": [
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
<button
|
|
2
|
-
[attr.type]="type"
|
|
3
|
-
[attr.aria-label]="ariaLabel || null"
|
|
4
|
-
[attr.aria-busy]="loading || null"
|
|
5
|
-
[class]="class"
|
|
2
|
+
[attr.type]="type()"
|
|
3
|
+
[attr.aria-label]="ariaLabel() || null"
|
|
4
|
+
[attr.aria-busy]="loading() || null"
|
|
5
|
+
[class]="class()"
|
|
6
6
|
[ngClass]="{
|
|
7
|
-
'btn-default': buttonVariant === 'default',
|
|
8
|
-
'btn-primary': buttonVariant === 'primary',
|
|
9
|
-
'btn-success': buttonVariant === 'success',
|
|
10
|
-
'btn-alternative': buttonVariant === 'alternative',
|
|
7
|
+
'btn-default': buttonVariant() === 'default',
|
|
8
|
+
'btn-primary': buttonVariant() === 'primary',
|
|
9
|
+
'btn-success': buttonVariant() === 'success',
|
|
10
|
+
'btn-alternative': buttonVariant() === 'alternative',
|
|
11
11
|
}"
|
|
12
|
-
[disabled]="disabled || loading"
|
|
12
|
+
[disabled]="disabled() || loading()"
|
|
13
13
|
(click)="onClick()"
|
|
14
14
|
>
|
|
15
|
-
@if (loading) {
|
|
15
|
+
@if (loading()) {
|
|
16
16
|
<div class="flex w-full items-center justify-center" aria-hidden="true">
|
|
17
17
|
<svg
|
|
18
18
|
[attr.fill]="
|
|
19
|
-
buttonVariant !== 'alternative' ? 'rgb(var(--text-primary))' : 'rgb(var(--primary))'
|
|
19
|
+
buttonVariant() !== 'alternative' ? 'rgb(var(--text-primary))' : 'rgb(var(--primary))'
|
|
20
20
|
"
|
|
21
21
|
width="20"
|
|
22
22
|
height="20"
|
|
@@ -222,9 +222,9 @@
|
|
|
222
222
|
[size]="20"
|
|
223
223
|
class="flex"
|
|
224
224
|
[ngClass]="{
|
|
225
|
-
'text-text-inverse': buttonVariant === 'default',
|
|
226
|
-
'text-text-primary': buttonVariant === 'alternative',
|
|
227
|
-
'text-white': buttonVariant === 'primary' || buttonVariant === 'success',
|
|
225
|
+
'text-text-inverse': buttonVariant() === 'default',
|
|
226
|
+
'text-text-primary': buttonVariant() === 'alternative',
|
|
227
|
+
'text-white': buttonVariant() === 'primary' || buttonVariant() === 'success',
|
|
228
228
|
}"
|
|
229
229
|
></fx-ui-hero-icon>
|
|
230
230
|
}
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
<span
|
|
16
16
|
class="relative w-4 h-4 border rounded-full transition-colors duration-150 shrink-0 peer-focus-visible:ring-2 peer-focus-visible:ring-primary/50"
|
|
17
17
|
[ngClass]="{
|
|
18
|
-
'rounded-full': rounded,
|
|
19
|
-
'rounded-sm': !rounded,
|
|
18
|
+
'rounded-full': rounded(),
|
|
19
|
+
'rounded-sm': !rounded(),
|
|
20
20
|
'border-border-strong bg-transparent': !value,
|
|
21
21
|
'border-transparent bg-gradient-primary': value,
|
|
22
22
|
}"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
style="transition: stroke-dashoffset 300ms linear"
|
|
29
29
|
></circle>
|
|
30
30
|
|
|
31
|
-
@if(showPercent){
|
|
31
|
+
@if(showPercent()){
|
|
32
32
|
<text
|
|
33
33
|
[attr.x]="radius"
|
|
34
34
|
[attr.y]="radius"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
class="text-xs font-medium"
|
|
38
38
|
fill="currentColor"
|
|
39
39
|
>
|
|
40
|
-
{{ percent }}%
|
|
40
|
+
{{ percent() }}%
|
|
41
41
|
</text>
|
|
42
42
|
}
|
|
43
43
|
</svg>
|
|
@@ -2,39 +2,61 @@
|
|
|
2
2
|
@if (label) {
|
|
3
3
|
<label class="txt-field-label" [attr.for]="fieldId">
|
|
4
4
|
{{ label }}
|
|
5
|
-
@if (required) {
|
|
5
|
+
@if (required()) {
|
|
6
6
|
<span class="txt-required" aria-hidden="true">*</span>
|
|
7
7
|
}
|
|
8
8
|
</label>
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
<div class="
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
11
|
+
<div class="flex gap-normal">
|
|
12
|
+
@if (showDate) {
|
|
13
|
+
<div class="relative flex-1">
|
|
14
|
+
<input
|
|
15
|
+
[id]="fieldId"
|
|
16
|
+
[matDatepicker]="datePicker"
|
|
17
|
+
[placeholder]="placeholder()"
|
|
18
|
+
[disabled]="disabled"
|
|
19
|
+
[min]="min"
|
|
20
|
+
[max]="max"
|
|
21
|
+
[value]="dateValue"
|
|
22
|
+
(dateChange)="onDateChange($event.value)"
|
|
23
|
+
(click)="!disabled && datePicker.open()"
|
|
24
|
+
(blur)="onBlur()"
|
|
25
|
+
readonly
|
|
26
|
+
class="input-default pr-9"
|
|
27
|
+
/>
|
|
28
|
+
<span
|
|
29
|
+
(click)="!disabled && datePicker.open()"
|
|
30
|
+
class="absolute inset-y-0 right-0 flex items-center pr-2.5 cursor-pointer text-text-placeholder hover:text-text-primary transition-colors"
|
|
31
|
+
>
|
|
32
|
+
<fx-ui-hero-icon icon="calendar" [size]="20" class="text-text-primary"></fx-ui-hero-icon>
|
|
33
|
+
</span>
|
|
34
|
+
<mat-datepicker #datePicker></mat-datepicker>
|
|
35
|
+
</div>
|
|
36
|
+
}
|
|
37
|
+
@if (showTime) {
|
|
38
|
+
<div class="relative" [class.flex-1]="!showDate" [class.w-32]="showDate">
|
|
39
|
+
<input
|
|
40
|
+
[matTimepicker]="timePicker"
|
|
41
|
+
placeholder="HH:mm"
|
|
42
|
+
[disabled]="disabled"
|
|
43
|
+
[value]="dateValue"
|
|
44
|
+
(valueChange)="onTimeChange($event)"
|
|
45
|
+
(click)="!disabled && timePicker.open()"
|
|
46
|
+
(blur)="onBlur()"
|
|
47
|
+
readonly
|
|
48
|
+
class="input-default pr-9"
|
|
49
|
+
/>
|
|
50
|
+
<span
|
|
51
|
+
(click)="!disabled && timePicker.open()"
|
|
52
|
+
class="absolute inset-y-0 right-0 flex items-center pr-2.5 cursor-pointer text-text-placeholder hover:text-text-primary transition-colors"
|
|
53
|
+
>
|
|
54
|
+
<fx-ui-hero-icon icon="clock" [size]="20" class="text-text-primary"></fx-ui-hero-icon>
|
|
55
|
+
</span>
|
|
56
|
+
<mat-timepicker #timePicker></mat-timepicker>
|
|
57
|
+
</div>
|
|
58
|
+
}
|
|
31
59
|
</div>
|
|
32
|
-
<owl-date-time
|
|
33
|
-
#picker
|
|
34
|
-
[startAt]="startAt"
|
|
35
|
-
[pickerType]="type"
|
|
36
|
-
(afterPickerClosed)="onValueChange($event)"
|
|
37
|
-
></owl-date-time>
|
|
38
60
|
@if (invalid) {
|
|
39
61
|
<div class="txt-invalid">{{ getErrorMessage(label) }}</div>
|
|
40
62
|
}
|
|
@@ -1,147 +1,35 @@
|
|
|
1
1
|
/* Tailwind v4: component styles compile in isolation — @reference pulls in the theme for @apply without re-emitting it. */
|
|
2
2
|
@reference '../../../styles/tailwind.css';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/* ─── Material date/time picker popups, themed with the fx tokens ──────────
|
|
5
|
+
(Replaces the old Owl picker skin — the popups render in an overlay, so
|
|
6
|
+
everything below is ::ng-deep on the panel classes.) */
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
::ng-deep .
|
|
8
|
+
::ng-deep .mat-datepicker-content,
|
|
9
|
+
::ng-deep mat-timepicker .mat-timepicker-panel,
|
|
10
|
+
::ng-deep .mat-timepicker-panel {
|
|
8
11
|
@apply bg-bg-primary rounded-xl shadow-xl border border-border-default;
|
|
9
|
-
width: 320px !important;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Calendar table base
|
|
13
|
-
::ng-deep .owl-dt-calendar-table {
|
|
14
|
-
@apply w-full border-collapse;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Default cell hover — override red debug color
|
|
18
|
-
::ng-deep .owl-dt-calendar-table :not(.owl-dt-calendar-cell-disabled):hover > .owl-dt-calendar-cell-content:not(.owl-dt-calendar-cell-selected) {
|
|
19
|
-
@apply bg-bg-hover;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// ── Current-month cell text color ─────────────────────────────────────────────
|
|
23
|
-
// No !important here — lets out-month and disabled !important overrides win.
|
|
24
|
-
// A direct declaration still beats the library's inherited rgba(0,0,0,.85).
|
|
25
|
-
::ng-deep .owl-dt-calendar-table .owl-dt-calendar-cell-content {
|
|
26
12
|
color: rgb(var(--text-primary));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Selected cell
|
|
30
|
-
::ng-deep .owl-dt-calendar-table .owl-dt-calendar-cell-selected {
|
|
31
|
-
background-color: rgb(var(--primary)) !important;
|
|
32
|
-
color: #fff !important;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Today highlight (not selected)
|
|
36
|
-
::ng-deep .owl-dt-calendar-table .owl-dt-calendar-cell-today:not(.owl-dt-calendar-cell-selected) {
|
|
37
|
-
border-color: rgb(var(--primary)) !important;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ── Disabled dates: text-text-placeholder ────────────────────────────────────
|
|
41
|
-
// owl-dt-calendar-cell-disabled is on the <td>, content span is a direct child
|
|
42
|
-
::ng-deep .owl-dt-calendar-table .owl-dt-calendar-cell-disabled > .owl-dt-calendar-cell-content {
|
|
43
|
-
color: rgb(var(--text-placeholder)) !important;
|
|
44
|
-
opacity: 0.6 !important;
|
|
45
|
-
cursor: not-allowed;
|
|
46
|
-
pointer-events: none;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ── Other-month dates: text-text-secondary ────────────────────────────────────
|
|
50
|
-
// In v20, owl-dt-calendar-cell-out is applied ON the <span.owl-dt-calendar-cell-content>
|
|
51
|
-
// itself (via [ngClass]), NOT on the parent <td>. So target it directly.
|
|
52
|
-
::ng-deep .owl-dt-calendar-table .owl-dt-calendar-cell-content.owl-dt-calendar-cell-out {
|
|
53
|
-
color: rgb(var(--text-secondary)) !important;
|
|
54
|
-
opacity: 0.6 !important;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ── Timer input ───────────────────────────────────────────────────────────────
|
|
58
|
-
::ng-deep .owl-dt-timer-content .owl-dt-timer-input {
|
|
59
|
-
@apply bg-bg-primary border border-border-strong text-text-primary rounded-lg;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// ── Period button (hide arrow) ────────────────────────────────────────────────
|
|
63
|
-
::ng-deep .owl-dt-control-period-button .owl-dt-control-button-arrow {
|
|
64
|
-
display: none;
|
|
65
|
-
}
|
|
66
13
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
color: rgb(var(--
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
border-radius: 6px !important;
|
|
85
|
-
width: 60px !important;
|
|
86
|
-
padding-top: 4px !important;
|
|
87
|
-
padding-bottom: 4px !important;
|
|
88
|
-
font-size: 13px !important;
|
|
89
|
-
font-weight: 600 !important;
|
|
90
|
-
border: 1px solid rgb(var(--border-default)) !important;
|
|
91
|
-
background-color: rgb(var(--bg-primary)) !important;
|
|
92
|
-
color: rgb(var(--text-primary)) !important;
|
|
93
|
-
cursor: pointer;
|
|
94
|
-
transition: opacity 150ms ease;
|
|
95
|
-
|
|
96
|
-
&:hover {
|
|
97
|
-
background-color: rgb(var(--bg-hover)) !important;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// "Set" = last button — primary fill
|
|
102
|
-
::ng-deep .owl-dt-container-buttons .owl-dt-container-control-button:last-child {
|
|
103
|
-
background-color: rgb(var(--primary)) !important;
|
|
104
|
-
border-color: rgb(var(--primary)) !important;
|
|
105
|
-
color: #fff !important;
|
|
106
|
-
|
|
14
|
+
/* Material M3 token overrides so calendar internals follow the theme */
|
|
15
|
+
--mat-datepicker-calendar-container-background-color: rgb(var(--bg-primary));
|
|
16
|
+
--mat-datepicker-calendar-container-text-color: rgb(var(--text-primary));
|
|
17
|
+
--mat-datepicker-calendar-date-text-color: rgb(var(--text-primary));
|
|
18
|
+
--mat-datepicker-calendar-date-selected-state-background-color: rgb(var(--primary));
|
|
19
|
+
--mat-datepicker-calendar-date-selected-state-text-color: #fff;
|
|
20
|
+
--mat-datepicker-calendar-date-today-outline-color: rgb(var(--primary));
|
|
21
|
+
--mat-datepicker-calendar-date-hover-state-background-color: rgb(var(--bg-primary-hover));
|
|
22
|
+
--mat-datepicker-calendar-header-text-color: rgb(var(--text-secondary));
|
|
23
|
+
--mat-datepicker-calendar-period-button-text-color: rgb(var(--text-primary));
|
|
24
|
+
--mat-datepicker-calendar-navigation-button-icon-color: rgb(var(--text-primary));
|
|
25
|
+
--mat-datepicker-calendar-date-disabled-state-text-color: rgb(var(--text-placeholder));
|
|
26
|
+
--mat-timepicker-container-background-color: rgb(var(--bg-primary));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
::ng-deep .mat-timepicker-panel .mat-mdc-option {
|
|
30
|
+
color: rgb(var(--text-primary));
|
|
107
31
|
|
|
108
|
-
&:hover {
|
|
109
|
-
|
|
32
|
+
&:hover:not(.mdc-list-item--disabled) {
|
|
33
|
+
background-color: rgb(var(--bg-primary-hover));
|
|
110
34
|
}
|
|
111
35
|
}
|
|
112
|
-
|
|
113
|
-
// Inner content: height:100% now resolves against fixed 32px button, and
|
|
114
|
-
// background must be transparent so the button's own bg shows through
|
|
115
|
-
::ng-deep .owl-dt-container-buttons .owl-dt-container-control-button .owl-dt-control-button-content {
|
|
116
|
-
height: 100% !important;
|
|
117
|
-
width: 100% !important;
|
|
118
|
-
padding: 0 !important;
|
|
119
|
-
background-color: transparent !important;
|
|
120
|
-
color: inherit !important;
|
|
121
|
-
display: flex !important;
|
|
122
|
-
align-items: center !important;
|
|
123
|
-
justify-content: center !important;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// ── Header / navigation ───────────────────────────────────────────────────────
|
|
127
|
-
::ng-deep .owl-dt-calendar-control-content .owl-dt-control-button-content {
|
|
128
|
-
@apply text-text-primary font-medium;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
::ng-deep .owl-dt-control-arrow-button .owl-dt-control-button-content {
|
|
132
|
-
@apply text-text-primary;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
::ng-deep .owl-dt-calendar-table .owl-dt-calendar-header {
|
|
136
|
-
@apply text-text-secondary;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
::ng-deep .owl-dt-calendar-table .owl-dt-calendar-header .owl-dt-weekdays th {
|
|
140
|
-
@apply text-text-secondary font-medium;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// ── Popup container border ────────────────────────────────────────────────────
|
|
144
|
-
::ng-deep .owl-dt-inline-container,
|
|
145
|
-
::ng-deep .owl-dt-popup-container {
|
|
146
|
-
@apply rounded-xl shadow-lg border border-border-strong;
|
|
147
|
-
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
(keydown.enter)="onAreaClick(fileInput, $event)"
|
|
15
15
|
>
|
|
16
16
|
<fx-ui-hero-icon
|
|
17
|
-
[icon]="icon"
|
|
17
|
+
[icon]="icon()"
|
|
18
18
|
[size]="40"
|
|
19
19
|
class="flex dnd-icon"
|
|
20
20
|
></fx-ui-hero-icon>
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
} @else {
|
|
29
29
|
Any file type
|
|
30
30
|
}
|
|
31
|
-
— Max {{ maxSizeMB }} MB
|
|
31
|
+
— Max {{ maxSizeMB() }} MB
|
|
32
32
|
</div>
|
|
33
33
|
|
|
34
34
|
<input
|
|
35
35
|
#fileInput
|
|
36
36
|
type="file"
|
|
37
37
|
class="dnd-input"
|
|
38
|
-
[attr.multiple]="multiple ? '' : null"
|
|
38
|
+
[attr.multiple]="multiple() ? '' : null"
|
|
39
39
|
[attr.accept]="accept"
|
|
40
40
|
(change)="onFileSelected($event)"
|
|
41
41
|
/>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<div class="drawer-container" [@drawerExpand]="getDrawerState()">
|
|
19
19
|
<!-- Navigation Items -->
|
|
20
20
|
<nav class="drawer-nav">
|
|
21
|
-
@for (item of items; track item) {
|
|
21
|
+
@for (item of items(); track item) {
|
|
22
22
|
<ng-container
|
|
23
23
|
*ngTemplateOutlet="drawerItem; context: { $implicit: item, level: 0 }"
|
|
24
24
|
></ng-container>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<div
|
|
2
2
|
class="flex flex-col items-center justify-center gap-small w-full"
|
|
3
|
-
[style.minHeight]="height"
|
|
3
|
+
[style.minHeight]="height()"
|
|
4
4
|
>
|
|
5
5
|
@if (icon) {
|
|
6
6
|
<fx-ui-hero-icon class="text-text-placeholder" [icon]="icon" [size]="24"></fx-ui-hero-icon>
|
|
7
7
|
}
|
|
8
|
-
<div class="txt-default text-text-placeholder">{{ message }}</div>
|
|
8
|
+
<div class="txt-default text-text-placeholder">{{ message() }}</div>
|
|
9
9
|
</div>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
<
|
|
2
|
-
[
|
|
3
|
-
[
|
|
4
|
-
[
|
|
5
|
-
[
|
|
6
|
-
[
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/>
|
|
1
|
+
<svg
|
|
2
|
+
[attr.width]="size() || 24"
|
|
3
|
+
[attr.height]="size() || 24"
|
|
4
|
+
[attr.stroke-width]="solid() ? null : stroke()"
|
|
5
|
+
[style.color]="color() || null"
|
|
6
|
+
[class]="class()"
|
|
7
|
+
aria-hidden="true"
|
|
8
|
+
>
|
|
9
|
+
<use [attr.href]="href" />
|
|
10
|
+
</svg>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<div class="mb-4 text-left w-full text-text-primary" [class]="class">
|
|
1
|
+
<div class="mb-4 text-left w-full text-text-primary" [class]="class()">
|
|
2
2
|
@if (label) {
|
|
3
3
|
<label class="block txt-field-label" [attr.for]="fieldId">
|
|
4
4
|
{{ label }}
|
|
5
|
-
@if (required) {
|
|
5
|
+
@if (required()) {
|
|
6
6
|
<span class="txt-required" aria-hidden="true">*</span>
|
|
7
7
|
}
|
|
8
8
|
@if (tooltip) {
|
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
[appTrimOnBlurCollapse]="true"
|
|
25
25
|
[id]="fieldId"
|
|
26
26
|
[type]="displayType"
|
|
27
|
-
[placeholder]="placeholder"
|
|
27
|
+
[placeholder]="placeholder()"
|
|
28
28
|
[disabled]="disabled"
|
|
29
29
|
[value]="value"
|
|
30
30
|
(input)="onInput($event)"
|
|
31
31
|
(blur)="onBlur()"
|
|
32
32
|
(focus)="onFocus()"
|
|
33
|
-
[attr.maxlength]="maxlength"
|
|
33
|
+
[attr.maxlength]="maxlength()"
|
|
34
34
|
[attr.aria-invalid]="invalid || null"
|
|
35
35
|
[attr.aria-describedby]="invalid ? fieldId + '-error' : null"
|
|
36
|
-
[attr.aria-required]="required ? true : null"
|
|
36
|
+
[attr.aria-required]="required() ? true : null"
|
|
37
37
|
[class]="type === 'otp' ? 'input-otp' : 'input-default'"
|
|
38
38
|
[class.input-invalid]="invalid"
|
|
39
39
|
[class.pr-8]="type === 'password' || suffixIcon"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
[attr.aria-label]="
|
|
49
49
|
type === 'password'
|
|
50
50
|
? (showPassword ? 'Hide password' : 'Show password')
|
|
51
|
-
: (suffixAriaLabel || null)
|
|
51
|
+
: (suffixAriaLabel() || null)
|
|
52
52
|
"
|
|
53
53
|
[attr.aria-pressed]="type === 'password' ? showPassword : null"
|
|
54
54
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="kanban-board">
|
|
2
2
|
<div class="kanban-columns">
|
|
3
|
-
@for (column of columns; track column.id) {
|
|
3
|
+
@for (column of columns(); track column.id) {
|
|
4
4
|
<div class="kanban-column">
|
|
5
5
|
<div class="kanban-column-header">
|
|
6
6
|
<h3 class="kanban-column-title">{{ column.title }}</h3>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<div class="flex flex-col lg:flex-row items-start gap-xl" [style.--fx-md-list-width]="listWidth">
|
|
1
|
+
<div class="flex flex-col lg:flex-row items-start gap-xl" [style.--fx-md-list-width]="listWidth()">
|
|
2
2
|
<!-- Master: list pane -->
|
|
3
3
|
<div class="fx-md-list card-common">
|
|
4
4
|
<ng-content select="[mdHeader]"></ng-content>
|
|
5
5
|
<ng-content select="[mdFilters]"></ng-content>
|
|
6
6
|
<div
|
|
7
7
|
class="flex flex-col gap-normal overflow-auto pr-xs"
|
|
8
|
-
[style.maxHeight]="maxListHeight"
|
|
8
|
+
[style.maxHeight]="maxListHeight()"
|
|
9
9
|
role="listbox"
|
|
10
|
-
[attr.aria-label]="listLabel || null"
|
|
10
|
+
[attr.aria-label]="listLabel() || null"
|
|
11
11
|
>
|
|
12
12
|
@if (table.loading) {
|
|
13
13
|
<fx-ui-skeleton-list [rows]="table.pageSize"></fx-ui-skeleton-list>
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
"
|
|
30
30
|
>
|
|
31
31
|
<ng-container
|
|
32
|
-
[ngTemplateOutlet]="rowTemplate"
|
|
32
|
+
[ngTemplateOutlet]="rowTemplate()"
|
|
33
33
|
[ngTemplateOutletContext]="{ $implicit: row, selected: isSelected(row) }"
|
|
34
34
|
></ng-container>
|
|
35
35
|
</button>
|
|
36
36
|
}
|
|
37
37
|
@if (!table.dataSource.data.length) {
|
|
38
|
-
<fx-ui-empty-state [message]="emptyMessage"></fx-ui-empty-state>
|
|
38
|
+
<fx-ui-empty-state [message]="emptyMessage()"></fx-ui-empty-state>
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
</div>
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
class="mt-normal"
|
|
47
47
|
[length]="table.total"
|
|
48
48
|
[pageSize]="table.pageSize"
|
|
49
|
-
[pageSizeOptions]="pageSizeOptions"
|
|
49
|
+
[pageSizeOptions]="pageSizeOptions()"
|
|
50
50
|
></mat-paginator>
|
|
51
51
|
</div>
|
|
52
52
|
|
|
@@ -54,16 +54,16 @@
|
|
|
54
54
|
<div class="w-full lg:flex-1 min-w-0">
|
|
55
55
|
@if (table.selected) {
|
|
56
56
|
@if (table.detailBusy) {
|
|
57
|
-
<fx-ui-skeleton-detail [cards]="skeletonCards"></fx-ui-skeleton-detail>
|
|
57
|
+
<fx-ui-skeleton-detail [cards]="skeletonCards()"></fx-ui-skeleton-detail>
|
|
58
58
|
} @else {
|
|
59
59
|
<ng-container
|
|
60
|
-
[ngTemplateOutlet]="detailTemplate"
|
|
60
|
+
[ngTemplateOutlet]="detailTemplate()"
|
|
61
61
|
[ngTemplateOutletContext]="{ $implicit: table.detail, selected: table.selected }"
|
|
62
62
|
></ng-container>
|
|
63
63
|
}
|
|
64
64
|
} @else {
|
|
65
65
|
<div class="card-common flex items-center justify-center h-[300px]">
|
|
66
|
-
<fx-ui-empty-state [message]="emptyMessage"></fx-ui-empty-state>
|
|
66
|
+
<fx-ui-empty-state [message]="emptyMessage()"></fx-ui-empty-state>
|
|
67
67
|
</div>
|
|
68
68
|
}
|
|
69
69
|
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<button
|
|
2
|
+
type="button"
|
|
3
|
+
class="inline-flex items-center justify-center rounded-lg p-1 hover:bg-bg-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
4
|
+
[matMenuTriggerFor]="menu"
|
|
5
|
+
[disabled]="disabled()"
|
|
6
|
+
[attr.aria-label]="ariaLabel()"
|
|
7
|
+
>
|
|
8
|
+
<ng-content></ng-content>
|
|
9
|
+
</button>
|
|
10
|
+
|
|
11
|
+
<mat-menu #menu="matMenu">
|
|
12
|
+
@for (item of items(); track item.label) {
|
|
13
|
+
<button
|
|
14
|
+
mat-menu-item
|
|
15
|
+
type="button"
|
|
16
|
+
[disabled]="item.disabled"
|
|
17
|
+
(click)="select.emit(item)"
|
|
18
|
+
>
|
|
19
|
+
<span class="flex items-center gap-normal" [class]="toneClass(item)">
|
|
20
|
+
@if (item.icon) {
|
|
21
|
+
<fx-ui-hero-icon [icon]="item.icon" [size]="18"></fx-ui-hero-icon>
|
|
22
|
+
}
|
|
23
|
+
<span>{{ item.label }}</span>
|
|
24
|
+
</span>
|
|
25
|
+
</button>
|
|
26
|
+
}
|
|
27
|
+
</mat-menu>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div
|
|
2
2
|
class="w-full rounded-lg overflow-hidden"
|
|
3
|
-
[class]="class"
|
|
3
|
+
[class]="class()"
|
|
4
4
|
role="radiogroup"
|
|
5
5
|
[attr.aria-labelledby]="label ? groupId + '-label' : null"
|
|
6
6
|
>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
@if (label) {
|
|
9
9
|
<span class="txt-field-label block" [id]="groupId + '-label'">
|
|
10
10
|
{{ label }}
|
|
11
|
-
@if (required) {
|
|
11
|
+
@if (required()) {
|
|
12
12
|
<span class="txt-required" aria-hidden="true">*</span>
|
|
13
13
|
}
|
|
14
14
|
@if (tooltip) {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
</span>
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
@for (opt of options; track opt) {
|
|
27
|
+
@for (opt of options(); track opt) {
|
|
28
28
|
<button
|
|
29
29
|
type="button"
|
|
30
30
|
role="radio"
|