@cdevhub/ngx-tw 0.2.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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +108 -0
  4. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -0
  5. package/fesm2022/cdevhub-ngx-tw-alert.mjs +240 -0
  6. package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -0
  7. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +287 -0
  8. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -0
  9. package/fesm2022/cdevhub-ngx-tw-badge.mjs +332 -0
  10. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -0
  11. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +452 -0
  12. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -0
  13. package/fesm2022/cdevhub-ngx-tw-button.mjs +227 -0
  14. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -0
  15. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +417 -0
  16. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -0
  17. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +232 -0
  18. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -0
  19. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +4482 -0
  20. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -0
  21. package/fesm2022/cdevhub-ngx-tw-card.mjs +157 -0
  22. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -0
  23. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +1454 -0
  24. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -0
  25. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +593 -0
  26. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -0
  27. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +228 -0
  28. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -0
  29. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +510 -0
  30. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -0
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +1721 -0
  32. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -0
  33. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +721 -0
  34. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -0
  35. package/fesm2022/cdevhub-ngx-tw-core.mjs +861 -0
  36. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -0
  37. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +1558 -0
  38. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -0
  39. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +1833 -0
  40. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -0
  41. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +693 -0
  42. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -0
  43. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +331 -0
  44. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -0
  45. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +289 -0
  46. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -0
  47. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +572 -0
  48. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -0
  49. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs +36 -0
  50. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs.map +1 -0
  51. package/fesm2022/cdevhub-ngx-tw-icon.mjs +278 -0
  52. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -0
  53. package/fesm2022/cdevhub-ngx-tw-input.mjs +355 -0
  54. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -0
  55. package/fesm2022/cdevhub-ngx-tw-item.mjs +241 -0
  56. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -0
  57. package/fesm2022/cdevhub-ngx-tw-menu.mjs +433 -0
  58. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -0
  59. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +691 -0
  60. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -0
  61. package/fesm2022/cdevhub-ngx-tw-popover.mjs +678 -0
  62. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -0
  63. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +335 -0
  64. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -0
  65. package/fesm2022/cdevhub-ngx-tw-radio.mjs +708 -0
  66. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -0
  67. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +319 -0
  68. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -0
  69. package/fesm2022/cdevhub-ngx-tw-select.mjs +1722 -0
  70. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -0
  71. package/fesm2022/cdevhub-ngx-tw-separator.mjs +115 -0
  72. package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -0
  73. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +768 -0
  74. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -0
  75. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs +149 -0
  76. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs.map +1 -0
  77. package/fesm2022/cdevhub-ngx-tw-slider.mjs +1147 -0
  78. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -0
  79. package/fesm2022/cdevhub-ngx-tw-sort.mjs +346 -0
  80. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -0
  81. package/fesm2022/cdevhub-ngx-tw-spinner.mjs +186 -0
  82. package/fesm2022/cdevhub-ngx-tw-spinner.mjs.map +1 -0
  83. package/fesm2022/cdevhub-ngx-tw-split.mjs +1082 -0
  84. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -0
  85. package/fesm2022/cdevhub-ngx-tw-stat.mjs +579 -0
  86. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -0
  87. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +443 -0
  88. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -0
  89. package/fesm2022/cdevhub-ngx-tw-switch.mjs +391 -0
  90. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -0
  91. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +315 -0
  92. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -0
  93. package/fesm2022/cdevhub-ngx-tw-table.mjs +994 -0
  94. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -0
  95. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +508 -0
  96. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -0
  97. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +147 -0
  98. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -0
  99. package/fesm2022/cdevhub-ngx-tw-theme.mjs +178 -0
  100. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -0
  101. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +1344 -0
  102. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -0
  103. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +1136 -0
  104. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -0
  105. package/fesm2022/cdevhub-ngx-tw-toast.mjs +1311 -0
  106. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -0
  107. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +533 -0
  108. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -0
  109. package/fesm2022/cdevhub-ngx-tw.mjs +61 -0
  110. package/fesm2022/cdevhub-ngx-tw.mjs.map +1 -0
  111. package/package.json +265 -0
  112. package/theme/_base.css +394 -0
  113. package/theme/_dark.css +510 -0
  114. package/theme/_high-contrast.css +290 -0
  115. package/theme/_semantic.css +317 -0
  116. package/theme/_typography.css +9 -0
  117. package/theme/index.css +54 -0
  118. package/types/cdevhub-ngx-tw-accordion.d.ts +48 -0
  119. package/types/cdevhub-ngx-tw-alert.d.ts +67 -0
  120. package/types/cdevhub-ngx-tw-avatar.d.ts +79 -0
  121. package/types/cdevhub-ngx-tw-badge.d.ts +94 -0
  122. package/types/cdevhub-ngx-tw-breadcrumbs.d.ts +227 -0
  123. package/types/cdevhub-ngx-tw-button.d.ts +74 -0
  124. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +200 -0
  125. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +113 -0
  126. package/types/cdevhub-ngx-tw-calendar.d.ts +1704 -0
  127. package/types/cdevhub-ngx-tw-card.d.ts +48 -0
  128. package/types/cdevhub-ngx-tw-carousel.d.ts +406 -0
  129. package/types/cdevhub-ngx-tw-checkbox.d.ts +136 -0
  130. package/types/cdevhub-ngx-tw-code-block.d.ts +93 -0
  131. package/types/cdevhub-ngx-tw-collapsible.d.ts +151 -0
  132. package/types/cdevhub-ngx-tw-combobox.d.ts +389 -0
  133. package/types/cdevhub-ngx-tw-command-palette.d.ts +215 -0
  134. package/types/cdevhub-ngx-tw-core.d.ts +719 -0
  135. package/types/cdevhub-ngx-tw-date-picker.d.ts +317 -0
  136. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +313 -0
  137. package/types/cdevhub-ngx-tw-dialog.d.ts +303 -0
  138. package/types/cdevhub-ngx-tw-empty-state.d.ts +104 -0
  139. package/types/cdevhub-ngx-tw-flip-card.d.ts +95 -0
  140. package/types/cdevhub-ngx-tw-form-field.d.ts +210 -0
  141. package/types/cdevhub-ngx-tw-icon-lucide.d.ts +29 -0
  142. package/types/cdevhub-ngx-tw-icon.d.ts +134 -0
  143. package/types/cdevhub-ngx-tw-input.d.ts +110 -0
  144. package/types/cdevhub-ngx-tw-item.d.ts +70 -0
  145. package/types/cdevhub-ngx-tw-menu.d.ts +99 -0
  146. package/types/cdevhub-ngx-tw-paginator.d.ts +305 -0
  147. package/types/cdevhub-ngx-tw-popover.d.ts +157 -0
  148. package/types/cdevhub-ngx-tw-progress-bar.d.ts +100 -0
  149. package/types/cdevhub-ngx-tw-radio.d.ts +174 -0
  150. package/types/cdevhub-ngx-tw-segmented-control.d.ts +66 -0
  151. package/types/cdevhub-ngx-tw-select.d.ts +384 -0
  152. package/types/cdevhub-ngx-tw-separator.d.ts +28 -0
  153. package/types/cdevhub-ngx-tw-sheet.d.ts +335 -0
  154. package/types/cdevhub-ngx-tw-skeleton.d.ts +52 -0
  155. package/types/cdevhub-ngx-tw-slider.d.ts +258 -0
  156. package/types/cdevhub-ngx-tw-sort.d.ts +136 -0
  157. package/types/cdevhub-ngx-tw-spinner.d.ts +50 -0
  158. package/types/cdevhub-ngx-tw-split.d.ts +265 -0
  159. package/types/cdevhub-ngx-tw-stat.d.ts +140 -0
  160. package/types/cdevhub-ngx-tw-stepper.d.ts +127 -0
  161. package/types/cdevhub-ngx-tw-switch.d.ts +88 -0
  162. package/types/cdevhub-ngx-tw-tab-nav.d.ts +107 -0
  163. package/types/cdevhub-ngx-tw-table.d.ts +479 -0
  164. package/types/cdevhub-ngx-tw-tabs.d.ts +121 -0
  165. package/types/cdevhub-ngx-tw-textarea.d.ts +62 -0
  166. package/types/cdevhub-ngx-tw-theme.d.ts +106 -0
  167. package/types/cdevhub-ngx-tw-time-picker.d.ts +303 -0
  168. package/types/cdevhub-ngx-tw-timeline.d.ts +278 -0
  169. package/types/cdevhub-ngx-tw-toast.d.ts +388 -0
  170. package/types/cdevhub-ngx-tw-tooltip.d.ts +95 -0
  171. package/types/cdevhub-ngx-tw.d.ts +49 -0
@@ -0,0 +1,287 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, input, output, inject, ElementRef, signal, isDevMode, effect, computed, linkedSignal, ChangeDetectionStrategy, Component, contentChildren } from '@angular/core';
3
+ import { tv } from 'tailwind-variants';
4
+
5
+ /**
6
+ * Injection token used by `AvatarGroupComponent` to propagate its size
7
+ * to child avatars. When present, overrides the individual avatar's `size` input.
8
+ */
9
+ const AVATAR_GROUP_SIZE = new InjectionToken('AVATAR_GROUP_SIZE');
10
+ const avatarVariants = tv({
11
+ slots: {
12
+ root: 'relative inline-flex items-center justify-center overflow-hidden shrink-0',
13
+ img: 'size-full object-cover',
14
+ initials: 'font-medium select-none uppercase',
15
+ // size-[60%]: keeps the fallback glyph proportional to the avatar; no Tailwind size token expresses a percentage of parent.
16
+ // Container scale — avatars are surfaces, not glyphs (see CLAUDE.md icon sizing).
17
+ // The fallback child glyph is sized as a percentage of the avatar container
18
+ // so it scales proportionally across every TwSize.
19
+ fallback: 'size-[60%] text-fg-subtle',
20
+ status: 'absolute rounded-full ring-2 ring-surface',
21
+ },
22
+ variants: {
23
+ size: {
24
+ xs: { root: 'size-6 text-xs', status: 'size-2' },
25
+ sm: { root: 'size-8 text-xs', status: 'size-2' },
26
+ md: { root: 'size-10 text-sm', status: 'size-2.5' },
27
+ lg: { root: 'size-12 text-sm', status: 'size-3' },
28
+ // Container scale — avatars are surfaces, not glyphs (see CLAUDE.md icon sizing).
29
+ // The xl avatar lands at 64px, which sits above the glyph scale's ceiling
30
+ // (size-10 / 40px) because avatars host imagery, initials, or icon glyphs.
31
+ xl: { root: 'size-16 text-base', status: 'size-3' },
32
+ },
33
+ rounded: {
34
+ full: { root: 'rounded-full', status: 'bottom-0 right-0' },
35
+ lg: { root: 'rounded-lg', status: '-bottom-0.5 -right-0.5' },
36
+ none: { root: 'rounded-none', status: '-bottom-0.5 -right-0.5' },
37
+ },
38
+ color: {
39
+ primary: { root: 'bg-primary-100 text-primary-700' },
40
+ secondary: { root: 'bg-secondary-100 text-secondary-700' },
41
+ accent: { root: 'bg-accent-100 text-accent-700' },
42
+ neutral: { root: 'bg-surface-muted text-fg-muted' },
43
+ info: { root: 'bg-info-100 text-info-700' },
44
+ success: { root: 'bg-success-100 text-success-700' },
45
+ warning: { root: 'bg-warning-100 text-warning-700' },
46
+ error: { root: 'bg-error-100 text-error-700' },
47
+ },
48
+ },
49
+ defaultVariants: {
50
+ size: 'md',
51
+ rounded: 'full',
52
+ color: 'neutral',
53
+ },
54
+ }, {
55
+ twMerge: true,
56
+ });
57
+ const statusColorMap = {
58
+ online: 'bg-success-500',
59
+ busy: 'bg-error-500',
60
+ away: 'bg-warning-500',
61
+ offline: 'bg-fg-subtle',
62
+ };
63
+ class AvatarComponent {
64
+ /** URL of the avatar image. When set, renders an `<img>`. Falls back to initials or projected content on load error. Defaults to `null`. */
65
+ src = input(null, ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
66
+ /** Alt text for the avatar image. Also used as `aria-label` for non-image avatars. Defaults to `''`. */
67
+ alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
68
+ /** Text initials displayed when no image is available (1-2 characters). Rendered uppercase regardless of input casing. Defaults to `null`. */
69
+ initials = input(null, ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
70
+ /** Semantic color for the initials/icon background. Only applies when no image is shown. Defaults to `'neutral'`. */
71
+ color = input('neutral', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
72
+ /** Controls the avatar dimensions. Defaults to `'md'`. */
73
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
74
+ /** Bundles decorative axes: `rounded` (shape) and `status` (indicator dot). Defaults to `{ rounded: 'full', status: null }`. */
75
+ appearance = input({}, ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
76
+ /** Fires when the avatar image fails to load. Payload is the native `Event` from the `<img>` `error` event. */
77
+ imageError = output();
78
+ /** @internal */
79
+ elementRef = inject((ElementRef));
80
+ /**
81
+ * @internal
82
+ * Toggled by `AvatarGroupComponent` to hide overflow avatars. Drives the
83
+ * host `[attr.hidden]` binding so the group's effect stays declarative
84
+ * (no direct `style.display` mutation).
85
+ */
86
+ groupHidden = signal(false, ...(ngDevMode ? [{ debugName: "groupHidden" }] : /* istanbul ignore next */ []));
87
+ groupSize = inject(AVATAR_GROUP_SIZE, { optional: true });
88
+ constructor() {
89
+ if (isDevMode()) {
90
+ effect(() => {
91
+ if (this.displayMode() === 'image' && !this.alt()) {
92
+ console.warn('<tw-avatar> rendered as image without alt text — provide alt for accessibility');
93
+ }
94
+ });
95
+ }
96
+ }
97
+ resolvedSize = computed(() => this.groupSize ? this.groupSize() : this.size(), ...(ngDevMode ? [{ debugName: "resolvedSize" }] : /* istanbul ignore next */ []));
98
+ resolvedRounded = computed(() => this.appearance().rounded ?? 'full', ...(ngDevMode ? [{ debugName: "resolvedRounded" }] : /* istanbul ignore next */ []));
99
+ resolvedStatus = computed(() => this.appearance().status ?? null, ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
100
+ imageLoaded = linkedSignal({ ...(ngDevMode ? { debugName: "imageLoaded" } : /* istanbul ignore next */ {}), source: this.src,
101
+ computation: () => null });
102
+ displayMode = computed(() => {
103
+ if (this.src() && this.imageLoaded() !== false)
104
+ return 'image';
105
+ if (this.initials())
106
+ return 'initials';
107
+ return 'fallback';
108
+ }, ...(ngDevMode ? [{ debugName: "displayMode" }] : /* istanbul ignore next */ []));
109
+ variantResult = computed(() => avatarVariants({
110
+ size: this.resolvedSize(),
111
+ rounded: this.resolvedRounded(),
112
+ color: this.color(),
113
+ }), ...(ngDevMode ? [{ debugName: "variantResult" }] : /* istanbul ignore next */ []));
114
+ rootClasses = computed(() => this.variantResult().root(), ...(ngDevMode ? [{ debugName: "rootClasses" }] : /* istanbul ignore next */ []));
115
+ imgClasses = computed(() => this.variantResult().img(), ...(ngDevMode ? [{ debugName: "imgClasses" }] : /* istanbul ignore next */ []));
116
+ initialsClasses = computed(() => this.variantResult().initials(), ...(ngDevMode ? [{ debugName: "initialsClasses" }] : /* istanbul ignore next */ []));
117
+ fallbackClasses = computed(() => this.variantResult().fallback(), ...(ngDevMode ? [{ debugName: "fallbackClasses" }] : /* istanbul ignore next */ []));
118
+ statusClasses = computed(() => {
119
+ const base = this.variantResult().status();
120
+ const statusValue = this.resolvedStatus();
121
+ if (!statusValue)
122
+ return base;
123
+ return `${base} ${statusColorMap[statusValue]}`;
124
+ }, ...(ngDevMode ? [{ debugName: "statusClasses" }] : /* istanbul ignore next */ []));
125
+ onImageError(event) {
126
+ this.imageLoaded.set(false);
127
+ this.imageError.emit(event);
128
+ }
129
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
130
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AvatarComponent, isStandalone: true, selector: "tw-avatar", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { imageError: "imageError" }, host: { properties: { "class": "rootClasses()", "attr.role": "displayMode() !== \"image\" ? \"img\" : null", "attr.aria-label": "displayMode() !== \"image\" && alt() ? alt() : null", "attr.aria-hidden": "displayMode() !== \"image\" && !alt() ? \"true\" : null", "attr.hidden": "groupHidden() ? \"\" : null" } }, ngImport: i0, template: `
131
+ @switch (displayMode()) {
132
+ @case ('image') {
133
+ <img
134
+ [src]="src()"
135
+ [alt]="alt()"
136
+ [class]="imgClasses()"
137
+ (load)="imageLoaded.set(true)"
138
+ (error)="onImageError($event)"
139
+ />
140
+ }
141
+ @case ('initials') {
142
+ <span [class]="initialsClasses()">{{ initials() }}</span>
143
+ }
144
+ @case ('fallback') {
145
+ <ng-content>
146
+ <svg [class]="fallbackClasses()" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
147
+ <path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd" />
148
+ </svg>
149
+ </ng-content>
150
+ }
151
+ }
152
+ @if (resolvedStatus()) {
153
+ <span [class]="statusClasses()" aria-hidden="true"></span>
154
+ }
155
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
156
+ }
157
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AvatarComponent, decorators: [{
158
+ type: Component,
159
+ args: [{
160
+ selector: 'tw-avatar',
161
+ changeDetection: ChangeDetectionStrategy.OnPush,
162
+ host: {
163
+ '[class]': 'rootClasses()',
164
+ '[attr.role]': 'displayMode() !== "image" ? "img" : null',
165
+ '[attr.aria-label]': 'displayMode() !== "image" && alt() ? alt() : null',
166
+ // Only hide non-image avatars without alt text from AT. Image-mode avatars
167
+ // expose their `alt` attribute directly on the underlying `<img>`; hiding
168
+ // the host would suppress the image from assistive tech entirely.
169
+ '[attr.aria-hidden]': 'displayMode() !== "image" && !alt() ? "true" : null',
170
+ '[attr.hidden]': 'groupHidden() ? "" : null',
171
+ },
172
+ template: `
173
+ @switch (displayMode()) {
174
+ @case ('image') {
175
+ <img
176
+ [src]="src()"
177
+ [alt]="alt()"
178
+ [class]="imgClasses()"
179
+ (load)="imageLoaded.set(true)"
180
+ (error)="onImageError($event)"
181
+ />
182
+ }
183
+ @case ('initials') {
184
+ <span [class]="initialsClasses()">{{ initials() }}</span>
185
+ }
186
+ @case ('fallback') {
187
+ <ng-content>
188
+ <svg [class]="fallbackClasses()" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
189
+ <path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd" />
190
+ </svg>
191
+ </ng-content>
192
+ }
193
+ }
194
+ @if (resolvedStatus()) {
195
+ <span [class]="statusClasses()" aria-hidden="true"></span>
196
+ }
197
+ `,
198
+ }]
199
+ }], ctorParameters: () => [], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], imageError: [{ type: i0.Output, args: ["imageError"] }] } });
200
+ const groupOverlapMap = {
201
+ xs: '[&>tw-avatar+tw-avatar]:-ml-1.5 [&>tw-avatar+span]:-ml-1.5',
202
+ sm: '[&>tw-avatar+tw-avatar]:-ml-1.5 [&>tw-avatar+span]:-ml-1.5',
203
+ md: '[&>tw-avatar+tw-avatar]:-ml-2 [&>tw-avatar+span]:-ml-2',
204
+ lg: '[&>tw-avatar+tw-avatar]:-ml-3 [&>tw-avatar+span]:-ml-3',
205
+ xl: '[&>tw-avatar+tw-avatar]:-ml-3 [&>tw-avatar+span]:-ml-3',
206
+ };
207
+ class AvatarGroupComponent {
208
+ /** Sets the size for all child avatars. Individual avatar size inputs are ignored when inside a group. Defaults to `'md'`. */
209
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
210
+ /** Maximum number of avatars to display. Remaining count is shown as a "+N" overflow indicator. Defaults to `null` (show all). */
211
+ max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
212
+ /** Accessible label for the avatar group. Defaults to `'Avatar group'` (English) — override for localisation. */
213
+ ariaLabel = input('Avatar group', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
214
+ avatars = contentChildren(AvatarComponent, ...(ngDevMode ? [{ debugName: "avatars" }] : /* istanbul ignore next */ []));
215
+ overflowCount = computed(() => {
216
+ const all = this.avatars();
217
+ const maxVal = this.max();
218
+ if (maxVal === null || maxVal >= all.length)
219
+ return 0;
220
+ return all.length - maxVal;
221
+ }, ...(ngDevMode ? [{ debugName: "overflowCount" }] : /* istanbul ignore next */ []));
222
+ hostClasses = computed(() => {
223
+ const s = this.size();
224
+ return `inline-flex items-center [&>tw-avatar]:ring-2 [&>tw-avatar]:ring-surface ${groupOverlapMap[s]}`;
225
+ }, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
226
+ overflowClasses = computed(() => {
227
+ const s = this.size();
228
+ const sizeClasses = avatarVariants({ size: s, rounded: 'full', color: 'neutral' });
229
+ return `${sizeClasses.root()} bg-surface-muted text-fg-muted font-medium ring-2 ring-surface`;
230
+ }, ...(ngDevMode ? [{ debugName: "overflowClasses" }] : /* istanbul ignore next */ []));
231
+ visibilityEffect = effect(() => {
232
+ const all = this.avatars();
233
+ const maxVal = this.max();
234
+ all.forEach((avatar, index) => {
235
+ avatar.groupHidden.set(maxVal !== null && index >= maxVal);
236
+ });
237
+ }, ...(ngDevMode ? [{ debugName: "visibilityEffect" }] : /* istanbul ignore next */ []));
238
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AvatarGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
239
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AvatarGroupComponent, isStandalone: true, selector: "tw-avatar-group", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "class": "hostClasses()", "attr.aria-label": "ariaLabel()" } }, providers: [
240
+ {
241
+ provide: AVATAR_GROUP_SIZE,
242
+ useFactory: () => {
243
+ const group = inject(AvatarGroupComponent);
244
+ return () => group.size();
245
+ },
246
+ },
247
+ ], queries: [{ propertyName: "avatars", predicate: AvatarComponent, isSignal: true }], ngImport: i0, template: `
248
+ <ng-content />
249
+ @if (overflowCount() > 0) {
250
+ <span [class]="overflowClasses()">+{{ overflowCount() }}</span>
251
+ }
252
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
253
+ }
254
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AvatarGroupComponent, decorators: [{
255
+ type: Component,
256
+ args: [{
257
+ selector: 'tw-avatar-group',
258
+ changeDetection: ChangeDetectionStrategy.OnPush,
259
+ providers: [
260
+ {
261
+ provide: AVATAR_GROUP_SIZE,
262
+ useFactory: () => {
263
+ const group = inject(AvatarGroupComponent);
264
+ return () => group.size();
265
+ },
266
+ },
267
+ ],
268
+ host: {
269
+ role: 'group',
270
+ '[class]': 'hostClasses()',
271
+ '[attr.aria-label]': 'ariaLabel()',
272
+ },
273
+ template: `
274
+ <ng-content />
275
+ @if (overflowCount() > 0) {
276
+ <span [class]="overflowClasses()">+{{ overflowCount() }}</span>
277
+ }
278
+ `,
279
+ }]
280
+ }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], avatars: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AvatarComponent), { isSignal: true }] }] } });
281
+
282
+ /**
283
+ * Generated bundle index. Do not edit.
284
+ */
285
+
286
+ export { AVATAR_GROUP_SIZE, AvatarComponent, AvatarGroupComponent };
287
+ //# sourceMappingURL=cdevhub-ngx-tw-avatar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdevhub-ngx-tw-avatar.mjs","sources":["../../../projects/ngx-tw/avatar/avatar.ts","../../../projects/ngx-tw/avatar/cdevhub-ngx-tw-avatar.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChildren,\n effect,\n ElementRef,\n InjectionToken,\n inject,\n input,\n isDevMode,\n linkedSignal,\n output,\n signal,\n} from '@angular/core';\nimport { tv } from 'tailwind-variants';\nimport type { TwColor, TwSize } from '@cdevhub/ngx-tw/core';\n\n/** Status indicator for the avatar. */\nexport type AvatarStatus = 'online' | 'busy' | 'away' | 'offline';\n\n/** Border radius shape for the avatar. */\nexport type AvatarRounded = 'full' | 'lg' | 'none';\n\n/** Decorative axes bundled into a single avatar input. */\nexport interface AvatarAppearance {\n /** Border-radius shape. Defaults to `'full'`. */\n rounded?: AvatarRounded;\n /** Status indicator dot. Defaults to `null` (no indicator). */\n status?: AvatarStatus | null;\n}\n\n/**\n * Injection token used by `AvatarGroupComponent` to propagate its size\n * to child avatars. When present, overrides the individual avatar's `size` input.\n */\nexport const AVATAR_GROUP_SIZE = new InjectionToken<() => TwSize>('AVATAR_GROUP_SIZE');\n\nconst avatarVariants = tv({\n slots: {\n root: 'relative inline-flex items-center justify-center overflow-hidden shrink-0',\n img: 'size-full object-cover',\n initials: 'font-medium select-none uppercase',\n // size-[60%]: keeps the fallback glyph proportional to the avatar; no Tailwind size token expresses a percentage of parent.\n // Container scale — avatars are surfaces, not glyphs (see CLAUDE.md icon sizing).\n // The fallback child glyph is sized as a percentage of the avatar container\n // so it scales proportionally across every TwSize.\n fallback: 'size-[60%] text-fg-subtle',\n status: 'absolute rounded-full ring-2 ring-surface',\n },\n variants: {\n size: {\n xs: { root: 'size-6 text-xs', status: 'size-2' },\n sm: { root: 'size-8 text-xs', status: 'size-2' },\n md: { root: 'size-10 text-sm', status: 'size-2.5' },\n lg: { root: 'size-12 text-sm', status: 'size-3' },\n // Container scale — avatars are surfaces, not glyphs (see CLAUDE.md icon sizing).\n // The xl avatar lands at 64px, which sits above the glyph scale's ceiling\n // (size-10 / 40px) because avatars host imagery, initials, or icon glyphs.\n xl: { root: 'size-16 text-base', status: 'size-3' },\n },\n rounded: {\n full: { root: 'rounded-full', status: 'bottom-0 right-0' },\n lg: { root: 'rounded-lg', status: '-bottom-0.5 -right-0.5' },\n none: { root: 'rounded-none', status: '-bottom-0.5 -right-0.5' },\n },\n color: {\n primary: { root: 'bg-primary-100 text-primary-700' },\n secondary: { root: 'bg-secondary-100 text-secondary-700' },\n accent: { root: 'bg-accent-100 text-accent-700' },\n neutral: { root: 'bg-surface-muted text-fg-muted' },\n info: { root: 'bg-info-100 text-info-700' },\n success: { root: 'bg-success-100 text-success-700' },\n warning: { root: 'bg-warning-100 text-warning-700' },\n error: { root: 'bg-error-100 text-error-700' },\n },\n },\n defaultVariants: {\n size: 'md',\n rounded: 'full',\n color: 'neutral',\n },\n}, {\n twMerge: true,\n});\n\nconst statusColorMap: Record<AvatarStatus, string> = {\n online: 'bg-success-500',\n busy: 'bg-error-500',\n away: 'bg-warning-500',\n offline: 'bg-fg-subtle',\n};\n\n@Component({\n selector: 'tw-avatar',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'rootClasses()',\n '[attr.role]': 'displayMode() !== \"image\" ? \"img\" : null',\n '[attr.aria-label]': 'displayMode() !== \"image\" && alt() ? alt() : null',\n // Only hide non-image avatars without alt text from AT. Image-mode avatars\n // expose their `alt` attribute directly on the underlying `<img>`; hiding\n // the host would suppress the image from assistive tech entirely.\n '[attr.aria-hidden]': 'displayMode() !== \"image\" && !alt() ? \"true\" : null',\n '[attr.hidden]': 'groupHidden() ? \"\" : null',\n },\n template: `\n @switch (displayMode()) {\n @case ('image') {\n <img\n [src]=\"src()\"\n [alt]=\"alt()\"\n [class]=\"imgClasses()\"\n (load)=\"imageLoaded.set(true)\"\n (error)=\"onImageError($event)\"\n />\n }\n @case ('initials') {\n <span [class]=\"initialsClasses()\">{{ initials() }}</span>\n }\n @case ('fallback') {\n <ng-content>\n <svg [class]=\"fallbackClasses()\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clip-rule=\"evenodd\" />\n </svg>\n </ng-content>\n }\n }\n @if (resolvedStatus()) {\n <span [class]=\"statusClasses()\" aria-hidden=\"true\"></span>\n }\n `,\n})\nexport class AvatarComponent {\n /** URL of the avatar image. When set, renders an `<img>`. Falls back to initials or projected content on load error. Defaults to `null`. */\n readonly src = input<string | null>(null);\n\n /** Alt text for the avatar image. Also used as `aria-label` for non-image avatars. Defaults to `''`. */\n readonly alt = input('');\n\n /** Text initials displayed when no image is available (1-2 characters). Rendered uppercase regardless of input casing. Defaults to `null`. */\n readonly initials = input<string | null>(null);\n\n /** Semantic color for the initials/icon background. Only applies when no image is shown. Defaults to `'neutral'`. */\n readonly color = input<TwColor>('neutral');\n\n /** Controls the avatar dimensions. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /** Bundles decorative axes: `rounded` (shape) and `status` (indicator dot). Defaults to `{ rounded: 'full', status: null }`. */\n readonly appearance = input<AvatarAppearance>({});\n\n /** Fires when the avatar image fails to load. Payload is the native `Event` from the `<img>` `error` event. */\n readonly imageError = output<Event>();\n\n /** @internal */\n readonly elementRef = inject(ElementRef<HTMLElement>);\n\n /**\n * @internal\n * Toggled by `AvatarGroupComponent` to hide overflow avatars. Drives the\n * host `[attr.hidden]` binding so the group's effect stays declarative\n * (no direct `style.display` mutation).\n */\n readonly groupHidden = signal(false);\n\n private readonly groupSize = inject(AVATAR_GROUP_SIZE, { optional: true });\n\n constructor() {\n if (isDevMode()) {\n effect(() => {\n if (this.displayMode() === 'image' && !this.alt()) {\n console.warn(\n '<tw-avatar> rendered as image without alt text — provide alt for accessibility',\n );\n }\n });\n }\n }\n\n readonly resolvedSize = computed(() => this.groupSize ? this.groupSize() : this.size());\n readonly resolvedRounded = computed<AvatarRounded>(() => this.appearance().rounded ?? 'full');\n readonly resolvedStatus = computed<AvatarStatus | null>(() => this.appearance().status ?? null);\n\n readonly imageLoaded = linkedSignal<string | null, boolean | null>({\n source: this.src,\n computation: () => null,\n });\n\n readonly displayMode = computed<'image' | 'initials' | 'fallback'>(() => {\n if (this.src() && this.imageLoaded() !== false) return 'image';\n if (this.initials()) return 'initials';\n return 'fallback';\n });\n\n private readonly variantResult = computed(() =>\n avatarVariants({\n size: this.resolvedSize(),\n rounded: this.resolvedRounded(),\n color: this.color(),\n }),\n );\n\n readonly rootClasses = computed(() => this.variantResult().root());\n readonly imgClasses = computed(() => this.variantResult().img());\n readonly initialsClasses = computed(() => this.variantResult().initials());\n readonly fallbackClasses = computed(() => this.variantResult().fallback());\n\n readonly statusClasses = computed(() => {\n const base = this.variantResult().status();\n const statusValue = this.resolvedStatus();\n if (!statusValue) return base;\n return `${base} ${statusColorMap[statusValue]}`;\n });\n\n protected onImageError(event: Event): void {\n this.imageLoaded.set(false);\n this.imageError.emit(event);\n }\n}\n\nconst groupOverlapMap: Record<TwSize, string> = {\n xs: '[&>tw-avatar+tw-avatar]:-ml-1.5 [&>tw-avatar+span]:-ml-1.5',\n sm: '[&>tw-avatar+tw-avatar]:-ml-1.5 [&>tw-avatar+span]:-ml-1.5',\n md: '[&>tw-avatar+tw-avatar]:-ml-2 [&>tw-avatar+span]:-ml-2',\n lg: '[&>tw-avatar+tw-avatar]:-ml-3 [&>tw-avatar+span]:-ml-3',\n xl: '[&>tw-avatar+tw-avatar]:-ml-3 [&>tw-avatar+span]:-ml-3',\n};\n\n@Component({\n selector: 'tw-avatar-group',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: AVATAR_GROUP_SIZE,\n useFactory: () => {\n const group = inject(AvatarGroupComponent);\n return () => group.size();\n },\n },\n ],\n host: {\n role: 'group',\n '[class]': 'hostClasses()',\n '[attr.aria-label]': 'ariaLabel()',\n },\n template: `\n <ng-content />\n @if (overflowCount() > 0) {\n <span [class]=\"overflowClasses()\">+{{ overflowCount() }}</span>\n }\n `,\n})\nexport class AvatarGroupComponent {\n /** Sets the size for all child avatars. Individual avatar size inputs are ignored when inside a group. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /** Maximum number of avatars to display. Remaining count is shown as a \"+N\" overflow indicator. Defaults to `null` (show all). */\n readonly max = input<number | null>(null);\n\n /** Accessible label for the avatar group. Defaults to `'Avatar group'` (English) — override for localisation. */\n readonly ariaLabel = input('Avatar group');\n\n private readonly avatars = contentChildren(AvatarComponent);\n\n readonly overflowCount = computed(() => {\n const all = this.avatars();\n const maxVal = this.max();\n if (maxVal === null || maxVal >= all.length) return 0;\n return all.length - maxVal;\n });\n\n readonly hostClasses = computed(() => {\n const s = this.size();\n return `inline-flex items-center [&>tw-avatar]:ring-2 [&>tw-avatar]:ring-surface ${groupOverlapMap[s]}`;\n });\n\n readonly overflowClasses = computed(() => {\n const s = this.size();\n const sizeClasses = avatarVariants({ size: s, rounded: 'full', color: 'neutral' });\n return `${sizeClasses.root()} bg-surface-muted text-fg-muted font-medium ring-2 ring-surface`;\n });\n\n private readonly visibilityEffect = effect(() => {\n const all = this.avatars();\n const maxVal = this.max();\n all.forEach((avatar, index) => {\n avatar.groupHidden.set(maxVal !== null && index >= maxVal);\n });\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}