@kraft.stitch/angular 0.0.1 → 0.0.2
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/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,129 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-textarea` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-textarea.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
|
-
/** DOM shape of the real `<ks-textarea>` custom element, typed for the wrapper. */
|
|
9
|
-
type KsTextareaElement = HTMLElement & {
|
|
10
|
-
label: string;
|
|
11
|
-
placeholder: string;
|
|
12
|
-
rows: number;
|
|
13
|
-
maxLength: number;
|
|
14
|
-
showCounter: boolean;
|
|
15
|
-
autoResize: boolean;
|
|
16
|
-
disabled: boolean;
|
|
17
|
-
error: string;
|
|
18
|
-
hint: string;
|
|
19
|
-
value: string;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Angular wrapper around the `<ks-textarea>` Stencil custom element.
|
|
24
|
-
*
|
|
25
|
-
* Two-way binding is via `ControlValueAccessor` (see `Inputs/input/input.ts`
|
|
26
|
-
* for the equivalent no-`writeValue()`-method pattern this follows —
|
|
27
|
-
* `writeValue` here sets `el.value` directly). The native `ksBlur` event
|
|
28
|
-
* is re-exposed as `ksBlurred` for the same reason.
|
|
29
|
-
*
|
|
30
|
-
* For plain (non-forms) two-way use, bind explicitly instead:
|
|
31
|
-
* `[value]="v" (ksValueChange)="v = $event"`.
|
|
32
|
-
*
|
|
33
|
-
* `template: ''` — no `<slot>` in the wrapped Stencil render.
|
|
34
|
-
*/
|
|
35
|
-
@Component({
|
|
36
|
-
selector: 'ks-textarea',
|
|
37
|
-
standalone: true,
|
|
38
|
-
template: '',
|
|
39
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
40
|
-
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: KsTextareaComponent, multi: true }],
|
|
41
|
-
})
|
|
42
|
-
export class KsTextareaComponent implements ControlValueAccessor {
|
|
43
|
-
private readonly el: KsTextareaElement;
|
|
44
|
-
private onChange: (value: string) => void = () => {};
|
|
45
|
-
private onTouched: () => void = () => {};
|
|
46
|
-
|
|
47
|
-
/** Textarea label */
|
|
48
|
-
readonly label = input('');
|
|
49
|
-
|
|
50
|
-
/** Placeholder text */
|
|
51
|
-
readonly placeholder = input('');
|
|
52
|
-
|
|
53
|
-
/** Number of visible rows */
|
|
54
|
-
readonly rows = input(3);
|
|
55
|
-
|
|
56
|
-
/** Maximum character count */
|
|
57
|
-
readonly maxLength = input(500);
|
|
58
|
-
|
|
59
|
-
/** Show character counter */
|
|
60
|
-
readonly showCounter = input(false);
|
|
61
|
-
|
|
62
|
-
/** Auto-resize based on content */
|
|
63
|
-
readonly autoResize = input(false);
|
|
64
|
-
|
|
65
|
-
/** Disabled state */
|
|
66
|
-
readonly disabled = input(false);
|
|
67
|
-
|
|
68
|
-
/** Error state */
|
|
69
|
-
readonly error = input('');
|
|
70
|
-
|
|
71
|
-
/** Helper/error text */
|
|
72
|
-
readonly hint = input('');
|
|
73
|
-
|
|
74
|
-
/** Initial/controlled value. Prefer `[(ngModel)]` / `formControlName`. */
|
|
75
|
-
readonly value = input('');
|
|
76
|
-
|
|
77
|
-
/** Emits the newly-typed value. From the native `valueChange` event. */
|
|
78
|
-
readonly ksValueChange = output<string>();
|
|
79
|
-
|
|
80
|
-
/** Emitted on native blur. From the native `ksBlur` event. */
|
|
81
|
-
readonly ksBlurred = output<void>();
|
|
82
|
-
|
|
83
|
-
constructor(ref: ElementRef<KsTextareaElement>) {
|
|
84
|
-
this.el = ref.nativeElement;
|
|
85
|
-
|
|
86
|
-
effect(() => (this.el.label = this.label()));
|
|
87
|
-
effect(() => (this.el.placeholder = this.placeholder()));
|
|
88
|
-
effect(() => (this.el.rows = this.rows()));
|
|
89
|
-
effect(() => (this.el.maxLength = this.maxLength()));
|
|
90
|
-
effect(() => (this.el.showCounter = this.showCounter()));
|
|
91
|
-
effect(() => (this.el.autoResize = this.autoResize()));
|
|
92
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
93
|
-
effect(() => (this.el.error = this.error()));
|
|
94
|
-
effect(() => (this.el.hint = this.hint()));
|
|
95
|
-
effect(() => (this.el.value = this.value()));
|
|
96
|
-
|
|
97
|
-
const onNativeValueChange = (event: Event): void => {
|
|
98
|
-
const detail = (event as CustomEvent<string>).detail;
|
|
99
|
-
this.ksValueChange.emit(detail);
|
|
100
|
-
this.onChange(detail);
|
|
101
|
-
};
|
|
102
|
-
const onNativeBlur = (): void => {
|
|
103
|
-
this.ksBlurred.emit();
|
|
104
|
-
this.onTouched();
|
|
105
|
-
};
|
|
106
|
-
this.el.addEventListener('valueChange', onNativeValueChange);
|
|
107
|
-
this.el.addEventListener('ksBlur', onNativeBlur);
|
|
108
|
-
inject(DestroyRef).onDestroy(() => {
|
|
109
|
-
this.el.removeEventListener('valueChange', onNativeValueChange);
|
|
110
|
-
this.el.removeEventListener('ksBlur', onNativeBlur);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
writeValue(value: string): void {
|
|
115
|
-
this.el.value = value ?? '';
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
registerOnChange(fn: (value: string) => void): void {
|
|
119
|
-
this.onChange = fn;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
registerOnTouched(fn: () => void): void {
|
|
123
|
-
this.onTouched = fn;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
setDisabledState(isDisabled: boolean): void {
|
|
127
|
-
this.el.disabled = isDisabled;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-theme-switch` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-theme-switch.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
-
import { ThemeMode } from '@kraft.stitch/core';
|
|
7
|
-
import type { Palette } from '@kraft.stitch/core';
|
|
8
|
-
|
|
9
|
-
/** DOM shape of the real `<ks-theme-switch>` custom element, typed for the wrapper. */
|
|
10
|
-
type KsThemeSwitchElement = HTMLElement & {
|
|
11
|
-
includeSystem: boolean;
|
|
12
|
-
includePalette: boolean;
|
|
13
|
-
onlyIcon: boolean;
|
|
14
|
-
palette: Palette;
|
|
15
|
-
mode: ThemeMode;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Angular wrapper around the `<ks-theme-switch>` Stencil custom element.
|
|
20
|
-
*
|
|
21
|
-
* Purely presentational — it drives the shared `themeService` singleton
|
|
22
|
-
* (see `core/src/utils/ks-theme.util.ts`) directly and dispatches no
|
|
23
|
-
* events of its own, so this wrapper has plain inputs only, no outputs
|
|
24
|
-
* and no `ControlValueAccessor`.
|
|
25
|
-
*
|
|
26
|
-
* `template: ''` — no `<slot>` in the wrapped Stencil render.
|
|
27
|
-
*/
|
|
28
|
-
@Component({
|
|
29
|
-
selector: 'ks-theme-switch',
|
|
30
|
-
standalone: true,
|
|
31
|
-
template: '',
|
|
32
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
33
|
-
})
|
|
34
|
-
export class KsThemeSwitchComponent {
|
|
35
|
-
private readonly el: KsThemeSwitchElement;
|
|
36
|
-
|
|
37
|
-
/** When true the mode-toggle shows three options: System | Light | Dark. */
|
|
38
|
-
readonly includeSystem = input(true);
|
|
39
|
-
|
|
40
|
-
/** When true the colour-palette switcher is shown. */
|
|
41
|
-
readonly includePalette = input(false);
|
|
42
|
-
|
|
43
|
-
/** When true only icons are shown in the mode-toggle switch. */
|
|
44
|
-
readonly onlyIcon = input(false);
|
|
45
|
-
|
|
46
|
-
/** The palette that should be active on init. */
|
|
47
|
-
readonly palette = input<Palette>('ForestGreen');
|
|
48
|
-
|
|
49
|
-
/** The mode that should be active on init. */
|
|
50
|
-
readonly mode = input<ThemeMode>(ThemeMode.Light);
|
|
51
|
-
|
|
52
|
-
constructor(ref: ElementRef<KsThemeSwitchElement>) {
|
|
53
|
-
this.el = ref.nativeElement;
|
|
54
|
-
|
|
55
|
-
effect(() => (this.el.includeSystem = this.includeSystem()));
|
|
56
|
-
effect(() => (this.el.includePalette = this.includePalette()));
|
|
57
|
-
effect(() => (this.el.onlyIcon = this.onlyIcon()));
|
|
58
|
-
effect(() => (this.el.palette = this.palette()));
|
|
59
|
-
effect(() => (this.el.mode = this.mode()));
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-uploader` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-uploader.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Mirrors `KsUploadedFile` exported by
|
|
9
|
-
* `core/src/components/Inputs/uploader/uploader.tsx`. Duplicated locally
|
|
10
|
-
* — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
-
*/
|
|
12
|
-
export interface KsUploadedFile {
|
|
13
|
-
file: File;
|
|
14
|
-
name: string;
|
|
15
|
-
size: number;
|
|
16
|
-
type: string;
|
|
17
|
-
/** Data-URL preview (images only, when previewImages is true) */
|
|
18
|
-
preview?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** DOM shape of the real `<ks-uploader>` custom element, typed for the wrapper. */
|
|
22
|
-
type KsUploaderElement = HTMLElement & {
|
|
23
|
-
accept: string;
|
|
24
|
-
multiple: boolean;
|
|
25
|
-
maxSize: number;
|
|
26
|
-
previewImages: boolean;
|
|
27
|
-
label: string;
|
|
28
|
-
disabled: boolean;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Angular wrapper around the `<ks-uploader>` Stencil custom element.
|
|
33
|
-
*
|
|
34
|
-
* No two-way "value" here — the Stencil source has no `writeValue()`
|
|
35
|
-
* method and no single controlled prop, just a plain `filesChange`/
|
|
36
|
-
* `filesRejected` event pair, so no `ControlValueAccessor` is implemented
|
|
37
|
-
* (unlike the other `Inputs/*` wrappers).
|
|
38
|
-
*
|
|
39
|
-
* `template: ''` — no `<slot>` in the wrapped Stencil render.
|
|
40
|
-
*/
|
|
41
|
-
@Component({
|
|
42
|
-
selector: 'ks-uploader',
|
|
43
|
-
standalone: true,
|
|
44
|
-
template: '',
|
|
45
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
46
|
-
})
|
|
47
|
-
export class KsUploaderComponent {
|
|
48
|
-
private readonly el: KsUploaderElement;
|
|
49
|
-
|
|
50
|
-
/** Accepted MIME types / extensions, e.g. "image/*,.pdf" */
|
|
51
|
-
readonly accept = input('');
|
|
52
|
-
|
|
53
|
-
/** Allow selecting multiple files */
|
|
54
|
-
readonly multiple = input(false);
|
|
55
|
-
|
|
56
|
-
/** Maximum file size in bytes (0 = no limit) */
|
|
57
|
-
readonly maxSize = input(0);
|
|
58
|
-
|
|
59
|
-
/** Show image thumbnails for image/* files */
|
|
60
|
-
readonly previewImages = input(true);
|
|
61
|
-
|
|
62
|
-
/** Custom drop-zone label */
|
|
63
|
-
readonly label = input('or Drop files here');
|
|
64
|
-
|
|
65
|
-
/** Disabled state */
|
|
66
|
-
readonly disabled = input(false);
|
|
67
|
-
|
|
68
|
-
/** Emits the accepted files whenever the selection changes. From the native `filesChange` event. */
|
|
69
|
-
readonly ksFilesChange = output<KsUploadedFile[]>();
|
|
70
|
-
|
|
71
|
-
/** Emits rejected files (wrong type / over size limit). From the native `filesRejected` event. */
|
|
72
|
-
readonly ksFilesRejected = output<File[]>();
|
|
73
|
-
|
|
74
|
-
constructor(ref: ElementRef<KsUploaderElement>) {
|
|
75
|
-
this.el = ref.nativeElement;
|
|
76
|
-
|
|
77
|
-
effect(() => (this.el.accept = this.accept()));
|
|
78
|
-
effect(() => (this.el.multiple = this.multiple()));
|
|
79
|
-
effect(() => (this.el.maxSize = this.maxSize()));
|
|
80
|
-
effect(() => (this.el.previewImages = this.previewImages()));
|
|
81
|
-
effect(() => (this.el.label = this.label()));
|
|
82
|
-
effect(() => (this.el.disabled = this.disabled()));
|
|
83
|
-
|
|
84
|
-
const onNativeFilesChange = (event: Event): void => {
|
|
85
|
-
this.ksFilesChange.emit((event as CustomEvent<KsUploadedFile[]>).detail);
|
|
86
|
-
};
|
|
87
|
-
const onNativeFilesRejected = (event: Event): void => {
|
|
88
|
-
this.ksFilesRejected.emit((event as CustomEvent<File[]>).detail);
|
|
89
|
-
};
|
|
90
|
-
this.el.addEventListener('filesChange', onNativeFilesChange);
|
|
91
|
-
this.el.addEventListener('filesRejected', onNativeFilesRejected);
|
|
92
|
-
inject(DestroyRef).onDestroy(() => {
|
|
93
|
-
this.el.removeEventListener('filesChange', onNativeFilesChange);
|
|
94
|
-
this.el.removeEventListener('filesRejected', onNativeFilesRejected);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-avatar` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-avatar.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
-
import type { KsBaseVariant, KsSize } from '@kraft.stitch/core';
|
|
7
|
-
|
|
8
|
-
/** DOM shape of the real `<ks-avatar>` custom element, typed for the wrapper. */
|
|
9
|
-
type KsAvatarElement = HTMLElement & {
|
|
10
|
-
src: string;
|
|
11
|
-
alt: string;
|
|
12
|
-
initials: string;
|
|
13
|
-
icon: string;
|
|
14
|
-
size: KsSize;
|
|
15
|
-
variant: KsBaseVariant;
|
|
16
|
-
square: boolean;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Angular wrapper around the `<ks-avatar>` Stencil custom element.
|
|
21
|
-
*
|
|
22
|
-
* Purely presentational — no events, no `<slot>` in the wrapped Stencil
|
|
23
|
-
* render, plain inputs only (same shape as `Inputs/theme-switch/theme-switch.ts`).
|
|
24
|
-
*/
|
|
25
|
-
@Component({
|
|
26
|
-
selector: 'ks-avatar',
|
|
27
|
-
standalone: true,
|
|
28
|
-
template: '',
|
|
29
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
30
|
-
})
|
|
31
|
-
export class KsAvatarComponent {
|
|
32
|
-
private readonly el: KsAvatarElement;
|
|
33
|
-
|
|
34
|
-
/** Image URL — takes priority over initials */
|
|
35
|
-
readonly src = input('');
|
|
36
|
-
|
|
37
|
-
/** Alt text for the image */
|
|
38
|
-
readonly alt = input('');
|
|
39
|
-
|
|
40
|
-
/** Initials shown when no image (e.g. "KS") */
|
|
41
|
-
readonly initials = input('');
|
|
42
|
-
|
|
43
|
-
/** Icon class shown when neither src nor initials */
|
|
44
|
-
readonly icon = input('');
|
|
45
|
-
|
|
46
|
-
/** Size */
|
|
47
|
-
readonly size = input<KsSize>('md');
|
|
48
|
-
|
|
49
|
-
/** Colour variant — used when showing initials or icon */
|
|
50
|
-
readonly variant = input<KsBaseVariant>('brand');
|
|
51
|
-
|
|
52
|
-
/** Circular (default) or rounded-square */
|
|
53
|
-
readonly square = input(false);
|
|
54
|
-
|
|
55
|
-
constructor(ref: ElementRef<KsAvatarElement>) {
|
|
56
|
-
this.el = ref.nativeElement;
|
|
57
|
-
|
|
58
|
-
effect(() => (this.el.src = this.src()));
|
|
59
|
-
effect(() => (this.el.alt = this.alt()));
|
|
60
|
-
effect(() => (this.el.initials = this.initials()));
|
|
61
|
-
effect(() => (this.el.icon = this.icon()));
|
|
62
|
-
effect(() => (this.el.size = this.size()));
|
|
63
|
-
effect(() => (this.el.variant = this.variant()));
|
|
64
|
-
effect(() => (this.el.square = this.square()));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-card` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-card.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
|
|
7
|
-
/** Mirrors the inline union used by `core/src/components/Layout/card/card.tsx`. */
|
|
8
|
-
export type KsCardVariant = 'default' | 'outlined' | 'elevated' | 'flat';
|
|
9
|
-
|
|
10
|
-
/** DOM shape of the real `<ks-card>` custom element, typed for the wrapper. */
|
|
11
|
-
type KsCardElement = HTMLElement & {
|
|
12
|
-
label: string;
|
|
13
|
-
cardTitle: string;
|
|
14
|
-
subtitle: string;
|
|
15
|
-
imageUrl: string;
|
|
16
|
-
imageAlt: string;
|
|
17
|
-
iconClass: string;
|
|
18
|
-
variant: KsCardVariant;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Angular wrapper around the `<ks-card>` Stencil custom element.
|
|
23
|
-
*
|
|
24
|
-
* ## Slots
|
|
25
|
-
* Unlike the Buttons/Calendars/Dropdowns wrappers, `<ks-card>` renders
|
|
26
|
-
* real, consumer-facing `<slot name="header" />`, `<slot />` (default) and
|
|
27
|
-
* `<slot name="footer" />` in its scoped (non-shadow) Stencil `render()`.
|
|
28
|
-
* `template: '<ng-content></ng-content>'` (a single unfiltered pass-through,
|
|
29
|
-
* not per-slot `<ng-content select="...">`) projects ALL of this Angular
|
|
30
|
-
* component's content as real light-DOM children of the `<ks-card>` host
|
|
31
|
-
* node; Stencil's own scoped-slot relocation logic (see `shadow: false,
|
|
32
|
-
* scoped: true` on the Stencil class) then places each child into the
|
|
33
|
-
* right native `<slot>` based on that child's own `slot="header"` /
|
|
34
|
-
* `slot="footer"` attribute — same as plain HTML, nothing Angular-specific
|
|
35
|
-
* needed beyond forwarding the projected content through untouched.
|
|
36
|
-
* Usage: `<ks-card><ks-header slot="header">…</ks-header>Body<ks-footer slot="footer">…</ks-footer></ks-card>`.
|
|
37
|
-
*/
|
|
38
|
-
@Component({
|
|
39
|
-
selector: 'ks-card',
|
|
40
|
-
standalone: true,
|
|
41
|
-
template: '<ng-content></ng-content>',
|
|
42
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
43
|
-
})
|
|
44
|
-
export class KsCardComponent {
|
|
45
|
-
private readonly el: KsCardElement;
|
|
46
|
-
|
|
47
|
-
/** Card title */
|
|
48
|
-
readonly label = input('');
|
|
49
|
-
|
|
50
|
-
/** Card title (Angular input name was `title`; aliased to avoid clashing with the native `title` attribute/tooltip). */
|
|
51
|
-
readonly cardTitle = input('');
|
|
52
|
-
|
|
53
|
-
/** Subtitle / subheading */
|
|
54
|
-
readonly subtitle = input('');
|
|
55
|
-
|
|
56
|
-
/** URL for header image */
|
|
57
|
-
readonly imageUrl = input('');
|
|
58
|
-
|
|
59
|
-
/** Alt text for image */
|
|
60
|
-
readonly imageAlt = input('');
|
|
61
|
-
|
|
62
|
-
/** SVG icon class */
|
|
63
|
-
readonly iconClass = input('');
|
|
64
|
-
|
|
65
|
-
/** Card visual variant */
|
|
66
|
-
readonly variant = input<KsCardVariant>('default');
|
|
67
|
-
|
|
68
|
-
/** Emits when clicked (only when clickable). From the native `cardClick` event. */
|
|
69
|
-
readonly ksCardClick = output<MouseEvent>();
|
|
70
|
-
|
|
71
|
-
constructor(ref: ElementRef<KsCardElement>) {
|
|
72
|
-
this.el = ref.nativeElement;
|
|
73
|
-
|
|
74
|
-
effect(() => (this.el.label = this.label()));
|
|
75
|
-
effect(() => (this.el.cardTitle = this.cardTitle()));
|
|
76
|
-
effect(() => (this.el.subtitle = this.subtitle()));
|
|
77
|
-
effect(() => (this.el.imageUrl = this.imageUrl()));
|
|
78
|
-
effect(() => (this.el.imageAlt = this.imageAlt()));
|
|
79
|
-
effect(() => (this.el.iconClass = this.iconClass()));
|
|
80
|
-
effect(() => (this.el.variant = this.variant()));
|
|
81
|
-
|
|
82
|
-
const onNativeCardClick = (event: Event): void => {
|
|
83
|
-
this.ksCardClick.emit((event as CustomEvent<MouseEvent>).detail);
|
|
84
|
-
};
|
|
85
|
-
this.el.addEventListener('cardClick', onNativeCardClick);
|
|
86
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('cardClick', onNativeCardClick));
|
|
87
|
-
}
|
|
88
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-code-view` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-code-view.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
-
|
|
7
|
-
/** Mirrors the inline union used by `core/src/components/Layout/code-view/code-view.tsx`. */
|
|
8
|
-
export type KsCodeViewLanguage = 'html' | 'css' | 'typescript' | 'javascript' | 'json' | 'bash' | 'text';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Mirrors `ActionButtonsConfig` exported by
|
|
12
|
-
* `core/src/components/Layout/code-view/code-view.tsx`. Duplicated
|
|
13
|
-
* locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
14
|
-
*/
|
|
15
|
-
export interface ActionButtonsConfig {
|
|
16
|
-
expand?: boolean;
|
|
17
|
-
code?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** DOM shape of the real `<ks-code-view>` custom element, typed for the wrapper. */
|
|
21
|
-
type KsCodeViewElement = HTMLElement & {
|
|
22
|
-
code: string;
|
|
23
|
-
language: KsCodeViewLanguage;
|
|
24
|
-
label: string;
|
|
25
|
-
maxHeight: string;
|
|
26
|
-
showHeader: boolean;
|
|
27
|
-
collapsed: boolean;
|
|
28
|
-
actionButtonConfig: ActionButtonsConfig;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Angular wrapper around the `<ks-code-view>` Stencil custom element.
|
|
33
|
-
* Purely presentational — no events, no `<slot>` in the wrapped Stencil
|
|
34
|
-
* render, plain inputs only.
|
|
35
|
-
*/
|
|
36
|
-
@Component({
|
|
37
|
-
selector: 'ks-code-view',
|
|
38
|
-
standalone: true,
|
|
39
|
-
template: '',
|
|
40
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
41
|
-
})
|
|
42
|
-
export class KsCodeViewComponent {
|
|
43
|
-
private readonly el: KsCodeViewElement;
|
|
44
|
-
|
|
45
|
-
/** The source code string to display */
|
|
46
|
-
readonly code = input('');
|
|
47
|
-
|
|
48
|
-
/** Language hint shown in the header badge */
|
|
49
|
-
readonly language = input<KsCodeViewLanguage>('html');
|
|
50
|
-
|
|
51
|
-
/** Optional title shown in the header */
|
|
52
|
-
readonly label = input('');
|
|
53
|
-
|
|
54
|
-
/** Max visible height before scroll kicks in (CSS value, e.g. '20rem') */
|
|
55
|
-
readonly maxHeight = input('24rem');
|
|
56
|
-
|
|
57
|
-
/** Show the header bar with language badge & copy button */
|
|
58
|
-
readonly showHeader = input(true);
|
|
59
|
-
|
|
60
|
-
/** Whether the code block is currently collapsed */
|
|
61
|
-
readonly collapsed = input(false);
|
|
62
|
-
|
|
63
|
-
/** Whether the code block is to show and hide buttons */
|
|
64
|
-
readonly actionButtonConfig = input<ActionButtonsConfig>({ expand: true, code: true });
|
|
65
|
-
|
|
66
|
-
constructor(ref: ElementRef<KsCodeViewElement>) {
|
|
67
|
-
this.el = ref.nativeElement;
|
|
68
|
-
|
|
69
|
-
effect(() => (this.el.code = this.code()));
|
|
70
|
-
effect(() => (this.el.language = this.language()));
|
|
71
|
-
effect(() => (this.el.label = this.label()));
|
|
72
|
-
effect(() => (this.el.maxHeight = this.maxHeight()));
|
|
73
|
-
effect(() => (this.el.showHeader = this.showHeader()));
|
|
74
|
-
effect(() => (this.el.collapsed = this.collapsed()));
|
|
75
|
-
effect(() => (this.el.actionButtonConfig = this.actionButtonConfig()));
|
|
76
|
-
}
|
|
77
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-dialog` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-dialog.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
|
|
7
|
-
/** Mirrors the inline union used by `core/src/components/Layout/dialog/dialog.tsx`. */
|
|
8
|
-
export type KsDialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
9
|
-
|
|
10
|
-
/** DOM shape of the real `<ks-dialog>` custom element, typed for the wrapper. */
|
|
11
|
-
type KsDialogElement = HTMLElement & {
|
|
12
|
-
open: boolean;
|
|
13
|
-
label: string;
|
|
14
|
-
hideClose: boolean;
|
|
15
|
-
persistent: boolean;
|
|
16
|
-
size: KsDialogSize;
|
|
17
|
-
target: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Angular wrapper around the `<ks-dialog>` Stencil custom element.
|
|
22
|
-
*
|
|
23
|
-
* `open` is a plain input, not `ControlValueAccessor` — a dialog's open
|
|
24
|
-
* state isn't form data. For the same reason described throughout this
|
|
25
|
-
* repo, the output can't be named `openChange` (it would collide with the
|
|
26
|
-
* native `openChange`-style close event — see below), so bind explicitly:
|
|
27
|
-
* `[open]="isOpen" (ksCloseDialog)="isOpen = false"`.
|
|
28
|
-
*
|
|
29
|
-
* ## Slots
|
|
30
|
-
* `<ks-dialog>` renders real, consumer-facing `<slot />` (default) and
|
|
31
|
-
* `<slot name="footer" />`. Same single unfiltered `<ng-content>`
|
|
32
|
-
* pass-through as `Layout/card/card.ts` — see that file's doc comment for
|
|
33
|
-
* the full explanation of how native `slot="footer"` attributes on
|
|
34
|
-
* projected children route into the right Stencil `<slot>`.
|
|
35
|
-
*/
|
|
36
|
-
@Component({
|
|
37
|
-
selector: 'ks-dialog',
|
|
38
|
-
standalone: true,
|
|
39
|
-
template: '<ng-content></ng-content>',
|
|
40
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
41
|
-
})
|
|
42
|
-
export class KsDialogComponent {
|
|
43
|
-
private readonly el: KsDialogElement;
|
|
44
|
-
|
|
45
|
-
/** Whether the dialog is open */
|
|
46
|
-
readonly open = input(false);
|
|
47
|
-
|
|
48
|
-
/** Dialog title */
|
|
49
|
-
readonly label = input('');
|
|
50
|
-
|
|
51
|
-
/** Hide the built-in close (✕) button */
|
|
52
|
-
readonly hideClose = input(false);
|
|
53
|
-
|
|
54
|
-
/** Prevent closing by clicking the backdrop */
|
|
55
|
-
readonly persistent = input(false);
|
|
56
|
-
|
|
57
|
-
/** Panel size */
|
|
58
|
-
readonly size = input<KsDialogSize>('md');
|
|
59
|
-
|
|
60
|
-
/** Target element id (without #), or '' to use `<body>`. When set, the overlay covers only that element and the dialog is centred inside it. */
|
|
61
|
-
readonly target = input('');
|
|
62
|
-
|
|
63
|
-
/** Emits when the dialog requests close. From the native `closeDialog` event. */
|
|
64
|
-
readonly ksCloseDialog = output<void>();
|
|
65
|
-
|
|
66
|
-
constructor(ref: ElementRef<KsDialogElement>) {
|
|
67
|
-
this.el = ref.nativeElement;
|
|
68
|
-
|
|
69
|
-
effect(() => (this.el.open = this.open()));
|
|
70
|
-
effect(() => (this.el.label = this.label()));
|
|
71
|
-
effect(() => (this.el.hideClose = this.hideClose()));
|
|
72
|
-
effect(() => (this.el.persistent = this.persistent()));
|
|
73
|
-
effect(() => (this.el.size = this.size()));
|
|
74
|
-
effect(() => (this.el.target = this.target()));
|
|
75
|
-
|
|
76
|
-
const onNativeCloseDialog = (): void => this.ksCloseDialog.emit();
|
|
77
|
-
this.el.addEventListener('closeDialog', onNativeCloseDialog);
|
|
78
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('closeDialog', onNativeCloseDialog));
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// Side-effect import: registers the `ks-not-found` tag — see
|
|
2
|
-
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
-
import '@kraft.stitch/core/dist/components/ks-not-found.js';
|
|
4
|
-
|
|
5
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
-
|
|
7
|
-
/** DOM shape of the real `<ks-not-found>` custom element, typed for the wrapper. */
|
|
8
|
-
type KsNotFoundElement = HTMLElement & {
|
|
9
|
-
buttonLabel: string;
|
|
10
|
-
homeHref: string;
|
|
11
|
-
countdown: number;
|
|
12
|
-
showActionButtons: boolean;
|
|
13
|
-
code: string;
|
|
14
|
-
message: string;
|
|
15
|
-
description: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Angular wrapper around the `<ks-not-found>` Stencil custom element.
|
|
20
|
-
*
|
|
21
|
-
* `<ks-not-found>` renders a real, consumer-facing default `<slot />`.
|
|
22
|
-
* Same single unfiltered `<ng-content>` pass-through as
|
|
23
|
-
* `Layout/card/card.ts` — see that file's doc comment for the full
|
|
24
|
-
* explanation of how projected content routes into the Stencil `<slot>`.
|
|
25
|
-
*/
|
|
26
|
-
@Component({
|
|
27
|
-
selector: 'ks-not-found',
|
|
28
|
-
standalone: true,
|
|
29
|
-
template: '<ng-content></ng-content>',
|
|
30
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
31
|
-
})
|
|
32
|
-
export class KsNotFoundComponent {
|
|
33
|
-
private readonly el: KsNotFoundElement;
|
|
34
|
-
|
|
35
|
-
/** Label shown on the redirect button (default: "Go to Home") */
|
|
36
|
-
readonly buttonLabel = input('Go to Home');
|
|
37
|
-
|
|
38
|
-
/** href the button and auto-redirect navigate to (default: "./") */
|
|
39
|
-
readonly homeHref = input('./');
|
|
40
|
-
|
|
41
|
-
/** Seconds before auto-redirect fires. Set to `0` to disable the countdown. */
|
|
42
|
-
readonly countdown = input(30);
|
|
43
|
-
|
|
44
|
-
readonly showActionButtons = input(true);
|
|
45
|
-
|
|
46
|
-
/** Custom heading (default: "404") */
|
|
47
|
-
readonly code = input('404');
|
|
48
|
-
|
|
49
|
-
/** Custom sub-heading (default: "Page not found") */
|
|
50
|
-
readonly message = input('Page not found');
|
|
51
|
-
|
|
52
|
-
/** Custom description below the heading */
|
|
53
|
-
readonly description = input("The page you're looking for doesn't exist or has been moved.");
|
|
54
|
-
|
|
55
|
-
/** Emitted just before the auto-redirect navigates away. From the native `redirecting` event. */
|
|
56
|
-
readonly ksRedirecting = output<void>();
|
|
57
|
-
|
|
58
|
-
constructor(ref: ElementRef<KsNotFoundElement>) {
|
|
59
|
-
this.el = ref.nativeElement;
|
|
60
|
-
|
|
61
|
-
effect(() => (this.el.buttonLabel = this.buttonLabel()));
|
|
62
|
-
effect(() => (this.el.homeHref = this.homeHref()));
|
|
63
|
-
effect(() => (this.el.countdown = this.countdown()));
|
|
64
|
-
effect(() => (this.el.showActionButtons = this.showActionButtons()));
|
|
65
|
-
effect(() => (this.el.code = this.code()));
|
|
66
|
-
effect(() => (this.el.message = this.message()));
|
|
67
|
-
effect(() => (this.el.description = this.description()));
|
|
68
|
-
|
|
69
|
-
const onNativeRedirecting = (): void => this.ksRedirecting.emit();
|
|
70
|
-
this.el.addEventListener('redirecting', onNativeRedirecting);
|
|
71
|
-
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('redirecting', onNativeRedirecting));
|
|
72
|
-
}
|
|
73
|
-
}
|