@kouji-ui/core 0.0.4 → 0.1.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.
Files changed (127) hide show
  1. package/fesm2022/kouji-ui-core.mjs +26789 -0
  2. package/fesm2022/kouji-ui-core.mjs.map +1 -0
  3. package/icon/icon.css +40 -0
  4. package/package.json +20 -9
  5. package/types/kouji-ui-core.d.ts +13545 -0
  6. package/typography/prose.css +312 -0
  7. package/.turbo/turbo-build.log +0 -27
  8. package/CHANGELOG.md +0 -21
  9. package/ng-package.json +0 -7
  10. package/src/a11y/.gitkeep +0 -0
  11. package/src/a11y/aria-describedby.spec.ts +0 -55
  12. package/src/a11y/aria-describedby.ts +0 -33
  13. package/src/a11y/focus-trap.spec.ts +0 -86
  14. package/src/a11y/focus-trap.ts +0 -70
  15. package/src/a11y/index.ts +0 -9
  16. package/src/a11y/live-region.spec.ts +0 -58
  17. package/src/a11y/live-region.ts +0 -48
  18. package/src/a11y/roving-tabindex.spec.ts +0 -62
  19. package/src/a11y/roving-tabindex.ts +0 -104
  20. package/src/a11y/visually-hidden.spec.ts +0 -34
  21. package/src/a11y/visually-hidden.ts +0 -24
  22. package/src/accordion/accordion.context.ts +0 -22
  23. package/src/accordion/accordion.spec.ts +0 -32
  24. package/src/accordion/accordion.ts +0 -129
  25. package/src/accordion/index.ts +0 -2
  26. package/src/avatar/avatar.spec.ts +0 -18
  27. package/src/avatar/avatar.ts +0 -26
  28. package/src/avatar/index.ts +0 -1
  29. package/src/badge/badge.spec.ts +0 -20
  30. package/src/badge/badge.ts +0 -14
  31. package/src/badge/index.ts +0 -1
  32. package/src/button/button.example.ts +0 -30
  33. package/src/button/button.finance.example.ts +0 -37
  34. package/src/button/button.retro.example.ts +0 -47
  35. package/src/button/button.sizes.example.ts +0 -25
  36. package/src/button/button.spec.ts +0 -32
  37. package/src/button/button.ts +0 -44
  38. package/src/button/index.ts +0 -1
  39. package/src/chart/chart.spec.ts +0 -27
  40. package/src/chart/chart.ts +0 -48
  41. package/src/chart/index.ts +0 -1
  42. package/src/checkbox/checkbox.spec.ts +0 -35
  43. package/src/checkbox/checkbox.ts +0 -82
  44. package/src/checkbox/index.ts +0 -1
  45. package/src/dialog/dialog.confirm.example.ts +0 -57
  46. package/src/dialog/dialog.context.ts +0 -11
  47. package/src/dialog/dialog.example.ts +0 -40
  48. package/src/dialog/dialog.finance.example.ts +0 -47
  49. package/src/dialog/dialog.retro.example.ts +0 -46
  50. package/src/dialog/dialog.service.ts +0 -176
  51. package/src/dialog/dialog.spec.ts +0 -122
  52. package/src/dialog/dialog.ts +0 -201
  53. package/src/dialog/index.ts +0 -9
  54. package/src/example-components.ts +0 -33
  55. package/src/form/form.context.ts +0 -3
  56. package/src/form/form.spec.ts +0 -25
  57. package/src/form/form.ts +0 -46
  58. package/src/form/index.ts +0 -2
  59. package/src/input/index.ts +0 -1
  60. package/src/input/input.spec.ts +0 -43
  61. package/src/input/input.ts +0 -80
  62. package/src/menu/index.ts +0 -2
  63. package/src/menu/menu.context.ts +0 -10
  64. package/src/menu/menu.example.ts +0 -39
  65. package/src/menu/menu.spec.ts +0 -168
  66. package/src/menu/menu.ts +0 -176
  67. package/src/popover/index.ts +0 -12
  68. package/src/popover/popover.context.ts +0 -18
  69. package/src/popover/popover.example.ts +0 -50
  70. package/src/popover/popover.finance.example.ts +0 -52
  71. package/src/popover/popover.retro.example.ts +0 -53
  72. package/src/popover/popover.spec.ts +0 -52
  73. package/src/popover/popover.ts +0 -124
  74. package/src/primitives/.gitkeep +0 -0
  75. package/src/primitives/forms/form-control.spec.ts +0 -59
  76. package/src/primitives/forms/form-control.ts +0 -90
  77. package/src/primitives/forms/index.ts +0 -1
  78. package/src/primitives/index.ts +0 -3
  79. package/src/primitives/interaction/disabled.spec.ts +0 -47
  80. package/src/primitives/interaction/disabled.ts +0 -24
  81. package/src/primitives/interaction/focus-ring.spec.ts +0 -62
  82. package/src/primitives/interaction/focus-ring.ts +0 -57
  83. package/src/primitives/interaction/index.ts +0 -2
  84. package/src/primitives/overlay/index.ts +0 -1
  85. package/src/primitives/overlay/overlay.spec.ts +0 -90
  86. package/src/primitives/overlay/overlay.ts +0 -106
  87. package/src/public-api.ts +0 -35
  88. package/src/radio/index.ts +0 -2
  89. package/src/radio/radio.context.ts +0 -3
  90. package/src/radio/radio.spec.ts +0 -36
  91. package/src/radio/radio.ts +0 -55
  92. package/src/select/index.ts +0 -2
  93. package/src/select/select.context.ts +0 -3
  94. package/src/select/select.spec.ts +0 -145
  95. package/src/select/select.ts +0 -250
  96. package/src/styles/docs-themes.css +0 -82
  97. package/src/table/index.ts +0 -1
  98. package/src/table/table.spec.ts +0 -113
  99. package/src/table/table.ts +0 -126
  100. package/src/tabs/index.ts +0 -2
  101. package/src/tabs/tabs.context.ts +0 -9
  102. package/src/tabs/tabs.spec.ts +0 -40
  103. package/src/tabs/tabs.ts +0 -130
  104. package/src/test-setup.ts +0 -5
  105. package/src/toast/index.ts +0 -21
  106. package/src/toast/toast.example.ts +0 -134
  107. package/src/toast/toast.finance.example.ts +0 -68
  108. package/src/toast/toast.retro.example.ts +0 -69
  109. package/src/toast/toast.service.ts +0 -153
  110. package/src/toast/toast.spec.ts +0 -95
  111. package/src/toast/toast.strategy.ts +0 -102
  112. package/src/toast/toast.ts +0 -307
  113. package/src/toast/toast.types.ts +0 -5
  114. package/src/toggle/index.ts +0 -1
  115. package/src/toggle/toggle.spec.ts +0 -24
  116. package/src/toggle/toggle.ts +0 -40
  117. package/src/tooltip/index.ts +0 -5
  118. package/src/tooltip/tooltip.example.ts +0 -46
  119. package/src/tooltip/tooltip.finance.example.ts +0 -54
  120. package/src/tooltip/tooltip.placements.example.ts +0 -56
  121. package/src/tooltip/tooltip.retro.example.ts +0 -65
  122. package/src/tooltip/tooltip.spec.ts +0 -104
  123. package/src/tooltip/tooltip.ts +0 -129
  124. package/tsconfig.lib.json +0 -13
  125. package/tsconfig.lib.prod.json +0 -11
  126. package/tsconfig.spec.json +0 -10
  127. package/vite.config.ts +0 -19
@@ -1,47 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { KjButton } from './button';
3
-
4
- @Component({
5
- selector: 'kj-example-button-retro',
6
- standalone: true,
7
- imports: [KjButton],
8
- styleUrls: ['../styles/docs-themes.css'],
9
- styles: [`
10
- :host { display: block; padding: 2rem; background: var(--kj-bg); font-family: var(--kj-font); color: var(--kj-text); }
11
- .row { display: flex; gap: 0.625rem; flex-wrap: wrap; }
12
- button[kjButton] {
13
- padding: 0.35rem 0.875rem; font-family: var(--kj-font); font-size: 0.75rem;
14
- font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
15
- border: var(--kj-btn-border); border-radius: var(--kj-radius-md); cursor: pointer;
16
- box-shadow: var(--kj-shadow-sm); transition: var(--kj-transition);
17
- }
18
- button[kjButton]:not([data-variant="link"]):not([data-variant="ghost"]):hover {
19
- transform: translate(-1px, -1px); box-shadow: var(--kj-shadow-md);
20
- }
21
- button[kjButton][data-variant="default"] { background: var(--kj-text); color: var(--kj-bg); }
22
- button[kjButton][data-variant="destructive"] { background: var(--kj-destructive); color: #fff; }
23
- button[kjButton][data-variant="link"] {
24
- background: transparent; color: var(--kj-text); border: none; box-shadow: none;
25
- border-radius: 0; padding: 0.35rem 0.875rem; text-decoration: none;
26
- }
27
- button[kjButton][data-variant="link"]:hover {
28
- text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px;
29
- }
30
- button[kjButton][data-variant="ghost"] {
31
- background: transparent; color: var(--kj-text); border: 2px solid transparent; box-shadow: none; opacity: 0.7;
32
- }
33
- button[kjButton][data-variant="ghost"]:hover { opacity: 1; background: rgba(0,0,0,0.06); }
34
- [aria-disabled="true"] { opacity: 0.4; pointer-events: none; }
35
- `],
36
- host: { class: 'kj-theme-retro' },
37
- template: `
38
- <div class="row">
39
- <button kjButton [kjVariant]="'default'">Default</button>
40
- <button kjButton [kjVariant]="'destructive'">Destructive</button>
41
- <button kjButton [kjVariant]="'link'">Link</button>
42
- <button kjButton [kjVariant]="'ghost'">Ghost</button>
43
- <button kjButton [kjDisabled]="true">Disabled</button>
44
- </div>
45
- `,
46
- })
47
- export class ButtonRetroExample {}
@@ -1,25 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { KjButton } from './button';
3
-
4
- @Component({
5
- selector: 'kj-example-button-sizes',
6
- standalone: true,
7
- imports: [KjButton],
8
- styleUrls: ['../styles/docs-themes.css'],
9
- styles: [`
10
- :host { display: block; padding: 2rem; background: var(--kj-bg); font-family: var(--kj-font); }
11
- .row { display: flex; flex-direction: row; gap: 0.75rem; align-items: center; flex-wrap: wrap; }
12
- button[kjButton] { background: var(--kj-accent); color: var(--kj-accent-on); border: var(--kj-btn-border); cursor: pointer; font-family: var(--kj-font); transition: var(--kj-transition); }
13
- [data-size="sm"] { padding: 0.3rem 0.75rem; font-size: 0.75rem; }
14
- [data-size="md"] { padding: 0.5rem 1.25rem; font-size: 0.875rem; }
15
- [data-size="lg"] { padding: 0.75rem 1.75rem; font-size: 1rem; }
16
- `],
17
- template: `
18
- <div class="row">
19
- <button kjButton [kjSize]="'sm'">Small</button>
20
- <button kjButton [kjSize]="'md'">Medium (default)</button>
21
- <button kjButton [kjSize]="'lg'">Large</button>
22
- </div>
23
- `,
24
- })
25
- export class ButtonSizesExample {}
@@ -1,32 +0,0 @@
1
- import { render } from '@testing-library/angular';
2
- import { axe, toHaveNoViolations } from 'jest-axe';
3
- import { KjButton } from './button';
4
-
5
- expect.extend(toHaveNoViolations);
6
-
7
- describe('KjButton', () => {
8
- it('renders a button element', async () => {
9
- const { getByRole } = await render(`<button kjButton>Click</button>`, { imports: [KjButton] });
10
- expect(getByRole('button')).toBeInTheDocument();
11
- });
12
-
13
- it('sets data-variant attribute', async () => {
14
- const { getByRole } = await render(`<button kjButton [kjVariant]="'destructive'">Delete</button>`, { imports: [KjButton] });
15
- expect(getByRole('button')).toHaveAttribute('data-variant', 'destructive');
16
- });
17
-
18
- it('sets data-size attribute', async () => {
19
- const { getByRole } = await render(`<button kjButton [kjSize]="'sm'">Small</button>`, { imports: [KjButton] });
20
- expect(getByRole('button')).toHaveAttribute('data-size', 'sm');
21
- });
22
-
23
- it('sets aria-disabled when disabled via hostDirective', async () => {
24
- const { getByRole } = await render(`<button kjButton [kjDisabled]="true">Disabled</button>`, { imports: [KjButton] });
25
- expect(getByRole('button')).toHaveAttribute('aria-disabled', 'true');
26
- });
27
-
28
- it('passes axe audit', async () => {
29
- const { container } = await render(`<button kjButton>Action</button>`, { imports: [KjButton] });
30
- expect(await axe(container)).toHaveNoViolations();
31
- });
32
- });
@@ -1,44 +0,0 @@
1
- import { Directive, input } from '@angular/core';
2
- import { KjDisabled, KjFocusRing } from '../primitives';
3
-
4
- export type KjButtonVariant = 'default' | 'destructive' | 'outline' | 'ghost' | 'link';
5
- export type KjButtonSize = 'sm' | 'md' | 'lg' | 'icon';
6
-
7
- /**
8
- * Enhances a native ```<button>``` with variant, size, disabled state, and focus-ring behavior.
9
- * Composes `KjDisabled` and `KjFocusRing` via `hostDirectives`.
10
- *
11
- * @example
12
- * ```html
13
- * <button kjButton [kjVariant]="'destructive'" [kjDisabled]="isLoading()">Delete</button>
14
- * ```
15
- * @doc
16
- * @doc-example Variants
17
- * @doc-theme default
18
- * @doc-file button.example.ts
19
- * @doc-theme retro
20
- * @doc-file button.retro.example.ts
21
- * @doc-theme finance
22
- * @doc-file button.finance.example.ts
23
- * @doc-example Sizes
24
- * @doc-file button.sizes.example.ts
25
- * @category Core/Base
26
- */
27
- @Directive({
28
- selector: '[kjButton]',
29
- standalone: true,
30
- hostDirectives: [
31
- { directive: KjDisabled, inputs: ['kjDisabled'] },
32
- KjFocusRing,
33
- ],
34
- host: {
35
- '[attr.data-variant]': 'kjVariant()',
36
- '[attr.data-size]': 'kjSize()',
37
- },
38
- })
39
- export class KjButton {
40
- /** The visual variant of the button. Defaults to `'default'`. */
41
- kjVariant = input<KjButtonVariant>('default');
42
- /** The size of the button. Defaults to `'md'`. */
43
- kjSize = input<KjButtonSize>('md');
44
- }
@@ -1 +0,0 @@
1
- export { KjButton, type KjButtonVariant, type KjButtonSize } from './button';
@@ -1,27 +0,0 @@
1
- import { render } from '@testing-library/angular';
2
- import { axe, toHaveNoViolations } from 'jest-axe';
3
- import { KjChart } from './chart';
4
-
5
- expect.extend(toHaveNoViolations);
6
-
7
- describe('KjChart', () => {
8
- it('renders the host element', async () => {
9
- const { container } = await render(`<div kjChart [kjChartOption]="{}"></div>`, { imports: [KjChart] });
10
- expect(container.querySelector('[kjChart]')).toBeInTheDocument();
11
- });
12
-
13
- it('sets role=img', async () => {
14
- const { container } = await render(`<div kjChart [kjChartOption]="{}" kjChartLabel="Sales"></div>`, { imports: [KjChart] });
15
- expect(container.querySelector('[kjChart]')).toHaveAttribute('role', 'img');
16
- });
17
-
18
- it('sets aria-label', async () => {
19
- const { container } = await render(`<div kjChart [kjChartOption]="{}" kjChartLabel="Revenue chart"></div>`, { imports: [KjChart] });
20
- expect(container.querySelector('[kjChart]')).toHaveAttribute('aria-label', 'Revenue chart');
21
- });
22
-
23
- it('passes axe audit', async () => {
24
- const { container } = await render(`<div kjChart [kjChartOption]="{}" kjChartLabel="Revenue chart"></div>`, { imports: [KjChart] });
25
- expect(await axe(container)).toHaveNoViolations();
26
- });
27
- });
@@ -1,48 +0,0 @@
1
- import { Directive, DestroyRef, ElementRef, inject, input, afterNextRender, afterEveryRender } from '@angular/core';
2
- import type { EChartsOption } from 'echarts';
3
-
4
- /**
5
- * Wraps Apache ECharts. Initializes after first render, updates reactively, disposes on destroy.
6
- * Always provide `kjChartLabel` for WCAG AAA compliance.
7
- *
8
- * @example
9
- * ```html
10
- * <div kjChart [kjChartOption]="chartOption()" kjChartLabel="Monthly revenue" style="height:300px"></div>
11
- * ```
12
- * @category Core/Data
13
- */
14
- @Directive({
15
- selector: '[kjChart]', standalone: true,
16
- host: { role: 'img', '[attr.aria-label]': 'kjChartLabel() || null' },
17
- })
18
- export class KjChart {
19
- private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);
20
- private readonly destroyRef = inject(DestroyRef);
21
-
22
- /** ECharts option object defining the chart. */
23
- kjChartOption = input.required<EChartsOption>();
24
- /** Accessible label for the chart. Required for WCAG AAA compliance. */
25
- kjChartLabel = input<string>('');
26
-
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- private chart: any;
29
-
30
- constructor() {
31
- afterNextRender(async () => {
32
- try {
33
- const echarts = await import('echarts');
34
- this.chart = echarts.init(this.el.nativeElement);
35
- this.chart.setOption(this.kjChartOption());
36
- this.destroyRef.onDestroy(() => this.chart?.dispose());
37
- } catch {
38
- // ECharts cannot initialize in non-browser environments (jsdom, SSR)
39
- }
40
- });
41
-
42
- afterEveryRender(() => {
43
- if (this.chart) {
44
- this.chart.setOption(this.kjChartOption());
45
- }
46
- });
47
- }
48
- }
@@ -1 +0,0 @@
1
- export { KjChart } from './chart';
@@ -1,35 +0,0 @@
1
- import { render, fireEvent } from '@testing-library/angular';
2
- import { axe, toHaveNoViolations } from 'jest-axe';
3
- import { KjCheckbox } from './checkbox';
4
-
5
- expect.extend(toHaveNoViolations);
6
-
7
- describe('KjCheckbox', () => {
8
- it('sets role=checkbox', async () => {
9
- const { getByRole } = await render(`<div kjCheckbox tabindex="0">Check</div>`, { imports: [KjCheckbox] });
10
- expect(getByRole('checkbox')).toBeInTheDocument();
11
- });
12
-
13
- it('has aria-checked=false by default', async () => {
14
- const { getByRole } = await render(`<div kjCheckbox tabindex="0">Check</div>`, { imports: [KjCheckbox] });
15
- expect(getByRole('checkbox')).toHaveAttribute('aria-checked', 'false');
16
- });
17
-
18
- it('toggles checked on click', async () => {
19
- const { getByRole } = await render(`<div kjCheckbox tabindex="0">Check</div>`, { imports: [KjCheckbox] });
20
- fireEvent.click(getByRole('checkbox'));
21
- expect(getByRole('checkbox')).toHaveAttribute('aria-checked', 'true');
22
- expect(getByRole('checkbox')).toHaveAttribute('data-checked', '');
23
- });
24
-
25
- it('toggles on Space key', async () => {
26
- const { getByRole } = await render(`<div kjCheckbox tabindex="0">Check</div>`, { imports: [KjCheckbox] });
27
- fireEvent.keyDown(getByRole('checkbox'), { key: ' ' });
28
- expect(getByRole('checkbox')).toHaveAttribute('aria-checked', 'true');
29
- });
30
-
31
- it('passes axe audit', async () => {
32
- const { container } = await render(`<div kjCheckbox tabindex="0" aria-label="Accept terms">Accept</div>`, { imports: [KjCheckbox] });
33
- expect(await axe(container)).toHaveNoViolations();
34
- });
35
- });
@@ -1,82 +0,0 @@
1
- import { Directive, inject, model } from '@angular/core';
2
- import { KjDisabled, KjFocusRing, KjFormControl } from '../primitives';
3
-
4
- /**
5
- * Adds checkbox semantics with Angular forms integration.
6
- * Supports `formControl`, `formControlName`, and `ngModel` bindings.
7
- *
8
- * @example
9
- * ```html
10
- * <div kjCheckbox tabindex="0" [(kjChecked)]="accepted" aria-label="Accept terms">Accept</div>
11
- * ```
12
- * @doc
13
- * @doc-file checkbox.example.ts
14
- * ```typescript
15
- * import { Component, signal } from '@angular/core';
16
- * import { KjCheckbox } from '@kouji-ui/core';
17
- *
18
- * @Component({
19
- * standalone: true,
20
- * imports: [KjCheckbox],
21
- * styles: [`
22
- * .row { display: flex; flex-direction: column; gap: 1rem; padding: 2rem; background: #0c0c0c; }
23
- * .item { display: flex; align-items: center; gap: 0.75rem; }
24
- * [kjCheckbox] { width: 18px; height: 18px; border: 2px solid #333; background: #111; cursor: pointer; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
25
- * [data-checked] { background: #b8f500; border-color: #b8f500; }
26
- * [data-checked]::after { content: '✓'; color: #0c0c0c; font-size: 0.75rem; font-weight: bold; }
27
- * span { color: #888; font-family: 'JetBrains Mono', monospace; font-size: 0.875rem; }
28
- * `],
29
- * template: `
30
- * <div class="row">
31
- * <div class="item">
32
- * <div kjCheckbox tabindex="0" [(kjChecked)]="terms" aria-label="Accept terms"></div>
33
- * <span>Accept terms — {{ terms() ? 'checked' : 'unchecked' }}</span>
34
- * </div>
35
- * <div class="item">
36
- * <div kjCheckbox tabindex="0" [(kjChecked)]="newsletter" aria-label="Newsletter"></div>
37
- * <span>Subscribe to newsletter</span>
38
- * </div>
39
- * </div>
40
- * `,
41
- * })
42
- * export class CheckboxExampleComponent {
43
- * terms = signal(false);
44
- * newsletter = signal(true);
45
- * }
46
- * ```
47
- * @category Core/Inputs
48
- */
49
- @Directive({
50
- selector: '[kjCheckbox]',
51
- standalone: true,
52
- hostDirectives: [
53
- { directive: KjDisabled, inputs: ['kjDisabled'] },
54
- KjFocusRing,
55
- KjFormControl,
56
- ],
57
- host: {
58
- role: 'checkbox',
59
- '[attr.aria-checked]': 'kjChecked().toString()',
60
- '[attr.data-checked]': 'kjChecked() ? "" : null',
61
- '[attr.disabled]': 'formCtrl.disabled() ? "" : null',
62
- '(click)': 'toggle()',
63
- '(keydown.space)': 'onSpace($event)',
64
- '(blur)': 'formCtrl.notifyTouched()',
65
- },
66
- })
67
- export class KjCheckbox {
68
- readonly formCtrl = inject(KjFormControl);
69
-
70
- /** Whether the checkbox is checked. Supports two-way binding. */
71
- kjChecked = model<boolean>(false);
72
-
73
- /** @internal */
74
- toggle(): void {
75
- const next = !this.kjChecked();
76
- this.kjChecked.set(next);
77
- this.formCtrl.notifyChange(next);
78
- }
79
-
80
- /** @internal */
81
- onSpace(e: Event): void { e.preventDefault(); this.toggle(); }
82
- }
@@ -1 +0,0 @@
1
- export { KjCheckbox } from './checkbox';
@@ -1,57 +0,0 @@
1
- import { Component, signal } from '@angular/core';
2
- import { KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle } from './dialog';
3
- import { KjButton } from '../button/button';
4
-
5
- @Component({
6
- selector: 'kj-example-dialog-confirm',
7
- standalone: true,
8
- imports: [KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle, KjButton],
9
- styleUrls: ['../styles/docs-themes.css'],
10
- styles: [`
11
- :host { display: flex; align-items: center; justify-content: center; gap: 1rem; padding: 3rem 2rem; background: var(--kj-bg); font-family: var(--kj-font); min-height: 160px; flex-direction: column; color: var(--kj-text); }
12
- .status { font-size: 0.8125rem; color: var(--kj-text-muted); min-height: 1.25rem; }
13
- .status.confirmed { color: var(--kj-accent); }
14
- .status.cancelled { color: var(--kj-destructive); }
15
- button[kjButton] { padding: 0.5rem 1.5rem; border: var(--kj-btn-border); cursor: pointer; font-family: var(--kj-font); font-size: 0.875rem; }
16
- [data-variant="destructive"] { background: var(--kj-destructive); color: #fff; }
17
- [data-variant="outline"] { background: transparent; color: var(--kj-text); border: 1px solid var(--kj-border); }
18
- ::ng-deep .kj-dialog-backdrop { background: var(--kj-backdrop); }
19
- ::ng-deep .kj-dialog-panel { background: transparent; box-shadow: none; }
20
- ::ng-deep [kjDialogOverlay] { display: flex; align-items: center; justify-content: center; position: fixed; inset: 0; }
21
- ::ng-deep [kjDialog] { background: var(--kj-surface); border: 1px solid var(--kj-border); border-radius: var(--kj-radius-lg); padding: 1.5rem; min-width: 22rem; color: var(--kj-text); font-family: var(--kj-font); box-shadow: var(--kj-shadow-hard); }
22
- ::ng-deep [kjDialogTitle] { margin: 0 0 0.5rem; font-size: 1.125rem; color: var(--kj-text); }
23
- ::ng-deep .dialog-body { margin: 0 0 1.5rem; font-size: 0.875rem; color: var(--kj-text-muted); line-height: 1.6; }
24
- ::ng-deep .dialog-actions { display: flex; gap: 0.75rem; justify-content: flex-end; }
25
- ::ng-deep .dialog-actions button[kjButton] { padding: 0.4rem 1rem; font-size: 0.8125rem; }
26
- `],
27
- template: `
28
- <button kjButton [kjVariant]="'destructive'"
29
- [kjDialogTrigger]="confirmDialog"
30
- (kjDialogClosed)="onResult($event)">
31
- Delete Account
32
- </button>
33
- <ng-template #confirmDialog>
34
- <div kjDialogOverlay>
35
- <div kjDialog #dlg="kjDialog">
36
- <h2 kjDialogTitle>Are you absolutely sure?</h2>
37
- <p class="dialog-body">This action cannot be undone. All your data will be permanently removed.</p>
38
- <div class="dialog-actions">
39
- <button kjButton [kjVariant]="'outline'" (click)="dlg.close('cancelled')">Cancel</button>
40
- <button kjButton [kjVariant]="'destructive'" (click)="dlg.close('confirmed')">Yes, delete</button>
41
- </div>
42
- </div>
43
- </div>
44
- </ng-template>
45
- <span class="status"
46
- [class.confirmed]="result() === 'confirmed'"
47
- [class.cancelled]="result() === 'cancelled'">
48
- {{ result() === 'confirmed' ? '✓ Account deleted' : result() === 'cancelled' ? '✕ Cancelled' : '' }}
49
- </span>
50
- `,
51
- })
52
- export class DialogConfirmExample {
53
- readonly result = signal<'confirmed' | 'cancelled' | null>(null);
54
- onResult(value: unknown): void {
55
- if (value === 'confirmed' || value === 'cancelled') this.result.set(value);
56
- }
57
- }
@@ -1,11 +0,0 @@
1
- import { InjectionToken, Signal } from '@angular/core';
2
-
3
- export interface KjDialogContext {
4
- readonly open: Signal<boolean>;
5
- readonly dialogId: string;
6
- readonly closeOnEscape: Signal<boolean>;
7
- readonly closeOnBackdrop: Signal<boolean>;
8
- close(result?: unknown): void;
9
- }
10
-
11
- export const KJ_DIALOG = new InjectionToken<KjDialogContext>('KjDialog');
@@ -1,40 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle, KjDialogClose } from './dialog';
3
- import { KjButton } from '../button/button';
4
-
5
- @Component({
6
- selector: 'kj-example-dialog-basic',
7
- standalone: true,
8
- imports: [KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle, KjDialogClose, KjButton],
9
- styleUrls: ['../styles/docs-themes.css'],
10
- styles: [`
11
- :host { display: flex; align-items: center; justify-content: center; padding: 3rem 2rem; background: var(--kj-bg); font-family: var(--kj-font); min-height: 160px; }
12
- button[kjButton] { padding: 0.5rem 1.5rem; border: var(--kj-btn-border); cursor: pointer; font-family: var(--kj-font); font-size: 0.875rem; transition: var(--kj-transition); }
13
- [data-variant="default"] { background: var(--kj-accent); color: var(--kj-accent-on); }
14
- [data-variant="outline"] { background: transparent; color: var(--kj-text); border: 1px solid var(--kj-border); }
15
- ::ng-deep .kj-dialog-backdrop { background: var(--kj-backdrop); }
16
- ::ng-deep .kj-dialog-panel { background: transparent; box-shadow: none; }
17
- ::ng-deep [kjDialogOverlay] { display: flex; align-items: center; justify-content: center; position: fixed; inset: 0; }
18
- ::ng-deep [kjDialog] { background: var(--kj-surface); border: 1px solid var(--kj-border); border-radius: var(--kj-radius-lg); padding: 1.5rem; min-width: 20rem; color: var(--kj-text); font-family: var(--kj-font); box-shadow: var(--kj-shadow-hard); }
19
- ::ng-deep [kjDialogTitle] { margin: 0 0 0.5rem; font-size: 1.125rem; color: var(--kj-text); }
20
- ::ng-deep .dialog-body { margin: 0 0 1.5rem; font-size: 0.875rem; color: var(--kj-text-muted); line-height: 1.6; }
21
- ::ng-deep .dialog-actions { display: flex; gap: 0.75rem; justify-content: flex-end; }
22
- ::ng-deep .dialog-actions button[kjButton] { padding: 0.4rem 1rem; font-size: 0.8125rem; }
23
- `],
24
- template: `
25
- <button kjButton [kjVariant]="'default'" [kjDialogTrigger]="myDialog">Open Dialog</button>
26
- <ng-template #myDialog>
27
- <div kjDialogOverlay>
28
- <div kjDialog>
29
- <h2 kjDialogTitle>Edit Profile</h2>
30
- <p class="dialog-body">Make changes to your profile settings here.</p>
31
- <div class="dialog-actions">
32
- <button kjButton [kjVariant]="'outline'" kjDialogClose>Cancel</button>
33
- <button kjButton [kjVariant]="'default'" kjDialogClose>Save Changes</button>
34
- </div>
35
- </div>
36
- </div>
37
- </ng-template>
38
- `,
39
- })
40
- export class DialogBasicExample {}
@@ -1,47 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle, KjDialogClose } from './dialog';
3
-
4
- @Component({
5
- selector: 'kj-example-dialog-finance',
6
- standalone: true,
7
- imports: [KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle, KjDialogClose],
8
- styleUrls: ['../styles/docs-themes.css'],
9
- styles: [`
10
- :host { display: flex; align-items: center; justify-content: center; padding: 3rem 2rem; background: var(--kj-bg); font-family: var(--kj-font); min-height: 160px; }
11
- button {
12
- padding: 0.45rem 1.125rem; background: var(--kj-accent); color: var(--kj-accent-on);
13
- border: var(--kj-btn-border); border-color: var(--kj-accent);
14
- border-radius: var(--kj-radius-md); cursor: pointer; font-family: var(--kj-font); font-size: 0.875rem; font-weight: 500;
15
- }
16
- button:hover { background: #2563eb; }
17
- ::ng-deep .kj-dialog-backdrop { background: var(--kj-backdrop); }
18
- ::ng-deep .kj-dialog-panel { background: transparent; box-shadow: none; }
19
- ::ng-deep [kjDialogOverlay] { display: flex; align-items: center; justify-content: center; position: fixed; inset: 0; }
20
- ::ng-deep [kjDialog] { background: var(--kj-surface); border: 1px solid var(--kj-border); border-radius: var(--kj-radius-lg); padding: 1.5rem; min-width: 22rem; box-shadow: var(--kj-shadow-hard); font-family: var(--kj-font); color: var(--kj-text); }
21
- ::ng-deep [kjDialogTitle] { margin: 0 0 0.375rem; font-size: 1.0625rem; font-weight: 600; color: var(--kj-text); }
22
- ::ng-deep .dialog-body { margin: 0 0 1.5rem; font-size: 0.875rem; color: var(--kj-text-muted); line-height: 1.6; }
23
- ::ng-deep .dialog-actions { display: flex; gap: 0.5rem; justify-content: flex-end; }
24
- ::ng-deep [kjDialogOverlay] button { padding: 0.4rem 1rem; font-size: 0.8125rem; font-weight: 500; border-radius: var(--kj-radius-md); }
25
- ::ng-deep .btn-cancel { background: var(--kj-surface); color: var(--kj-text); border: 1px solid var(--kj-border); }
26
- ::ng-deep .btn-cancel:hover { background: var(--kj-bg); }
27
- ::ng-deep .btn-primary { background: var(--kj-accent); color: var(--kj-accent-on); border-color: var(--kj-accent); }
28
- ::ng-deep .btn-primary:hover { background: #2563eb; }
29
- `],
30
- host: { class: 'kj-theme-finance' },
31
- template: `
32
- <button [kjDialogTrigger]="myDialog">Open Dialog</button>
33
- <ng-template #myDialog>
34
- <div kjDialogOverlay>
35
- <div kjDialog>
36
- <h2 kjDialogTitle>Edit Profile</h2>
37
- <p class="dialog-body">Make changes to your profile settings here.</p>
38
- <div class="dialog-actions">
39
- <button class="btn-cancel" kjDialogClose>Cancel</button>
40
- <button class="btn-primary" kjDialogClose>Save Changes</button>
41
- </div>
42
- </div>
43
- </div>
44
- </ng-template>
45
- `,
46
- })
47
- export class DialogFinanceExample {}
@@ -1,46 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle, KjDialogClose } from './dialog';
3
-
4
- @Component({
5
- selector: 'kj-example-dialog-retro',
6
- standalone: true,
7
- imports: [KjDialogTrigger, KjDialog, KjDialogOverlay, KjDialogTitle, KjDialogClose],
8
- styleUrls: ['../styles/docs-themes.css'],
9
- styles: [`
10
- :host { display: flex; align-items: center; justify-content: center; padding: 3rem 2rem; background: var(--kj-bg); font-family: var(--kj-font); min-height: 160px; color: var(--kj-text); }
11
- button {
12
- padding: 0.4rem 1rem; font-family: var(--kj-font); font-size: 0.8rem; font-weight: 700;
13
- letter-spacing: 0.06em; text-transform: uppercase; background: var(--kj-surface); color: var(--kj-text);
14
- border: var(--kj-btn-border); cursor: pointer;
15
- box-shadow: var(--kj-shadow-sm); transition: var(--kj-transition);
16
- }
17
- button:hover { transform: translate(-1px, -1px); box-shadow: var(--kj-shadow-md); }
18
- ::ng-deep .kj-dialog-backdrop { background: var(--kj-backdrop); }
19
- ::ng-deep .kj-dialog-panel { background: transparent; box-shadow: none; }
20
- ::ng-deep [kjDialogOverlay] { display: flex; align-items: center; justify-content: center; position: fixed; inset: 0; }
21
- ::ng-deep [kjDialog] { background: var(--kj-surface); border: var(--kj-btn-border); padding: 1.5rem; min-width: 20rem; box-shadow: var(--kj-shadow-hard); font-family: var(--kj-font); color: var(--kj-text); }
22
- ::ng-deep [kjDialogTitle] { margin: 0 0 0.5rem; font-size: 1rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; border-bottom: 2px solid var(--kj-border); padding-bottom: 0.5rem; color: var(--kj-text); }
23
- ::ng-deep .dialog-body { margin: 0.75rem 0 1.5rem; font-size: 0.8rem; color: var(--kj-text-muted); line-height: 1.6; }
24
- ::ng-deep .dialog-actions { display: flex; gap: 0.5rem; justify-content: flex-end; }
25
- ::ng-deep [kjDialogOverlay] button { font-size: 0.75rem; padding: 0.3rem 0.875rem; box-shadow: var(--kj-shadow-sm); }
26
- ::ng-deep [kjDialogOverlay] button:hover { box-shadow: var(--kj-shadow-md); }
27
- ::ng-deep .btn-primary { background: var(--kj-accent); color: var(--kj-accent-on); }
28
- `],
29
- host: { class: 'kj-theme-retro' },
30
- template: `
31
- <button [kjDialogTrigger]="myDialog">Open Dialog</button>
32
- <ng-template #myDialog>
33
- <div kjDialogOverlay>
34
- <div kjDialog>
35
- <h2 kjDialogTitle>Edit Profile</h2>
36
- <p class="dialog-body">Make changes to your profile settings here.</p>
37
- <div class="dialog-actions">
38
- <button kjDialogClose>Cancel</button>
39
- <button class="btn-primary" kjDialogClose>Save Changes</button>
40
- </div>
41
- </div>
42
- </div>
43
- </ng-template>
44
- `,
45
- })
46
- export class DialogRetroExample {}