@cdevhub/ngx-tw 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +264 -49
  2. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +11 -7
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
  4. package/fesm2022/cdevhub-ngx-tw-alert.mjs +43 -29
  5. package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -1
  6. package/fesm2022/cdevhub-ngx-tw-aspect-ratio.mjs +103 -0
  7. package/fesm2022/cdevhub-ngx-tw-aspect-ratio.mjs.map +1 -0
  8. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +56 -31
  9. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
  10. package/fesm2022/cdevhub-ngx-tw-badge.mjs +61 -35
  11. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
  12. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +154 -93
  13. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
  14. package/fesm2022/cdevhub-ngx-tw-button.mjs +24 -15
  15. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
  16. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +3 -3
  17. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
  18. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +408 -215
  19. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
  20. package/fesm2022/cdevhub-ngx-tw-card.mjs +33 -24
  21. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
  22. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +144 -79
  23. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
  24. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +99 -47
  25. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
  26. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +34 -20
  27. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
  28. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +46 -29
  29. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
  30. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +195 -110
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
  32. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +140 -73
  33. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
  34. package/fesm2022/cdevhub-ngx-tw-core.mjs +16 -11
  35. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
  36. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +393 -149
  37. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
  38. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +305 -150
  39. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
  40. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +56 -43
  41. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
  42. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +51 -33
  43. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
  44. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +905 -0
  45. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -0
  46. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +49 -26
  47. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
  48. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +133 -74
  49. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
  50. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs +2 -2
  51. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs.map +1 -1
  52. package/fesm2022/cdevhub-ngx-tw-icon.mjs +28 -17
  53. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
  54. package/fesm2022/cdevhub-ngx-tw-input.mjs +37 -21
  55. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
  56. package/fesm2022/cdevhub-ngx-tw-item.mjs +33 -24
  57. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
  58. package/fesm2022/cdevhub-ngx-tw-menu.mjs +63 -48
  59. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
  60. package/fesm2022/cdevhub-ngx-tw-number-input.mjs +622 -0
  61. package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -0
  62. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +137 -71
  63. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
  64. package/fesm2022/cdevhub-ngx-tw-popover.mjs +101 -46
  65. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
  66. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +57 -30
  67. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
  68. package/fesm2022/cdevhub-ngx-tw-radio.mjs +108 -57
  69. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
  70. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +46 -26
  71. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
  72. package/fesm2022/cdevhub-ngx-tw-select.mjs +217 -122
  73. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
  74. package/fesm2022/cdevhub-ngx-tw-separator.mjs +21 -12
  75. package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -1
  76. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +58 -44
  77. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
  78. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs +25 -14
  79. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs.map +1 -1
  80. package/fesm2022/cdevhub-ngx-tw-slider.mjs +155 -79
  81. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
  82. package/fesm2022/cdevhub-ngx-tw-sort.mjs +44 -25
  83. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
  84. package/fesm2022/cdevhub-ngx-tw-spinner.mjs +29 -16
  85. package/fesm2022/cdevhub-ngx-tw-spinner.mjs.map +1 -1
  86. package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -42
  87. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
  88. package/fesm2022/cdevhub-ngx-tw-stat.mjs +107 -64
  89. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
  90. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +113 -47
  91. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
  92. package/fesm2022/cdevhub-ngx-tw-switch.mjs +61 -32
  93. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
  94. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +88 -42
  95. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
  96. package/fesm2022/cdevhub-ngx-tw-table.mjs +266 -118
  97. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
  98. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +101 -51
  99. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
  100. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +798 -0
  101. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -0
  102. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +11 -7
  103. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
  104. package/fesm2022/cdevhub-ngx-tw-theme.mjs +22 -14
  105. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
  106. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +243 -95
  107. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
  108. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +149 -82
  109. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
  110. package/fesm2022/cdevhub-ngx-tw-toast.mjs +89 -55
  111. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
  112. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +50 -28
  113. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
  114. package/fesm2022/cdevhub-ngx-tw-transfer.mjs +1129 -0
  115. package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -0
  116. package/fesm2022/cdevhub-ngx-tw-tree.mjs +554 -0
  117. package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -0
  118. package/fesm2022/cdevhub-ngx-tw.mjs +7 -0
  119. package/fesm2022/cdevhub-ngx-tw.mjs.map +1 -1
  120. package/index.json +1 -0
  121. package/package.json +45 -20
  122. package/theme/index.css +10 -2
  123. package/types/cdevhub-ngx-tw-aspect-ratio.d.ts +40 -0
  124. package/types/cdevhub-ngx-tw-calendar.d.ts +39 -8
  125. package/types/cdevhub-ngx-tw-command-palette.d.ts +7 -0
  126. package/types/cdevhub-ngx-tw-date-picker.d.ts +36 -10
  127. package/types/cdevhub-ngx-tw-file-upload.d.ts +250 -0
  128. package/types/cdevhub-ngx-tw-form-field.d.ts +22 -3
  129. package/types/cdevhub-ngx-tw-icon-lucide.d.ts +21 -3
  130. package/types/cdevhub-ngx-tw-number-input.d.ts +130 -0
  131. package/types/cdevhub-ngx-tw-popover.d.ts +8 -0
  132. package/types/cdevhub-ngx-tw-stepper.d.ts +30 -2
  133. package/types/cdevhub-ngx-tw-tab-nav.d.ts +8 -0
  134. package/types/cdevhub-ngx-tw-table.d.ts +30 -1
  135. package/types/cdevhub-ngx-tw-tabs.d.ts +8 -0
  136. package/types/cdevhub-ngx-tw-tags-input.d.ts +217 -0
  137. package/types/cdevhub-ngx-tw-time-picker.d.ts +31 -6
  138. package/types/cdevhub-ngx-tw-transfer.d.ts +330 -0
  139. package/types/cdevhub-ngx-tw-tree.d.ts +189 -0
  140. package/types/cdevhub-ngx-tw.d.ts +7 -0
@@ -1,6 +1,6 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { Provider, OnInit, Signal } from '@angular/core';
3
- import { ControlValueAccessor } from '@angular/forms';
3
+ import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
4
4
  import { TwSize, TwColor, TimePickerFormat, ErrorStateMatcher, TimePickerMeridiem } from '@cdevhub/ngx-tw/core';
5
5
  export { TimePickerFormat, TimePickerMeridiem } from '@cdevhub/ngx-tw/core';
6
6
  import { FormFieldControl } from '@cdevhub/ngx-tw/form-field';
@@ -97,7 +97,24 @@ interface TimePickerInputEvent<D> {
97
97
  * `DateAdapter<D>`, so the component works with the default native adapter
98
98
  * (`provideNativeDateAdapter()`) or any custom adapter a consumer ships.
99
99
  */
100
- declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implements ControlValueAccessor, OnInit {
100
+ /**
101
+ * Validation errors a `tw-time-picker` can place on its bound control.
102
+ *
103
+ * Mirrors the shape of `CalendarValidationErrors` so the two pickers report
104
+ * constraint violations the same way: a code keyed by what was violated, with
105
+ * the offending value and the bound it broke.
106
+ */
107
+ type TimePickerValidationErrors = Partial<{
108
+ timePickerMin: {
109
+ min: unknown;
110
+ actual: unknown;
111
+ };
112
+ timePickerMax: {
113
+ max: unknown;
114
+ actual: unknown;
115
+ };
116
+ }>;
117
+ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implements ControlValueAccessor, Validator, OnInit {
101
118
  /** Id on the time-picker's host element. Auto-generated when not provided. Used by the form-field's `<label for>` attribute. */
102
119
  readonly idInput: _angular_core.InputSignal<string | undefined>;
103
120
  /** When true, the whole component is disabled and every field sets `aria-disabled="true"`. Defaults to `false`. */
@@ -122,9 +139,9 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
122
139
  readonly minuteStep: _angular_core.InputSignal<number>;
123
140
  /** Amount to add/subtract when stepping seconds. Defaults to `1`. */
124
141
  readonly secondStep: _angular_core.InputSignal<number>;
125
- /** Earliest accepted time-of-day. Values earlier than this set `errorState`. Defaults to `null`. Note: when `showSeconds` is `false`, the seconds component of any value still participates in the range comparison — supply `minTime` with zeroed seconds to match the 2-field display. */
142
+ /** Earliest accepted time-of-day. Values earlier than this set `errorState` and mark the bound control invalid with `timePickerMin`. Defaults to `null`. Note: when `showSeconds` is `false`, the seconds component of any value still participates in the range comparison — supply `minTime` with zeroed seconds to match the 2-field display. */
126
143
  readonly minTime: _angular_core.InputSignal<D | null>;
127
- /** Latest accepted time-of-day. Values later than this set `errorState`. Defaults to `null`. Note: when `showSeconds` is `false`, the seconds component of any value still participates in the range comparison — supply `maxTime` with zeroed seconds to match the 2-field display. */
144
+ /** Latest accepted time-of-day. Values later than this set `errorState` and mark the bound control invalid with `timePickerMax`. Defaults to `null`. Note: when `showSeconds` is `false`, the seconds component of any value still participates in the range comparison — supply `maxTime` with zeroed seconds to match the 2-field display. */
128
145
  readonly maxTime: _angular_core.InputSignal<D | null>;
129
146
  /** Date portion used when the user types a time while `value` is `null`. Defaults to today. */
130
147
  readonly referenceDate: _angular_core.InputSignal<D | null>;
@@ -155,8 +172,9 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
155
172
  private readonly liveAnnouncer;
156
173
  private readonly elementRef;
157
174
  private readonly destroyRef;
175
+ private readonly injector;
158
176
  private readonly formField;
159
- private readonly ngControl;
177
+ private ngControl;
160
178
  private readonly parentForm;
161
179
  private readonly parentFormGroup;
162
180
  private readonly defaultMatcher;
@@ -287,6 +305,13 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
287
305
  private stepFor;
288
306
  private fieldMinFor;
289
307
  private fieldMaxFor;
308
+ private validatorOnChange;
309
+ /** @internal */
310
+ validate(control: AbstractControl): ValidationErrors | null;
311
+ /** @internal */
312
+ registerOnValidatorChange(fn: () => void): void;
313
+ /** Time-of-day in seconds, ignoring the date part — the same basis `isInRange` uses. */
314
+ private secondsOf;
290
315
  writeValue(value: unknown): void;
291
316
  registerOnChange(fn: (value: D | null) => void): void;
292
317
  registerOnTouched(fn: () => void): void;
@@ -300,4 +325,4 @@ declare class TimePickerComponent<D = Date> extends FormFieldControl<D> implemen
300
325
  }
301
326
 
302
327
  export { TimePickerComponent, TimePickerIntl, provideTimePickerIntl };
303
- export type { TimePickerChangeEvent, TimePickerChangeSource, TimePickerField, TimePickerInputEvent, TimePickerVariant };
328
+ export type { TimePickerChangeEvent, TimePickerChangeSource, TimePickerField, TimePickerInputEvent, TimePickerValidationErrors, TimePickerVariant };
@@ -0,0 +1,330 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { OnInit, Signal, TemplateRef } from '@angular/core';
3
+ import { ControlValueAccessor } from '@angular/forms';
4
+ import { ListboxValueChangeEvent } from '@angular/cdk/listbox';
5
+ import { TwSize, ErrorStateMatcher } from '@cdevhub/ngx-tw/core';
6
+ import { FormFieldControl } from '@cdevhub/ngx-tw/form-field';
7
+
8
+ /** Which panel of the transfer an item / event belongs to. */
9
+ type TwTransferSide = 'source' | 'target';
10
+ /** i18n strings for the transfer. Pass any subset; unset keys fall back to the English defaults. */
11
+ interface TwTransferLabels {
12
+ /** Source (left) panel title. Defaults to `'Source'`. */
13
+ sourceTitle?: string;
14
+ /** Target (right) panel title. Defaults to `'Target'`. */
15
+ targetTitle?: string;
16
+ /** Placeholder + accessible name for the per-panel search inputs. Defaults to `'Search'`. */
17
+ searchPlaceholder?: string;
18
+ /** Text shown in a panel body when it has no visible items. Defaults to `'No items'`. */
19
+ emptyText?: string;
20
+ /** Accessible name for the header select-all checkbox. Defaults to `'Select all'`. */
21
+ selectAllLabel?: string;
22
+ /** Accessible name for the → (move-to-target) button. Defaults to `'Move selected to target'`. */
23
+ moveToTargetLabel?: string;
24
+ /** Accessible name for the ← (move-to-source) button. Defaults to `'Move selected to source'`. */
25
+ moveToSourceLabel?: string;
26
+ /** Count template rendered in each panel header. Variables: `{total}`, `{selected}`. Defaults to `'{total} items'`. */
27
+ countFormat?: string;
28
+ /** LiveAnnouncer template announced after a move. Variables: `{count}`, `{target}`. Defaults to `'{count} items moved to {target}'`. */
29
+ moveAnnouncement?: string;
30
+ }
31
+ /** Visual configuration for the transfer. Pass any subset; unset keys fall back to the defaults. */
32
+ interface TwTransferDisplayConfig {
33
+ /** Row / control density across the design-system ramps. Defaults to `'md'`. */
34
+ size?: TwSize;
35
+ /** Scroll-viewport height of each list, in px (a number) or `'auto'` (flow with content). Defaults to `240`. */
36
+ listHeight?: number | 'auto';
37
+ /** When true, each panel gets a labelled search input above its list. Defaults to `false`. */
38
+ showSearch?: boolean;
39
+ /** When true, each panel header shows a tri-state select-all checkbox. Defaults to `true`. */
40
+ showSelectAll?: boolean;
41
+ }
42
+ /** Behavioural configuration for the transfer. Generic over item type `T`. Pass any subset; unset keys fall back to the defaults. */
43
+ interface TwTransferBehaviorConfig<T = unknown> {
44
+ /** When true, items only flow source → target; the ← button is not rendered. Defaults to `false`. */
45
+ oneWay?: boolean;
46
+ /** Custom search predicate. Defaults to a case-insensitive substring match of the query against `labelFn(item)`. */
47
+ filterFn?: (item: T, query: string) => boolean;
48
+ /** Per-item disable predicate. A disabled item renders as a disabled option and is excluded from select-all and all moves. Defaults to `() => false`. */
49
+ disabledItem?: (item: T) => boolean;
50
+ }
51
+ /** Context surfaced to a `*twTransferItem` template. Generic over the item type `T`. */
52
+ interface TwTransferItemContext<T> {
53
+ /** The item data (implicit `let-item`). */
54
+ $implicit: T;
55
+ /** Resolved `labelFn(item)`. */
56
+ label: string;
57
+ /** Ephemeral pending-move checked state of this row's option. */
58
+ checked: boolean;
59
+ /** Whether the item is disabled (via `behavior.disabledItem`). */
60
+ disabled: boolean;
61
+ /** Which panel this row renders in. */
62
+ side: TwTransferSide;
63
+ }
64
+ /** Payload emitted by `moved`. Generic over the key type `K`. */
65
+ interface TwTransferMovedEvent<K> {
66
+ /** The keys that moved in this interaction. */
67
+ keys: readonly K[];
68
+ /** The direction of the move. */
69
+ direction: 'toTarget' | 'toSource';
70
+ }
71
+ /** Structural directive (`*twTransferItem="let item"`) declaring the per-item template. Typed as `TwTransferItemContext<T>`. */
72
+ declare class TransferItemDefDirective<T = unknown> {
73
+ /** @internal Consumer-projected per-item template. */
74
+ readonly template: TemplateRef<any>;
75
+ /** @internal */
76
+ static ngTemplateContextGuard<T>(_dir: TransferItemDefDirective<T>, _ctx: unknown): _ctx is TwTransferItemContext<T>;
77
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TransferItemDefDirective<any>, never>;
78
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TransferItemDefDirective<any>, "[twTransferItem]", never, {}, {}, never, never, true, never>;
79
+ }
80
+ interface RowBase<T, K> {
81
+ readonly item: T;
82
+ readonly key: K;
83
+ readonly label: string;
84
+ readonly disabled: boolean;
85
+ }
86
+ interface RowView<T, K> extends RowBase<T, K> {
87
+ readonly checked: boolean;
88
+ readonly optionClass: string;
89
+ readonly checkClass: string;
90
+ readonly context: TwTransferItemContext<T>;
91
+ }
92
+ interface PanelView<T, K> {
93
+ readonly side: TwTransferSide;
94
+ readonly title: string;
95
+ readonly titleId: string;
96
+ readonly countText: string;
97
+ readonly emptyText: string;
98
+ readonly searchPlaceholder: string;
99
+ readonly selectAllLabel: string;
100
+ readonly query: string;
101
+ readonly rows: readonly RowView<T, K>[];
102
+ readonly checkedValue: readonly K[];
103
+ readonly selectAllChecked: boolean;
104
+ readonly selectAllIndeterminate: boolean;
105
+ }
106
+ /**
107
+ * A dual-listbox shuttle: two panels (source / target) with a column of move
108
+ * buttons between them. The user ticks items in a panel and shuttles them across;
109
+ * an optional per-panel search and a tri-state header select-all accelerate bulk
110
+ * moves. The component's value is the set of keys on the target side, exposed
111
+ * through `ControlValueAccessor` + `FormFieldControl` so it works with reactive,
112
+ * template-driven, and signal forms and integrates with `<tw-form-field>`.
113
+ *
114
+ * Each panel composes `@angular/cdk/listbox` (`CdkListbox` / `CdkOption`) for
115
+ * focus-managed, accessible, keyboard-navigable selection. Consumers supply
116
+ * `keyFn` (required) and `labelFn` (defaulted to `String(item)`), and may project
117
+ * a `*twTransferItem` template for rich row content.
118
+ */
119
+ declare class TransferComponent<T = unknown, K = unknown> extends FormFieldControl<readonly K[]> implements ControlValueAccessor, OnInit {
120
+ /** All items across both panels. The source/target split derives from the value, not the reverse. Defaults to `[]`. */
121
+ readonly data: _angular_core.InputSignal<readonly T[]>;
122
+ /** Resolves a stable key for an item — drives membership (the value), checked state, tracking, the cdkOption value, and compareWith. Required. */
123
+ readonly keyFn: _angular_core.InputSignal<(item: T) => K>;
124
+ /** Resolves an item's display label — used for the default row render, search filtering, and listbox typeahead. Defaults to `(item) => String(item)`. */
125
+ readonly labelFn: _angular_core.InputSignal<(item: T) => string>;
126
+ /** Per-panel text + ARIA labels. Partial; unset keys fall back to the English defaults. */
127
+ readonly labels: _angular_core.InputSignal<Partial<TwTransferLabels>>;
128
+ /** Visual configuration — size, list viewport height, search / select-all visibility. Partial; unset keys fall back to the defaults. */
129
+ readonly display: _angular_core.InputSignal<Partial<TwTransferDisplayConfig>>;
130
+ /** Behavioural configuration — oneWay, custom filterFn, per-item disabledItem predicate. Partial; unset keys fall back to the defaults. */
131
+ readonly behavior: _angular_core.InputSignal<Partial<TwTransferBehaviorConfig<T>>>;
132
+ /** Disables the entire control — panels non-interactive, search + buttons disabled, muted styling. Also driven by Forms `setDisabledState`. Defaults to `false`. */
133
+ readonly disabledInput: _angular_core.InputSignal<boolean>;
134
+ /** Marks the control as required. Mirrored to `aria-required` chrome via the form-field; also inferred from `Validators.required` on a bound control. Defaults to `false`. */
135
+ readonly requiredInput: _angular_core.InputSignal<boolean>;
136
+ /** Reserved for control identification (e.g. analytics, future native-submission parity). The transfer has no single native value element, so it is not currently reflected to the DOM. Defaults to `undefined`. */
137
+ readonly name: _angular_core.InputSignal<string | undefined>;
138
+ /** Id on the host element. Auto-generated as `tw-transfer-N` when unset. Used by the form-field's `<label for>` association. */
139
+ readonly idInput: _angular_core.InputSignal<string | undefined>;
140
+ /** Accessible name applied to the control when no visible label is wired. Mirrored to `aria-label`. Defaults to `undefined`. */
141
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
142
+ /** ID of an external element that labels the control. Mirrored to `aria-labelledby`. Defaults to `undefined`. */
143
+ readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
144
+ /** ID of an external element that describes the control. The form-field merges its hint / error ids alongside. Defaults to `undefined`. */
145
+ readonly ariaDescribedby: _angular_core.InputSignal<string | undefined>;
146
+ /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, uses the `TW_ERROR_STATE_MATCHER` token's value. Defaults to `undefined`. */
147
+ readonly errorStateMatcher: _angular_core.InputSignal<ErrorStateMatcher | undefined>;
148
+ /** Fires when items move between panels by user interaction. Payload is the new full target-keys array. Does not fire on `writeValue`. */
149
+ readonly valueChange: _angular_core.OutputEmitterRef<readonly K[]>;
150
+ /** Fires after each directional move, identifying the moved keys and their direction. Does not fire on `writeValue`. */
151
+ readonly moved: _angular_core.OutputEmitterRef<TwTransferMovedEvent<K>>;
152
+ /** @internal Consumer-projected per-item template (`*twTransferItem`). */
153
+ readonly itemTemplate: Signal<TransferItemDefDirective<any> | undefined>;
154
+ private readonly elementRef;
155
+ private readonly injector;
156
+ private readonly destroyRef;
157
+ private readonly focusMonitor;
158
+ private readonly liveAnnouncer;
159
+ private readonly ngControl;
160
+ private readonly parentForm;
161
+ private readonly parentFormGroup;
162
+ private readonly defaultMatcher;
163
+ private readonly platform;
164
+ private readonly uid;
165
+ /** @internal Fallback id used when the consumer does not set `[id]`. */
166
+ readonly hostId: string;
167
+ private readonly sourceTitleId;
168
+ private readonly targetTitleId;
169
+ /** @internal The value: keys currently on the target side. Source of truth for membership. */
170
+ private readonly targetKeys;
171
+ /** @internal Per-panel search queries. */
172
+ private readonly sourceQuery;
173
+ private readonly targetQuery;
174
+ private readonly cvaDisabled;
175
+ private readonly _focused;
176
+ private readonly _ngControlRev;
177
+ private readonly _formSubmitRev;
178
+ private readonly describedByIdsSignal;
179
+ private readonly labelledByIdsSignal;
180
+ private onChange;
181
+ private onTouched;
182
+ /** @internal Stable comparator for `[cdkListboxCompareWith]`. Keys are identity-comparable. */
183
+ readonly compareKeys: (a: K, b: K) => boolean;
184
+ /** @internal */
185
+ readonly resolvedLabels: Signal<Required<TwTransferLabels>>;
186
+ private readonly resolvedDisplay;
187
+ private readonly resolvedBehavior;
188
+ /** @internal */
189
+ readonly resolvedSize: Signal<TwSize>;
190
+ /** @internal Checkbox tops out at `lg` density; map xl → lg. */
191
+ readonly checkboxSize: Signal<TwSize>;
192
+ /** @internal */
193
+ readonly showSearch: Signal<boolean>;
194
+ /** @internal */
195
+ readonly showSelectAll: Signal<boolean>;
196
+ /** @internal */
197
+ readonly oneWay: Signal<boolean>;
198
+ /** @internal Fixed list height in px, or `null` when `'auto'`. */
199
+ readonly listHeightPx: Signal<number | null>;
200
+ /** @internal Map from key to item across all data — for orphan-aware target rendering and disabled lookups. */
201
+ private readonly itemByKey;
202
+ private readonly targetKeySet;
203
+ /** @internal Items on the source side (in `data` order). */
204
+ private readonly sourceItems;
205
+ /** @internal Items on the target side (in `targetKeys` order; orphan keys with no item are skipped). */
206
+ private readonly targetItems;
207
+ private readonly sourceRowsBase;
208
+ private readonly sourceRenderedKeys;
209
+ /**
210
+ * @internal Ephemeral pending-move checked keys for the source panel — the
211
+ * controlled `[cdkListboxValue]`. A `linkedSignal` over the rendered-key set so
212
+ * it auto-prunes keys whose option a filter / move removed (kept ⊆ rendered → no
213
+ * CdkListbox `_invalid`; dropped keys do not re-surface). Cleared after moves.
214
+ */
215
+ readonly sourceChecked: _angular_core.WritableSignal<readonly K[]>;
216
+ private readonly sourceCheckedSet;
217
+ private readonly sourceRows;
218
+ private readonly targetRowsBase;
219
+ private readonly targetRenderedKeys;
220
+ /** @internal Ephemeral pending-move checked keys for the target panel — see {@link sourceChecked}. */
221
+ readonly targetChecked: _angular_core.WritableSignal<readonly K[]>;
222
+ private readonly targetCheckedSet;
223
+ private readonly targetRows;
224
+ /** @internal Checked, enabled, visible source keys — what the → button moves. */
225
+ readonly sourceMovableKeys: Signal<readonly K[]>;
226
+ /** @internal Checked, enabled, visible target keys — what the ← button moves. */
227
+ readonly targetMovableKeys: Signal<readonly K[]>;
228
+ private readonly sourceSelectAllKeys;
229
+ private readonly targetSelectAllKeys;
230
+ /** @internal */
231
+ readonly sourcePanel: Signal<PanelView<T, K>>;
232
+ /** @internal */
233
+ readonly targetPanel: Signal<PanelView<T, K>>;
234
+ private readonly variants;
235
+ /** @internal */
236
+ readonly rootClasses: Signal<string>;
237
+ /** @internal */
238
+ readonly panelClasses: Signal<string>;
239
+ /** @internal */
240
+ readonly panelHeaderClasses: Signal<string>;
241
+ /** @internal */
242
+ readonly panelTitleClasses: Signal<string>;
243
+ /** @internal */
244
+ readonly panelCountClasses: Signal<string>;
245
+ /** @internal */
246
+ readonly searchClasses: Signal<string>;
247
+ /** @internal */
248
+ readonly listClasses: Signal<string>;
249
+ /** @internal */
250
+ readonly optionLabelClasses: Signal<string>;
251
+ /** @internal */
252
+ readonly controlsClasses: Signal<string>;
253
+ /** @internal */
254
+ readonly moveButtonClasses: Signal<string>;
255
+ /** @internal */
256
+ readonly moveIconClasses: Signal<string>;
257
+ /** @internal */
258
+ readonly emptyClasses: Signal<string>;
259
+ constructor();
260
+ /** Moves the given items (by key) to the target side; ignores keys already there or whose item is disabled. Clears the source panel's pending checks, emits `valueChange` + `moved`, calls the CVA onChange, and announces the move. No-op when the control is disabled. */
261
+ moveToTarget(keys: readonly K[]): void;
262
+ /** Moves the given items (by key) to the source side; ignores keys not on target or whose item is disabled. Clears the target panel's pending checks. No-op when the control is disabled or `behavior.oneWay` is on. Same emissions as {@link moveToTarget}. */
263
+ moveToSource(keys: readonly K[]): void;
264
+ /** @internal */
265
+ onCheckedChange(side: TwTransferSide, event: ListboxValueChangeEvent<K>): void;
266
+ /** @internal Select-all toggles the visible, enabled keys for the panel (replace semantics). */
267
+ onSelectAll(side: TwTransferSide, checked: boolean): void;
268
+ /** @internal */
269
+ onSearch(side: TwTransferSide, event: Event): void;
270
+ /** @internal */
271
+ onMoveToTarget(): void;
272
+ /** @internal */
273
+ onMoveToSource(): void;
274
+ /**
275
+ * @internal Focuses the destination panel's listbox after the move re-renders.
276
+ * Deferred to the next render (the destination listbox may have just mounted
277
+ * from empty) and matched by its title id rather than DOM order (the *other*
278
+ * panel may have emptied, removing its listbox).
279
+ */
280
+ private focusDestination;
281
+ private applyValue;
282
+ private filterItems;
283
+ private toRowsBase;
284
+ private toRows;
285
+ private buildPanel;
286
+ private selectAllState;
287
+ private hasAccessibleNameHint;
288
+ /** @internal */
289
+ readonly id: Signal<string>;
290
+ /** The current target-keys array. Doubles as the `FormFieldControl` value member. */
291
+ readonly value: Signal<readonly K[]>;
292
+ /** @internal */
293
+ readonly focused: Signal<boolean>;
294
+ /** @internal Empty when nothing is on the target side — drives the form-field floating label. */
295
+ readonly empty: Signal<boolean>;
296
+ /** @internal */
297
+ readonly disabled: Signal<boolean>;
298
+ /** @internal */
299
+ readonly required: Signal<boolean>;
300
+ /** @internal */
301
+ readonly errorState: Signal<boolean>;
302
+ /** @internal Active validation errors from the bound control, for `[twError match="…"]` filtering. */
303
+ readonly errors: Signal<Record<string, unknown> | null>;
304
+ /** @internal */
305
+ readonly controlType = "transfer";
306
+ /** @internal */
307
+ readonly userAriaDescribedBy: Signal<string | undefined>;
308
+ /** @internal */
309
+ readonly userAriaLabelledby: Signal<string | undefined>;
310
+ /** @internal Merged `aria-describedby` (form-field hint/error ids + consumer-supplied). */
311
+ readonly resolvedDescribedBy: Signal<string>;
312
+ /** @internal Merged `aria-labelledby` (form-field label id + consumer-supplied). */
313
+ readonly resolvedLabelledBy: Signal<string>;
314
+ writeValue(value: readonly K[] | null | undefined): void;
315
+ registerOnChange(fn: (value: readonly K[]) => void): void;
316
+ registerOnTouched(fn: () => void): void;
317
+ setDisabledState(isDisabled: boolean): void;
318
+ /** @internal */
319
+ setDescribedByIds(ids: string[]): void;
320
+ /** @internal */
321
+ setLabelledByIds(ids: string[]): void;
322
+ /** @internal Clicking the form-field surface focuses the first listbox. */
323
+ onContainerClick(event: MouseEvent): void;
324
+ ngOnInit(): void;
325
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TransferComponent<any, any>, never>;
326
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TransferComponent<any, any>, "tw-transfer", ["twTransfer"], { "data": { "alias": "data"; "required": false; "isSignal": true; }; "keyFn": { "alias": "keyFn"; "required": true; "isSignal": true; }; "labelFn": { "alias": "labelFn"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "display": { "alias": "display"; "required": false; "isSignal": true; }; "behavior": { "alias": "behavior"; "required": false; "isSignal": true; }; "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; "requiredInput": { "alias": "required"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "idInput": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "aria-labelledby"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "aria-describedby"; "required": false; "isSignal": true; }; "errorStateMatcher": { "alias": "errorStateMatcher"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "moved": "moved"; }, ["itemTemplate"], never, true, never>;
327
+ }
328
+
329
+ export { TransferComponent, TransferItemDefDirective };
330
+ export type { TwTransferBehaviorConfig, TwTransferDisplayConfig, TwTransferItemContext, TwTransferLabels, TwTransferMovedEvent, TwTransferSide };
@@ -0,0 +1,189 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { TemplateRef, TrackByFunction } from '@angular/core';
3
+ import { TwSize } from '@cdevhub/ngx-tw/core';
4
+
5
+ /** Tri-state selection status of a tree node. */
6
+ type TwTreeSelectionState = 'checked' | 'unchecked' | 'indeterminate';
7
+ /** Configuration for node selection behavior. Pass any subset; unset keys fall back to the defaults. */
8
+ interface TwTreeSelectionConfig {
9
+ /** Selection mode. `'single'` is scalar (one node, no cascade/indeterminate); `'multiple'` supports cascade + tri-state. `'none'` disables selection. Defaults to `'none'`. */
10
+ mode: 'none' | 'single' | 'multiple';
11
+ /** In `'multiple'` mode, selecting a branch selects all its leaf descendants and a branch renders `'indeterminate'` when only some are selected. Ignored in `'single'`/`'none'`. Defaults to `true`. */
12
+ cascade?: boolean;
13
+ /** Pre-selected node keys (matched via `trackBy`). In cascade mode these are leaf-node keys. Defaults to `[]`. */
14
+ initialKeys?: readonly unknown[];
15
+ }
16
+ /** Display configuration for the tree. Pass any subset; unset keys fall back to the defaults. */
17
+ interface TwTreeDisplayConfig {
18
+ /** Row vertical density. Defaults to `'md'`. */
19
+ size?: TwSize;
20
+ /** Indentation per level, in pixels. Defaults to `16`. */
21
+ indent?: number;
22
+ /** Render connecting guide lines down the indent gutter. Defaults to `false`. */
23
+ showLines?: boolean;
24
+ }
25
+ /** Context surfaced to a `*twTreeNode` template. Generic over the node type `T`. */
26
+ interface TwTreeNodeContext<T> {
27
+ /** The node data (implicit `let-node`). */
28
+ $implicit: T;
29
+ /** The node data, aliased for readability. */
30
+ node: T;
31
+ /** Zero-based depth of the node. */
32
+ level: number;
33
+ /** Whether the node is currently expanded. Always `false` for leaf nodes. */
34
+ expanded: boolean;
35
+ /** Whether the node has children (is a branch, not a leaf). */
36
+ hasChildren: boolean;
37
+ /** Tri-state selection status of this node. `'unchecked'` when selection is disabled. */
38
+ selectionState: TwTreeSelectionState;
39
+ /** Toggles this node's expand/collapse state. No-op on leaf nodes. */
40
+ toggle: () => void;
41
+ /** Expands this node. No-op on leaf nodes or when already expanded. */
42
+ expand: () => void;
43
+ /** Collapses this node. No-op when already collapsed. */
44
+ collapse: () => void;
45
+ /** Toggles this node's selection (cascades in `'multiple'` mode with `cascade` on). No-op when selection is disabled. */
46
+ toggleSelection: () => void;
47
+ }
48
+ /** Structural directive (`*twTreeNode="let node"`) declaring the per-node template. Typed as `TwTreeNodeContext<T>`. */
49
+ declare class TreeNodeDefDirective<T = unknown> {
50
+ /** @internal Consumer-projected per-node template. */
51
+ readonly template: TemplateRef<any>;
52
+ /** @internal */
53
+ static ngTemplateContextGuard<T>(_dir: TreeNodeDefDirective<T>, _ctx: unknown): _ctx is TwTreeNodeContext<T>;
54
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TreeNodeDefDirective<any>, never>;
55
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TreeNodeDefDirective<any>, "[twTreeNode]", never, {}, {}, never, never, true, never>;
56
+ }
57
+ /**
58
+ * A hierarchical, keyboard-navigable tree-view wrapping `@angular/cdk/tree`
59
+ * (children-accessor model). Consumers supply the per-node template via the
60
+ * `*twTreeNode` structural directive and receive a typed context exposing the
61
+ * node, its depth/expansion/children flags, its selection state, and action
62
+ * functions (`toggle`, `expand`, `collapse`, `toggleSelection`).
63
+ *
64
+ * Selection is optional and managed internally (`'none' | 'single' | 'multiple'`).
65
+ * In `'multiple'` mode with `cascade`, selecting a branch selects all its leaf
66
+ * descendants and the branch reports `'indeterminate'` when partially selected.
67
+ * This is NOT a form control — selection is exposed via the `selectionChange`
68
+ * output and the public `toggleSelection` / `selectionState` methods.
69
+ */
70
+ declare class TreeComponent<T = unknown> {
71
+ /** Root nodes of the tree. Each node's children are resolved via `childrenAccessor`. Defaults to `[]`. */
72
+ readonly data: _angular_core.InputSignal<readonly T[]>;
73
+ /** Resolves a node's direct children; return an empty array for leaf nodes. Required. */
74
+ readonly childrenAccessor: _angular_core.InputSignal<(node: T) => readonly T[]>;
75
+ /** Identifies a node across data changes and keys both expansion and selection state. When unset, node identity is used. */
76
+ readonly trackBy: _angular_core.InputSignal<((node: T) => unknown) | undefined>;
77
+ /** Node-selection behavior — `mode`, `cascade`, `initialKeys`. Accepts a partial; unset keys fall back to the defaults. Defaults to selection disabled. */
78
+ readonly selection: _angular_core.InputSignal<Partial<TwTreeSelectionConfig>>;
79
+ /** Display configuration — `size`, `indent`, `showLines`. Accepts a partial; unset keys fall back to the defaults. */
80
+ readonly display: _angular_core.InputSignal<Partial<TwTreeDisplayConfig>>;
81
+ /** Two-way bound list of expansion key values (resolved via `trackBy`) for currently-expanded nodes. Set a new array on every change; do not mutate in place. Changes when a node is expanded or collapsed. Defaults to `[]` (all collapsed). */
82
+ readonly expandedKeys: _angular_core.ModelSignal<readonly unknown[]>;
83
+ /** Fires after the selection changes by user interaction. Payload is every node whose `selectionState` is `'checked'` (selected leaves plus fully-checked branches in cascade mode). */
84
+ readonly selectionChange: _angular_core.OutputEmitterRef<readonly T[]>;
85
+ /** Fires after a node is expanded or collapsed by user interaction. Payload identifies the node and its new expansion state. */
86
+ readonly expandedChange: _angular_core.OutputEmitterRef<{
87
+ node: T;
88
+ expanded: boolean;
89
+ }>;
90
+ /** @internal Consumer-projected per-node template (`*twTreeNode`). */
91
+ readonly nodeTemplate: _angular_core.Signal<TreeNodeDefDirective<any> | undefined>;
92
+ /** @internal The CDK tree inside our view. */
93
+ private readonly cdkTree;
94
+ /** @internal Selected node keys. In cascade mode this holds leaf keys only; branch state is derived. */
95
+ private readonly selectedKeys;
96
+ /** @internal One-shot guard so `initialKeys` seeds selection exactly once. */
97
+ private seeded;
98
+ /** @internal Resolved selection configuration. */
99
+ private readonly resolvedSelection;
100
+ /** @internal Resolved display configuration. */
101
+ private readonly resolvedDisplay;
102
+ /** @internal Indentation width in px per level. */
103
+ readonly indentWidth: _angular_core.Signal<number>;
104
+ /** @internal Snapshot of the root nodes as a mutable array (CDK's `dataSource` rejects `readonly T[]`). */
105
+ readonly dataArray: _angular_core.Signal<T[]>;
106
+ private readonly variants;
107
+ readonly rootClasses: _angular_core.Signal<string>;
108
+ readonly spacerClasses: _angular_core.Signal<string>;
109
+ readonly contentClasses: _angular_core.Signal<string>;
110
+ constructor();
111
+ /** @internal Resolves a node's identity key via `trackBy`, falling back to the node itself. */
112
+ private keyOf;
113
+ /** @internal Direct children of a node (always a fresh mutable array). */
114
+ private childrenOf;
115
+ /** Whether the node has at least one child (is a branch). */
116
+ hasChildren(node: T): boolean;
117
+ /** @internal Depth-first list of every node in the tree (under collapsed parents too). */
118
+ private flattenAll;
119
+ /** @internal All leaf descendants of a node (the node itself if it is a leaf). */
120
+ private leavesOf;
121
+ /** @internal Array of length `level` used to render per-level indent spacers. */
122
+ indentMarkers(level: number): readonly number[];
123
+ /** @internal Per-node row classes (incorporates the selected state). */
124
+ nodeClasses(node: T): string;
125
+ /** @internal Builds the typed context handed to the consumer's `*twTreeNode` template. */
126
+ buildContext(node: T, level: number): TwTreeNodeContext<T>;
127
+ /**
128
+ * @internal `aria-selected` for `'single'` mode (boolean selection), or `null`
129
+ * otherwise. Multiple mode uses `aria-checked` instead so the tri-state
130
+ * `'mixed'` value is exposed to assistive tech on the focusable treeitem.
131
+ */
132
+ ariaSelected(node: T): 'true' | 'false' | null;
133
+ /**
134
+ * @internal Tri-state `aria-checked` for `'multiple'` mode (`'mixed'` for a
135
+ * partially-selected branch), or `null` otherwise. APG exposes checkbox-tree
136
+ * selection on the treeitem via `aria-checked`; `aria-selected` cannot carry
137
+ * the indeterminate state.
138
+ */
139
+ ariaChecked(node: T): 'true' | 'false' | 'mixed' | null;
140
+ /** @internal Adapts the consumer's `readonly`-returning accessor to CDK's mutable-array contract. */
141
+ readonly cdkChildrenAccessor: (node: T) => T[];
142
+ /** @internal CDK row-tracking function keyed via `trackBy`. */
143
+ readonly cdkTrackBy: TrackByFunction<T>;
144
+ /** @internal Keys CDK's expansion model via `trackBy`. */
145
+ readonly cdkExpansionKey: (node: T) => unknown;
146
+ /** Whether the node is currently expanded. */
147
+ isExpanded(node: T): boolean;
148
+ /** Expands the node if collapsed. Emits `expandedChange` and updates `expandedKeys` via the CDK callback. */
149
+ expand(node: T): void;
150
+ /** Collapses the node if expanded. Emits `expandedChange` and updates `expandedKeys` via the CDK callback. */
151
+ collapse(node: T): void;
152
+ /** Toggles the node's expand/collapse state. No-op on leaf nodes. */
153
+ toggle(node: T): void;
154
+ /**
155
+ * @internal Bridges CDK's per-node `(expandedChange)` to the `expandedKeys`
156
+ * model. Compare-before-write: only mutates the model and emits when the
157
+ * key's membership actually changes, so the model→CDK effect cannot loop.
158
+ */
159
+ onCdkExpandedChange(node: T, expanded: boolean): void;
160
+ /**
161
+ * Returns the tri-state selection status of a node. `'unchecked'` when
162
+ * selection is disabled.
163
+ *
164
+ * For cascade branches this walks the node's leaf descendants on each call and
165
+ * is invoked a few times per node per change-detection pass (row class, ARIA,
166
+ * context). This assumes small-to-medium trees; the component has no
167
+ * virtualization and is not tuned for very large data sets.
168
+ */
169
+ selectionState(node: T): TwTreeSelectionState;
170
+ /** Toggles selection for a node (cascades to leaf descendants in `'multiple'` mode with `cascade` on). No-op when `selection.mode === 'none'`. */
171
+ toggleSelection(node: T): void;
172
+ /** @internal Every node currently reporting `selectionState() === 'checked'`. */
173
+ private selectedNodes;
174
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TreeComponent<any>, never>;
175
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<TreeComponent<any>, "tw-tree", ["twTree"], { "data": { "alias": "data"; "required": false; "isSignal": true; }; "childrenAccessor": { "alias": "childrenAccessor"; "required": true; "isSignal": true; }; "trackBy": { "alias": "trackBy"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "display": { "alias": "display"; "required": false; "isSignal": true; }; "expandedKeys": { "alias": "expandedKeys"; "required": false; "isSignal": true; }; }, { "expandedKeys": "expandedKeysChange"; "selectionChange": "selectionChange"; "expandedChange": "expandedChange"; }, ["nodeTemplate"], never, true, never>;
176
+ }
177
+ /** Attribute directive (`[twTreeNodeToggle]="node"`) that toggles the given node's expansion on click. */
178
+ declare class TreeNodeToggleDirective<T = unknown> {
179
+ private readonly tree;
180
+ /** The node whose expansion this control toggles. */
181
+ readonly node: _angular_core.InputSignal<T>;
182
+ /** @internal Toggles the node and stops the click from bubbling to row activation. */
183
+ onClick(event: Event): void;
184
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TreeNodeToggleDirective<any>, never>;
185
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TreeNodeToggleDirective<any>, "[twTreeNodeToggle]", never, { "node": { "alias": "twTreeNodeToggle"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
186
+ }
187
+
188
+ export { TreeComponent, TreeNodeDefDirective, TreeNodeToggleDirective };
189
+ export type { TwTreeDisplayConfig, TwTreeNodeContext, TwTreeSelectionConfig, TwTreeSelectionState };
@@ -19,6 +19,7 @@ export * from '@cdevhub/ngx-tw/popover';
19
19
  export * from '@cdevhub/ngx-tw/dialog';
20
20
  export * from '@cdevhub/ngx-tw/command-palette';
21
21
  export * from '@cdevhub/ngx-tw/toast';
22
+ export * from '@cdevhub/ngx-tw/transfer';
22
23
  export * from '@cdevhub/ngx-tw/form-field';
23
24
  export * from '@cdevhub/ngx-tw/switch';
24
25
  export * from '@cdevhub/ngx-tw/checkbox';
@@ -26,6 +27,9 @@ export * from '@cdevhub/ngx-tw/radio';
26
27
  export * from '@cdevhub/ngx-tw/select';
27
28
  export * from '@cdevhub/ngx-tw/input';
28
29
  export * from '@cdevhub/ngx-tw/textarea';
30
+ export * from '@cdevhub/ngx-tw/file-upload';
31
+ export * from '@cdevhub/ngx-tw/number-input';
32
+ export * from '@cdevhub/ngx-tw/tags-input';
29
33
  export * from '@cdevhub/ngx-tw/spinner';
30
34
  export * from '@cdevhub/ngx-tw/progress-bar';
31
35
  export * from '@cdevhub/ngx-tw/skeleton';
@@ -47,3 +51,6 @@ export * from '@cdevhub/ngx-tw/stat';
47
51
  export * from '@cdevhub/ngx-tw/combobox';
48
52
  export * from '@cdevhub/ngx-tw/empty-state';
49
53
  export * from '@cdevhub/ngx-tw/sheet';
54
+ export * from '@cdevhub/ngx-tw/aspect-ratio';
55
+ export * from '@cdevhub/ngx-tw/tree';
56
+ export * from '@cdevhub/ngx-tw/theme';