@kraft.stitch/angular 0.0.2 → 0.0.4
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 +41 -0
- package/README.md +97 -2
- package/ng-package.json +10 -0
- package/package.json +28 -17
- 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/Buttons/split-button/split-button.ts +111 -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/rolling-number/rolling-number.ts +136 -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 +68 -0
- package/src/utils/theme-service.ts +11 -0
- package/tsconfig.json +23 -0
- package/fesm2022/kraft.stitch-angular.mjs +0 -2873
- package/fesm2022/kraft.stitch-angular.mjs.map +0 -1
- package/types/kraft.stitch-angular.d.ts +0 -2247
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-tree-view` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-tree-view.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors `KsTreeNode` exported by
|
|
9
|
+
* `core/src/components/Navigation/tree-view/tree-view.tsx`. Duplicated
|
|
10
|
+
* locally — see the note in `Buttons/button-group/button-group.ts` for why.
|
|
11
|
+
*/
|
|
12
|
+
export interface KsTreeNode {
|
|
13
|
+
key: string;
|
|
14
|
+
label: string;
|
|
15
|
+
icon?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
children?: KsTreeNode[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** DOM shape of the real `<ks-tree-view>` custom element, typed for the wrapper. */
|
|
21
|
+
type KsTreeViewElement = HTMLElement & {
|
|
22
|
+
nodes: KsTreeNode[];
|
|
23
|
+
expandedKeys: string[];
|
|
24
|
+
multi: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Angular wrapper around the `<ks-tree-view>` Stencil custom element.
|
|
29
|
+
* No `<slot>` in the wrapped Stencil render — data-driven only.
|
|
30
|
+
*/
|
|
31
|
+
@Component({
|
|
32
|
+
selector: 'ks-tree-view',
|
|
33
|
+
standalone: true,
|
|
34
|
+
template: '',
|
|
35
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
36
|
+
})
|
|
37
|
+
export class KsTreeViewComponent {
|
|
38
|
+
private readonly el: KsTreeViewElement;
|
|
39
|
+
|
|
40
|
+
/** Tree data */
|
|
41
|
+
readonly nodes = input<KsTreeNode[]>([]);
|
|
42
|
+
|
|
43
|
+
/** Keys of nodes that start expanded */
|
|
44
|
+
readonly expandedKeys = input<string[]>([]);
|
|
45
|
+
|
|
46
|
+
/** Allow selecting multiple nodes */
|
|
47
|
+
readonly multi = input(false);
|
|
48
|
+
|
|
49
|
+
/** Emits key(s) when selection changes. From the native `selectionChanged` event. */
|
|
50
|
+
readonly ksSelectionChanged = output<string | string[]>();
|
|
51
|
+
|
|
52
|
+
/** Emits when a node is expanded/collapsed. From the native `expandChange` event. */
|
|
53
|
+
readonly ksExpandChange = output<{ key: string; expanded: boolean }>();
|
|
54
|
+
|
|
55
|
+
constructor(ref: ElementRef<KsTreeViewElement>) {
|
|
56
|
+
this.el = ref.nativeElement;
|
|
57
|
+
|
|
58
|
+
effect(() => (this.el.nodes = this.nodes()));
|
|
59
|
+
effect(() => (this.el.expandedKeys = this.expandedKeys()));
|
|
60
|
+
effect(() => (this.el.multi = this.multi()));
|
|
61
|
+
|
|
62
|
+
const onNativeSelectionChanged = (event: Event): void => {
|
|
63
|
+
this.ksSelectionChanged.emit((event as CustomEvent<string | string[]>).detail);
|
|
64
|
+
};
|
|
65
|
+
const onNativeExpandChange = (event: Event): void => {
|
|
66
|
+
this.ksExpandChange.emit((event as CustomEvent<{ key: string; expanded: boolean }>).detail);
|
|
67
|
+
};
|
|
68
|
+
this.el.addEventListener('selectionChanged', onNativeSelectionChanged);
|
|
69
|
+
this.el.addEventListener('expandChange', onNativeExpandChange);
|
|
70
|
+
inject(DestroyRef).onDestroy(() => {
|
|
71
|
+
this.el.removeEventListener('selectionChanged', onNativeSelectionChanged);
|
|
72
|
+
this.el.removeEventListener('expandChange', onNativeExpandChange);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-badge` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-badge.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
+
import type { KsBaseSize, KsBaseVariant } from '@kraft.stitch/core';
|
|
7
|
+
|
|
8
|
+
/** DOM shape of the real `<ks-badge>` custom element, typed for the wrapper. */
|
|
9
|
+
type KsBadgeElement = HTMLElement & {
|
|
10
|
+
label: string;
|
|
11
|
+
variant: KsBaseVariant;
|
|
12
|
+
size: KsBaseSize;
|
|
13
|
+
dot: boolean;
|
|
14
|
+
pill: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Angular wrapper around the `<ks-badge>` Stencil custom element.
|
|
19
|
+
* Purely presentational — no events, no `<slot>` in the wrapped Stencil
|
|
20
|
+
* render, plain inputs only.
|
|
21
|
+
*/
|
|
22
|
+
@Component({
|
|
23
|
+
selector: 'ks-badge',
|
|
24
|
+
standalone: true,
|
|
25
|
+
template: '',
|
|
26
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
27
|
+
})
|
|
28
|
+
export class KsBadgeComponent {
|
|
29
|
+
private readonly el: KsBadgeElement;
|
|
30
|
+
|
|
31
|
+
/** Display text */
|
|
32
|
+
readonly label = input('');
|
|
33
|
+
|
|
34
|
+
/** Colour variant */
|
|
35
|
+
readonly variant = input<KsBaseVariant>('brand');
|
|
36
|
+
|
|
37
|
+
/** Size */
|
|
38
|
+
readonly size = input<KsBaseSize>('md');
|
|
39
|
+
|
|
40
|
+
/** Show a dot instead of text */
|
|
41
|
+
readonly dot = input(false);
|
|
42
|
+
|
|
43
|
+
/** Pill (fully rounded) shape */
|
|
44
|
+
readonly pill = input(true);
|
|
45
|
+
|
|
46
|
+
constructor(ref: ElementRef<KsBadgeElement>) {
|
|
47
|
+
this.el = ref.nativeElement;
|
|
48
|
+
|
|
49
|
+
effect(() => (this.el.label = this.label()));
|
|
50
|
+
effect(() => (this.el.variant = this.variant()));
|
|
51
|
+
effect(() => (this.el.size = this.size()));
|
|
52
|
+
effect(() => (this.el.dot = this.dot()));
|
|
53
|
+
effect(() => (this.el.pill = this.pill()));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-loader` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-loader.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
+
import { LoaderStateEnum } from '@kraft.stitch/core';
|
|
7
|
+
|
|
8
|
+
/** DOM shape of the real `<ks-loader>` custom element, typed for the wrapper. */
|
|
9
|
+
type KsLoaderElement = HTMLElement & {
|
|
10
|
+
state: LoaderStateEnum;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Angular wrapper around the `<ks-loader>` Stencil custom element.
|
|
15
|
+
*
|
|
16
|
+
* Renders real, consumer-facing named slots — `loading`, `empty`,
|
|
17
|
+
* `empty-action`, `error`, `error-action` — plus a default (unnamed)
|
|
18
|
+
* slot for the `Success` state. Same single unfiltered
|
|
19
|
+
* `<ng-content>` pass-through as `Layout/card/card.ts`: give each
|
|
20
|
+
* projected child its own native `slot="loading"` / `slot="empty"` /
|
|
21
|
+
* `slot="empty-action"` / `slot="error"` / `slot="error-action"`
|
|
22
|
+
* attribute (or none, for the default/success slot).
|
|
23
|
+
*/
|
|
24
|
+
@Component({
|
|
25
|
+
selector: 'ks-loader',
|
|
26
|
+
standalone: true,
|
|
27
|
+
template: '<ng-content></ng-content>',
|
|
28
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
29
|
+
})
|
|
30
|
+
export class KsLoaderComponent {
|
|
31
|
+
private readonly el: KsLoaderElement;
|
|
32
|
+
|
|
33
|
+
/** Current state */
|
|
34
|
+
readonly state = input<LoaderStateEnum>(LoaderStateEnum.Loading);
|
|
35
|
+
|
|
36
|
+
constructor(ref: ElementRef<KsLoaderElement>) {
|
|
37
|
+
this.el = ref.nativeElement;
|
|
38
|
+
|
|
39
|
+
effect(() => (this.el.state = this.state()));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-message` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-message.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, effect, inject, input, output } from '@angular/core';
|
|
6
|
+
import type { KsBaseVariant } from '@kraft.stitch/core';
|
|
7
|
+
|
|
8
|
+
/** DOM shape of the real `<ks-message>` custom element, typed for the wrapper. */
|
|
9
|
+
type KsMessageElement = HTMLElement & {
|
|
10
|
+
text: string;
|
|
11
|
+
icon: string;
|
|
12
|
+
variant: KsBaseVariant;
|
|
13
|
+
dismissible: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Angular wrapper around the `<ks-message>` Stencil custom element.
|
|
18
|
+
*
|
|
19
|
+
* `<ks-message>` renders a default `<slot />` only as a fallback when
|
|
20
|
+
* `text` is empty — same single unfiltered `<ng-content>` pass-through as
|
|
21
|
+
* `Layout/card/card.ts`; omit `text` and project content instead if
|
|
22
|
+
* richer markup is needed.
|
|
23
|
+
*/
|
|
24
|
+
@Component({
|
|
25
|
+
selector: 'ks-message',
|
|
26
|
+
standalone: true,
|
|
27
|
+
template: '<ng-content></ng-content>',
|
|
28
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
29
|
+
})
|
|
30
|
+
export class KsMessageComponent {
|
|
31
|
+
private readonly el: KsMessageElement;
|
|
32
|
+
|
|
33
|
+
/** Main message text */
|
|
34
|
+
readonly text = input('');
|
|
35
|
+
|
|
36
|
+
/** Optional icon class (e.g. Material Icon or Font Awesome) */
|
|
37
|
+
readonly icon = input('');
|
|
38
|
+
|
|
39
|
+
/** Colour variant */
|
|
40
|
+
readonly variant = input<KsBaseVariant>('info');
|
|
41
|
+
|
|
42
|
+
/** Show a dismiss (×) button */
|
|
43
|
+
readonly dismissible = input(false);
|
|
44
|
+
|
|
45
|
+
/** Emits when the message is dismissed. From the native `dismissed` event. */
|
|
46
|
+
readonly ksDismissed = output<void>();
|
|
47
|
+
|
|
48
|
+
constructor(ref: ElementRef<KsMessageElement>) {
|
|
49
|
+
this.el = ref.nativeElement;
|
|
50
|
+
|
|
51
|
+
effect(() => (this.el.text = this.text()));
|
|
52
|
+
effect(() => (this.el.icon = this.icon()));
|
|
53
|
+
effect(() => (this.el.variant = this.variant()));
|
|
54
|
+
effect(() => (this.el.dismissible = this.dismissible()));
|
|
55
|
+
|
|
56
|
+
const onNativeDismissed = (): void => this.ksDismissed.emit();
|
|
57
|
+
this.el.addEventListener('dismissed', onNativeDismissed);
|
|
58
|
+
inject(DestroyRef).onDestroy(() => this.el.removeEventListener('dismissed', onNativeDismissed));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-progress` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-progress.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
+
import type { KsBaseSize, KsBaseVariant } from '@kraft.stitch/core';
|
|
7
|
+
|
|
8
|
+
/** DOM shape of the real `<ks-progress>` custom element, typed for the wrapper. */
|
|
9
|
+
type KsProgressElement = HTMLElement & {
|
|
10
|
+
value: number;
|
|
11
|
+
max: number;
|
|
12
|
+
showLabel: boolean;
|
|
13
|
+
variant: KsBaseVariant;
|
|
14
|
+
size: KsBaseSize;
|
|
15
|
+
indeterminate: boolean;
|
|
16
|
+
label: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Angular wrapper around the `<ks-progress>` Stencil custom element.
|
|
21
|
+
* Purely presentational — no events, no `<slot>` in the wrapped Stencil
|
|
22
|
+
* render, plain inputs only.
|
|
23
|
+
*/
|
|
24
|
+
@Component({
|
|
25
|
+
selector: 'ks-progress',
|
|
26
|
+
standalone: true,
|
|
27
|
+
template: '',
|
|
28
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
29
|
+
})
|
|
30
|
+
export class KsProgressComponent {
|
|
31
|
+
private readonly el: KsProgressElement;
|
|
32
|
+
|
|
33
|
+
/** Progress value (0-100) */
|
|
34
|
+
readonly value = input(0);
|
|
35
|
+
|
|
36
|
+
/** Maximum value */
|
|
37
|
+
readonly max = input(100);
|
|
38
|
+
|
|
39
|
+
/** Show percentage label */
|
|
40
|
+
readonly showLabel = input(false);
|
|
41
|
+
|
|
42
|
+
/** Progress variant */
|
|
43
|
+
readonly variant = input<KsBaseVariant>('brand');
|
|
44
|
+
|
|
45
|
+
/** Progress size */
|
|
46
|
+
readonly size = input<KsBaseSize>('md');
|
|
47
|
+
|
|
48
|
+
/** Indeterminate/loading state */
|
|
49
|
+
readonly indeterminate = input(false);
|
|
50
|
+
|
|
51
|
+
/** Optional label text */
|
|
52
|
+
readonly label = input('');
|
|
53
|
+
|
|
54
|
+
constructor(ref: ElementRef<KsProgressElement>) {
|
|
55
|
+
this.el = ref.nativeElement;
|
|
56
|
+
|
|
57
|
+
effect(() => (this.el.value = this.value()));
|
|
58
|
+
effect(() => (this.el.max = this.max()));
|
|
59
|
+
effect(() => (this.el.showLabel = this.showLabel()));
|
|
60
|
+
effect(() => (this.el.variant = this.variant()));
|
|
61
|
+
effect(() => (this.el.size = this.size()));
|
|
62
|
+
effect(() => (this.el.indeterminate = this.indeterminate()));
|
|
63
|
+
effect(() => (this.el.label = this.label()));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-spinner` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-spinner.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-spinner>` custom element, typed for the wrapper. */
|
|
9
|
+
type KsSpinnerElement = HTMLElement & {
|
|
10
|
+
size: KsSize;
|
|
11
|
+
variant: KsBaseVariant;
|
|
12
|
+
text: string;
|
|
13
|
+
centered: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Angular wrapper around the `<ks-spinner>` Stencil custom element.
|
|
18
|
+
* Purely presentational — no events, no `<slot>` in the wrapped Stencil
|
|
19
|
+
* render, plain inputs only.
|
|
20
|
+
*/
|
|
21
|
+
@Component({
|
|
22
|
+
selector: 'ks-spinner',
|
|
23
|
+
standalone: true,
|
|
24
|
+
template: '',
|
|
25
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
26
|
+
})
|
|
27
|
+
export class KsSpinnerComponent {
|
|
28
|
+
private readonly el: KsSpinnerElement;
|
|
29
|
+
|
|
30
|
+
/** Spinner size */
|
|
31
|
+
readonly size = input<KsSize>('md');
|
|
32
|
+
|
|
33
|
+
/** Spinner variant/color */
|
|
34
|
+
readonly variant = input<KsBaseVariant>('brand');
|
|
35
|
+
|
|
36
|
+
/** Optional text to display */
|
|
37
|
+
readonly text = input('');
|
|
38
|
+
|
|
39
|
+
/** Center the spinner in container */
|
|
40
|
+
readonly centered = input(false);
|
|
41
|
+
|
|
42
|
+
constructor(ref: ElementRef<KsSpinnerElement>) {
|
|
43
|
+
this.el = ref.nativeElement;
|
|
44
|
+
|
|
45
|
+
effect(() => (this.el.size = this.size()));
|
|
46
|
+
effect(() => (this.el.variant = this.variant()));
|
|
47
|
+
effect(() => (this.el.text = this.text()));
|
|
48
|
+
effect(() => (this.el.centered = this.centered()));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Side-effect import: registers the `ks-toast-outlet` tag — see
|
|
2
|
+
// `Buttons/button/button.ts` for the full explanation of this pattern.
|
|
3
|
+
import '@kraft.stitch/core/dist/components/ks-toast-outlet.js';
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component, ElementRef, effect, input } from '@angular/core';
|
|
6
|
+
import type { KsToastPosition } from '@kraft.stitch/core';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Re-exported so Angular consumers don't need a separate `@kraft.stitch/core`
|
|
10
|
+
* import for the imperative side of the toast system. `toastStore` is a
|
|
11
|
+
* plain module-level singleton (see `core/src/utils/ks-toast.store.ts`)
|
|
12
|
+
* — there's no DI/service wrapper needed; call
|
|
13
|
+
* `toastStore.show('Saved!', { variant: 'success' })` directly from any
|
|
14
|
+
* component or service, and any mounted `<ks-toast>` (`KsToastComponent`)
|
|
15
|
+
* on the page will pick it up via its internal subscription.
|
|
16
|
+
*/
|
|
17
|
+
export { toastStore } from '@kraft.stitch/core';
|
|
18
|
+
export type { KsToast, KsToastPosition } from '@kraft.stitch/core';
|
|
19
|
+
|
|
20
|
+
/** DOM shape of the real `<ks-toast-outlet>` custom element, typed for the wrapper. */
|
|
21
|
+
type KsToastOutletElement = HTMLElement & {
|
|
22
|
+
position: KsToastPosition;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Angular wrapper around the `<ks-toast-outlet>` Stencil custom element.
|
|
27
|
+
* Named `KsToastOutletComponent` (matching the literal tag, not just
|
|
28
|
+
* `KsToastComponent`) for consistency with the React wrapper, which must
|
|
29
|
+
* avoid colliding with the re-exported `KsToast` *data* interface above
|
|
30
|
+
* (TypeScript disallows a value and a type export sharing one identifier
|
|
31
|
+
* from the same module) — see `react/src/components/Notification/toast/toast.tsx`.
|
|
32
|
+
* `<ks-toast-outlet position="top-right" />` is all a consumer needs; add
|
|
33
|
+
* one per screen corner they want to stack toasts in.
|
|
34
|
+
*
|
|
35
|
+
* No `<slot>`, no events — it purely subscribes to the shared
|
|
36
|
+
* `toastStore` singleton (re-exported above) and renders whatever's
|
|
37
|
+
* enqueued.
|
|
38
|
+
*/
|
|
39
|
+
@Component({
|
|
40
|
+
selector: 'ks-toast-outlet',
|
|
41
|
+
standalone: true,
|
|
42
|
+
template: '',
|
|
43
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
44
|
+
})
|
|
45
|
+
export class KsToastOutletComponent {
|
|
46
|
+
private readonly el: KsToastOutletElement;
|
|
47
|
+
|
|
48
|
+
/** Where on screen to stack toasts */
|
|
49
|
+
readonly position = input<KsToastPosition>('top-right');
|
|
50
|
+
|
|
51
|
+
constructor(ref: ElementRef<KsToastOutletElement>) {
|
|
52
|
+
this.el = ref.nativeElement;
|
|
53
|
+
|
|
54
|
+
effect(() => (this.el.position = this.position()));
|
|
55
|
+
}
|
|
56
|
+
}
|