@kouji-ui/core 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/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +14 -0
- package/README.md +75 -43
- package/package.json +1 -1
- package/src/button/button.spec.ts +1 -1
- package/src/dialog/dialog.spec.ts +1 -1
- package/src/primitives/forms/form-control.spec.ts +3 -3
- package/src/primitives/overlay/overlay.spec.ts +5 -5
- package/src/primitives/overlay/overlay.ts +5 -1
- package/src/select/select.ts +2 -2
- package/src/table/table.spec.ts +1 -1
- package/src/toast/toast.spec.ts +15 -14
- package/src/toast/toast.ts +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
|
|
2
|
-
> @kouji-ui/core@0.0.
|
|
2
|
+
> @kouji-ui/core@0.0.4 build /home/runner/work/kouji-ui/kouji-ui/packages/core
|
|
3
3
|
> ng-packagr -p ng-package.json
|
|
4
4
|
|
|
5
5
|
Building Angular Package
|
|
6
6
|
|
|
7
7
|
------------------------------------------------------------------------------
|
|
8
|
+
- Compiling with Angular sources in partial compilation mode.
|
|
8
9
|
Building entry point '@kouji-ui/core'
|
|
9
10
|
------------------------------------------------------------------------------
|
|
10
|
-
- Compiling with Angular sources in partial compilation mode.
|
|
11
11
|
[32m✔[39m Compiling with Angular sources in partial compilation mode.
|
|
12
12
|
[32m✔[39m Generating FESM and DTS bundles
|
|
13
13
|
- Copying assets
|
|
@@ -23,5 +23,5 @@ Built Angular Package
|
|
|
23
23
|
- to: /home/runner/work/kouji-ui/kouji-ui/dist/kj-core
|
|
24
24
|
------------------------------------------------------------------------------
|
|
25
25
|
|
|
26
|
-
Build at: 2026-05-
|
|
26
|
+
Build at: 2026-05-04T22:25:26.490Z - Time: 5957ms
|
|
27
27
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @kouji-ui/core
|
|
2
2
|
|
|
3
|
+
## 0.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 202d9de: CI fix: husky pre-push hook now skips in CI environments (`$CI` or `$GITHUB_ACTIONS` set). Prevents the Changesets action's automated push from being blocked by the changeset-status gate. No runtime effect on the published package.
|
|
8
|
+
- dc0fe0f: Test-only fix: rewrite `KjToastService` test suite to use `TestBed.inject()` so `inject(KJ_TOAST_STRATEGY)` resolves through Angular DI (was crashing with `new KjToastService()` outside an injection context). No runtime change.
|
|
9
|
+
- d6b40e1: Internal lint cleanup — replace `any` casts in select option storage with typed `HTMLElement & { __kjOptionValue?: unknown }` and convert ternary statement to if/else in overlay toggle. No public API or behavior change.
|
|
10
|
+
|
|
11
|
+
## 0.0.3
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- c177d1e: Rewrite README with real install/usage docs, primitive index, and design principles. Replaces the Angular CLI scaffold placeholder.
|
|
16
|
+
|
|
3
17
|
## 0.0.2
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,64 +1,96 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @kouji-ui/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Headless Angular 21 UI primitives — directives over CDK with WCAG 2.1 AAA semantics and zero CSS.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
You write the markup. You write the styles. The library wires up keyboard navigation, ARIA, focus management, and state.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[Documentation](https://kouji-ui.onrender.com) · [GitHub](https://github.com/kouji-dev/kouji-ui)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
ng generate component component-name
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
ng generate --help
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Building
|
|
20
|
-
|
|
21
|
-
To build the library, run:
|
|
9
|
+
## Install
|
|
22
10
|
|
|
23
11
|
```bash
|
|
24
|
-
|
|
12
|
+
pnpm add @kouji-ui/core @angular/cdk
|
|
25
13
|
```
|
|
26
14
|
|
|
27
|
-
|
|
15
|
+
Peer dependencies: `@angular/common` `@angular/core` `@angular/cdk` — all `^21.0.0`.
|
|
28
16
|
|
|
29
|
-
|
|
17
|
+
## Quick start
|
|
30
18
|
|
|
31
|
-
|
|
19
|
+
Every primitive is a standalone directive. Import it where you use it.
|
|
32
20
|
|
|
33
|
-
|
|
21
|
+
```ts
|
|
22
|
+
import { Component } from '@angular/core';
|
|
23
|
+
import { KjButton } from '@kouji-ui/core';
|
|
34
24
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
@Component({
|
|
26
|
+
selector: 'app-example',
|
|
27
|
+
imports: [KjButton],
|
|
28
|
+
template: `<button kjButton (click)="save()">Save</button>`,
|
|
29
|
+
})
|
|
30
|
+
export class ExampleComponent {
|
|
31
|
+
save() { /* ... */ }
|
|
32
|
+
}
|
|
33
|
+
```
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
The directive owns the keyboard contract, ARIA roles, and focus ring — not the look. Style the host element however you want.
|
|
36
|
+
|
|
37
|
+
### A more involved example: dialog
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { Component } from '@angular/core';
|
|
41
|
+
import {
|
|
42
|
+
KjDialog,
|
|
43
|
+
KjDialogTrigger,
|
|
44
|
+
KjDialogOverlay,
|
|
45
|
+
KjDialogTitle,
|
|
46
|
+
KjDialogClose,
|
|
47
|
+
} from '@kouji-ui/core';
|
|
48
|
+
|
|
49
|
+
@Component({
|
|
50
|
+
selector: 'app-confirm',
|
|
51
|
+
imports: [KjDialog, KjDialogTrigger, KjDialogOverlay, KjDialogTitle, KjDialogClose],
|
|
52
|
+
template: `
|
|
53
|
+
<button [kjDialogTrigger]="confirm">Delete</button>
|
|
54
|
+
|
|
55
|
+
<ng-template #confirm>
|
|
56
|
+
<div kjDialog>
|
|
57
|
+
<div kjDialogOverlay></div>
|
|
58
|
+
<h2 kjDialogTitle>Delete this item?</h2>
|
|
59
|
+
<p>This action cannot be undone.</p>
|
|
60
|
+
<button kjDialogClose>Cancel</button>
|
|
61
|
+
<button kjDialogClose (click)="delete()">Delete</button>
|
|
62
|
+
</div>
|
|
63
|
+
</ng-template>
|
|
64
|
+
`,
|
|
65
|
+
})
|
|
66
|
+
export class ConfirmComponent {
|
|
67
|
+
delete() { /* ... */ }
|
|
68
|
+
}
|
|
69
|
+
```
|
|
43
70
|
|
|
44
|
-
|
|
71
|
+
Focus trap, Escape-to-close, scroll lock, ARIA wiring — all handled.
|
|
45
72
|
|
|
46
|
-
|
|
73
|
+
## What's included
|
|
47
74
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
75
|
+
| Domain | Primitives |
|
|
76
|
+
| --------------- | ----------------------------------------------------------- |
|
|
77
|
+
| Buttons & inputs | `KjButton`, `KjInput`, `KjCheckbox`, `KjRadio`, `KjToggle`, `KjSelect` |
|
|
78
|
+
| Form composition | `KjFormField`, `KjFormLabel`, `KjFormError` |
|
|
79
|
+
| Overlays | `KjDialog`, `KjPopover`, `KjTooltip`, `KjToast`, `KjMenu` |
|
|
80
|
+
| Navigation | `KjTabs`, `KjAccordion` |
|
|
81
|
+
| Data display | `KjTable`, `KjBadge`, `KjAvatar`, `KjChart` |
|
|
82
|
+
| A11y primitives | `KjFocusTrap`, `KjFocusRing`, `KjLiveRegion`, `KjRovingTabindex`, `KjVisuallyHidden`, `KjAriaDescribedBy` |
|
|
51
83
|
|
|
52
|
-
|
|
84
|
+
Every primitive ships with examples and an inputs reference at [kouji-ui.onrender.com](https://kouji-ui.onrender.com).
|
|
53
85
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
ng e2e
|
|
58
|
-
```
|
|
86
|
+
## Design principles
|
|
59
87
|
|
|
60
|
-
|
|
88
|
+
- **Headless** — directives, not components. You own the DOM and CSS.
|
|
89
|
+
- **WCAG 2.1 AAA target** — keyboard contracts, focus management, ARIA, and contrast all designed for AAA.
|
|
90
|
+
- **CDK-aligned** — wraps `@angular/cdk` primitives where it makes sense (overlay, focus-trap), never reimplements from scratch.
|
|
91
|
+
- **Signals-first** — public APIs use `input()` / `signal()` / `effect()`.
|
|
92
|
+
- **Zero runtime CSS** — no shipped stylesheet. Bring your own design system.
|
|
61
93
|
|
|
62
|
-
##
|
|
94
|
+
## License
|
|
63
95
|
|
|
64
|
-
|
|
96
|
+
MIT © [kouji-dev](https://github.com/kouji-dev)
|
package/package.json
CHANGED
|
@@ -75,7 +75,7 @@ describe('KjDialogTrigger', () => {
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
it('closes dialog on overlay click (close on backdrop enabled by default)', async () => {
|
|
78
|
-
const { getByRole
|
|
78
|
+
const { getByRole } = await render(
|
|
79
79
|
`<button [kjDialogTrigger]="dlg">Open</button>
|
|
80
80
|
<ng-template #dlg>
|
|
81
81
|
<div kjDialogOverlay>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Component } from '@angular/core';
|
|
2
2
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
3
|
-
import { render
|
|
4
|
-
import {
|
|
3
|
+
import { render } from '@testing-library/angular';
|
|
4
|
+
import { toHaveNoViolations } from 'jest-axe';
|
|
5
5
|
import { KjFormControl } from './form-control';
|
|
6
6
|
|
|
7
7
|
expect.extend(toHaveNoViolations);
|
|
@@ -14,7 +14,7 @@ expect.extend(toHaveNoViolations);
|
|
|
14
14
|
class TestHostComponent {
|
|
15
15
|
ctrl = new FormControl('');
|
|
16
16
|
formCtrl!: KjFormControl;
|
|
17
|
-
onInput(
|
|
17
|
+
onInput(_e: Event): void {
|
|
18
18
|
// will be wired by the directive consumer pattern
|
|
19
19
|
}
|
|
20
20
|
onBlur(): void {}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, TemplateRef, ViewChild, ViewContainerRef, inject } from '@angular/core';
|
|
1
|
+
import { Component, TemplateRef, ViewChild, ViewContainerRef, inject, OnInit } from '@angular/core';
|
|
2
2
|
import { render } from '@testing-library/angular';
|
|
3
3
|
import { KjOverlayService, KjOverlayRef } from './overlay';
|
|
4
4
|
|
|
@@ -17,7 +17,7 @@ describe('KjOverlayService', () => {
|
|
|
17
17
|
standalone: true,
|
|
18
18
|
template: '<ng-template #tpl><div>overlay content</div></ng-template>',
|
|
19
19
|
})
|
|
20
|
-
class TestComponent {
|
|
20
|
+
class TestComponent implements OnInit {
|
|
21
21
|
@ViewChild('tpl', { static: true }) tpl!: TemplateRef<unknown>;
|
|
22
22
|
readonly svc = inject(KjOverlayService);
|
|
23
23
|
readonly vcr = inject(ViewContainerRef);
|
|
@@ -34,7 +34,7 @@ describe('KjOverlayService', () => {
|
|
|
34
34
|
standalone: true,
|
|
35
35
|
template: '<ng-template #tpl><div>overlay</div></ng-template>',
|
|
36
36
|
})
|
|
37
|
-
class TestComponent {
|
|
37
|
+
class TestComponent implements OnInit {
|
|
38
38
|
@ViewChild('tpl', { static: true }) tpl!: TemplateRef<unknown>;
|
|
39
39
|
readonly svc = inject(KjOverlayService);
|
|
40
40
|
readonly vcr = inject(ViewContainerRef);
|
|
@@ -53,7 +53,7 @@ describe('KjOverlayService', () => {
|
|
|
53
53
|
standalone: true,
|
|
54
54
|
template: '<ng-template #tpl><div>overlay</div></ng-template>',
|
|
55
55
|
})
|
|
56
|
-
class TestComponent {
|
|
56
|
+
class TestComponent implements OnInit {
|
|
57
57
|
@ViewChild('tpl', { static: true }) tpl!: TemplateRef<unknown>;
|
|
58
58
|
readonly svc = inject(KjOverlayService);
|
|
59
59
|
readonly vcr = inject(ViewContainerRef);
|
|
@@ -73,7 +73,7 @@ describe('KjOverlayService', () => {
|
|
|
73
73
|
standalone: true,
|
|
74
74
|
template: '<ng-template #tpl><div>overlay</div></ng-template>',
|
|
75
75
|
})
|
|
76
|
-
class TestComponent {
|
|
76
|
+
class TestComponent implements OnInit {
|
|
77
77
|
@ViewChild('tpl', { static: true }) tpl!: TemplateRef<unknown>;
|
|
78
78
|
readonly svc = inject(KjOverlayService);
|
|
79
79
|
readonly vcr = inject(ViewContainerRef);
|
package/src/select/select.ts
CHANGED
|
@@ -188,7 +188,7 @@ export class KjSelectContent {
|
|
|
188
188
|
this.el.nativeElement.querySelectorAll('[kjOption]')
|
|
189
189
|
) as HTMLElement[]).map((el, i) => ({
|
|
190
190
|
el,
|
|
191
|
-
value: (el as
|
|
191
|
+
value: (el as HTMLElement & { __kjOptionValue?: unknown }).__kjOptionValue,
|
|
192
192
|
id: el.id || `kj-option-${i}`,
|
|
193
193
|
}));
|
|
194
194
|
}
|
|
@@ -234,7 +234,7 @@ export class KjOption {
|
|
|
234
234
|
|
|
235
235
|
constructor() {
|
|
236
236
|
effect(() => {
|
|
237
|
-
(this.el.nativeElement as
|
|
237
|
+
(this.el.nativeElement as HTMLElement & { __kjOptionValue?: unknown }).__kjOptionValue = this.kjOptionValue();
|
|
238
238
|
});
|
|
239
239
|
afterNextRender(() => {
|
|
240
240
|
if (!this.el.nativeElement.id) {
|
package/src/table/table.spec.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component } from '@angular/core';
|
|
2
2
|
import { ColumnDef } from '@tanstack/angular-table';
|
|
3
|
-
import { render
|
|
3
|
+
import { render } from '@testing-library/angular';
|
|
4
4
|
import { axe, toHaveNoViolations } from 'jest-axe';
|
|
5
5
|
import { KjTable, KjTableHeader } from './table';
|
|
6
6
|
|
package/src/toast/toast.spec.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TestBed } from '@angular/core/testing';
|
|
2
|
+
import { render } from '@testing-library/angular';
|
|
2
3
|
import { axe, toHaveNoViolations } from 'jest-axe';
|
|
3
4
|
import { KjToast, KjToastViewport } from './toast';
|
|
4
5
|
import { KjToastService } from './toast.service';
|
|
5
|
-
import { Component, inject } from '@angular/core';
|
|
6
6
|
|
|
7
7
|
expect.extend(toHaveNoViolations);
|
|
8
8
|
|
|
@@ -47,43 +47,44 @@ describe('KjToastViewport', () => {
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
describe('KjToastService', () => {
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
let svc: KjToastService;
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
TestBed.configureTestingModule({});
|
|
54
|
+
svc = TestBed.inject(KjToastService);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('show(message) adds a toast', () => {
|
|
52
58
|
expect(svc.toasts().length).toBe(0);
|
|
53
59
|
svc.show('Hello', { duration: 0 });
|
|
54
60
|
expect(svc.toasts().length).toBe(1);
|
|
55
61
|
expect(svc.toasts()[0].message).toBe('Hello');
|
|
56
62
|
});
|
|
57
63
|
|
|
58
|
-
it('dismiss() removes a toast',
|
|
59
|
-
const svc = new KjToastService();
|
|
64
|
+
it('dismiss() removes a toast', () => {
|
|
60
65
|
const id = svc.show('Test', { duration: 0 });
|
|
61
66
|
svc.dismiss(id);
|
|
62
67
|
expect(svc.toasts().length).toBe(0);
|
|
63
68
|
});
|
|
64
69
|
|
|
65
|
-
it('success() sets variant=success',
|
|
66
|
-
const svc = new KjToastService();
|
|
70
|
+
it('success() sets variant=success', () => {
|
|
67
71
|
svc.success('Done', { duration: 0 });
|
|
68
72
|
expect(svc.toasts()[0].variant).toBe('success');
|
|
69
73
|
});
|
|
70
74
|
|
|
71
|
-
it('error() sets variant=destructive',
|
|
72
|
-
const svc = new KjToastService();
|
|
75
|
+
it('error() sets variant=destructive', () => {
|
|
73
76
|
svc.error('Fail', { duration: 0 });
|
|
74
77
|
expect(svc.toasts()[0].variant).toBe('destructive');
|
|
75
78
|
});
|
|
76
79
|
|
|
77
|
-
it('dismissAll() clears all toasts',
|
|
78
|
-
const svc = new KjToastService();
|
|
80
|
+
it('dismissAll() clears all toasts', () => {
|
|
79
81
|
svc.show('A', { duration: 0 });
|
|
80
82
|
svc.show('B', { duration: 0 });
|
|
81
83
|
svc.dismissAll();
|
|
82
84
|
expect(svc.toasts().length).toBe(0);
|
|
83
85
|
});
|
|
84
86
|
|
|
85
|
-
it('contextFor() exposes a bound dismiss callback',
|
|
86
|
-
const svc = new KjToastService();
|
|
87
|
+
it('contextFor() exposes a bound dismiss callback', () => {
|
|
87
88
|
const id = svc.show('Hello', { duration: 0 });
|
|
88
89
|
const ctx = svc.contextFor(svc.toasts()[0]);
|
|
89
90
|
expect(ctx.id).toBe(id);
|
package/src/toast/toast.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
DestroyRef, Directive, ElementRef, TemplateRef,
|
|
3
3
|
afterNextRender, computed, inject, input, signal,
|
|
4
4
|
} from '@angular/core';
|
|
5
|
-
import {
|
|
5
|
+
import { KjToastService, KjToastTemplateContext, KjToastVariant } from './toast.service';
|
|
6
6
|
import { KJ_TOAST_STRATEGY } from './toast.strategy';
|
|
7
7
|
import { KjToastPositionX, KjToastPositionY } from './toast.types';
|
|
8
8
|
|