@kraft.stitch/angular 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -2
- package/fesm2022/kraft.stitch-angular.mjs +2873 -0
- package/fesm2022/kraft.stitch-angular.mjs.map +1 -0
- package/package.json +17 -16
- package/types/kraft.stitch-angular.d.ts +2247 -0
- package/.github/workflows/npm-publish.yml +0 -33
- package/ng-package.json +0 -10
- package/src/lib/Buttons/button/button.ts +0 -152
- package/src/lib/Buttons/button-group/button-group.ts +0 -129
- package/src/lib/Buttons/chips/chips.ts +0 -131
- package/src/lib/Buttons/fab/fab.ts +0 -96
- package/src/lib/Calendars/datepicker/datepicker.ts +0 -105
- package/src/lib/Calendars/daterange/daterange.ts +0 -112
- package/src/lib/Calendars/timepicker/timepicker.ts +0 -117
- package/src/lib/Dropdowns/dropdown/dropdown.ts +0 -121
- package/src/lib/Dropdowns/listbox/listbox.ts +0 -116
- package/src/lib/Inputs/checkbox/checkbox.ts +0 -126
- package/src/lib/Inputs/colour-picker/colour-picker.ts +0 -101
- package/src/lib/Inputs/input/input.ts +0 -139
- package/src/lib/Inputs/otp-input/otp-input.ts +0 -113
- package/src/lib/Inputs/radio/radio.ts +0 -115
- package/src/lib/Inputs/rating/rating.ts +0 -104
- package/src/lib/Inputs/slider/slider.ts +0 -121
- package/src/lib/Inputs/switch/switch.ts +0 -100
- package/src/lib/Inputs/textarea/textarea.ts +0 -129
- package/src/lib/Inputs/theme-switch/theme-switch.ts +0 -61
- package/src/lib/Inputs/uploader/uploader.ts +0 -97
- package/src/lib/Layout/avatar/avatar.ts +0 -66
- package/src/lib/Layout/card/card.ts +0 -88
- package/src/lib/Layout/code-view/code-view.ts +0 -77
- package/src/lib/Layout/dialog/dialog.ts +0 -80
- package/src/lib/Layout/not-found/not-found.ts +0 -73
- package/src/lib/Layout/sidebar/sidebar.ts +0 -97
- package/src/lib/Layout/table/table.ts +0 -81
- package/src/lib/Layout/tooltip/tooltip.ts +0 -48
- package/src/lib/Navigation/accordion/accordion.ts +0 -80
- package/src/lib/Navigation/breadcrumb/breadcrumb.ts +0 -58
- package/src/lib/Navigation/carousel/carousel.ts +0 -70
- package/src/lib/Navigation/context-menu/context-menu.ts +0 -79
- package/src/lib/Navigation/nav-bar/nav-bar.ts +0 -72
- package/src/lib/Navigation/pagination/pagination.ts +0 -82
- package/src/lib/Navigation/stepper/stepper.ts +0 -77
- package/src/lib/Navigation/tab/tab.ts +0 -71
- package/src/lib/Navigation/toolbar/toolbar.ts +0 -60
- package/src/lib/Navigation/top-nav-bar/top-nav-bar.ts +0 -71
- package/src/lib/Navigation/tree-view/tree-view.ts +0 -75
- package/src/lib/Notification/badge/badge.ts +0 -55
- package/src/lib/Notification/loader/loader.ts +0 -41
- package/src/lib/Notification/message/message.ts +0 -60
- package/src/lib/Notification/progress/progress.ts +0 -65
- package/src/lib/Notification/spinner/spinner.ts +0 -50
- package/src/lib/Notification/toast/toast.ts +0 -56
- package/src/public-api.ts +0 -62
- package/tsconfig.json +0 -23
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-daterange` tag — see
|
|
2
|
-
// `button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-daterange.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Mirrors `KsDateRange` / `KsPresetRange` exported by
|
|
10
|
-
* `core/src/components/Calendars/daterange/daterange.types.ts`. Duplicated
|
|
11
|
-
* locally — see the note in `button-group/button-group.ts` for why.
|
|
12
|
-
*/
|
|
13
|
-
export interface KsDateRange {
|
|
14
|
-
start: Date | null;
|
|
15
|
-
end: Date | null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface KsPresetRange {
|
|
19
|
-
label: string;
|
|
20
|
-
range: () => KsDateRange;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** DOM shape of the real `<ks-daterange>` custom element, typed for the wrapper. */
|
|
24
|
-
type KsDaterangeElement = HTMLElement & {
|
|
25
|
-
label: string;
|
|
26
|
-
placeholder: string;
|
|
27
|
-
minDate: Date | null;
|
|
28
|
-
maxDate: Date | null;
|
|
29
|
-
presets: KsPresetRange[];
|
|
30
|
-
showPresets: boolean;
|
|
31
|
-
disabled: boolean;
|
|
32
|
-
range: KsDateRange;
|
|
33
|
-
writeValue(val: KsDateRange | null): Promise<void>;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Angular wrapper around the `<ks-daterange>` Stencil custom element.
|
|
38
|
-
*
|
|
39
|
-
* Two-way binding is via `ControlValueAccessor` — use `[(ngModel)]` or
|
|
40
|
-
* `formControlName`. See `chips/chips.ts` for the full rationale (the
|
|
41
|
-
* native `rangeChange` event can't be reused verbatim as an Angular output
|
|
42
|
-
* name without a double-fire risk).
|
|
43
|
-
*
|
|
44
|
-
* For plain (non-forms) two-way use, bind explicitly instead:
|
|
45
|
-
* `[range]="r" (ksRangeChange)="r = $event"`.
|
|
46
|
-
*
|
|
47
|
-
* `template: ''` — no slot is exposed on `<ks-daterange>` itself.
|
|
48
|
-
*/
|
|
49
|
-
@Component({
|
|
50
|
-
selector: 'ks-daterange',
|
|
51
|
-
standalone: true,
|
|
52
|
-
template: '',
|
|
53
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
54
|
-
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: KsDaterangeComponent, multi: true }],
|
|
55
|
-
})
|
|
56
|
-
export class KsDaterangeComponent implements ControlValueAccessor {
|
|
57
|
-
private readonly el: KsDaterangeElement;
|
|
58
|
-
private onChange: (value: KsDateRange) => void = () => {};
|
|
59
|
-
private onTouched: () => void = () => {};
|
|
60
|
-
|
|
61
|
-
readonly label = input('');
|
|
62
|
-
readonly placeholder = input('Select date range…');
|
|
63
|
-
readonly minDate = input<Date | null>(null);
|
|
64
|
-
readonly maxDate = input<Date | null>(null);
|
|
65
|
-
readonly presets = input<KsPresetRange[]>([]);
|
|
66
|
-
readonly showPresets = input(true);
|
|
67
|
-
readonly disabled = input(false);
|
|
68
|
-
|
|
69
|
-
/** Initial/controlled value for plain (non-forms) usage. Prefer `[(ngModel)]` / `formControlName` when inside a form. */
|
|
70
|
-
readonly range = input<KsDateRange>({ start: null, end: null });
|
|
71
|
-
|
|
72
|
-
/** Emits the newly-picked range. From the native `rangeChange` event. */
|
|
73
|
-
readonly ksRangeChange = output<KsDateRange>();
|
|
74
|
-
|
|
75
|
-
constructor(ref: ElementRef<KsDaterangeElement>) {
|
|
76
|
-
this.el = ref.nativeElement;
|
|
77
|
-
|
|
78
|
-
effect(() => (this.el.label = this.label()));
|
|
79
|
-
effect(() => (this.el.placeholder = this.placeholder()));
|
|
80
|
-
effect(() => (this.el.minDate = this.minDate()));
|
|
81
|
-
effect(() => (this.el.maxDate = this.maxDate()));
|
|
82
|
-
effect(() => (this.el.presets = this.presets()));
|
|
83
|
-
effect(() => (this.el.showPresets = this.showPresets()));
|
|
84
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
85
|
-
effect(() => void this.el.writeValue(this.range()));
|
|
86
|
-
|
|
87
|
-
const onNativeRangeChange = (event: Event): void => {
|
|
88
|
-
const detail = (event as CustomEvent<KsDateRange>).detail;
|
|
89
|
-
this.ksRangeChange.emit(detail);
|
|
90
|
-
this.onChange(detail);
|
|
91
|
-
this.onTouched();
|
|
92
|
-
};
|
|
93
|
-
this.el.addEventListener('rangeChange', onNativeRangeChange);
|
|
94
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('rangeChange', onNativeRangeChange));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
writeValue(value: KsDateRange | null): void {
|
|
98
|
-
void this.el.writeValue(value ?? { start: null, end: null });
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
registerOnChange(fn: (value: KsDateRange) => void): void {
|
|
102
|
-
this.onChange = fn;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
registerOnTouched(fn: () => void): void {
|
|
106
|
-
this.onTouched = fn;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
setDisabledState(isDisabled: boolean): void {
|
|
110
|
-
this.el.disabled = isDisabled;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-timepicker` tag — see
|
|
2
|
-
// `button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-timepicker.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, model, output } from '@angular/core';
|
|
6
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Mirrors `KsTimeValue` exported by
|
|
10
|
-
* `core/src/components/Calendars/timepicker/timepicker.tsx`. Duplicated
|
|
11
|
-
* locally — see the note in `button-group/button-group.ts` for why.
|
|
12
|
-
*/
|
|
13
|
-
export interface KsTimeValue {
|
|
14
|
-
hours: number;
|
|
15
|
-
minutes: number;
|
|
16
|
-
seconds?: number;
|
|
17
|
-
period?: 'AM' | 'PM';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** DOM shape of the real `<ks-timepicker>` custom element, typed for the wrapper. */
|
|
21
|
-
type KsTimepickerElement = HTMLElement & {
|
|
22
|
-
label: string;
|
|
23
|
-
placeholder: string;
|
|
24
|
-
use12Hour: boolean;
|
|
25
|
-
showSeconds: boolean;
|
|
26
|
-
disabled: boolean;
|
|
27
|
-
error: string;
|
|
28
|
-
value: KsTimeValue | null;
|
|
29
|
-
writeValue(val: KsTimeValue | null): Promise<void>;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Angular wrapper around the `<ks-timepicker>` Stencil custom element.
|
|
34
|
-
*
|
|
35
|
-
* Two-way binding is via `ControlValueAccessor` — use `[(ngModel)]` or
|
|
36
|
-
* `formControlName`. See `chips/chips.ts` for the full rationale (the
|
|
37
|
-
* native `valueChange` event can't be reused verbatim as an Angular output
|
|
38
|
-
* name without a double-fire risk).
|
|
39
|
-
*
|
|
40
|
-
* For plain (non-forms) two-way use, bind explicitly instead:
|
|
41
|
-
* `[value]="t" (ksValueChange)="t = $event"`.
|
|
42
|
-
*
|
|
43
|
-
* `template: ''` — no slot is exposed on `<ks-timepicker>` itself.
|
|
44
|
-
*/
|
|
45
|
-
@Component({
|
|
46
|
-
selector: 'ks-timepicker',
|
|
47
|
-
standalone: true,
|
|
48
|
-
template: '',
|
|
49
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
50
|
-
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: KsTimepickerComponent, multi: true }],
|
|
51
|
-
})
|
|
52
|
-
export class KsTimepickerComponent implements ControlValueAccessor {
|
|
53
|
-
private readonly el: KsTimepickerElement;
|
|
54
|
-
private onChange: (value: KsTimeValue) => void = () => {};
|
|
55
|
-
private onTouched: () => void = () => {};
|
|
56
|
-
|
|
57
|
-
/** Field label */
|
|
58
|
-
readonly label = input('');
|
|
59
|
-
|
|
60
|
-
/** Placeholder */
|
|
61
|
-
readonly placeholder = input('Select time…');
|
|
62
|
-
|
|
63
|
-
/** Use 12-hour clock (AM/PM) */
|
|
64
|
-
readonly use12Hour = input(false);
|
|
65
|
-
|
|
66
|
-
/** Show seconds */
|
|
67
|
-
readonly showSeconds = input(false);
|
|
68
|
-
|
|
69
|
-
/** Disabled */
|
|
70
|
-
readonly disabled = input(false);
|
|
71
|
-
|
|
72
|
-
/** Error message */
|
|
73
|
-
readonly error = input('');
|
|
74
|
-
|
|
75
|
-
/** Initial/controlled value for plain (non-forms) usage. Prefer `[(ngModel)]` / `formControlName` when inside a form. */
|
|
76
|
-
readonly value = model<KsTimeValue | null>(null);
|
|
77
|
-
|
|
78
|
-
/** Emits the confirmed time. From the native `valueChange` event. */
|
|
79
|
-
readonly ksValueChange = output<KsTimeValue>();
|
|
80
|
-
|
|
81
|
-
constructor(ref: ElementRef<KsTimepickerElement>) {
|
|
82
|
-
this.el = ref.nativeElement;
|
|
83
|
-
|
|
84
|
-
effect(() => (this.el.label = this.label()));
|
|
85
|
-
effect(() => (this.el.placeholder = this.placeholder()));
|
|
86
|
-
effect(() => (this.el.use12Hour = this.use12Hour()));
|
|
87
|
-
effect(() => (this.el.showSeconds = this.showSeconds()));
|
|
88
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
89
|
-
effect(() => (this.el.error = this.error()));
|
|
90
|
-
effect(() => void this.el.writeValue(this.value()));
|
|
91
|
-
|
|
92
|
-
const onNativeValueChange = (event: Event): void => {
|
|
93
|
-
const detail = (event as CustomEvent<KsTimeValue>).detail;
|
|
94
|
-
this.ksValueChange.emit(detail);
|
|
95
|
-
this.onChange(detail);
|
|
96
|
-
this.onTouched();
|
|
97
|
-
};
|
|
98
|
-
this.el.addEventListener('valueChange', onNativeValueChange);
|
|
99
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('valueChange', onNativeValueChange));
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
writeValue(value: KsTimeValue | null): void {
|
|
103
|
-
void this.el.writeValue(value ?? null);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
registerOnChange(fn: (value: KsTimeValue) => void): void {
|
|
107
|
-
this.onChange = fn;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
registerOnTouched(fn: () => void): void {
|
|
111
|
-
this.onTouched = fn;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
setDisabledState(isDisabled: boolean): void {
|
|
115
|
-
this.el.disabled = isDisabled;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-dropdown` tag — see
|
|
2
|
-
// `button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-dropdown.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Mirrors `KsDropdownOption` exported by
|
|
10
|
-
* `core/src/components/Dropdowns/dropdown/dropdown.tsx`. Duplicated
|
|
11
|
-
* locally — see the note in `button-group/button-group.ts` for why.
|
|
12
|
-
*/
|
|
13
|
-
export interface KsDropdownOption {
|
|
14
|
-
value: string | number;
|
|
15
|
-
label: string;
|
|
16
|
-
icon?: string;
|
|
17
|
-
disabled?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type KsDropdownValue = (string | number)[] | string | number;
|
|
21
|
-
|
|
22
|
-
/** DOM shape of the real `<ks-dropdown>` custom element, typed for the wrapper. */
|
|
23
|
-
type KsDropdownElement = HTMLElement & {
|
|
24
|
-
options: KsDropdownOption[];
|
|
25
|
-
placeholder: string;
|
|
26
|
-
multi: boolean;
|
|
27
|
-
searchable: boolean;
|
|
28
|
-
label: string;
|
|
29
|
-
disabled: boolean;
|
|
30
|
-
selectedValues: (string | number)[];
|
|
31
|
-
writeValue(val: (string | number) | (string | number)[] | null): Promise<void>;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Angular wrapper around the `<ks-dropdown>` Stencil custom element.
|
|
36
|
-
*
|
|
37
|
-
* Two-way binding is via `ControlValueAccessor` — use `[(ngModel)]` or
|
|
38
|
-
* `formControlName`. See `chips/chips.ts` for the full rationale (the
|
|
39
|
-
* native `selectedValuesChange` event can't be reused verbatim as an
|
|
40
|
-
* Angular output name without a double-fire risk).
|
|
41
|
-
*
|
|
42
|
-
* For plain (non-forms) two-way use, bind explicitly instead:
|
|
43
|
-
* `[selectedValues]="v" (ksSelectedValuesChange)="v = $event"`.
|
|
44
|
-
*
|
|
45
|
-
* `template: ''` — the option list / search box in the Stencil render are
|
|
46
|
-
* projected into the shared, internal `<ks-overlay-field>` slot; there is
|
|
47
|
-
* no slot exposed on `<ks-dropdown>` itself for a consumer to project into.
|
|
48
|
-
*/
|
|
49
|
-
@Component({
|
|
50
|
-
selector: 'ks-dropdown',
|
|
51
|
-
standalone: true,
|
|
52
|
-
template: '',
|
|
53
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
54
|
-
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: KsDropdownComponent, multi: true }],
|
|
55
|
-
})
|
|
56
|
-
export class KsDropdownComponent implements ControlValueAccessor {
|
|
57
|
-
private readonly el: KsDropdownElement;
|
|
58
|
-
private onChange: (value: KsDropdownValue) => void = () => {};
|
|
59
|
-
private onTouched: () => void = () => {};
|
|
60
|
-
|
|
61
|
-
/** Full list of options */
|
|
62
|
-
readonly options = input<KsDropdownOption[]>([]);
|
|
63
|
-
|
|
64
|
-
/** Placeholder text shown when nothing is selected */
|
|
65
|
-
readonly placeholder = input('Select…');
|
|
66
|
-
|
|
67
|
-
/** Allow selecting multiple options */
|
|
68
|
-
readonly multi = input(false);
|
|
69
|
-
|
|
70
|
-
/** Show a search box inside the dropdown */
|
|
71
|
-
readonly searchable = input(false);
|
|
72
|
-
|
|
73
|
-
/** Field label */
|
|
74
|
-
readonly label = input('');
|
|
75
|
-
|
|
76
|
-
/** Disabled state */
|
|
77
|
-
readonly disabled = input(false);
|
|
78
|
-
|
|
79
|
-
/** Initial/controlled selected value(s) for plain (non-forms) usage. Prefer `[(ngModel)]` / `formControlName` when inside a form. */
|
|
80
|
-
readonly selectedValues = input<(string | number)[]>([]);
|
|
81
|
-
|
|
82
|
-
/** Emits the new selection — an array when `multi`, otherwise a single value. From the native `selectedValuesChange` event. */
|
|
83
|
-
readonly ksSelectedValuesChange = output<KsDropdownValue>();
|
|
84
|
-
|
|
85
|
-
constructor(ref: ElementRef<KsDropdownElement>) {
|
|
86
|
-
this.el = ref.nativeElement;
|
|
87
|
-
|
|
88
|
-
effect(() => (this.el.options = this.options()));
|
|
89
|
-
effect(() => (this.el.placeholder = this.placeholder()));
|
|
90
|
-
effect(() => (this.el.multi = this.multi()));
|
|
91
|
-
effect(() => (this.el.searchable = this.searchable()));
|
|
92
|
-
effect(() => (this.el.label = this.label()));
|
|
93
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
94
|
-
effect(() => void this.el.writeValue(this.selectedValues()));
|
|
95
|
-
|
|
96
|
-
const onNativeSelectedValuesChange = (event: Event): void => {
|
|
97
|
-
const detail = (event as CustomEvent<KsDropdownValue>).detail;
|
|
98
|
-
this.ksSelectedValuesChange.emit(detail);
|
|
99
|
-
this.onChange(detail);
|
|
100
|
-
this.onTouched();
|
|
101
|
-
};
|
|
102
|
-
this.el.addEventListener('selectedValuesChange', onNativeSelectedValuesChange);
|
|
103
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('selectedValuesChange', onNativeSelectedValuesChange));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
writeValue(value: KsDropdownValue | null): void {
|
|
107
|
-
void this.el.writeValue(value ?? null);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
registerOnChange(fn: (value: KsDropdownValue) => void): void {
|
|
111
|
-
this.onChange = fn;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
registerOnTouched(fn: () => void): void {
|
|
115
|
-
this.onTouched = fn;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
setDisabledState(isDisabled: boolean): void {
|
|
119
|
-
this.el.disabled = isDisabled;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-listbox` tag — see
|
|
2
|
-
// `button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-listbox.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Mirrors `KsListBoxOption` exported by
|
|
10
|
-
* `core/src/components/Dropdowns/listbox/listbox.tsx`. Duplicated locally
|
|
11
|
-
* — see the note in `button-group/button-group.ts` for why.
|
|
12
|
-
*/
|
|
13
|
-
export interface KsListBoxOption {
|
|
14
|
-
value: string | number;
|
|
15
|
-
label: string;
|
|
16
|
-
icon?: string;
|
|
17
|
-
disabled?: boolean;
|
|
18
|
-
/** Optional group key — used when `groupBy` is enabled */
|
|
19
|
-
group?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type KsListBoxValue = (string | number)[] | string | number;
|
|
23
|
-
|
|
24
|
-
/** DOM shape of the real `<ks-listbox>` custom element, typed for the wrapper. */
|
|
25
|
-
type KsListBoxElement = HTMLElement & {
|
|
26
|
-
options: KsListBoxOption[];
|
|
27
|
-
multi: boolean;
|
|
28
|
-
searchable: boolean;
|
|
29
|
-
disabled: boolean;
|
|
30
|
-
selected: (string | number)[];
|
|
31
|
-
groupBy: boolean;
|
|
32
|
-
writeValue(val: (string | number) | (string | number)[] | null): Promise<void>;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Angular wrapper around the `<ks-listbox>` Stencil custom element.
|
|
37
|
-
*
|
|
38
|
-
* Two-way binding is via `ControlValueAccessor` — use `[(ngModel)]` or
|
|
39
|
-
* `formControlName`. See `chips/chips.ts` for the full rationale (the
|
|
40
|
-
* native `selectedChange` event can't be reused verbatim as an Angular
|
|
41
|
-
* output name without a double-fire risk).
|
|
42
|
-
*
|
|
43
|
-
* For plain (non-forms) two-way use, bind explicitly instead:
|
|
44
|
-
* `[selected]="v" (ksSelectedChange)="v = $event"`.
|
|
45
|
-
*
|
|
46
|
-
* `template: ''` — no slot is exposed on `<ks-listbox>` itself.
|
|
47
|
-
*/
|
|
48
|
-
@Component({
|
|
49
|
-
selector: 'ks-listbox',
|
|
50
|
-
standalone: true,
|
|
51
|
-
template: '',
|
|
52
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
53
|
-
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: KsListBoxComponent, multi: true }],
|
|
54
|
-
})
|
|
55
|
-
export class KsListBoxComponent implements ControlValueAccessor {
|
|
56
|
-
private readonly el: KsListBoxElement;
|
|
57
|
-
private onChange: (value: KsListBoxValue) => void = () => {};
|
|
58
|
-
private onTouched: () => void = () => {};
|
|
59
|
-
|
|
60
|
-
/** Options list */
|
|
61
|
-
readonly options = input<KsListBoxOption[]>([]);
|
|
62
|
-
|
|
63
|
-
/** Allow multi-select */
|
|
64
|
-
readonly multi = input(false);
|
|
65
|
-
|
|
66
|
-
/** Show search box */
|
|
67
|
-
readonly searchable = input(false);
|
|
68
|
-
|
|
69
|
-
/** Disabled */
|
|
70
|
-
readonly disabled = input(false);
|
|
71
|
-
|
|
72
|
-
/** Enable group headers using the `group` field on each option */
|
|
73
|
-
readonly groupBy = input(false);
|
|
74
|
-
|
|
75
|
-
/** Initial/controlled selected value(s) for plain (non-forms) usage. Prefer `[(ngModel)]` / `formControlName` when inside a form. */
|
|
76
|
-
readonly selected = input<(string | number)[]>([]);
|
|
77
|
-
|
|
78
|
-
/** Emits the new selection — an array when `multi`, otherwise a single value. From the native `selectedChange` event. */
|
|
79
|
-
readonly ksSelectedChange = output<KsListBoxValue>();
|
|
80
|
-
|
|
81
|
-
constructor(ref: ElementRef<KsListBoxElement>) {
|
|
82
|
-
this.el = ref.nativeElement;
|
|
83
|
-
|
|
84
|
-
effect(() => (this.el.options = this.options()));
|
|
85
|
-
effect(() => (this.el.multi = this.multi()));
|
|
86
|
-
effect(() => (this.el.searchable = this.searchable()));
|
|
87
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
88
|
-
effect(() => (this.el.groupBy = this.groupBy()));
|
|
89
|
-
effect(() => void this.el.writeValue(this.selected()));
|
|
90
|
-
|
|
91
|
-
const onNativeSelectedChange = (event: Event): void => {
|
|
92
|
-
const detail = (event as CustomEvent<KsListBoxValue>).detail;
|
|
93
|
-
this.ksSelectedChange.emit(detail);
|
|
94
|
-
this.onChange(detail);
|
|
95
|
-
this.onTouched();
|
|
96
|
-
};
|
|
97
|
-
this.el.addEventListener('selectedChange', onNativeSelectedChange);
|
|
98
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('selectedChange', onNativeSelectedChange));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
writeValue(value: KsListBoxValue | null): void {
|
|
102
|
-
void this.el.writeValue(value ?? null);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
registerOnChange(fn: (value: KsListBoxValue) => void): void {
|
|
106
|
-
this.onChange = fn;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
registerOnTouched(fn: () => void): void {
|
|
110
|
-
this.onTouched = fn;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
setDisabledState(isDisabled: boolean): void {
|
|
114
|
-
this.el.disabled = isDisabled;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-checkbox` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-checkbox.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Mirrors `KsCheckboxOption` exported by
|
|
10
|
-
* `core/src/components/Inputs/checkbox/checkbox.tsx`. Duplicated locally
|
|
11
|
-
* — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
12
|
-
*/
|
|
13
|
-
export interface KsCheckboxOption {
|
|
14
|
-
value: string;
|
|
15
|
-
label?: string;
|
|
16
|
-
disabled?: boolean;
|
|
17
|
-
checked?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** DOM shape of the real `<ks-checkbox>` custom element, typed for the wrapper. */
|
|
21
|
-
type KsCheckboxElement = HTMLElement & {
|
|
22
|
-
label: string;
|
|
23
|
-
options: KsCheckboxOption[];
|
|
24
|
-
disabled: boolean;
|
|
25
|
-
checked: boolean;
|
|
26
|
-
selected: string[];
|
|
27
|
-
writeValue(val: unknown): Promise<void>;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Angular wrapper around the `<ks-checkbox>` Stencil custom element.
|
|
32
|
-
*
|
|
33
|
-
* Supports two modes, mirroring the Stencil source:
|
|
34
|
-
* - **Single** mode (no `options`): two-way bind `checked` (boolean).
|
|
35
|
-
* - **Group** mode (`options` set): two-way bind `selected` (string[]).
|
|
36
|
-
*
|
|
37
|
-
* Two-way binding for either mode is via `ControlValueAccessor` — use
|
|
38
|
-
* `[(ngModel)]`/`formControlName` and it works for whichever mode is
|
|
39
|
-
* active (see `Buttons/chips/chips.ts` for the full rationale on why CVA
|
|
40
|
-
* is used instead of reusing a native event name as an Angular output).
|
|
41
|
-
*
|
|
42
|
-
* For plain (non-forms) two-way use, bind explicitly instead:
|
|
43
|
-
* `[checked]="c" (ksCheckedChange)="c = $event"` or
|
|
44
|
-
* `[selected]="s" (ksSelectedChange)="s = $event"`.
|
|
45
|
-
*
|
|
46
|
-
* `template: ''` — no `<slot>` in the wrapped Stencil render.
|
|
47
|
-
*/
|
|
48
|
-
@Component({
|
|
49
|
-
selector: 'ks-checkbox',
|
|
50
|
-
standalone: true,
|
|
51
|
-
template: '',
|
|
52
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
53
|
-
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: KsCheckboxComponent, multi: true }],
|
|
54
|
-
})
|
|
55
|
-
export class KsCheckboxComponent implements ControlValueAccessor {
|
|
56
|
-
private readonly el: KsCheckboxElement;
|
|
57
|
-
private onChange: (value: unknown) => void = () => {};
|
|
58
|
-
private onTouched: () => void = () => {};
|
|
59
|
-
|
|
60
|
-
/** Label shown next to the control (single mode) */
|
|
61
|
-
readonly label = input('');
|
|
62
|
-
|
|
63
|
-
/** Optional set of multiple options (multi-select / group mode) */
|
|
64
|
-
readonly options = input<KsCheckboxOption[]>([]);
|
|
65
|
-
|
|
66
|
-
/** Disabled state */
|
|
67
|
-
readonly disabled = input(false);
|
|
68
|
-
|
|
69
|
-
/** Single mode: initial/controlled checked value. Prefer `[(ngModel)]` / `formControlName`. */
|
|
70
|
-
readonly checked = input(false);
|
|
71
|
-
|
|
72
|
-
/** Group mode: initial/controlled selected values. Prefer `[(ngModel)]` / `formControlName`. */
|
|
73
|
-
readonly selected = input<string[]>([]);
|
|
74
|
-
|
|
75
|
-
/** Emits whenever `checked` changes (single mode). From the native `checkedChange` event. */
|
|
76
|
-
readonly ksCheckedChange = output<boolean>();
|
|
77
|
-
|
|
78
|
-
/** Emits whenever `selected` changes (group mode). From the native `selectedChange` event. */
|
|
79
|
-
readonly ksSelectedChange = output<string[]>();
|
|
80
|
-
|
|
81
|
-
constructor(ref: ElementRef<KsCheckboxElement>) {
|
|
82
|
-
this.el = ref.nativeElement;
|
|
83
|
-
|
|
84
|
-
effect(() => (this.el.label = this.label()));
|
|
85
|
-
effect(() => (this.el.options = this.options()));
|
|
86
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
87
|
-
effect(() => (this.el.checked = this.checked()));
|
|
88
|
-
effect(() => (this.el.selected = this.selected()));
|
|
89
|
-
|
|
90
|
-
const onNativeCheckedChange = (event: Event): void => {
|
|
91
|
-
const detail = (event as CustomEvent<boolean>).detail;
|
|
92
|
-
this.ksCheckedChange.emit(detail);
|
|
93
|
-
this.onChange(detail);
|
|
94
|
-
this.onTouched();
|
|
95
|
-
};
|
|
96
|
-
const onNativeSelectedChange = (event: Event): void => {
|
|
97
|
-
const detail = (event as CustomEvent<string[]>).detail;
|
|
98
|
-
this.ksSelectedChange.emit(detail);
|
|
99
|
-
this.onChange(detail);
|
|
100
|
-
this.onTouched();
|
|
101
|
-
};
|
|
102
|
-
this.el.addEventListener('checkedChange', onNativeCheckedChange);
|
|
103
|
-
this.el.addEventListener('selectedChange', onNativeSelectedChange);
|
|
104
|
-
inject(DestroyRef).onDestroy(() => {
|
|
105
|
-
this.el.removeEventListener('checkedChange', onNativeCheckedChange);
|
|
106
|
-
this.el.removeEventListener('selectedChange', onNativeSelectedChange);
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** `ControlValueAccessor` — called by `ngModel`/`formControl` to push a value in (either mode). */
|
|
111
|
-
writeValue(value: unknown): void {
|
|
112
|
-
void this.el.writeValue(value);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
registerOnChange(fn: (value: unknown) => void): void {
|
|
116
|
-
this.onChange = fn;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
registerOnTouched(fn: () => void): void {
|
|
120
|
-
this.onTouched = fn;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
setDisabledState(isDisabled: boolean): void {
|
|
124
|
-
this.el.disabled = isDisabled;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-colour-picker` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-colour-picker.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
|
|
8
|
-
/** Mirrors the inline union used by `core/src/components/Inputs/colour-picker/colour-picker.tsx`. */
|
|
9
|
-
export type KsColourPickerVariant = 'input' | 'swatch';
|
|
10
|
-
|
|
11
|
-
const DEFAULT_SWATCHES = ['#ef4444', '#f97316', '#eab308', '#22c55e', '#3b82f6', '#8b5cf6', '#ec4899', '#64748b', '#000000', '#ffffff'];
|
|
12
|
-
|
|
13
|
-
/** DOM shape of the real `<ks-colour-picker>` custom element, typed for the wrapper. */
|
|
14
|
-
type KsColourPickerElement = HTMLElement & {
|
|
15
|
-
label: string;
|
|
16
|
-
variant: KsColourPickerVariant;
|
|
17
|
-
swatches: string[];
|
|
18
|
-
disabled: boolean;
|
|
19
|
-
value: string;
|
|
20
|
-
writeValue(val: string): Promise<void>;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Angular wrapper around the `<ks-colour-picker>` Stencil custom element.
|
|
25
|
-
*
|
|
26
|
-
* Two-way binding is via `ControlValueAccessor` — use `[(ngModel)]` or
|
|
27
|
-
* `formControlName`. See `Buttons/chips/chips.ts` for the full rationale
|
|
28
|
-
* (the native `valueChange` event can't be reused verbatim as an Angular
|
|
29
|
-
* output name without a double-fire risk).
|
|
30
|
-
*
|
|
31
|
-
* For plain (non-forms) two-way use, bind explicitly instead:
|
|
32
|
-
* `[value]="hex" (ksValueChange)="hex = $event"`.
|
|
33
|
-
*
|
|
34
|
-
* `template: ''` — the panel is rendered into the internal
|
|
35
|
-
* `<ks-overlay-field>`; there is no slot on `<ks-colour-picker>` itself.
|
|
36
|
-
*/
|
|
37
|
-
@Component({
|
|
38
|
-
selector: 'ks-colour-picker',
|
|
39
|
-
standalone: true,
|
|
40
|
-
template: '',
|
|
41
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
42
|
-
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: KsColourPickerComponent, multi: true }],
|
|
43
|
-
})
|
|
44
|
-
export class KsColourPickerComponent implements ControlValueAccessor {
|
|
45
|
-
private readonly el: KsColourPickerElement;
|
|
46
|
-
private onChange: (value: string) => void = () => {};
|
|
47
|
-
private onTouched: () => void = () => {};
|
|
48
|
-
|
|
49
|
-
/** Field label */
|
|
50
|
-
readonly label = input('');
|
|
51
|
-
|
|
52
|
-
/** Picker UI variant */
|
|
53
|
-
readonly variant = input<KsColourPickerVariant>('input');
|
|
54
|
-
|
|
55
|
-
/** Preset swatch colours */
|
|
56
|
-
readonly swatches = input<string[]>(DEFAULT_SWATCHES);
|
|
57
|
-
|
|
58
|
-
/** Disabled */
|
|
59
|
-
readonly disabled = input(false);
|
|
60
|
-
|
|
61
|
-
/** Initial/controlled hex value. Prefer `[(ngModel)]` / `formControlName`. */
|
|
62
|
-
readonly value = input('#3b82f6');
|
|
63
|
-
|
|
64
|
-
/** Emits the newly-picked hex colour. From the native `valueChange` event. */
|
|
65
|
-
readonly ksValueChange = output<string>();
|
|
66
|
-
|
|
67
|
-
constructor(ref: ElementRef<KsColourPickerElement>) {
|
|
68
|
-
this.el = ref.nativeElement;
|
|
69
|
-
|
|
70
|
-
effect(() => (this.el.label = this.label()));
|
|
71
|
-
effect(() => (this.el.variant = this.variant()));
|
|
72
|
-
effect(() => (this.el.swatches = this.swatches()));
|
|
73
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
74
|
-
effect(() => void this.el.writeValue(this.value()));
|
|
75
|
-
|
|
76
|
-
const onNativeValueChange = (event: Event): void => {
|
|
77
|
-
const detail = (event as CustomEvent<string>).detail;
|
|
78
|
-
this.ksValueChange.emit(detail);
|
|
79
|
-
this.onChange(detail);
|
|
80
|
-
this.onTouched();
|
|
81
|
-
};
|
|
82
|
-
this.el.addEventListener('valueChange', onNativeValueChange);
|
|
83
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('valueChange', onNativeValueChange));
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
writeValue(value: string): void {
|
|
87
|
-
void this.el.writeValue(value ?? '#3b82f6');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
registerOnChange(fn: (value: string) => void): void {
|
|
91
|
-
this.onChange = fn;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
registerOnTouched(fn: () => void): void {
|
|
95
|
-
this.onTouched = fn;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
setDisabledState(isDisabled: boolean): void {
|
|
99
|
-
this.el.disabled = isDisabled;
|
|
100
|
-
}
|
|
101
|
-
}
|