@foxeltech/angular-ui 0.0.14 → 0.3.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/BeVietnamPro/BeVietnamPro-Bold.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-ExtraLight.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Light.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Medium.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Regular.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-SemiBold.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Thin.woff2 +0 -0
- package/SpaceMono-Regular.woff2 +0 -0
- package/components.css +7 -17
- package/dm-sans/DMSans-Bold.woff2 +0 -0
- package/dm-sans/DMSans-Light.woff2 +0 -0
- package/dm-sans/DMSans-Medium.woff2 +0 -0
- package/dm-sans/DMSans-Regular.woff2 +0 -0
- package/dm-sans/DMSans-SemiBold.woff2 +0 -0
- package/dm-sans/DMSans-Thin.woff2 +0 -0
- package/fesm2022/foxeltech-angular-ui.mjs +1349 -285
- package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
- package/fonts.css +68 -34
- package/index.d.ts +624 -139
- package/orbitron/Orbitron-Bold.woff2 +0 -0
- package/orbitron/Orbitron-Medium.woff2 +0 -0
- package/orbitron/Orbitron-Regular.woff2 +0 -0
- package/orbitron/Orbitron-SemiBold.woff2 +0 -0
- package/package.json +9 -10
- package/roboto/Roboto-Black.woff2 +0 -0
- package/roboto/Roboto-BlackItalic.woff2 +0 -0
- package/roboto/Roboto-Bold.woff2 +0 -0
- package/roboto/Roboto-BoldCondensed.woff2 +0 -0
- package/roboto/Roboto-BoldCondensedItalic.woff2 +0 -0
- package/roboto/Roboto-BoldItalic.woff2 +0 -0
- package/roboto/Roboto-Condensed.woff2 +0 -0
- package/roboto/Roboto-CondensedItalic.woff2 +0 -0
- package/roboto/Roboto-Italic.woff2 +0 -0
- package/roboto/Roboto-Light.woff2 +0 -0
- package/roboto/Roboto-LightItalic.woff2 +0 -0
- package/roboto/Roboto-Medium.woff2 +0 -0
- package/roboto/Roboto-MediumItalic.woff2 +0 -0
- package/roboto/Roboto-Regular.woff2 +0 -0
- package/roboto/Roboto-Thin.woff2 +0 -0
- package/roboto/Roboto-ThinItalic.woff2 +0 -0
- package/src/lib/styles/components.css +7 -17
- package/src/lib/styles/fonts.css +68 -34
- package/src/lib/styles/tailwind.css +11 -8
- package/src/lib/styles/tokens.css +131 -0
- package/src/lib/styles/utilities.css +24 -0
- package/src/lib/ui/components/button/button.component.html +4 -1
- package/src/lib/ui/components/button/button.component.scss +0 -0
- package/src/lib/ui/components/chart/chart.component.scss +49 -0
- package/src/lib/ui/components/checkbox/checkbox.component.html +3 -2
- package/src/lib/ui/components/checkbox/checkbox.component.scss +0 -0
- package/src/lib/ui/components/circle-progress-bar/circle-progress-bar.component.scss +0 -0
- package/src/lib/ui/components/datetime-picker/datetime-picker.component.html +3 -2
- package/src/lib/ui/components/datetime-picker/datetime-picker.component.scss +147 -0
- package/src/lib/ui/components/dnd-upload/dnd-upload.component.scss +87 -0
- package/src/lib/ui/components/drawer/drawer.component.html +3 -0
- package/src/lib/ui/components/drawer/drawer.component.scss +134 -0
- package/src/lib/ui/components/empty-state/empty-state.component.html +9 -0
- package/src/lib/ui/components/filter-chips/filter-chips.component.html +12 -0
- package/src/lib/ui/components/flow-connection/flow-connection.component.scss +0 -0
- package/src/lib/ui/components/hero-icon/hero-icon.component.scss +0 -0
- package/src/lib/ui/components/info-field/info-field.component.html +4 -0
- package/src/lib/ui/components/input/input.component.html +15 -3
- package/src/lib/ui/components/kanban-board/kanban-board.component.scss +70 -0
- package/src/lib/ui/components/loading-panel/loading-panel.component.scss +0 -0
- package/src/lib/ui/components/master-detail/master-detail.component.css +11 -0
- package/src/lib/ui/components/master-detail/master-detail.component.html +70 -0
- package/src/lib/ui/components/meter/meter.component.html +22 -0
- package/src/lib/ui/components/radio-button/radio-button.component.html +10 -4
- package/src/lib/ui/components/radio-button-toggle/radio-button-toggle.component.html +8 -3
- package/src/lib/ui/components/radio-button-toggle/radio-button-toggle.component.scss +0 -0
- package/src/lib/ui/components/rich-text-area/rich-text-area.component.scss +18 -0
- package/src/lib/ui/components/search-bar/search-bar.component.scss +0 -0
- package/src/lib/ui/components/section-card/section-card.component.html +9 -0
- package/src/lib/ui/components/select/select.component.html +9 -4
- package/src/lib/ui/components/severity-badges/severity-badges.component.html +11 -0
- package/src/lib/ui/components/skeleton-detail/skeleton-detail.component.html +22 -0
- package/src/lib/ui/components/skeleton-list/skeleton-list.component.html +12 -0
- package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.scss +0 -0
- package/src/lib/ui/components/slider/slider.component.html +3 -0
- package/src/lib/ui/components/slider/slider.component.scss +0 -0
- package/src/lib/ui/components/stat-cards/stat-cards.component.html +18 -0
- package/src/lib/ui/components/switch/switch.component.html +11 -6
- package/src/lib/ui/components/switch/switch.component.scss +0 -0
- package/src/lib/ui/components/tab-component/tab.component.scss +0 -0
- package/src/lib/ui/components/tab-group/tab-group.component.html +15 -1
- package/src/lib/ui/components/tab-group/tab-group.component.scss +51 -0
- package/src/lib/ui/components/table-cell/table-cell.component.scss +0 -0
- package/src/lib/ui/components/tag/tag.component.html +6 -1
- package/src/lib/ui/components/tag/tag.component.scss +0 -0
- package/src/lib/ui/components/toast/toast.component.html +2 -1
- package/src/lib/ui/components/toast/toast.component.scss +0 -0
- package/src/lib/ui/components/toast-container/toast-container.component.scss +0 -0
- package/src/lib/ui/components/tree-diagram/tree-diagram.component.scss +0 -0
- package/src/lib/ui/dialogs/confirmation/confirmation.component.html +1 -1
- package/src/lib/ui/dialogs/confirmation/confirmation.component.scss +0 -0
- package/tailwind.css +11 -8
- package/tokens.css +131 -0
- package/utilities.css +24 -0
- package/BeVietnamPro/BeVietnamPro-Bold.ttf +0 -0
- package/BeVietnamPro/BeVietnamPro-ExtraLight.ttf +0 -0
- package/BeVietnamPro/BeVietnamPro-Light.ttf +0 -0
- package/BeVietnamPro/BeVietnamPro-Medium.ttf +0 -0
- package/BeVietnamPro/BeVietnamPro-Regular.ttf +0 -0
- package/BeVietnamPro/BeVietnamPro-SemiBold.ttf +0 -0
- package/BeVietnamPro/BeVietnamPro-Thin.ttf +0 -0
- package/SpaceMono-Regular.ttf +0 -0
- package/dm-sans/DMSans-Bold.ttf +0 -0
- package/dm-sans/DMSans-Light.ttf +0 -0
- package/dm-sans/DMSans-Medium.ttf +0 -0
- package/dm-sans/DMSans-Regular.ttf +0 -0
- package/dm-sans/DMSans-SemiBold.ttf +0 -0
- package/dm-sans/DMSans-Thin.ttf +0 -0
- package/orbitron/Orbitron-Bold.ttf +0 -0
- package/orbitron/Orbitron-Medium.ttf +0 -0
- package/orbitron/Orbitron-Regular.ttf +0 -0
- package/orbitron/Orbitron-SemiBold.ttf +0 -0
- package/roboto/Roboto-Black.ttf +0 -0
- package/roboto/Roboto-BlackItalic.ttf +0 -0
- package/roboto/Roboto-Bold.ttf +0 -0
- package/roboto/Roboto-BoldCondensed.ttf +0 -0
- package/roboto/Roboto-BoldCondensedItalic.ttf +0 -0
- package/roboto/Roboto-BoldItalic.ttf +0 -0
- package/roboto/Roboto-Condensed.ttf +0 -0
- package/roboto/Roboto-CondensedItalic.ttf +0 -0
- package/roboto/Roboto-Italic.ttf +0 -0
- package/roboto/Roboto-Light.ttf +0 -0
- package/roboto/Roboto-LightItalic.ttf +0 -0
- package/roboto/Roboto-Medium.ttf +0 -0
- package/roboto/Roboto-MediumItalic.ttf +0 -0
- package/roboto/Roboto-Regular.ttf +0 -0
- package/roboto/Roboto-Thin.ttf +0 -0
- package/roboto/Roboto-ThinItalic.ttf +0 -0
- package/tailwind-config.d.ts +0 -4
- package/tailwind.config.js +0 -95
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<button
|
|
2
|
+
[attr.type]="type"
|
|
3
|
+
[attr.aria-label]="ariaLabel || null"
|
|
4
|
+
[attr.aria-busy]="loading || null"
|
|
2
5
|
[class]="class"
|
|
3
6
|
[ngClass]="{
|
|
4
7
|
'btn-default': buttonVariant === 'default',
|
|
@@ -10,7 +13,7 @@
|
|
|
10
13
|
(click)="onClick()"
|
|
11
14
|
>
|
|
12
15
|
@if (loading) {
|
|
13
|
-
<div class="flex w-full items-center justify-center">
|
|
16
|
+
<div class="flex w-full items-center justify-center" aria-hidden="true">
|
|
14
17
|
<svg
|
|
15
18
|
[attr.fill]="
|
|
16
19
|
buttonVariant !== 'alternative' ? 'rgb(var(--text-primary))' : 'rgb(var(--primary))'
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.chart-wrapper {
|
|
7
|
+
position: relative;
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.chart-container {
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.chart-loader {
|
|
18
|
+
position: absolute;
|
|
19
|
+
inset: 0;
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
background: rgba(var(--bg-primary-hover) / 0.6);
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
font-size: 1.1rem;
|
|
26
|
+
z-index: 2;
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.chart-empty {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
height: 100%;
|
|
36
|
+
gap: 12px;
|
|
37
|
+
color: rgba(var(--text-secondary) / 1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.chart-empty-icon {
|
|
41
|
+
width: 48px;
|
|
42
|
+
height: 48px;
|
|
43
|
+
opacity: 0.4;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.chart-empty-text {
|
|
47
|
+
font-size: 14px;
|
|
48
|
+
font-weight: 500;
|
|
49
|
+
}
|
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
[class.opacity-50]="disabled"
|
|
4
4
|
[class.cursor-not-allowed]="disabled"
|
|
5
5
|
>
|
|
6
|
+
<!-- sr-only (not `hidden`): keeps the input focusable and in the a11y tree -->
|
|
6
7
|
<input
|
|
7
8
|
type="checkbox"
|
|
8
|
-
class="
|
|
9
|
+
class="peer sr-only"
|
|
9
10
|
[checked]="value"
|
|
10
11
|
[disabled]="disabled"
|
|
11
12
|
(change)="onInputChange($event)"
|
|
12
13
|
(blur)="onTouched()"
|
|
13
14
|
/>
|
|
14
15
|
<span
|
|
15
|
-
class="relative w-4 h-4 border rounded-full transition-colors duration-150 shrink-0"
|
|
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"
|
|
16
17
|
[ngClass]="{
|
|
17
18
|
'rounded-full': rounded,
|
|
18
19
|
'rounded-sm': !rounded,
|
|
File without changes
|
|
File without changes
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
<div class="flex flex-col mb-4 w-full text-left">
|
|
2
2
|
@if (label) {
|
|
3
|
-
<label class="txt-field-label">
|
|
3
|
+
<label class="txt-field-label" [attr.for]="fieldId">
|
|
4
4
|
{{ label }}
|
|
5
|
-
<span *ngIf="required" class="txt-required">*</span>
|
|
5
|
+
<span *ngIf="required" class="txt-required" aria-hidden="true">*</span>
|
|
6
6
|
</label>
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
<div class="relative">
|
|
10
10
|
<input
|
|
11
|
+
[id]="fieldId"
|
|
11
12
|
[owlDateTimeTrigger]="picker"
|
|
12
13
|
[owlDateTime]="picker"
|
|
13
14
|
[placeholder]="placeholder"
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/* Tailwind v4: component styles compile in isolation — @reference pulls in the theme for @apply without re-emitting it. */
|
|
2
|
+
@reference '../../../styles/tailwind.css';
|
|
3
|
+
|
|
4
|
+
// ─── Owl DateTime Picker Custom Styles ───────────────────────────────────────
|
|
5
|
+
|
|
6
|
+
// Container
|
|
7
|
+
::ng-deep .owl-dt-container {
|
|
8
|
+
@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
|
+
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
|
+
|
|
67
|
+
// ── Set / Cancel footer buttons ───────────────────────────────────────────────
|
|
68
|
+
// Library sets .owl-dt-container-buttons { height: 2em; color: #3f51b5 } — override both
|
|
69
|
+
::ng-deep .owl-dt-container-buttons {
|
|
70
|
+
height: auto !important;
|
|
71
|
+
color: rgb(var(--text-primary)) !important; // reset inherited primary color on text
|
|
72
|
+
display: flex !important;
|
|
73
|
+
align-items: center !important;
|
|
74
|
+
justify-content: flex-end !important;
|
|
75
|
+
gap: 8px;
|
|
76
|
+
padding: 8px 12px;
|
|
77
|
+
border-top: 1px solid rgb(var(--border-default));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Both buttons — explicit 32px height so inner height:100% resolves correctly
|
|
81
|
+
::ng-deep .owl-dt-container-buttons .owl-dt-container-control-button {
|
|
82
|
+
width: auto !important;
|
|
83
|
+
height: 32px !important;
|
|
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
|
+
|
|
107
|
+
|
|
108
|
+
&:hover {
|
|
109
|
+
opacity: 0.85;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
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
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
--dnd-accent: rgba(var(--gradient-primary-start) / 1);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.dnd-wrapper {
|
|
6
|
+
display: block;
|
|
7
|
+
width: 100%;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.dnd-area {
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
gap: 12px;
|
|
16
|
+
min-height: 160px;
|
|
17
|
+
padding: 32px 24px;
|
|
18
|
+
border: 2px dashed color-mix(in srgb, var(--dnd-accent) 40%, transparent);
|
|
19
|
+
border-radius: 12px;
|
|
20
|
+
background: color-mix(in srgb, var(--dnd-accent) 4%, transparent);
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
outline: none;
|
|
23
|
+
transition: all 0.2s ease;
|
|
24
|
+
position: relative;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.dnd-area:hover {
|
|
28
|
+
border-color: color-mix(in srgb, var(--dnd-accent) 70%, transparent);
|
|
29
|
+
background: color-mix(in srgb, var(--dnd-accent) 8%, transparent);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.dnd-area:focus-visible {
|
|
33
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--dnd-accent) 20%, transparent);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.dnd-area.drag-over {
|
|
37
|
+
border-color: var(--dnd-accent);
|
|
38
|
+
background: color-mix(in srgb, var(--dnd-accent) 10%, transparent);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.dnd-icon {
|
|
42
|
+
color: var(--dnd-accent);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.dnd-text {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 4px;
|
|
49
|
+
font-size: 14px;
|
|
50
|
+
flex-wrap: wrap;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.dnd-link {
|
|
55
|
+
color: var(--dnd-accent);
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
text-decoration: underline;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.dnd-or {
|
|
61
|
+
color: rgba(var(--text-secondary) / 1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.dnd-hint {
|
|
65
|
+
font-size: 12px;
|
|
66
|
+
color: rgba(var(--text-secondary) / 0.7);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.dnd-input {
|
|
70
|
+
position: absolute;
|
|
71
|
+
width: 0;
|
|
72
|
+
height: 0;
|
|
73
|
+
overflow: hidden;
|
|
74
|
+
opacity: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Responsive */
|
|
78
|
+
@media (max-width: 640px) {
|
|
79
|
+
.dnd-area {
|
|
80
|
+
min-height: 120px;
|
|
81
|
+
padding: 24px 16px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.dnd-text {
|
|
85
|
+
font-size: 13px;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
@if (logo) {
|
|
8
8
|
<img
|
|
9
9
|
[src]="logo"
|
|
10
|
+
alt="Home"
|
|
10
11
|
class="h-[20px] w-auto transition-all duration-300 ease-in-out"
|
|
11
12
|
[ngClass]="{ 'scale-90': !isExpanded, 'ml-5': isExpanded }"
|
|
12
13
|
/>
|
|
@@ -35,6 +36,8 @@
|
|
|
35
36
|
<button
|
|
36
37
|
type="button"
|
|
37
38
|
class="toggle-btn"
|
|
39
|
+
[attr.aria-label]="isExpanded ? 'Collapse navigation' : 'Expand navigation'"
|
|
40
|
+
[attr.aria-expanded]="isExpanded"
|
|
38
41
|
(click)="toggleDrawer()"
|
|
39
42
|
[matTooltip]="isExpanded ? 'Collapse' : 'Expand'"
|
|
40
43
|
matTooltipClass="text-text-primary text-xs font-semibold"
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/* Tailwind v4: component styles compile in isolation — @reference pulls in the theme for @apply without re-emitting it. */
|
|
2
|
+
@reference '../../../styles/tailwind.css';
|
|
3
|
+
|
|
4
|
+
:host {
|
|
5
|
+
@apply block h-full;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.drawer-host-wrapper {
|
|
9
|
+
@apply relative h-full border-r border-border-default;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.drawer-container {
|
|
13
|
+
@apply px-2 h-full bg-bg-primary flex flex-col overflow-auto;
|
|
14
|
+
transition: width 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Floating toggle button — sits on the right border, vertically centered */
|
|
18
|
+
.toggle-btn {
|
|
19
|
+
@apply absolute top-1/2 -translate-y-1/2 z-50 flex items-center justify-center w-6 h-6 rounded-full bg-bg-primary border border-border-default cursor-pointer shadow-sm;
|
|
20
|
+
right: -12px; /* half of button width to straddle the border */
|
|
21
|
+
transition: all 200ms ease;
|
|
22
|
+
|
|
23
|
+
&:hover {
|
|
24
|
+
@apply bg-bg-hover shadow-md;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&:active {
|
|
28
|
+
transform: translateY(-50%) scale(0.9);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&:focus-visible {
|
|
32
|
+
@apply outline-2 outline-primary outline-offset-2;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.drawer-nav {
|
|
37
|
+
@apply flex-1 overflow-y-auto overflow-x-hidden py-2;
|
|
38
|
+
|
|
39
|
+
/* Custom scrollbar */
|
|
40
|
+
&::-webkit-scrollbar {
|
|
41
|
+
@apply w-1.5;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&::-webkit-scrollbar-track {
|
|
45
|
+
@apply bg-transparent;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&::-webkit-scrollbar-thumb {
|
|
49
|
+
@apply bg-border-default rounded-sm;
|
|
50
|
+
|
|
51
|
+
&:hover {
|
|
52
|
+
@apply bg-text-placeholder;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.drawer-item-wrapper {
|
|
58
|
+
@apply relative;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.drawer-item {
|
|
62
|
+
@apply flex items-center mt-1 w-full min-h-8 py-2 px-large border-none bg-transparent cursor-pointer no-underline text-text-primary relative rounded;
|
|
63
|
+
transition: all 200ms ease;
|
|
64
|
+
|
|
65
|
+
&:hover {
|
|
66
|
+
@apply bg-bg-hover text-text-primary scale-95;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&.active {
|
|
70
|
+
@apply bg-gradient-primary text-white font-medium;
|
|
71
|
+
|
|
72
|
+
.item-icon {
|
|
73
|
+
@apply text-white;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&:active {
|
|
78
|
+
transform: scale(0.98);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&:focus-visible {
|
|
82
|
+
@apply outline-2 outline-primary outline-offset-2;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
-webkit-tap-highlight-color: transparent;
|
|
86
|
+
@apply outline-none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.item-content {
|
|
90
|
+
@apply flex items-center gap-3 w-full overflow-hidden;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.item-icon {
|
|
94
|
+
@apply flex-shrink-0;
|
|
95
|
+
color: inherit;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.item-label {
|
|
99
|
+
@apply flex-1 whitespace-nowrap overflow-hidden text-ellipsis text-[13px] leading-5 text-left;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.chevron-icon {
|
|
103
|
+
@apply flex-shrink-0 ml-auto text-text-primary;
|
|
104
|
+
transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
105
|
+
|
|
106
|
+
&.rotated {
|
|
107
|
+
transform: rotate(180deg);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.accordion-children {
|
|
112
|
+
@apply overflow-hidden;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.drawer-version {
|
|
116
|
+
@apply flex items-center justify-center py-3 px-4 text-text-placeholder text-[11px] border-t border-border-default select-none;
|
|
117
|
+
font-family: 'Roboto', monospace;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.drawer-version-dot {
|
|
121
|
+
@apply block w-1.5 h-1.5 rounded-full bg-text-placeholder;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Collapsed mode: center the icons */
|
|
125
|
+
.drawer-container[style*='width: 64px'] {
|
|
126
|
+
.drawer-item {
|
|
127
|
+
@apply justify-center;
|
|
128
|
+
padding-left: 16px !important;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.item-content {
|
|
132
|
+
@apply justify-center;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<div
|
|
2
|
+
class="flex flex-col items-center justify-center gap-small w-full"
|
|
3
|
+
[style.minHeight]="height"
|
|
4
|
+
>
|
|
5
|
+
@if (icon) {
|
|
6
|
+
<fx-ui-hero-icon class="text-text-placeholder" [icon]="icon" [size]="24"></fx-ui-hero-icon>
|
|
7
|
+
}
|
|
8
|
+
<div class="txt-default text-text-placeholder">{{ message }}</div>
|
|
9
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<div class="flex flex-wrap items-center gap-small">
|
|
2
|
+
@for (option of options; track option.value) {
|
|
3
|
+
<button
|
|
4
|
+
type="button"
|
|
5
|
+
class="px-3 py-1 rounded-full txt-utility-caption font-medium transition-colors cursor-pointer"
|
|
6
|
+
[ngClass]="chipClass(option)"
|
|
7
|
+
(click)="select(option)"
|
|
8
|
+
>
|
|
9
|
+
{{ option.label }}
|
|
10
|
+
</button>
|
|
11
|
+
}
|
|
12
|
+
</div>
|
|
File without changes
|
|
File without changes
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<div class="mb-4 text-left w-full text-text-primary" [class]="class">
|
|
2
2
|
@if (label) {
|
|
3
|
-
<label class="block txt-field-label">
|
|
3
|
+
<label class="block txt-field-label" [attr.for]="fieldId">
|
|
4
4
|
{{ label }}
|
|
5
5
|
@if (required) {
|
|
6
|
-
<span class="txt-required">*</span>
|
|
6
|
+
<span class="txt-required" aria-hidden="true">*</span>
|
|
7
7
|
}
|
|
8
8
|
@if (tooltip) {
|
|
9
9
|
<fx-ui-hero-icon
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<input
|
|
23
23
|
appTrimOnBlur
|
|
24
24
|
[appTrimOnBlurCollapse]="true"
|
|
25
|
+
[id]="fieldId"
|
|
25
26
|
[type]="displayType"
|
|
26
27
|
[placeholder]="placeholder"
|
|
27
28
|
[disabled]="disabled"
|
|
@@ -30,6 +31,9 @@
|
|
|
30
31
|
(blur)="onBlur()"
|
|
31
32
|
(focus)="onFocus()"
|
|
32
33
|
[attr.maxlength]="maxlength"
|
|
34
|
+
[attr.aria-invalid]="invalid || null"
|
|
35
|
+
[attr.aria-describedby]="invalid ? fieldId + '-error' : null"
|
|
36
|
+
[attr.aria-required]="required ? true : null"
|
|
33
37
|
[class]="type === 'otp' ? 'input-otp' : 'input-default'"
|
|
34
38
|
[class.input-invalid]="invalid"
|
|
35
39
|
[class.pr-8]="type === 'password' || suffixIcon"
|
|
@@ -41,18 +45,26 @@
|
|
|
41
45
|
class="absolute inset-y-0 right-2 flex items-center text-text-primary hover:text-text-secondary"
|
|
42
46
|
(click)="onSuffixClick()"
|
|
43
47
|
[disabled]="disabled"
|
|
48
|
+
[attr.aria-label]="
|
|
49
|
+
type === 'password'
|
|
50
|
+
? (showPassword ? 'Hide password' : 'Show password')
|
|
51
|
+
: (suffixAriaLabel || null)
|
|
52
|
+
"
|
|
53
|
+
[attr.aria-pressed]="type === 'password' ? showPassword : null"
|
|
44
54
|
>
|
|
45
55
|
@if (type === 'password') {
|
|
46
56
|
<fx-ui-hero-icon
|
|
47
57
|
[icon]="showPassword ? 'eye-slash' : 'eye'"
|
|
48
58
|
[size]="18"
|
|
49
59
|
class="text-text-primary"
|
|
60
|
+
aria-hidden="true"
|
|
50
61
|
></fx-ui-hero-icon>
|
|
51
62
|
} @else if (suffixIcon) {
|
|
52
63
|
<fx-ui-hero-icon
|
|
53
64
|
[icon]="suffixIcon"
|
|
54
65
|
[size]="18"
|
|
55
66
|
class="text-text-primary"
|
|
67
|
+
aria-hidden="true"
|
|
56
68
|
></fx-ui-hero-icon>
|
|
57
69
|
}
|
|
58
70
|
</button>
|
|
@@ -60,7 +72,7 @@
|
|
|
60
72
|
</div>
|
|
61
73
|
|
|
62
74
|
@if (invalid) {
|
|
63
|
-
<div class="txt-invalid">
|
|
75
|
+
<div class="txt-invalid" role="alert" [id]="fieldId + '-error'">
|
|
64
76
|
{{ getErrorMessage(label) }}
|
|
65
77
|
</div>
|
|
66
78
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* Tailwind v4: component styles compile in isolation — @reference pulls in the theme for @apply without re-emitting it. */
|
|
2
|
+
@reference '../../../styles/tailwind.css';
|
|
3
|
+
|
|
4
|
+
.kanban-board {
|
|
5
|
+
@apply w-full h-full overflow-x-auto;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.kanban-columns {
|
|
9
|
+
@apply flex gap-4 p-4 min-h-full;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.kanban-column {
|
|
13
|
+
@apply flex flex-col min-w-[300px] bg-gray-50 dark:bg-gray-800 rounded-lg;
|
|
14
|
+
flex-shrink: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.kanban-column-header {
|
|
18
|
+
@apply flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.kanban-column-title {
|
|
22
|
+
@apply text-lg font-semibold text-gray-900 dark:text-gray-100 m-0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.kanban-column-count {
|
|
26
|
+
@apply px-2 py-1 text-sm font-medium bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-full;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.kanban-column-content {
|
|
30
|
+
@apply flex-1 p-4 space-y-3 overflow-y-auto;
|
|
31
|
+
min-height: 200px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.kanban-item {
|
|
35
|
+
@apply bg-white dark:bg-gray-700 rounded-lg shadow-sm border border-gray-200 dark:border-gray-600;
|
|
36
|
+
@apply transition-shadow duration-200;
|
|
37
|
+
cursor: move;
|
|
38
|
+
|
|
39
|
+
&:hover {
|
|
40
|
+
@apply shadow-md;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.kanban-item-default {
|
|
45
|
+
@apply p-4 text-gray-900 dark:text-gray-100;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.kanban-item-placeholder {
|
|
49
|
+
@apply bg-gray-200 dark:bg-gray-600 rounded-lg border-2 border-dashed border-gray-400 dark:border-gray-500;
|
|
50
|
+
@apply opacity-50;
|
|
51
|
+
min-height: 60px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.kanban-column-empty {
|
|
55
|
+
@apply flex items-center justify-center h-32 text-gray-400 dark:text-gray-500 text-sm;
|
|
56
|
+
@apply border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// CDK Drag and Drop Styles
|
|
60
|
+
.cdk-drag-preview {
|
|
61
|
+
@apply opacity-80 shadow-lg rounded-lg;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.cdk-drag-animating {
|
|
65
|
+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.kanban-column-content.cdk-drop-list-dragging .kanban-item:not(.cdk-drag-placeholder) {
|
|
69
|
+
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
70
|
+
}
|
|
File without changes
|