@spartan-ng/cli 0.0.1-alpha.566 → 0.0.1-alpha.567
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/package.json +1 -1
- package/src/generators/healthcheck/generator.js +6 -2
- package/src/generators/healthcheck/generator.js.map +1 -1
- package/src/generators/healthcheck/healthchecks/hlm-menu.d.ts +2 -0
- package/src/generators/healthcheck/healthchecks/hlm-menu.js +37 -0
- package/src/generators/healthcheck/healthchecks/hlm-menu.js.map +1 -0
- package/src/generators/healthcheck/healthchecks.d.ts +2 -1
- package/src/generators/healthcheck/healthchecks.js.map +1 -1
- package/src/generators/healthcheck/utils/runner.d.ts +1 -1
- package/src/generators/healthcheck/utils/runner.js +2 -2
- package/src/generators/healthcheck/utils/runner.js.map +1 -1
- package/src/generators/migrate-menu/compat.d.ts +2 -0
- package/src/generators/migrate-menu/compat.js +6 -0
- package/src/generators/migrate-menu/compat.js.map +1 -0
- package/src/generators/migrate-menu/generator.d.ts +5 -0
- package/src/generators/migrate-menu/generator.js +138 -0
- package/src/generators/migrate-menu/generator.js.map +1 -0
- package/src/generators/migrate-menu/schema.d.ts +4 -0
- package/src/generators/migrate-menu/schema.json +19 -0
- package/src/generators/migrate-module-imports/import-map.js +10 -10
- package/src/generators/migrate-module-imports/import-map.js.map +1 -1
- package/src/generators/ui/generator.js +1 -30
- package/src/generators/ui/generator.js.map +1 -1
- package/src/generators/ui/libs/context-menu/files/index.ts.template +6 -0
- package/src/generators/ui/libs/context-menu/files/lib/hlm-context-menu-token.ts.template +22 -0
- package/src/generators/ui/libs/context-menu/files/lib/hlm-context-menu-trigger.ts.template +54 -0
- package/src/generators/ui/libs/context-menu/generator.js +9 -0
- package/src/generators/ui/libs/context-menu/generator.js.map +1 -0
- package/src/generators/ui/libs/dropdown-menu/files/index.ts.template +45 -0
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-item-check.ts.template → dropdown-menu/files/lib/hlm-dropdown-menu-checkbox-indicator.ts.template} +5 -7
- package/src/generators/ui/libs/dropdown-menu/files/lib/hlm-dropdown-menu-checkbox.ts.template +36 -0
- package/src/generators/ui/libs/dropdown-menu/files/lib/hlm-dropdown-menu-group.ts.template +17 -0
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-item-sub-indicator.ts.template → dropdown-menu/files/lib/hlm-dropdown-menu-item-sub-indicator.ts.template} +4 -5
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-item.ts.template → dropdown-menu/files/lib/hlm-dropdown-menu-item.ts.template} +19 -14
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-label.ts.template → dropdown-menu/files/lib/hlm-dropdown-menu-label.ts.template} +10 -13
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-item-radio-indicator.ts.template → dropdown-menu/files/lib/hlm-dropdown-menu-radio-indicator.ts.template} +5 -7
- package/src/generators/ui/libs/dropdown-menu/files/lib/hlm-dropdown-menu-radio.ts.template +36 -0
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-separator.ts.template → dropdown-menu/files/lib/hlm-dropdown-menu-separator.ts.template} +5 -6
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-shortcut.ts.template → dropdown-menu/files/lib/hlm-dropdown-menu-shortcut.ts.template} +5 -8
- package/src/generators/ui/libs/dropdown-menu/files/lib/hlm-dropdown-menu-sub.ts.template +63 -0
- package/src/generators/ui/libs/dropdown-menu/files/lib/hlm-dropdown-menu-token.ts.template +22 -0
- package/src/generators/ui/libs/dropdown-menu/files/lib/hlm-dropdown-menu-trigger.ts.template +46 -0
- package/src/generators/ui/libs/dropdown-menu/files/lib/hlm-dropdown-menu.ts.template +67 -0
- package/src/generators/ui/libs/dropdown-menu/generator.d.ts +3 -0
- package/src/generators/ui/libs/dropdown-menu/generator.js +9 -0
- package/src/generators/ui/libs/dropdown-menu/generator.js.map +1 -0
- package/src/generators/ui/libs/menubar/files/index.ts.template +8 -0
- package/src/generators/ui/libs/menubar/files/lib/hlm-menubar-token.ts.template +22 -0
- package/src/generators/ui/libs/menubar/files/lib/hlm-menubar-trigger.ts.template +66 -0
- package/src/generators/ui/libs/{menu/files/lib/hlm-menu-bar.ts.template → menubar/files/lib/hlm-menubar.ts.template} +7 -8
- package/src/generators/ui/libs/menubar/generator.d.ts +3 -0
- package/src/generators/ui/libs/{menu → menubar}/generator.js +1 -1
- package/src/generators/ui/libs/menubar/generator.js.map +1 -0
- package/src/generators/ui/primitive-deps.js +3 -3
- package/src/generators/ui/primitive-deps.js.map +1 -1
- package/src/generators/ui/primitives.d.ts +1 -1
- package/src/generators/ui/supported-ui-libraries.json +61 -42
- package/src/utils/config.d.ts +1 -0
- package/src/utils/config.js +11 -0
- package/src/utils/config.js.map +1 -1
- package/src/utils/import-alias.d.ts +1 -0
- package/src/utils/import-alias.js +7 -0
- package/src/utils/import-alias.js.map +1 -0
- package/src/generators/ui/libs/menu/files/index.ts.template +0 -49
- package/src/generators/ui/libs/menu/files/lib/hlm-menu-bar-item.ts.template +0 -21
- package/src/generators/ui/libs/menu/files/lib/hlm-menu-group.ts.template +0 -15
- package/src/generators/ui/libs/menu/files/lib/hlm-menu-item-checkbox.ts.template +0 -27
- package/src/generators/ui/libs/menu/files/lib/hlm-menu-item-icon.ts.template +0 -16
- package/src/generators/ui/libs/menu/files/lib/hlm-menu-item-radio.ts.template +0 -27
- package/src/generators/ui/libs/menu/files/lib/hlm-menu.ts.template +0 -39
- package/src/generators/ui/libs/menu/files/lib/hlm-sub-menu.ts.template +0 -25
- package/src/generators/ui/libs/menu/generator.js.map +0 -1
- /package/src/generators/ui/libs/{menu → context-menu}/generator.d.ts +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { HlmDropdownMenu } from './lib/hlm-dropdown-menu';
|
|
2
|
+
import { HlmDropdownMenuCheckbox } from './lib/hlm-dropdown-menu-checkbox';
|
|
3
|
+
import { HlmDropdownMenuCheckboxIndicator } from './lib/hlm-dropdown-menu-checkbox-indicator';
|
|
4
|
+
import { HlmDropdownMenuGroup } from './lib/hlm-dropdown-menu-group';
|
|
5
|
+
import { HlmDropdownMenuItem } from './lib/hlm-dropdown-menu-item';
|
|
6
|
+
import { HlmDropdownMenuItemSubIndicator } from './lib/hlm-dropdown-menu-item-sub-indicator';
|
|
7
|
+
import { HlmDropdownMenuLabel } from './lib/hlm-dropdown-menu-label';
|
|
8
|
+
import { HlmDropdownMenuRadio } from './lib/hlm-dropdown-menu-radio';
|
|
9
|
+
import { HlmDropdownMenuRadioIndicator } from './lib/hlm-dropdown-menu-radio-indicator';
|
|
10
|
+
import { HlmDropdownMenuSeparator } from './lib/hlm-dropdown-menu-separator';
|
|
11
|
+
import { HlmDropdownMenuShortcut } from './lib/hlm-dropdown-menu-shortcut';
|
|
12
|
+
import { HlmDropdownMenuSub } from './lib/hlm-dropdown-menu-sub';
|
|
13
|
+
|
|
14
|
+
import { HlmDropdownMenuTrigger } from './lib/hlm-dropdown-menu-trigger';
|
|
15
|
+
|
|
16
|
+
export * from './lib/hlm-dropdown-menu';
|
|
17
|
+
export * from './lib/hlm-dropdown-menu-checkbox';
|
|
18
|
+
export * from './lib/hlm-dropdown-menu-checkbox-indicator';
|
|
19
|
+
export * from './lib/hlm-dropdown-menu-group';
|
|
20
|
+
export * from './lib/hlm-dropdown-menu-item';
|
|
21
|
+
export * from './lib/hlm-dropdown-menu-item-sub-indicator';
|
|
22
|
+
export * from './lib/hlm-dropdown-menu-label';
|
|
23
|
+
export * from './lib/hlm-dropdown-menu-radio';
|
|
24
|
+
export * from './lib/hlm-dropdown-menu-radio-indicator';
|
|
25
|
+
export * from './lib/hlm-dropdown-menu-separator';
|
|
26
|
+
export * from './lib/hlm-dropdown-menu-shortcut';
|
|
27
|
+
export * from './lib/hlm-dropdown-menu-sub';
|
|
28
|
+
export * from './lib/hlm-dropdown-menu-token';
|
|
29
|
+
export * from './lib/hlm-dropdown-menu-trigger';
|
|
30
|
+
|
|
31
|
+
export const HlmDropdownMenuImports = [
|
|
32
|
+
HlmDropdownMenu,
|
|
33
|
+
HlmDropdownMenuCheckbox,
|
|
34
|
+
HlmDropdownMenuCheckboxIndicator,
|
|
35
|
+
HlmDropdownMenuGroup,
|
|
36
|
+
HlmDropdownMenuItem,
|
|
37
|
+
HlmDropdownMenuItemSubIndicator,
|
|
38
|
+
HlmDropdownMenuLabel,
|
|
39
|
+
HlmDropdownMenuRadio,
|
|
40
|
+
HlmDropdownMenuRadioIndicator,
|
|
41
|
+
HlmDropdownMenuSeparator,
|
|
42
|
+
HlmDropdownMenuShortcut,
|
|
43
|
+
HlmDropdownMenuSub,
|
|
44
|
+
HlmDropdownMenuTrigger,
|
|
45
|
+
] as const;
|
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
2
2
|
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
3
3
|
import { lucideCheck } from '@ng-icons/lucide';
|
|
4
|
-
import { HlmIcon } from '<%- importAlias %>/icon';
|
|
5
4
|
import { hlm } from '<%- importAlias %>/utils';
|
|
6
5
|
import type { ClassValue } from 'clsx';
|
|
7
6
|
|
|
8
7
|
@Component({
|
|
9
|
-
selector: 'hlm-menu-
|
|
10
|
-
imports: [NgIcon
|
|
8
|
+
selector: 'hlm-dropdown-menu-checkbox-indicator',
|
|
9
|
+
imports: [NgIcon],
|
|
11
10
|
providers: [provideIcons({ lucideCheck })],
|
|
12
11
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13
12
|
host: {
|
|
14
13
|
'[class]': '_computedClass()',
|
|
15
14
|
},
|
|
16
15
|
template: `
|
|
17
|
-
|
|
18
|
-
<ng-icon hlm size="1rem" name="lucideCheck" />
|
|
16
|
+
<ng-icon class="text-base" name="lucideCheck" />
|
|
19
17
|
`,
|
|
20
18
|
})
|
|
21
|
-
export class
|
|
19
|
+
export class HlmDropdownMenuCheckboxIndicator {
|
|
22
20
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
23
21
|
protected readonly _computedClass = computed(() =>
|
|
24
22
|
hlm(
|
|
25
|
-
'absolute left-2 flex
|
|
23
|
+
'pointer-events-none absolute left-2 flex size-3.5 items-center justify-center opacity-0 group-data-[checked]:opacity-100',
|
|
26
24
|
this.userClass(),
|
|
27
25
|
),
|
|
28
26
|
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type BooleanInput } from '@angular/cdk/coercion';
|
|
2
|
+
import { CdkMenuItemCheckbox } from '@angular/cdk/menu';
|
|
3
|
+
import { Directive, booleanAttribute, computed, inject, input } from '@angular/core';
|
|
4
|
+
import { hlm } from '<%- importAlias %>/utils';
|
|
5
|
+
import type { ClassValue } from 'clsx';
|
|
6
|
+
|
|
7
|
+
@Directive({
|
|
8
|
+
selector: '[hlmDropdownMenuCheckbox]',
|
|
9
|
+
hostDirectives: [
|
|
10
|
+
{
|
|
11
|
+
directive: CdkMenuItemCheckbox,
|
|
12
|
+
inputs: ['cdkMenuItemDisabled: disabled', 'cdkMenuItemChecked: checked'],
|
|
13
|
+
outputs: ['cdkMenuItemTriggered: triggered'],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
host: {
|
|
17
|
+
'data-slot': 'dropdown-menu-checkbox-item',
|
|
18
|
+
'[attr.data-disabled]': 'disabled() ? "" : null',
|
|
19
|
+
'[attr.data-checked]': 'checked() ? "" : null',
|
|
20
|
+
'[class]': '_computedClass()',
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
export class HlmDropdownMenuCheckbox {
|
|
24
|
+
private readonly _cdkMenuItem = inject(CdkMenuItemCheckbox);
|
|
25
|
+
|
|
26
|
+
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
27
|
+
protected readonly _computedClass = computed(() =>
|
|
28
|
+
hlm(
|
|
29
|
+
'hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground group relative flex w-full cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
30
|
+
this.userClass(),
|
|
31
|
+
),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
public readonly checked = input<boolean, BooleanInput>(this._cdkMenuItem.checked, { transform: booleanAttribute });
|
|
35
|
+
public readonly disabled = input<boolean, BooleanInput>(this._cdkMenuItem.disabled, { transform: booleanAttribute });
|
|
36
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CdkMenuGroup } from '@angular/cdk/menu';
|
|
2
|
+
import { computed, Directive, input } from '@angular/core';
|
|
3
|
+
import { hlm } from '<%- importAlias %>/utils';
|
|
4
|
+
import type { ClassValue } from 'clsx';
|
|
5
|
+
|
|
6
|
+
@Directive({
|
|
7
|
+
selector: '[hlmDropdownMenuGroup],hlm-dropdown-menu-group',
|
|
8
|
+
hostDirectives: [CdkMenuGroup],
|
|
9
|
+
host: {
|
|
10
|
+
'data-slot': 'dropdown-menu-group',
|
|
11
|
+
'[class]': '_computedClass()',
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
export class HlmDropdownMenuGroup {
|
|
15
|
+
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
16
|
+
protected readonly _computedClass = computed(() => hlm('block', this.userClass()));
|
|
17
|
+
}
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
2
2
|
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
3
3
|
import { lucideChevronRight } from '@ng-icons/lucide';
|
|
4
|
-
import { HlmIcon } from '<%- importAlias %>/icon';
|
|
5
4
|
import { hlm } from '<%- importAlias %>/utils';
|
|
6
5
|
import type { ClassValue } from 'clsx';
|
|
7
6
|
|
|
8
7
|
@Component({
|
|
9
|
-
selector: 'hlm-menu-item-sub-indicator',
|
|
10
|
-
imports: [NgIcon
|
|
8
|
+
selector: 'hlm-dropdown-menu-item-sub-indicator',
|
|
9
|
+
imports: [NgIcon],
|
|
11
10
|
providers: [provideIcons({ lucideChevronRight })],
|
|
12
11
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13
12
|
host: {
|
|
14
13
|
'[class]': '_computedClass()',
|
|
15
14
|
},
|
|
16
15
|
template: `
|
|
17
|
-
<ng-icon
|
|
16
|
+
<ng-icon name="lucideChevronRight" class="text-base" />
|
|
18
17
|
`,
|
|
19
18
|
})
|
|
20
|
-
export class
|
|
19
|
+
export class HlmDropdownMenuItemSubIndicator {
|
|
21
20
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
22
21
|
protected readonly _computedClass = computed(() => hlm('ml-auto size-4', this.userClass()));
|
|
23
22
|
}
|
|
@@ -1,36 +1,41 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type BooleanInput } from '@angular/cdk/coercion';
|
|
2
|
+
import { CdkMenuItem } from '@angular/cdk/menu';
|
|
2
3
|
import { booleanAttribute, computed, Directive, input } from '@angular/core';
|
|
3
|
-
import { BrnMenuItem } from '@spartan-ng/brain/menu';
|
|
4
4
|
import { hlm } from '<%- importAlias %>/utils';
|
|
5
5
|
import type { ClassValue } from 'clsx';
|
|
6
6
|
|
|
7
7
|
@Directive({
|
|
8
|
-
selector: '[
|
|
8
|
+
selector: 'button[hlmDropdownMenuItem]',
|
|
9
9
|
hostDirectives: [
|
|
10
10
|
{
|
|
11
|
-
directive:
|
|
12
|
-
inputs: ['
|
|
13
|
-
outputs: ['
|
|
11
|
+
directive: CdkMenuItem,
|
|
12
|
+
inputs: ['cdkMenuItemDisabled: disabled'],
|
|
13
|
+
outputs: ['cdkMenuItemTriggered: triggered'],
|
|
14
14
|
},
|
|
15
15
|
],
|
|
16
16
|
host: {
|
|
17
|
+
'data-slot': 'dropdown-menu-item',
|
|
17
18
|
'[class]': '_computedClass()',
|
|
19
|
+
'[disabled]': 'disabled() || null',
|
|
20
|
+
'[attr.data-disabled]': 'disabled() ? "" : null',
|
|
18
21
|
'[attr.data-variant]': 'variant()',
|
|
19
22
|
'[attr.data-inset]': 'inset() ? "" : null',
|
|
20
23
|
},
|
|
21
24
|
})
|
|
22
|
-
export class
|
|
23
|
-
public readonly variant = input<'default' | 'destructive'>('default');
|
|
24
|
-
|
|
25
|
-
public readonly inset = input<boolean, BooleanInput>(false, {
|
|
26
|
-
transform: booleanAttribute,
|
|
27
|
-
});
|
|
28
|
-
|
|
25
|
+
export class HlmDropdownMenuItem {
|
|
29
26
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
30
27
|
protected readonly _computedClass = computed(() =>
|
|
31
28
|
hlm(
|
|
32
|
-
|
|
29
|
+
"hover:bg-accent focus-visible:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[ng-icon]:!text-destructive [&_ng-icon:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0 [&_svg:not([class*='text-'])]:text-base",
|
|
33
30
|
this.userClass(),
|
|
34
31
|
),
|
|
35
32
|
);
|
|
33
|
+
|
|
34
|
+
public readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });
|
|
35
|
+
|
|
36
|
+
public readonly variant = input<'default' | 'destructive'>('default');
|
|
37
|
+
|
|
38
|
+
public readonly inset = input<boolean, BooleanInput>(false, {
|
|
39
|
+
transform: booleanAttribute,
|
|
40
|
+
});
|
|
36
41
|
}
|
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { booleanAttribute,
|
|
1
|
+
import { type BooleanInput } from '@angular/cdk/coercion';
|
|
2
|
+
import { booleanAttribute, computed, Directive, input } from '@angular/core';
|
|
3
3
|
import { hlm } from '<%- importAlias %>/utils';
|
|
4
4
|
import type { ClassValue } from 'clsx';
|
|
5
5
|
|
|
6
|
-
@
|
|
7
|
-
selector: 'hlm-menu-label',
|
|
8
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
6
|
+
@Directive({
|
|
7
|
+
selector: '[hlmDropdownMenuLabel],hlm-dropdown-menu-label',
|
|
9
8
|
host: {
|
|
9
|
+
'data-slot': 'dropdown-menu-label',
|
|
10
10
|
'[class]': '_computedClass()',
|
|
11
11
|
'[attr.data-inset]': 'inset() ? "" : null',
|
|
12
12
|
},
|
|
13
|
-
template: `
|
|
14
|
-
<ng-content />
|
|
15
|
-
`,
|
|
16
13
|
})
|
|
17
|
-
export class
|
|
18
|
-
public readonly inset = input<boolean, BooleanInput>(false, {
|
|
19
|
-
transform: booleanAttribute,
|
|
20
|
-
});
|
|
21
|
-
|
|
14
|
+
export class HlmDropdownMenuLabel {
|
|
22
15
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
23
16
|
protected readonly _computedClass = computed(() =>
|
|
24
17
|
hlm('block px-2 py-1.5 text-sm font-medium data-[inset]:pl-8', this.userClass()),
|
|
25
18
|
);
|
|
19
|
+
|
|
20
|
+
public readonly inset = input<boolean, BooleanInput>(false, {
|
|
21
|
+
transform: booleanAttribute,
|
|
22
|
+
});
|
|
26
23
|
}
|
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
2
2
|
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
3
3
|
import { lucideCircle } from '@ng-icons/lucide';
|
|
4
|
-
import { HlmIcon } from '<%- importAlias %>/icon';
|
|
5
4
|
import { hlm } from '<%- importAlias %>/utils';
|
|
6
5
|
import type { ClassValue } from 'clsx';
|
|
7
6
|
|
|
8
7
|
@Component({
|
|
9
|
-
selector: 'hlm-menu-
|
|
10
|
-
imports: [NgIcon
|
|
8
|
+
selector: 'hlm-dropdown-menu-radio-indicator',
|
|
9
|
+
imports: [NgIcon],
|
|
11
10
|
providers: [provideIcons({ lucideCircle })],
|
|
12
11
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13
12
|
host: {
|
|
14
13
|
'[class]': '_computedClass()',
|
|
15
14
|
},
|
|
16
15
|
template: `
|
|
17
|
-
|
|
18
|
-
<ng-icon hlm size="0.5rem" class="*:*:fill-current" name="lucideCircle" />
|
|
16
|
+
<ng-icon name="lucideCircle" class="text-[0.5rem] *:[svg]:fill-current" />
|
|
19
17
|
`,
|
|
20
18
|
})
|
|
21
|
-
export class
|
|
19
|
+
export class HlmDropdownMenuRadioIndicator {
|
|
22
20
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
23
21
|
protected readonly _computedClass = computed(() =>
|
|
24
22
|
hlm(
|
|
25
|
-
'absolute left-2 flex
|
|
23
|
+
'pointer-events-none absolute left-2 flex size-3.5 items-center justify-center opacity-0 group-data-[checked]:opacity-100',
|
|
26
24
|
this.userClass(),
|
|
27
25
|
),
|
|
28
26
|
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type BooleanInput } from '@angular/cdk/coercion';
|
|
2
|
+
import { CdkMenuItemRadio } from '@angular/cdk/menu';
|
|
3
|
+
import { Directive, booleanAttribute, computed, inject, input } from '@angular/core';
|
|
4
|
+
import { hlm } from '<%- importAlias %>/utils';
|
|
5
|
+
import type { ClassValue } from 'clsx';
|
|
6
|
+
|
|
7
|
+
@Directive({
|
|
8
|
+
selector: '[hlmDropdownMenuRadio]',
|
|
9
|
+
hostDirectives: [
|
|
10
|
+
{
|
|
11
|
+
directive: CdkMenuItemRadio,
|
|
12
|
+
inputs: ['cdkMenuItemDisabled: disabled', 'cdkMenuItemChecked: checked'],
|
|
13
|
+
outputs: ['cdkMenuItemTriggered: triggered'],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
host: {
|
|
17
|
+
'data-slot': 'dropdown-menu-radio-item',
|
|
18
|
+
'[attr.data-disabled]': 'disabled() ? "" : null',
|
|
19
|
+
'[attr.data-checked]': 'checked() ? "" : null',
|
|
20
|
+
'[class]': '_computedClass()',
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
export class HlmDropdownMenuRadio {
|
|
24
|
+
private readonly _cdkMenuItem = inject(CdkMenuItemRadio);
|
|
25
|
+
|
|
26
|
+
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
27
|
+
protected readonly _computedClass = computed(() =>
|
|
28
|
+
hlm(
|
|
29
|
+
'hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground group relative flex w-full cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
30
|
+
this.userClass(),
|
|
31
|
+
),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
public readonly checked = input<boolean, BooleanInput>(this._cdkMenuItem.checked, { transform: booleanAttribute });
|
|
35
|
+
public readonly disabled = input<boolean, BooleanInput>(this._cdkMenuItem.disabled, { transform: booleanAttribute });
|
|
36
|
+
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { computed, Directive, input } from '@angular/core';
|
|
2
2
|
import { hlm } from '<%- importAlias %>/utils';
|
|
3
3
|
import type { ClassValue } from 'clsx';
|
|
4
4
|
|
|
5
|
-
@
|
|
6
|
-
selector: 'hlm-menu-separator',
|
|
7
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5
|
+
@Directive({
|
|
6
|
+
selector: '[hlmDropdownMenuSeparator],hlm-dropdown-menu-separator',
|
|
8
7
|
host: {
|
|
8
|
+
'data-slot': 'dropdown-menu-separator',
|
|
9
9
|
'[class]': '_computedClass()',
|
|
10
10
|
},
|
|
11
|
-
template: '',
|
|
12
11
|
})
|
|
13
|
-
export class
|
|
12
|
+
export class HlmDropdownMenuSeparator {
|
|
14
13
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
15
14
|
protected readonly _computedClass = computed(() => hlm('bg-border -mx-1 my-1 block h-px', this.userClass()));
|
|
16
15
|
}
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { computed, Directive, input } from '@angular/core';
|
|
2
2
|
import { hlm } from '<%- importAlias %>/utils';
|
|
3
3
|
import type { ClassValue } from 'clsx';
|
|
4
4
|
|
|
5
|
-
@
|
|
6
|
-
selector: 'hlm-menu-shortcut',
|
|
7
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5
|
+
@Directive({
|
|
6
|
+
selector: '[hlmDropdownMenuShortcut],hlm-dropdown-menu-shortcut',
|
|
8
7
|
host: {
|
|
8
|
+
'data-slot': 'dropdown-menu-shortcut',
|
|
9
9
|
'[class]': '_computedClass()',
|
|
10
10
|
},
|
|
11
|
-
template: `
|
|
12
|
-
<ng-content />
|
|
13
|
-
`,
|
|
14
11
|
})
|
|
15
|
-
export class
|
|
12
|
+
export class HlmDropdownMenuShortcut {
|
|
16
13
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
17
14
|
protected readonly _computedClass = computed(() =>
|
|
18
15
|
hlm('text-muted-foreground ml-auto text-xs tracking-widest', this.userClass()),
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CdkMenu } from '@angular/cdk/menu';
|
|
2
|
+
import { computed, Directive, inject, input, signal } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { hlm } from '<%- importAlias %>/utils';
|
|
5
|
+
import type { ClassValue } from 'clsx';
|
|
6
|
+
|
|
7
|
+
@Directive({
|
|
8
|
+
selector: '[hlmDropdownMenuSub],hlm-dropdown-menu-sub',
|
|
9
|
+
hostDirectives: [CdkMenu],
|
|
10
|
+
host: {
|
|
11
|
+
'data-slot': 'dropdown-menu-sub',
|
|
12
|
+
'[attr.data-state]': '_state()',
|
|
13
|
+
'[attr.data-side]': '_side()',
|
|
14
|
+
'[class]': '_computedClass()',
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
export class HlmDropdownMenuSub {
|
|
18
|
+
private readonly _host = inject(CdkMenu);
|
|
19
|
+
|
|
20
|
+
protected readonly _state = signal('open');
|
|
21
|
+
protected readonly _side = signal('top');
|
|
22
|
+
|
|
23
|
+
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
24
|
+
protected readonly _computedClass = computed(() =>
|
|
25
|
+
hlm(
|
|
26
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-top overflow-hidden rounded-md border p-1 shadow-lg',
|
|
27
|
+
this.userClass(),
|
|
28
|
+
),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
constructor() {
|
|
32
|
+
this.setSideWithDarkMagic();
|
|
33
|
+
// this is a best effort, but does not seem to work currently
|
|
34
|
+
// TODO: figure out a way for us to know the host is about to be closed. might not be possible with CDK
|
|
35
|
+
this._host.closed.pipe(takeUntilDestroyed()).subscribe(() => this._state.set('closed'));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private setSideWithDarkMagic() {
|
|
39
|
+
/**
|
|
40
|
+
* This is an ugly workaround to at least figure out the correct side of where a submenu
|
|
41
|
+
* will appear and set the attribute to the host accordingly
|
|
42
|
+
*
|
|
43
|
+
* First of all we take advantage of the menu stack not being aware of the root
|
|
44
|
+
* object immediately after it is added. This code executes before the root element is added,
|
|
45
|
+
* which means the stack is still empty and the peek method returns undefined.
|
|
46
|
+
*/
|
|
47
|
+
const isRoot = this._host.menuStack.peek() === undefined;
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
// our menu trigger directive leaves the last position used for use immediately after opening
|
|
50
|
+
// we can access it here and determine the correct side.
|
|
51
|
+
// eslint-disable-next-line
|
|
52
|
+
const ps = (this._host as any)._parentTrigger._spartanLastPosition;
|
|
53
|
+
if (!ps) {
|
|
54
|
+
// if we have no last position we default to the most likely option
|
|
55
|
+
// I hate that we have to do this and hope we can revisit soon and improve
|
|
56
|
+
this._side.set(isRoot ? 'top' : 'left');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const side = isRoot ? ps.originY : ps.originX === 'end' ? 'right' : 'left';
|
|
60
|
+
this._side.set(side);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { InjectionToken, type ValueProvider, inject } from '@angular/core';
|
|
2
|
+
import { type MenuAlign, type MenuSide } from '@spartan-ng/brain/core';
|
|
3
|
+
|
|
4
|
+
export interface HlmDropdownMenuConfig {
|
|
5
|
+
align: MenuAlign;
|
|
6
|
+
side: MenuSide;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const defaultConfig: HlmDropdownMenuConfig = {
|
|
10
|
+
align: 'start',
|
|
11
|
+
side: 'bottom',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const HlmDropdownMenuConfigToken = new InjectionToken<HlmDropdownMenuConfig>('HlmDropdownMenuConfig');
|
|
15
|
+
|
|
16
|
+
export function provideHlmDropdownMenuConfig(config: Partial<HlmDropdownMenuConfig>): ValueProvider {
|
|
17
|
+
return { provide: HlmDropdownMenuConfigToken, useValue: { ...defaultConfig, ...config } };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function injectHlmDropdownMenuConfig(): HlmDropdownMenuConfig {
|
|
21
|
+
return inject(HlmDropdownMenuConfigToken, { optional: true }) ?? defaultConfig;
|
|
22
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CdkMenuTrigger } from '@angular/cdk/menu';
|
|
2
|
+
import { computed, Directive, effect, inject, input } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { createMenuPosition, type MenuAlign, type MenuSide } from '@spartan-ng/brain/core';
|
|
5
|
+
import { injectHlmDropdownMenuConfig } from './hlm-dropdown-menu-token';
|
|
6
|
+
|
|
7
|
+
@Directive({
|
|
8
|
+
selector: '[hlmDropdownMenuTrigger]',
|
|
9
|
+
hostDirectives: [
|
|
10
|
+
{
|
|
11
|
+
directive: CdkMenuTrigger,
|
|
12
|
+
inputs: ['cdkMenuTriggerFor: hlmDropdownMenuTrigger', 'cdkMenuTriggerData: hlmDropdownMenuTriggerData'],
|
|
13
|
+
outputs: ['cdkMenuOpened: hlmDropdownMenuOpened', 'cdkMenuClosed: hlmDropdownMenuClosed'],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
host: {
|
|
17
|
+
'data-slot': 'dropdown-menu-trigger',
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
export class HlmDropdownMenuTrigger {
|
|
21
|
+
private readonly _cdkTrigger = inject(CdkMenuTrigger, { host: true });
|
|
22
|
+
private readonly _config = injectHlmDropdownMenuConfig();
|
|
23
|
+
|
|
24
|
+
public readonly align = input<MenuAlign>(this._config.align);
|
|
25
|
+
public readonly side = input<MenuSide>(this._config.side);
|
|
26
|
+
|
|
27
|
+
private readonly _menuPosition = computed(() => createMenuPosition(this.align(), this.side()));
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
// once the trigger opens we wait until the next tick and then grab the last position
|
|
31
|
+
// used to position the menu. we store this in our trigger which the brnMenu directive has
|
|
32
|
+
// access to through DI
|
|
33
|
+
this._cdkTrigger.opened.pipe(takeUntilDestroyed()).subscribe(() =>
|
|
34
|
+
setTimeout(
|
|
35
|
+
() =>
|
|
36
|
+
// eslint-disable-next-line
|
|
37
|
+
((this._cdkTrigger as any)._spartanLastPosition = // eslint-disable-next-line
|
|
38
|
+
(this._cdkTrigger as any).overlayRef._positionStrategy._lastPosition),
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
effect(() => {
|
|
43
|
+
this._cdkTrigger.menuPosition = this._menuPosition();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type NumberInput } from '@angular/cdk/coercion';
|
|
2
|
+
import { CdkMenu } from '@angular/cdk/menu';
|
|
3
|
+
import { computed, Directive, inject, input, numberAttribute, signal } from '@angular/core';
|
|
4
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { hlm } from '<%- importAlias %>/utils';
|
|
6
|
+
import type { ClassValue } from 'clsx';
|
|
7
|
+
|
|
8
|
+
@Directive({
|
|
9
|
+
selector: '[hlmDropdownMenu],hlm-dropdown-menu',
|
|
10
|
+
hostDirectives: [CdkMenu],
|
|
11
|
+
host: {
|
|
12
|
+
'data-slot': 'dropdown-menu',
|
|
13
|
+
'[attr.data-state]': '_state()',
|
|
14
|
+
'[attr.data-side]': '_side()',
|
|
15
|
+
'[class]': '_computedClass()',
|
|
16
|
+
'[style.--side-offset]': 'sideOffset()',
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
export class HlmDropdownMenu {
|
|
20
|
+
private readonly _host = inject(CdkMenu);
|
|
21
|
+
|
|
22
|
+
protected readonly _state = signal('open');
|
|
23
|
+
protected readonly _side = signal('top');
|
|
24
|
+
|
|
25
|
+
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
26
|
+
protected readonly _computedClass = computed(() =>
|
|
27
|
+
hlm(
|
|
28
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 my-[--spacing(var(--side-offset))] min-w-[8rem] origin-top overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md',
|
|
29
|
+
this.userClass(),
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
public readonly sideOffset = input<number, NumberInput>(1, { transform: numberAttribute });
|
|
34
|
+
|
|
35
|
+
constructor() {
|
|
36
|
+
this.setSideWithDarkMagic();
|
|
37
|
+
// this is a best effort, but does not seem to work currently
|
|
38
|
+
// TODO: figure out a way for us to know the host is about to be closed. might not be possible with CDK
|
|
39
|
+
this._host.closed.pipe(takeUntilDestroyed()).subscribe(() => this._state.set('closed'));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private setSideWithDarkMagic() {
|
|
43
|
+
/**
|
|
44
|
+
* This is an ugly workaround to at least figure out the correct side of where a submenu
|
|
45
|
+
* will appear and set the attribute to the host accordingly
|
|
46
|
+
*
|
|
47
|
+
* First of all we take advantage of the menu stack not being aware of the root
|
|
48
|
+
* object immediately after it is added. This code executes before the root element is added,
|
|
49
|
+
* which means the stack is still empty and the peek method returns undefined.
|
|
50
|
+
*/
|
|
51
|
+
const isRoot = this._host.menuStack.peek() === undefined;
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
// our menu trigger directive leaves the last position used for use immediately after opening
|
|
54
|
+
// we can access it here and determine the correct side.
|
|
55
|
+
// eslint-disable-next-line
|
|
56
|
+
const ps = (this._host as any)._parentTrigger._spartanLastPosition;
|
|
57
|
+
if (!ps) {
|
|
58
|
+
// if we have no last position we default to the most likely option
|
|
59
|
+
// I hate that we have to do this and hope we can revisit soon and improve
|
|
60
|
+
this._side.set(isRoot ? 'top' : 'left');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const side = isRoot ? ps.originY : ps.originX === 'end' ? 'right' : 'left';
|
|
64
|
+
this._side.set(side);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generator = generator;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const generator_1 = tslib_1.__importDefault(require("../../../base/generator"));
|
|
6
|
+
async function generator(tree, options) {
|
|
7
|
+
return await (0, generator_1.default)(tree, { ...options, name: 'dropdown-menu' });
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../../../libs/cli/src/generators/ui/libs/dropdown-menu/generator.ts"],"names":[],"mappings":";;AAIA,8BAEC;;AALD,gFAAuD;AAGhD,KAAK,UAAU,SAAS,CAAC,IAAU,EAAE,OAA+B;IAC1E,OAAO,MAAM,IAAA,mBAAgB,EAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HlmMenubar } from './lib/hlm-menubar';
|
|
2
|
+
import { HlmMenubarTrigger } from './lib/hlm-menubar-trigger';
|
|
3
|
+
|
|
4
|
+
export * from './lib/hlm-menubar';
|
|
5
|
+
export * from './lib/hlm-menubar-token';
|
|
6
|
+
export * from './lib/hlm-menubar-trigger';
|
|
7
|
+
|
|
8
|
+
export const HlmMenubarImports = [HlmMenubar, HlmMenubarTrigger] as const;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { InjectionToken, type ValueProvider, inject } from '@angular/core';
|
|
2
|
+
import { type MenuAlign, type MenuSide } from '@spartan-ng/brain/core';
|
|
3
|
+
|
|
4
|
+
export interface HlmMenubarConfig {
|
|
5
|
+
align: MenuAlign;
|
|
6
|
+
side: MenuSide;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const defaultConfig: HlmMenubarConfig = {
|
|
10
|
+
align: 'start',
|
|
11
|
+
side: 'bottom',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const HlmMenubarConfigToken = new InjectionToken<HlmMenubarConfig>('HlmMenubarConfig');
|
|
15
|
+
|
|
16
|
+
export function provideHlmMenubarConfig(config: Partial<HlmMenubarConfig>): ValueProvider {
|
|
17
|
+
return { provide: HlmMenubarConfigToken, useValue: { ...defaultConfig, ...config } };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function injectHlmMenubarConfig(): HlmMenubarConfig {
|
|
21
|
+
return inject(HlmMenubarConfigToken, { optional: true }) ?? defaultConfig;
|
|
22
|
+
}
|