@foxeltech/angular-ui 0.3.1 → 0.7.44

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.
Files changed (193) hide show
  1. package/archivo/archivo-400-latin-ext.woff2 +0 -0
  2. package/archivo/archivo-400-latin.woff2 +0 -0
  3. package/archivo/archivo-400-vietnamese.woff2 +0 -0
  4. package/archivo/archivo-500-latin-ext.woff2 +0 -0
  5. package/archivo/archivo-500-latin.woff2 +0 -0
  6. package/archivo/archivo-500-vietnamese.woff2 +0 -0
  7. package/archivo/archivo-600-latin-ext.woff2 +0 -0
  8. package/archivo/archivo-600-latin.woff2 +0 -0
  9. package/archivo/archivo-600-vietnamese.woff2 +0 -0
  10. package/archivo/archivo-700-latin-ext.woff2 +0 -0
  11. package/archivo/archivo-700-latin.woff2 +0 -0
  12. package/archivo/archivo-700-vietnamese.woff2 +0 -0
  13. package/components.css +12 -12
  14. package/dialogs.css +2 -2
  15. package/fesm2022/foxeltech-angular-ui-chart.mjs +560 -0
  16. package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -0
  17. package/fesm2022/foxeltech-angular-ui-flow.mjs +211 -0
  18. package/fesm2022/foxeltech-angular-ui-flow.mjs.map +1 -0
  19. package/fesm2022/foxeltech-angular-ui-rich-text.mjs +156 -0
  20. package/fesm2022/foxeltech-angular-ui-rich-text.mjs.map +1 -0
  21. package/fesm2022/foxeltech-angular-ui.mjs +1580 -1409
  22. package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
  23. package/fonts.css +462 -138
  24. package/fx-icons.svg +97 -0
  25. package/ibm-plex-mono/ibm-plex-mono-400-cyrillic-ext.woff2 +0 -0
  26. package/ibm-plex-mono/ibm-plex-mono-400-cyrillic.woff2 +0 -0
  27. package/ibm-plex-mono/ibm-plex-mono-400-latin-ext.woff2 +0 -0
  28. package/ibm-plex-mono/ibm-plex-mono-400-latin.woff2 +0 -0
  29. package/ibm-plex-mono/ibm-plex-mono-400-vietnamese.woff2 +0 -0
  30. package/ibm-plex-mono/ibm-plex-mono-500-cyrillic-ext.woff2 +0 -0
  31. package/ibm-plex-mono/ibm-plex-mono-500-cyrillic.woff2 +0 -0
  32. package/ibm-plex-mono/ibm-plex-mono-500-latin-ext.woff2 +0 -0
  33. package/ibm-plex-mono/ibm-plex-mono-500-latin.woff2 +0 -0
  34. package/ibm-plex-mono/ibm-plex-mono-500-vietnamese.woff2 +0 -0
  35. package/ibm-plex-mono/ibm-plex-mono-600-cyrillic-ext.woff2 +0 -0
  36. package/ibm-plex-mono/ibm-plex-mono-600-cyrillic.woff2 +0 -0
  37. package/ibm-plex-mono/ibm-plex-mono-600-latin-ext.woff2 +0 -0
  38. package/ibm-plex-mono/ibm-plex-mono-600-latin.woff2 +0 -0
  39. package/ibm-plex-mono/ibm-plex-mono-600-vietnamese.woff2 +0 -0
  40. package/jetbrains-mono/jetbrains-mono-400-cyrillic-ext.woff2 +0 -0
  41. package/jetbrains-mono/jetbrains-mono-400-cyrillic.woff2 +0 -0
  42. package/jetbrains-mono/jetbrains-mono-400-greek.woff2 +0 -0
  43. package/jetbrains-mono/jetbrains-mono-400-latin-ext.woff2 +0 -0
  44. package/jetbrains-mono/jetbrains-mono-400-latin.woff2 +0 -0
  45. package/jetbrains-mono/jetbrains-mono-400-vietnamese.woff2 +0 -0
  46. package/jetbrains-mono/jetbrains-mono-500-cyrillic-ext.woff2 +0 -0
  47. package/jetbrains-mono/jetbrains-mono-500-cyrillic.woff2 +0 -0
  48. package/jetbrains-mono/jetbrains-mono-500-greek.woff2 +0 -0
  49. package/jetbrains-mono/jetbrains-mono-500-latin-ext.woff2 +0 -0
  50. package/jetbrains-mono/jetbrains-mono-500-latin.woff2 +0 -0
  51. package/jetbrains-mono/jetbrains-mono-500-vietnamese.woff2 +0 -0
  52. package/jetbrains-mono/jetbrains-mono-600-cyrillic-ext.woff2 +0 -0
  53. package/jetbrains-mono/jetbrains-mono-600-cyrillic.woff2 +0 -0
  54. package/jetbrains-mono/jetbrains-mono-600-greek.woff2 +0 -0
  55. package/jetbrains-mono/jetbrains-mono-600-latin-ext.woff2 +0 -0
  56. package/jetbrains-mono/jetbrains-mono-600-latin.woff2 +0 -0
  57. package/jetbrains-mono/jetbrains-mono-600-vietnamese.woff2 +0 -0
  58. package/jetbrains-mono/jetbrains-mono-700-cyrillic-ext.woff2 +0 -0
  59. package/jetbrains-mono/jetbrains-mono-700-cyrillic.woff2 +0 -0
  60. package/jetbrains-mono/jetbrains-mono-700-greek.woff2 +0 -0
  61. package/jetbrains-mono/jetbrains-mono-700-latin-ext.woff2 +0 -0
  62. package/jetbrains-mono/jetbrains-mono-700-latin.woff2 +0 -0
  63. package/jetbrains-mono/jetbrains-mono-700-vietnamese.woff2 +0 -0
  64. package/newsreader/newsreader-400-latin-ext.woff2 +0 -0
  65. package/newsreader/newsreader-400-latin.woff2 +0 -0
  66. package/newsreader/newsreader-400-vietnamese.woff2 +0 -0
  67. package/newsreader/newsreader-500-latin-ext.woff2 +0 -0
  68. package/newsreader/newsreader-500-latin.woff2 +0 -0
  69. package/newsreader/newsreader-500-vietnamese.woff2 +0 -0
  70. package/newsreader/newsreader-600-latin-ext.woff2 +0 -0
  71. package/newsreader/newsreader-600-latin.woff2 +0 -0
  72. package/newsreader/newsreader-600-vietnamese.woff2 +0 -0
  73. package/package.json +18 -9
  74. package/source-serif-4/source-serif-4-400-cyrillic-ext.woff2 +0 -0
  75. package/source-serif-4/source-serif-4-400-cyrillic.woff2 +0 -0
  76. package/source-serif-4/source-serif-4-400-greek.woff2 +0 -0
  77. package/source-serif-4/source-serif-4-400-latin-ext.woff2 +0 -0
  78. package/source-serif-4/source-serif-4-400-latin.woff2 +0 -0
  79. package/source-serif-4/source-serif-4-400-vietnamese.woff2 +0 -0
  80. package/source-serif-4/source-serif-4-600-cyrillic-ext.woff2 +0 -0
  81. package/source-serif-4/source-serif-4-600-cyrillic.woff2 +0 -0
  82. package/source-serif-4/source-serif-4-600-greek.woff2 +0 -0
  83. package/source-serif-4/source-serif-4-600-latin-ext.woff2 +0 -0
  84. package/source-serif-4/source-serif-4-600-latin.woff2 +0 -0
  85. package/source-serif-4/source-serif-4-600-vietnamese.woff2 +0 -0
  86. package/src/lib/styles/components.css +12 -12
  87. package/src/lib/styles/dialogs.css +2 -2
  88. package/src/lib/styles/fonts.css +462 -138
  89. package/src/lib/styles/tailwind.css +1 -2
  90. package/src/lib/styles/theme.css +596 -69
  91. package/src/lib/styles/tokens.css +56 -19
  92. package/src/lib/styles/utilities.css +4 -1
  93. package/src/lib/ui/components/bar-list/bar-list.component.html +29 -0
  94. package/src/lib/ui/components/button/button.component.html +20 -18
  95. package/src/lib/ui/components/checkbox/checkbox.component.html +3 -3
  96. package/src/lib/ui/components/circle-progress-bar/circle-progress-bar.component.html +2 -2
  97. package/src/lib/ui/components/code-block/code-block.component.html +8 -0
  98. package/src/lib/ui/components/datetime-picker/datetime-picker.component.html +49 -27
  99. package/src/lib/ui/components/datetime-picker/datetime-picker.component.scss +25 -137
  100. package/src/lib/ui/components/dnd-upload/dnd-upload.component.html +3 -3
  101. package/src/lib/ui/components/drawer/drawer.component.html +36 -13
  102. package/src/lib/ui/components/drawer/drawer.component.scss +104 -18
  103. package/src/lib/ui/components/empty-state/empty-state.component.html +2 -2
  104. package/src/lib/ui/components/facets-rail/facets-rail.component.html +42 -0
  105. package/src/lib/ui/components/filter-pills/filter-pills.component.html +16 -0
  106. package/src/lib/ui/components/hero-icon/hero-icon.component.html +10 -9
  107. package/src/lib/ui/components/info-field/info-field.component.html +1 -1
  108. package/src/lib/ui/components/input/input.component.html +6 -6
  109. package/src/lib/ui/components/kanban-board/kanban-board.component.html +1 -1
  110. package/src/lib/ui/components/kanban-board/kanban-board.component.scss +9 -9
  111. package/src/lib/ui/components/list-row/list-row.component.html +20 -0
  112. package/src/lib/ui/components/loading-panel/loading-panel.component.html +1 -1
  113. package/src/lib/ui/components/master-detail/master-detail.component.css +22 -0
  114. package/src/lib/ui/components/master-detail/master-detail.component.html +42 -10
  115. package/src/lib/ui/components/menu/menu.component.html +27 -0
  116. package/src/lib/ui/components/pending-badge/pending-badge.component.html +15 -0
  117. package/src/lib/ui/components/pipeline-stepper/pipeline-stepper.component.html +45 -0
  118. package/src/lib/ui/components/project-card/project-card.component.html +102 -0
  119. package/src/lib/ui/components/radio-button/radio-button.component.html +4 -4
  120. package/src/lib/ui/components/radio-button-toggle/radio-button-toggle.component.html +4 -4
  121. package/src/lib/ui/components/sample-frame/sample-frame.component.html +18 -0
  122. package/src/lib/ui/components/score-badge/score-badge.component.html +7 -0
  123. package/src/lib/ui/components/screenshot-frame/screenshot-frame.component.html +40 -0
  124. package/src/lib/ui/components/search-bar/search-bar.component.html +1 -1
  125. package/src/lib/ui/components/section-card/section-card.component.html +19 -6
  126. package/src/lib/ui/components/segmented/segmented.component.html +42 -0
  127. package/src/lib/ui/components/segmented/segmented.component.scss +12 -0
  128. package/src/lib/ui/components/select/select.component.html +6 -6
  129. package/src/lib/ui/components/skeleton-detail/skeleton-detail.component.html +2 -2
  130. package/src/lib/ui/components/skeleton-list/skeleton-list.component.html +1 -1
  131. package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.html +5 -5
  132. package/src/lib/ui/components/slider/slider.component.html +8 -8
  133. package/src/lib/ui/components/sparkbar/sparkbar.component.html +14 -0
  134. package/src/lib/ui/components/stage-dots/stage-dots.component.html +13 -0
  135. package/src/lib/ui/components/stat-cards/stat-cards.component.html +45 -12
  136. package/src/lib/ui/components/status-dot/status-dot.component.html +13 -0
  137. package/src/lib/ui/components/switch/switch.component.html +1 -1
  138. package/src/lib/ui/components/tab-group/tab-group.component.html +41 -12
  139. package/src/lib/ui/components/tab-group/tab-group.component.scss +41 -1
  140. package/src/lib/ui/components/table-cell/table-cell.component.html +2 -2
  141. package/src/lib/ui/components/tag/tag.component.html +4 -4
  142. package/src/lib/ui/components/theme-picker/theme-picker.component.html +44 -0
  143. package/src/lib/ui/components/toast/toast.component.html +7 -7
  144. package/src/lib/ui/components/toast-container/toast-container.component.html +1 -0
  145. package/src/lib/ui/components/tree-diagram/tree-diagram.component.html +5 -5
  146. package/tailwind.css +1 -2
  147. package/theme.css +596 -69
  148. package/tokens.css +56 -19
  149. package/types/foxeltech-angular-ui-chart.d.ts +65 -0
  150. package/types/foxeltech-angular-ui-flow.d.ts +96 -0
  151. package/types/foxeltech-angular-ui-rich-text.d.ts +35 -0
  152. package/types/foxeltech-angular-ui.d.ts +1018 -395
  153. package/utilities.css +4 -1
  154. package/BeVietnamPro/BeVietnamPro-Bold.woff2 +0 -0
  155. package/BeVietnamPro/BeVietnamPro-ExtraLight.woff2 +0 -0
  156. package/BeVietnamPro/BeVietnamPro-Light.woff2 +0 -0
  157. package/BeVietnamPro/BeVietnamPro-Medium.woff2 +0 -0
  158. package/BeVietnamPro/BeVietnamPro-Regular.woff2 +0 -0
  159. package/BeVietnamPro/BeVietnamPro-SemiBold.woff2 +0 -0
  160. package/BeVietnamPro/BeVietnamPro-Thin.woff2 +0 -0
  161. package/SpaceMono-Regular.woff2 +0 -0
  162. package/dm-sans/DMSans-Bold.woff2 +0 -0
  163. package/dm-sans/DMSans-Light.woff2 +0 -0
  164. package/dm-sans/DMSans-Medium.woff2 +0 -0
  165. package/dm-sans/DMSans-Regular.woff2 +0 -0
  166. package/dm-sans/DMSans-SemiBold.woff2 +0 -0
  167. package/dm-sans/DMSans-Thin.woff2 +0 -0
  168. package/orbitron/Orbitron-Bold.woff2 +0 -0
  169. package/orbitron/Orbitron-Medium.woff2 +0 -0
  170. package/orbitron/Orbitron-Regular.woff2 +0 -0
  171. package/orbitron/Orbitron-SemiBold.woff2 +0 -0
  172. package/roboto/Roboto-Black.woff2 +0 -0
  173. package/roboto/Roboto-BlackItalic.woff2 +0 -0
  174. package/roboto/Roboto-Bold.woff2 +0 -0
  175. package/roboto/Roboto-BoldCondensed.woff2 +0 -0
  176. package/roboto/Roboto-BoldCondensedItalic.woff2 +0 -0
  177. package/roboto/Roboto-BoldItalic.woff2 +0 -0
  178. package/roboto/Roboto-Condensed.woff2 +0 -0
  179. package/roboto/Roboto-CondensedItalic.woff2 +0 -0
  180. package/roboto/Roboto-Italic.woff2 +0 -0
  181. package/roboto/Roboto-Light.woff2 +0 -0
  182. package/roboto/Roboto-LightItalic.woff2 +0 -0
  183. package/roboto/Roboto-Medium.woff2 +0 -0
  184. package/roboto/Roboto-MediumItalic.woff2 +0 -0
  185. package/roboto/Roboto-Regular.woff2 +0 -0
  186. package/roboto/Roboto-Thin.woff2 +0 -0
  187. package/roboto/Roboto-ThinItalic.woff2 +0 -0
  188. package/src/lib/ui/components/chart/chart.component.html +0 -20
  189. package/src/lib/ui/components/chart/chart.component.scss +0 -49
  190. package/src/lib/ui/components/flow-connection/flow-connection.component.html +0 -10
  191. package/src/lib/ui/components/flow-connection/flow-connection.component.scss +0 -0
  192. package/src/lib/ui/components/rich-text-area/rich-text-area.component.html +0 -3
  193. package/src/lib/ui/components/rich-text-area/rich-text-area.component.scss +0 -18
@@ -3,16 +3,43 @@
3
3
  * Replaces the old JS preset (tailwind.config.js / lodash.merge sharing).
4
4
  *
5
5
  * Colour tokens point at the runtime RGB-triplet variables from theme.css
6
- * (dark default on :root, light via .light_theme) so theme switching keeps
7
- * working; opacity modifiers like bg-critical/10 are handled by v4's
8
- * color-mix() and need no <alpha-value> plumbing.
6
+ * (OgeniumDashboards --og-* per [data-og-theme] on <html>, porcelain default)
7
+ * so theme switching keeps working; opacity modifiers like bg-critical/10 are
8
+ * handled by v4's color-mix() and need no <alpha-value> plumbing.
9
9
  */
10
10
  /* `inline` is load-bearing: without it the rgb(var(--x)) values are baked
11
- into :root once, so .light_theme's runtime triplet overrides never reach
11
+ into :root once, so [data-og-theme]'s runtime triplet overrides never reach
12
12
  the utilities. inline makes every utility carry rgb(var(--x)) itself and
13
13
  resolve at the element that uses it — same behavior as v3. */
14
14
  @theme inline {
15
- /* Colours (names match the v3 preset so every existing class keeps working) */
15
+ /* ---- OG palette use these in new/restyled markup ---- */
16
+ --color-page: rgb(var(--og-page-bg));
17
+ --color-surface: rgb(var(--og-surface));
18
+ --color-surface-raised: rgb(var(--og-surface-raised));
19
+ --color-surface-sunken: rgb(var(--og-surface-sunken));
20
+ --color-border: rgb(var(--og-border));
21
+ --color-border-subtle: rgb(var(--og-border-subtle));
22
+ --color-strong: rgb(var(--og-text));
23
+ --color-body: rgb(var(--og-text-body));
24
+ --color-muted: rgb(var(--og-text-muted));
25
+ --color-faint: rgb(var(--og-text-faint));
26
+ --color-accent: rgb(var(--og-accent));
27
+ --color-accent-fg: rgb(var(--og-accent-fg));
28
+ --color-accent-contrast: rgb(var(--og-accent-contrast));
29
+ --color-accent-soft: rgb(var(--og-accent-soft-bg));
30
+ --color-accent-soft-fg: rgb(var(--og-accent-soft-fg));
31
+ --color-positive: rgb(var(--og-positive));
32
+ --color-positive-soft: rgb(var(--og-positive-soft-bg));
33
+ --color-negative: rgb(var(--og-negative));
34
+ --color-negative-soft: rgb(var(--og-negative-soft-bg));
35
+ --color-warning-soft: rgb(var(--og-warning-soft-bg));
36
+ --color-neutral-soft: rgb(var(--og-neutral-soft-bg));
37
+ --color-neutral-soft-fg: rgb(var(--og-neutral-soft-fg));
38
+ --color-track: rgb(var(--og-track));
39
+
40
+ /* ---- Legacy colour names (@deprecated — remove after the V2 campaign;
41
+ they resolve through the alias layer in theme.css, so every existing
42
+ class already renders the OG palette) ---- */
16
43
  --color-gradient-primary-start: rgb(var(--gradient-primary-start));
17
44
  --color-gradient-primary-end: rgb(var(--gradient-primary-end));
18
45
  --color-gradient-success-start: rgb(var(--gradient-success-start));
@@ -61,14 +88,22 @@
61
88
  --shadow-2xl: 0 25px 50px -12px rgb(var(--shadow-color) / 0.25);
62
89
  --inset-shadow-sm: inset 0 2px 4px 0 rgb(var(--shadow-color) / 0.05);
63
90
 
64
- /* v3 default border radii, incl. DEFAULT so bare `rounded` keeps working */
65
- --radius-sm: 0.125rem;
66
- --radius: 0.25rem;
67
- --radius-md: 0.375rem;
68
- --radius-lg: 0.5rem;
69
- --radius-xl: 0.75rem;
70
- --radius-2xl: 1rem;
71
- --radius-3xl: 1.5rem;
91
+ /* Radius is a THEME variable in V2 (blueprint/terminal are square, ivory
92
+ controls are pills) — never hardcode border-radius in components. */
93
+ --radius-frame: var(--og-radius-frame);
94
+ --radius-card: var(--og-radius-card);
95
+ --radius-control: var(--og-radius-control);
96
+ --radius-pill: var(--og-radius-pill);
97
+ /* Legacy fixed scale remapped onto the theme radii so blueprint/terminal go
98
+ square with zero template edits. `rounded-full` stays Tailwind-native
99
+ 9999px — avatars/dots must remain circular in every theme. */
100
+ --radius-sm: var(--og-radius-control);
101
+ --radius: var(--og-radius-control);
102
+ --radius-md: var(--og-radius-control);
103
+ --radius-lg: var(--og-radius-card);
104
+ --radius-xl: var(--og-radius-card);
105
+ --radius-2xl: var(--og-radius-card);
106
+ --radius-3xl: var(--og-radius-frame);
72
107
 
73
108
  /* Named spacing scale (gap-small, p-semi, mb-large, …) */
74
109
  --spacing-xs: 0.125rem;
@@ -79,12 +114,14 @@
79
114
  --spacing-xl: 1.25rem;
80
115
  --spacing-2xl: 1.5rem;
81
116
 
82
- /* Font families */
83
- --font-spmono: 'SpaceMonoRegular', monospace;
84
- --font-dmsans: 'DMSans', sans-serif;
85
- --font-orbitron: 'Orbitron', sans-serif;
86
- --font-bevn: 'BeVietnamPro', sans-serif;
87
- --font-roboto: 'Roboto', sans-serif;
117
+ /* Font families — theme variables (blueprint/terminal switch to mono).
118
+ V2 set: Archivo (body/display), JetBrains Mono / IBM Plex Mono (mono),
119
+ Source Serif 4 (prose), Newsreader (ivory/blueprint display). */
120
+ --font-body: var(--og-font-body);
121
+ --font-display: var(--og-font-display);
122
+ --font-mono: var(--og-font-mono);
123
+ --font-prose: var(--og-font-prose);
124
+ --font-figure: var(--og-font-figure);
88
125
 
89
126
  /* Font-size overrides (v3 preset values) */
90
127
  --text-xs: 0.75rem;
@@ -8,7 +8,10 @@
8
8
  }
9
9
 
10
10
  @utility btn-common {
11
- @apply flex text-sm h-10 font-semibold px-xl py-normal items-center justify-center rounded-lg shadow-sm transition-all duration-200 disabled:opacity-50 disabled:pointer-events-none disabled:cursor-not-allowed;
11
+ /* Compact size (anh 29/08): h-8 + 13px label the pre-V2 h-10 read too
12
+ large against the V2 density. leading-none: arbitrary text-[13px] inherits
13
+ lh 1.5 and Archivo's uneven leading floats the ink ~1px above center. */
14
+ @apply flex text-[13px] leading-none h-8 font-semibold px-large py-small items-center justify-center rounded-lg shadow-sm transition-all duration-200 disabled:opacity-50 disabled:pointer-events-none disabled:cursor-not-allowed;
12
15
  }
13
16
 
14
17
  @utility btn-menu-common {
@@ -0,0 +1,29 @@
1
+ <div class="flex flex-col gap-small">
2
+ @for (item of items(); track item.label) {
3
+ <button
4
+ type="button"
5
+ class="text-left rounded-control px-normal py-small -mx-normal transition-colors"
6
+ [class.hover:bg-surface-sunken]="interactive()"
7
+ [class.cursor-default]="!interactive()"
8
+ [tabindex]="interactive() ? 0 : -1"
9
+ (click)="onSelect(item)"
10
+ >
11
+ <div class="flex items-baseline justify-between gap-normal">
12
+ <span class="txt-body-medium-01 truncate">{{ item.label }}</span>
13
+ <span class="text-sm font-semibold text-strong shrink-0" style="font-family: var(--og-font-figure)">
14
+ {{ item.valueLabel ?? item.value }}
15
+ </span>
16
+ </div>
17
+ @if (item.meta) {
18
+ <div class="txt-utility-description truncate">{{ item.meta }}</div>
19
+ }
20
+ <div class="mt-xs h-[var(--og-track-h)] rounded-pill bg-track overflow-hidden">
21
+ <div
22
+ class="h-full rounded-pill transition-all duration-500"
23
+ [ngClass]="barClass(item)"
24
+ [style.width.%]="widthOf(item)"
25
+ ></div>
26
+ </div>
27
+ </button>
28
+ }
29
+ </div>
@@ -1,25 +1,25 @@
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
- width="20"
22
- height="20"
21
+ width="16"
22
+ height="16"
23
23
  viewBox="0 0 24 24"
24
24
  xmlns="http://www.w3.org/2000/svg"
25
25
  >
@@ -219,17 +219,19 @@
219
219
  @if (icon) {
220
220
  <fx-ui-hero-icon
221
221
  [icon]="icon"
222
- [size]="20"
222
+ [size]="16"
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-accent-contrast': buttonVariant() === 'primary',
228
+ 'text-surface': buttonVariant() === 'success',
228
229
  }"
229
230
  ></fx-ui-hero-icon>
230
231
  }
231
232
  @if (label) {
232
- <div>{{ label }}</div>
233
+ <!-- text-box: optical centering — Archivo's leading floats ink up otherwise -->
234
+ <div class="[text-box:trim-both_cap_alphabetic]">{{ label }}</div>
233
235
  }
234
236
  </div>
235
237
  </ng-container>
@@ -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
  }"
@@ -25,7 +25,7 @@
25
25
  <span class="absolute inset-0 flex items-center justify-center">
26
26
  <svg
27
27
  xmlns="http://www.w3.org/2000/svg"
28
- class="text-white w-4 h-4 transition-opacity duration-150"
28
+ class="text-accent-contrast w-4 h-4 transition-opacity duration-150"
29
29
  viewBox="0 0 24 24"
30
30
  fill="none"
31
31
  stroke="currentColor"
@@ -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>
@@ -0,0 +1,8 @@
1
+ @if (label()) {
2
+ <div class="txt-utility-caption font-bold text-text-secondary mb-normal">{{ label() }}</div>
3
+ }
4
+ <pre
5
+ class="m-0 p-large rounded-control border border-border bg-surface overflow-auto txt-body-compact-01 text-strong"
6
+ [style.max-height]="maxHeight() || null"
7
+ style="font-family: var(--og-font-mono); white-space: pre; tab-size: 2"
8
+ >{{ code() }}</pre>
@@ -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="relative">
12
- <input
13
- [id]="fieldId"
14
- [owlDateTimeTrigger]="picker"
15
- [owlDateTime]="picker"
16
- [placeholder]="placeholder"
17
- [disabled]="disabled"
18
- [min]="minDate"
19
- [max]="maxDate"
20
- (blur)="onBlur()"
21
- [value]="value"
22
- readonly
23
- class="input-default pr-9"
24
- />
25
- <span
26
- [owlDateTimeTrigger]="picker"
27
- class="absolute inset-y-0 right-0 flex items-center pr-2.5 cursor-pointer text-text-placeholder hover:text-text-primary transition-colors"
28
- >
29
- <fx-ui-hero-icon icon="calendar" [size]="20" class="text-text-primary"></fx-ui-hero-icon>
30
- </span>
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
- // ─── Owl DateTime Picker Custom Styles ───────────────────────────────────────
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
- // Container
7
- ::ng-deep .owl-dt-container {
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
- // ── 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
-
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
- opacity: 0.85;
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
  />
@@ -1,30 +1,45 @@
1
1
  <div class="drawer-host-wrapper">
2
- <a
3
- href="/"
4
- class="h-[60px]"
5
- [ngClass]="{ 'flex items-center justify-center': !isExpanded, 'p-4': isExpanded }"
6
- >
2
+ <a href="/" class="drawer-brand" [class.is-collapsed]="!isExpanded">
7
3
  @if (logo) {
8
- <img
9
- [src]="logo"
10
- alt="Home"
11
- class="h-[20px] w-auto transition-all duration-300 ease-in-out"
12
- [ngClass]="{ 'scale-90': !isExpanded, 'ml-5': isExpanded }"
13
- />
4
+ <img [src]="logo" alt="Home" class="drawer-brand-mark" />
14
5
  } @else {
15
- <div class="h-[30px] w-auto transition-all duration-300 ease-in-out"></div>
6
+ <div class="drawer-brand-mark"></div>
7
+ }
8
+ @if (isExpanded && (logoText || logoSubtext)) {
9
+ <span class="drawer-brand-copy">
10
+ @if (logoText) {
11
+ <span class="drawer-brand-text">{{ logoText }}</span>
12
+ }
13
+ @if (logoSubtext) {
14
+ <span class="drawer-brand-subtext">{{ logoSubtext }}</span>
15
+ }
16
+ </span>
16
17
  }
17
18
  </a>
18
19
  <div class="drawer-container" [@drawerExpand]="getDrawerState()">
19
20
  <!-- Navigation Items -->
20
21
  <nav class="drawer-nav">
21
- @for (item of items; track item) {
22
+ @for (item of items(); track item) {
22
23
  <ng-container
23
24
  *ngTemplateOutlet="drawerItem; context: { $implicit: item, level: 0 }"
24
25
  ></ng-container>
25
26
  }
26
27
  </nav>
27
28
 
29
+ <!-- V2: bottom section (Administration group, user block, …) -->
30
+ <div class="mt-auto">
31
+ @if (footerItems().length) {
32
+ <nav class="drawer-footer-nav">
33
+ @for (item of footerItems(); track item) {
34
+ <ng-container
35
+ *ngTemplateOutlet="drawerItem; context: { $implicit: item, level: 0 }"
36
+ ></ng-container>
37
+ }
38
+ </nav>
39
+ }
40
+ <ng-content select="[drawerFooter]"></ng-content>
41
+ </div>
42
+
28
43
  <!-- Version -->
29
44
  @if (version) {
30
45
  <div class="drawer-version" [matTooltip]="!isExpanded ? version : ''" matTooltipPosition="right">
@@ -59,6 +74,13 @@
59
74
 
60
75
  <!-- Recursive Template for Drawer Items -->
61
76
  <ng-template #drawerItem let-item let-level="level">
77
+ @if (item.heading) {
78
+ @if (isExpanded) {
79
+ <div class="drawer-section-label">{{ item.label }}</div>
80
+ } @else {
81
+ <div class="drawer-section-rule"></div>
82
+ }
83
+ } @else {
62
84
  <div class="drawer-item-wrapper">
63
85
  <!-- Item Button/Link -->
64
86
  @if (item.route && !item.children) {
@@ -125,4 +147,5 @@
125
147
  </div>
126
148
  }
127
149
  </div>
150
+ }
128
151
  </ng-template>