@kraft.stitch/angular 0.0.0-stage → 0.0.1
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/.github/workflows/npm-publish.yml +33 -0
- package/README.md +2 -3
- package/ng-package.json +10 -0
- package/package.json +27 -4
- package/src/lib/Buttons/button/button.ts +152 -0
- package/src/lib/Buttons/button-group/button-group.ts +129 -0
- package/src/lib/Buttons/chips/chips.ts +131 -0
- package/src/lib/Buttons/fab/fab.ts +96 -0
- package/src/lib/Calendars/datepicker/datepicker.ts +105 -0
- package/src/lib/Calendars/daterange/daterange.ts +112 -0
- package/src/lib/Calendars/timepicker/timepicker.ts +117 -0
- package/src/lib/Dropdowns/dropdown/dropdown.ts +121 -0
- package/src/lib/Dropdowns/listbox/listbox.ts +116 -0
- package/src/lib/Inputs/checkbox/checkbox.ts +126 -0
- package/src/lib/Inputs/colour-picker/colour-picker.ts +101 -0
- package/src/lib/Inputs/input/input.ts +139 -0
- package/src/lib/Inputs/otp-input/otp-input.ts +113 -0
- package/src/lib/Inputs/radio/radio.ts +115 -0
- package/src/lib/Inputs/rating/rating.ts +104 -0
- package/src/lib/Inputs/slider/slider.ts +121 -0
- package/src/lib/Inputs/switch/switch.ts +100 -0
- package/src/lib/Inputs/textarea/textarea.ts +129 -0
- package/src/lib/Inputs/theme-switch/theme-switch.ts +61 -0
- package/src/lib/Inputs/uploader/uploader.ts +97 -0
- package/src/lib/Layout/avatar/avatar.ts +66 -0
- package/src/lib/Layout/card/card.ts +88 -0
- package/src/lib/Layout/code-view/code-view.ts +77 -0
- package/src/lib/Layout/dialog/dialog.ts +80 -0
- package/src/lib/Layout/not-found/not-found.ts +73 -0
- package/src/lib/Layout/sidebar/sidebar.ts +97 -0
- package/src/lib/Layout/table/table.ts +81 -0
- package/src/lib/Layout/tooltip/tooltip.ts +48 -0
- package/src/lib/Navigation/accordion/accordion.ts +80 -0
- package/src/lib/Navigation/breadcrumb/breadcrumb.ts +58 -0
- package/src/lib/Navigation/carousel/carousel.ts +70 -0
- package/src/lib/Navigation/context-menu/context-menu.ts +79 -0
- package/src/lib/Navigation/nav-bar/nav-bar.ts +72 -0
- package/src/lib/Navigation/pagination/pagination.ts +82 -0
- package/src/lib/Navigation/stepper/stepper.ts +77 -0
- package/src/lib/Navigation/tab/tab.ts +71 -0
- package/src/lib/Navigation/toolbar/toolbar.ts +60 -0
- package/src/lib/Navigation/top-nav-bar/top-nav-bar.ts +71 -0
- package/src/lib/Navigation/tree-view/tree-view.ts +75 -0
- package/src/lib/Notification/badge/badge.ts +55 -0
- package/src/lib/Notification/loader/loader.ts +41 -0
- package/src/lib/Notification/message/message.ts +60 -0
- package/src/lib/Notification/progress/progress.ts +65 -0
- package/src/lib/Notification/spinner/spinner.ts +50 -0
- package/src/lib/Notification/toast/toast.ts +56 -0
- package/src/public-api.ts +62 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-breadcrumb` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-breadcrumb.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
+
import type { KsBaseSize } from '@kraft.stitch/core';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Mirrors `KsBreadcrumbItem` exported by
|
|
10
|
+
* `core/src/components/Navigation/breadcrumb/breadcrumb.tsx`. Duplicated
|
|
11
|
+
* locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
12
|
+
*/
|
|
13
|
+
export interface KsBreadcrumbItem {
|
|
14
|
+
label: string;
|
|
15
|
+
/** Route path or href — omit for the active (last) item */
|
|
16
|
+
href?: string;
|
|
17
|
+
/** Optional icon class */
|
|
18
|
+
icon?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** DOM shape of the real `<ks-breadcrumb>` custom element, typed for the wrapper. */
|
|
22
|
+
type KsBreadcrumbElement = HTMLElement & {
|
|
23
|
+
items: KsBreadcrumbItem[];
|
|
24
|
+
separator: string;
|
|
25
|
+
size: KsBaseSize;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Angular wrapper around the `<ks-breadcrumb>` Stencil custom element.
|
|
30
|
+
* Purely presentational — no events, no `<slot>` in the wrapped Stencil
|
|
31
|
+
* render, plain inputs only.
|
|
32
|
+
*/
|
|
33
|
+
@Component({
|
|
34
|
+
selector: 'ks-breadcrumb',
|
|
35
|
+
standalone: true,
|
|
36
|
+
template: '',
|
|
37
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
38
|
+
})
|
|
39
|
+
export class KsBreadcrumbComponent {
|
|
40
|
+
private readonly el: KsBreadcrumbElement;
|
|
41
|
+
|
|
42
|
+
/** Ordered list of breadcrumb items */
|
|
43
|
+
readonly items = input<KsBreadcrumbItem[]>([]);
|
|
44
|
+
|
|
45
|
+
/** Separator character or symbol */
|
|
46
|
+
readonly separator = input('/');
|
|
47
|
+
|
|
48
|
+
/** Size */
|
|
49
|
+
readonly size = input<KsBaseSize>('lg');
|
|
50
|
+
|
|
51
|
+
constructor(ref: ElementRef<KsBreadcrumbElement>) {
|
|
52
|
+
this.el = ref.nativeElement;
|
|
53
|
+
|
|
54
|
+
effect(() => (this.el.items = this.items()));
|
|
55
|
+
effect(() => (this.el.separator = this.separator()));
|
|
56
|
+
effect(() => (this.el.size = this.size()));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-carousel` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-carousel.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors `KsCarouselSlide` exported by
|
|
9
|
+
* `core/src/components/Navigation/carousel/carousel.tsx`. Duplicated
|
|
10
|
+
* locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
+
*/
|
|
12
|
+
export interface KsCarouselSlide {
|
|
13
|
+
key: string;
|
|
14
|
+
imageUrl?: string;
|
|
15
|
+
alt?: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
caption?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** DOM shape of the real `<ks-carousel>` custom element, typed for the wrapper. */
|
|
21
|
+
type KsCarouselElement = HTMLElement & {
|
|
22
|
+
slides: KsCarouselSlide[];
|
|
23
|
+
autoPlay: number;
|
|
24
|
+
showControls: boolean;
|
|
25
|
+
showDots: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Angular wrapper around the `<ks-carousel>` Stencil custom element.
|
|
30
|
+
* No `<slot>` in the wrapped Stencil render — data-driven only.
|
|
31
|
+
*/
|
|
32
|
+
@Component({
|
|
33
|
+
selector: 'ks-carousel',
|
|
34
|
+
standalone: true,
|
|
35
|
+
template: '',
|
|
36
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
37
|
+
})
|
|
38
|
+
export class KsCarouselComponent {
|
|
39
|
+
private readonly el: KsCarouselElement;
|
|
40
|
+
|
|
41
|
+
/** Slides to display */
|
|
42
|
+
readonly slides = input<KsCarouselSlide[]>([]);
|
|
43
|
+
|
|
44
|
+
/** Auto-play interval in ms (0 = disabled) */
|
|
45
|
+
readonly autoPlay = input(0);
|
|
46
|
+
|
|
47
|
+
/** Show prev/next arrow controls */
|
|
48
|
+
readonly showControls = input(true);
|
|
49
|
+
|
|
50
|
+
/** Show dot indicators */
|
|
51
|
+
readonly showDots = input(true);
|
|
52
|
+
|
|
53
|
+
/** Emits the current slide index on change. From the native `slideChange` event. */
|
|
54
|
+
readonly ksSlideChange = output<number>();
|
|
55
|
+
|
|
56
|
+
constructor(ref: ElementRef<KsCarouselElement>) {
|
|
57
|
+
this.el = ref.nativeElement;
|
|
58
|
+
|
|
59
|
+
effect(() => (this.el.slides = this.slides()));
|
|
60
|
+
effect(() => (this.el.autoPlay = this.autoPlay()));
|
|
61
|
+
effect(() => (this.el.showControls = this.showControls()));
|
|
62
|
+
effect(() => (this.el.showDots = this.showDots()));
|
|
63
|
+
|
|
64
|
+
const onNativeSlideChange = (event: Event): void => {
|
|
65
|
+
this.ksSlideChange.emit((event as CustomEvent<number>).detail);
|
|
66
|
+
};
|
|
67
|
+
this.el.addEventListener('slideChange', onNativeSlideChange);
|
|
68
|
+
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('slideChange', onNativeSlideChange));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-context-menu` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-context-menu.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors `KsContextMenuItem` / `KsContextMenuPosition` exported by
|
|
9
|
+
* `core/src/components/Navigation/context-menu/context-menu.tsx`.
|
|
10
|
+
* Duplicated locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
+
*/
|
|
12
|
+
export interface KsContextMenuItem {
|
|
13
|
+
key: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
icon?: string;
|
|
16
|
+
divider?: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
danger?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface KsContextMenuPosition {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** DOM shape of the real `<ks-context-menu>` custom element, typed for the wrapper. */
|
|
27
|
+
type KsContextMenuElement = HTMLElement & {
|
|
28
|
+
items: KsContextMenuItem[];
|
|
29
|
+
open(pos: KsContextMenuPosition): Promise<void>;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Angular wrapper around the `<ks-context-menu>` Stencil custom element.
|
|
35
|
+
*
|
|
36
|
+
* `<ks-context-menu>`'s own `@Method()`s (`open(pos)`/`close()`) are
|
|
37
|
+
* exposed here as real passthrough methods — grab the component instance
|
|
38
|
+
* with `@ViewChild(KsContextMenuComponent)` and call them directly, e.g.
|
|
39
|
+
* `onContextMenu(e: MouseEvent) { menu.open({ x: e.clientX, y: e.clientY }); }`.
|
|
40
|
+
*
|
|
41
|
+
* No `<slot>` in the wrapped Stencil render — data-driven only.
|
|
42
|
+
*/
|
|
43
|
+
@Component({
|
|
44
|
+
selector: 'ks-context-menu',
|
|
45
|
+
standalone: true,
|
|
46
|
+
template: '',
|
|
47
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
48
|
+
})
|
|
49
|
+
export class KsContextMenuComponent {
|
|
50
|
+
private readonly el: KsContextMenuElement;
|
|
51
|
+
|
|
52
|
+
/** Menu items */
|
|
53
|
+
readonly items = input<KsContextMenuItem[]>([]);
|
|
54
|
+
|
|
55
|
+
/** Emits the clicked item key. From the native `itemClicked` event. */
|
|
56
|
+
readonly ksItemClicked = output<string>();
|
|
57
|
+
|
|
58
|
+
constructor(ref: ElementRef<KsContextMenuElement>) {
|
|
59
|
+
this.el = ref.nativeElement;
|
|
60
|
+
|
|
61
|
+
effect(() => (this.el.items = this.items()));
|
|
62
|
+
|
|
63
|
+
const onNativeItemClicked = (event: Event): void => {
|
|
64
|
+
this.ksItemClicked.emit((event as CustomEvent<string>).detail);
|
|
65
|
+
};
|
|
66
|
+
this.el.addEventListener('itemClicked', onNativeItemClicked);
|
|
67
|
+
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('itemClicked', onNativeItemClicked));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Passthrough to `<ks-context-menu>`'s own `@Method() open(pos)`. */
|
|
71
|
+
open(pos: KsContextMenuPosition): Promise<void> {
|
|
72
|
+
return this.el.open(pos);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Passthrough to `<ks-context-menu>`'s own `@Method() close()`. */
|
|
76
|
+
close(): Promise<void> {
|
|
77
|
+
return this.el.close();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-nav-bar` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-nav-bar.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors the types exported by
|
|
9
|
+
* `core/src/components/Navigation/nav-bar/nav-bar.tsx`. Duplicated
|
|
10
|
+
* locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
+
*/
|
|
12
|
+
export interface KsNavBarItem {
|
|
13
|
+
key: string;
|
|
14
|
+
name: string;
|
|
15
|
+
iconClass: string;
|
|
16
|
+
/** href to navigate to */
|
|
17
|
+
redirectLink: string;
|
|
18
|
+
activationFragment?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type KsNavBarSection = 'top' | 'mid' | 'bottom';
|
|
23
|
+
|
|
24
|
+
export interface KsNavBarSectionItem extends KsNavBarItem {
|
|
25
|
+
section: KsNavBarSection;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type KsNavBarMode = 'iconOnly' | 'hoverToExpand' | 'alwaysOpen';
|
|
29
|
+
|
|
30
|
+
/** DOM shape of the real `<ks-nav-bar>` custom element, typed for the wrapper. */
|
|
31
|
+
type KsNavBarElement = HTMLElement & {
|
|
32
|
+
items: KsNavBarSectionItem[];
|
|
33
|
+
mode: KsNavBarMode;
|
|
34
|
+
iconWidth: string;
|
|
35
|
+
expandedWidth: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Angular wrapper around the `<ks-nav-bar>` Stencil custom element.
|
|
40
|
+
* Renders a real, consumer-facing default `<slot />` — same single
|
|
41
|
+
* unfiltered `<ng-content>` pass-through as `Layout/card/card.ts`.
|
|
42
|
+
*/
|
|
43
|
+
@Component({
|
|
44
|
+
selector: 'ks-nav-bar',
|
|
45
|
+
standalone: true,
|
|
46
|
+
template: '<ng-content></ng-content>',
|
|
47
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
48
|
+
})
|
|
49
|
+
export class KsNavBarComponent {
|
|
50
|
+
private readonly el: KsNavBarElement;
|
|
51
|
+
|
|
52
|
+
/** All nav items with their section assignment */
|
|
53
|
+
readonly items = input<KsNavBarSectionItem[]>([]);
|
|
54
|
+
|
|
55
|
+
/** Expansion mode */
|
|
56
|
+
readonly mode = input<KsNavBarMode>('iconOnly');
|
|
57
|
+
|
|
58
|
+
/** Width of the icon-only rail */
|
|
59
|
+
readonly iconWidth = input('3.5rem');
|
|
60
|
+
|
|
61
|
+
/** Width of the expanded label panel */
|
|
62
|
+
readonly expandedWidth = input('13rem');
|
|
63
|
+
|
|
64
|
+
constructor(ref: ElementRef<KsNavBarElement>) {
|
|
65
|
+
this.el = ref.nativeElement;
|
|
66
|
+
|
|
67
|
+
effect(() => (this.el.items = this.items()));
|
|
68
|
+
effect(() => (this.el.mode = this.mode()));
|
|
69
|
+
effect(() => (this.el.iconWidth = this.iconWidth()));
|
|
70
|
+
effect(() => (this.el.expandedWidth = this.expandedWidth()));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-pagination` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-pagination.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/** DOM shape of the real `<ks-pagination>` custom element, typed for the wrapper. */
|
|
8
|
+
type KsPaginationElement = HTMLElement & {
|
|
9
|
+
total: number;
|
|
10
|
+
pageSize: number;
|
|
11
|
+
currentPage: number;
|
|
12
|
+
showPageSize: boolean;
|
|
13
|
+
pageSizeOptions: number[];
|
|
14
|
+
showQuickJumper: boolean;
|
|
15
|
+
maxPageButtons: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Angular wrapper around the `<ks-pagination>` Stencil custom element.
|
|
20
|
+
* No `<slot>` in the wrapped Stencil render — data-driven only.
|
|
21
|
+
*/
|
|
22
|
+
@Component({
|
|
23
|
+
selector: 'ks-pagination',
|
|
24
|
+
standalone: true,
|
|
25
|
+
template: '',
|
|
26
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
27
|
+
})
|
|
28
|
+
export class KsPaginationComponent {
|
|
29
|
+
private readonly el: KsPaginationElement;
|
|
30
|
+
|
|
31
|
+
/** Total number of items */
|
|
32
|
+
readonly total = input(0);
|
|
33
|
+
|
|
34
|
+
/** Items per page */
|
|
35
|
+
readonly pageSize = input(10);
|
|
36
|
+
|
|
37
|
+
/** Current page (1-indexed) */
|
|
38
|
+
readonly currentPage = input(1);
|
|
39
|
+
|
|
40
|
+
/** Show page size selector */
|
|
41
|
+
readonly showPageSize = input(false);
|
|
42
|
+
|
|
43
|
+
/** Available page sizes */
|
|
44
|
+
readonly pageSizeOptions = input<number[]>([10, 20, 50, 100]);
|
|
45
|
+
|
|
46
|
+
/** Show quick jumper */
|
|
47
|
+
readonly showQuickJumper = input(false);
|
|
48
|
+
|
|
49
|
+
/** Maximum number of page buttons to show */
|
|
50
|
+
readonly maxPageButtons = input(7);
|
|
51
|
+
|
|
52
|
+
/** Emits when page changes. From the native `pageChange` event. */
|
|
53
|
+
readonly ksPageChange = output<number>();
|
|
54
|
+
|
|
55
|
+
/** Emits when page size changes. From the native `pageSizeChange` event. */
|
|
56
|
+
readonly ksPageSizeChange = output<number>();
|
|
57
|
+
|
|
58
|
+
constructor(ref: ElementRef<KsPaginationElement>) {
|
|
59
|
+
this.el = ref.nativeElement;
|
|
60
|
+
|
|
61
|
+
effect(() => (this.el.total = this.total()));
|
|
62
|
+
effect(() => (this.el.pageSize = this.pageSize()));
|
|
63
|
+
effect(() => (this.el.currentPage = this.currentPage()));
|
|
64
|
+
effect(() => (this.el.showPageSize = this.showPageSize()));
|
|
65
|
+
effect(() => (this.el.pageSizeOptions = this.pageSizeOptions()));
|
|
66
|
+
effect(() => (this.el.showQuickJumper = this.showQuickJumper()));
|
|
67
|
+
effect(() => (this.el.maxPageButtons = this.maxPageButtons()));
|
|
68
|
+
|
|
69
|
+
const onNativePageChange = (event: Event): void => {
|
|
70
|
+
this.ksPageChange.emit((event as CustomEvent<number>).detail);
|
|
71
|
+
};
|
|
72
|
+
const onNativePageSizeChange = (event: Event): void => {
|
|
73
|
+
this.ksPageSizeChange.emit((event as CustomEvent<number>).detail);
|
|
74
|
+
};
|
|
75
|
+
this.el.addEventListener('pageChange', onNativePageChange);
|
|
76
|
+
this.el.addEventListener('pageSizeChange', onNativePageSizeChange);
|
|
77
|
+
inject(DestroyRef).onDestroy(() => {
|
|
78
|
+
this.el.removeEventListener('pageChange', onNativePageChange);
|
|
79
|
+
this.el.removeEventListener('pageSizeChange', onNativePageSizeChange);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-stepper` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-stepper.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors `KsStepItem` / `KsStepperOrientation` exported by
|
|
9
|
+
* `core/src/components/Navigation/stepper/stepper.tsx`. Duplicated
|
|
10
|
+
* locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
+
*/
|
|
12
|
+
export interface KsStepItem {
|
|
13
|
+
key: string;
|
|
14
|
+
label: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
icon?: string;
|
|
17
|
+
optional?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type KsStepperOrientation = 'horizontal' | 'vertical';
|
|
21
|
+
|
|
22
|
+
/** DOM shape of the real `<ks-stepper>` custom element, typed for the wrapper. */
|
|
23
|
+
type KsStepperElement = HTMLElement & {
|
|
24
|
+
steps: KsStepItem[];
|
|
25
|
+
activeStep: number;
|
|
26
|
+
orientation: KsStepperOrientation;
|
|
27
|
+
clickable: boolean;
|
|
28
|
+
completedSteps: number[];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Angular wrapper around the `<ks-stepper>` Stencil custom element.
|
|
33
|
+
* No `<slot>` in the wrapped Stencil render — data-driven only.
|
|
34
|
+
*/
|
|
35
|
+
@Component({
|
|
36
|
+
selector: 'ks-stepper',
|
|
37
|
+
standalone: true,
|
|
38
|
+
template: '',
|
|
39
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
40
|
+
})
|
|
41
|
+
export class KsStepperComponent {
|
|
42
|
+
private readonly el: KsStepperElement;
|
|
43
|
+
|
|
44
|
+
/** Step definitions */
|
|
45
|
+
readonly steps = input<KsStepItem[]>([]);
|
|
46
|
+
|
|
47
|
+
/** Currently active step index (0-based) */
|
|
48
|
+
readonly activeStep = input(0);
|
|
49
|
+
|
|
50
|
+
/** Layout orientation */
|
|
51
|
+
readonly orientation = input<KsStepperOrientation>('horizontal');
|
|
52
|
+
|
|
53
|
+
/** Allow clicking steps to navigate */
|
|
54
|
+
readonly clickable = input(false);
|
|
55
|
+
|
|
56
|
+
/** Marks completed steps */
|
|
57
|
+
readonly completedSteps = input<number[]>([]);
|
|
58
|
+
|
|
59
|
+
/** Emits the new step index. From the native `stepChange` event. */
|
|
60
|
+
readonly ksStepChange = output<number>();
|
|
61
|
+
|
|
62
|
+
constructor(ref: ElementRef<KsStepperElement>) {
|
|
63
|
+
this.el = ref.nativeElement;
|
|
64
|
+
|
|
65
|
+
effect(() => (this.el.steps = this.steps()));
|
|
66
|
+
effect(() => (this.el.activeStep = this.activeStep()));
|
|
67
|
+
effect(() => (this.el.orientation = this.orientation()));
|
|
68
|
+
effect(() => (this.el.clickable = this.clickable()));
|
|
69
|
+
effect(() => (this.el.completedSteps = this.completedSteps()));
|
|
70
|
+
|
|
71
|
+
const onNativeStepChange = (event: Event): void => {
|
|
72
|
+
this.ksStepChange.emit((event as CustomEvent<number>).detail);
|
|
73
|
+
};
|
|
74
|
+
this.el.addEventListener('stepChange', onNativeStepChange);
|
|
75
|
+
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('stepChange', onNativeStepChange));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-tab` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-tab.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors `KsTabItem` exported by
|
|
9
|
+
* `core/src/components/Navigation/tab/tab.tsx`. Duplicated locally — see
|
|
10
|
+
* the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
+
*/
|
|
12
|
+
export interface KsTabItem {
|
|
13
|
+
key: string;
|
|
14
|
+
label: string;
|
|
15
|
+
icon?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** DOM shape of the real `<ks-tab>` custom element, typed for the wrapper. */
|
|
20
|
+
type KsTabElement = HTMLElement & {
|
|
21
|
+
tabs: KsTabItem[];
|
|
22
|
+
activeKey: string;
|
|
23
|
+
tabHeaderStyle: 'default' | 'expanded' | 'card' | 'button';
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Angular wrapper around the `<ks-tab>` Stencil custom element.
|
|
28
|
+
*
|
|
29
|
+
* Same `ksPanel="key"` → named-`<slot>` strategy as
|
|
30
|
+
* `Navigation/accordion/accordion.ts` (NOT the native `slot="..."`
|
|
31
|
+
* attribute) — see that file's doc comment for the full explanation.
|
|
32
|
+
* Usage:
|
|
33
|
+
* `<ks-tab [tabs]="tabs" activeKey="tab1">
|
|
34
|
+
* <div ksPanel="tab1">Tab 1 content</div>
|
|
35
|
+
* <div ksPanel="tab2">Tab 2 content</div>
|
|
36
|
+
* </ks-tab>`
|
|
37
|
+
*/
|
|
38
|
+
@Component({
|
|
39
|
+
selector: 'ks-tab',
|
|
40
|
+
standalone: true,
|
|
41
|
+
template: '<ng-content></ng-content>',
|
|
42
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
43
|
+
})
|
|
44
|
+
export class KsTabComponent {
|
|
45
|
+
private readonly el: KsTabElement;
|
|
46
|
+
|
|
47
|
+
/** List of tab definitions */
|
|
48
|
+
readonly tabs = input<KsTabItem[]>([]);
|
|
49
|
+
|
|
50
|
+
/** Key of the initially active tab */
|
|
51
|
+
readonly activeKey = input('');
|
|
52
|
+
|
|
53
|
+
readonly tabHeaderStyle = input<'default' | 'expanded' | 'card' | 'button'>('default');
|
|
54
|
+
|
|
55
|
+
/** Emits the key of the newly selected tab. From the native `tabChange` event. */
|
|
56
|
+
readonly ksTabChange = output<string>();
|
|
57
|
+
|
|
58
|
+
constructor(ref: ElementRef<KsTabElement>) {
|
|
59
|
+
this.el = ref.nativeElement;
|
|
60
|
+
|
|
61
|
+
effect(() => (this.el.tabs = this.tabs()));
|
|
62
|
+
effect(() => (this.el.activeKey = this.activeKey()));
|
|
63
|
+
effect(() => (this.el.tabHeaderStyle = this.tabHeaderStyle()));
|
|
64
|
+
|
|
65
|
+
const onNativeTabChange = (event: Event): void => {
|
|
66
|
+
this.ksTabChange.emit((event as CustomEvent<string>).detail);
|
|
67
|
+
};
|
|
68
|
+
this.el.addEventListener('tabChange', onNativeTabChange);
|
|
69
|
+
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('tabChange', onNativeTabChange));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-toolbar` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-toolbar.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
import type { KsVariant } from '@kraft.stitch/core';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Mirrors `KsToolbarItem` exported by
|
|
10
|
+
* `core/src/components/Navigation/toolbar/toolbar.tsx`. Duplicated
|
|
11
|
+
* locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
12
|
+
*/
|
|
13
|
+
export interface KsToolbarItem {
|
|
14
|
+
key: string;
|
|
15
|
+
icon?: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
divider?: boolean;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
active?: boolean;
|
|
20
|
+
variant?: KsVariant;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** DOM shape of the real `<ks-toolbar>` custom element, typed for the wrapper. */
|
|
24
|
+
type KsToolbarElement = HTMLElement & {
|
|
25
|
+
items: KsToolbarItem[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Angular wrapper around the `<ks-toolbar>` Stencil custom element.
|
|
30
|
+
* Renders a real, consumer-facing default `<slot />` for extra trailing
|
|
31
|
+
* content — same single unfiltered `<ng-content>` pass-through as
|
|
32
|
+
* `Layout/card/card.ts`.
|
|
33
|
+
*/
|
|
34
|
+
@Component({
|
|
35
|
+
selector: 'ks-toolbar',
|
|
36
|
+
standalone: true,
|
|
37
|
+
template: '<ng-content></ng-content>',
|
|
38
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
39
|
+
})
|
|
40
|
+
export class KsToolbarComponent {
|
|
41
|
+
private readonly el: KsToolbarElement;
|
|
42
|
+
|
|
43
|
+
/** Toolbar items */
|
|
44
|
+
readonly items = input<KsToolbarItem[]>([]);
|
|
45
|
+
|
|
46
|
+
/** Emits the clicked item key. From the native `itemClicked` event. */
|
|
47
|
+
readonly ksItemClicked = output<string>();
|
|
48
|
+
|
|
49
|
+
constructor(ref: ElementRef<KsToolbarElement>) {
|
|
50
|
+
this.el = ref.nativeElement;
|
|
51
|
+
|
|
52
|
+
effect(() => (this.el.items = this.items()));
|
|
53
|
+
|
|
54
|
+
const onNativeItemClicked = (event: Event): void => {
|
|
55
|
+
this.ksItemClicked.emit((event as CustomEvent<string>).detail);
|
|
56
|
+
};
|
|
57
|
+
this.el.addEventListener('itemClicked', onNativeItemClicked);
|
|
58
|
+
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('itemClicked', onNativeItemClicked));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-top-nav-bar` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-top-nav-bar.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors the types exported by
|
|
9
|
+
* `core/src/components/Navigation/top-nav-bar/top-nav-bar.tsx`.
|
|
10
|
+
* Duplicated locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
+
*/
|
|
12
|
+
export type KsTopNavBarVariant = 'default' | 'underline' | 'pill';
|
|
13
|
+
|
|
14
|
+
export interface KsTopNavBarItem {
|
|
15
|
+
key: string;
|
|
16
|
+
name: string;
|
|
17
|
+
iconClass?: string;
|
|
18
|
+
/** href to navigate to */
|
|
19
|
+
redirectLink: string;
|
|
20
|
+
activationFragment?: string;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** DOM shape of the real `<ks-top-nav-bar>` custom element, typed for the wrapper. */
|
|
25
|
+
type KsTopNavBarElement = HTMLElement & {
|
|
26
|
+
items: KsTopNavBarItem[];
|
|
27
|
+
variant: KsTopNavBarVariant;
|
|
28
|
+
showIcons: boolean;
|
|
29
|
+
showLabels: boolean;
|
|
30
|
+
label: string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Angular wrapper around the `<ks-top-nav-bar>` Stencil custom element.
|
|
35
|
+
* Renders a real, consumer-facing default `<slot />` — same single
|
|
36
|
+
* unfiltered `<ng-content>` pass-through as `Layout/card/card.ts`.
|
|
37
|
+
*/
|
|
38
|
+
@Component({
|
|
39
|
+
selector: 'ks-top-nav-bar',
|
|
40
|
+
standalone: true,
|
|
41
|
+
template: '<ng-content></ng-content>',
|
|
42
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
43
|
+
})
|
|
44
|
+
export class KsTopNavBarComponent {
|
|
45
|
+
private readonly el: KsTopNavBarElement;
|
|
46
|
+
|
|
47
|
+
/** Navigation items */
|
|
48
|
+
readonly items = input<KsTopNavBarItem[]>([]);
|
|
49
|
+
|
|
50
|
+
/** Visual style of the active indicator */
|
|
51
|
+
readonly variant = input<KsTopNavBarVariant>('default');
|
|
52
|
+
|
|
53
|
+
/** Show icon alongside label */
|
|
54
|
+
readonly showIcons = input(true);
|
|
55
|
+
|
|
56
|
+
/** Show label text */
|
|
57
|
+
readonly showLabels = input(true);
|
|
58
|
+
|
|
59
|
+
/** Aria label for the nav element */
|
|
60
|
+
readonly label = input('Top navigation');
|
|
61
|
+
|
|
62
|
+
constructor(ref: ElementRef<KsTopNavBarElement>) {
|
|
63
|
+
this.el = ref.nativeElement;
|
|
64
|
+
|
|
65
|
+
effect(() => (this.el.items = this.items()));
|
|
66
|
+
effect(() => (this.el.variant = this.variant()));
|
|
67
|
+
effect(() => (this.el.showIcons = this.showIcons()));
|
|
68
|
+
effect(() => (this.el.showLabels = this.showLabels()));
|
|
69
|
+
effect(() => (this.el.label = this.label()));
|
|
70
|
+
}
|
|
71
|
+
}
|