@spartan-ng/cli 0.0.1-alpha.655 → 0.0.1-alpha.656

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 (61) hide show
  1. package/package.json +1 -1
  2. package/src/generators/base/lib/styles/index.d.ts +3 -0
  3. package/src/generators/base/lib/styles/index.js +7 -0
  4. package/src/generators/base/lib/styles/index.js.map +1 -0
  5. package/src/generators/healthcheck/generator.js +2 -0
  6. package/src/generators/healthcheck/generator.js.map +1 -1
  7. package/src/generators/healthcheck/healthchecks/brn-select.d.ts +2 -0
  8. package/src/generators/healthcheck/healthchecks/brn-select.js +35 -0
  9. package/src/generators/healthcheck/healthchecks/brn-select.js.map +1 -0
  10. package/src/generators/migrate-brn-select/compat.d.ts +2 -0
  11. package/src/generators/migrate-brn-select/compat.js +6 -0
  12. package/src/generators/migrate-brn-select/compat.js.map +1 -0
  13. package/src/generators/migrate-brn-select/generator.d.ts +4 -0
  14. package/src/generators/migrate-brn-select/generator.js +78 -0
  15. package/src/generators/migrate-brn-select/generator.js.map +1 -0
  16. package/src/generators/migrate-brn-select/schema.d.ts +3 -0
  17. package/src/generators/migrate-brn-select/schema.json +14 -0
  18. package/src/generators/migrate-module-imports/import-map.d.ts +0 -1
  19. package/src/generators/migrate-module-imports/import-map.js +1 -1
  20. package/src/generators/migrate-module-imports/import-map.js.map +1 -1
  21. package/src/generators/ui/libs/calendar/files/lib/hlm-calendar-multi.ts.template +19 -16
  22. package/src/generators/ui/libs/calendar/files/lib/hlm-calendar-range.ts.template +19 -16
  23. package/src/generators/ui/libs/calendar/files/lib/hlm-calendar.ts.template +19 -16
  24. package/src/generators/ui/libs/combobox/files/index.ts.template +6 -0
  25. package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-placeholder.ts.template +17 -0
  26. package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-trigger.ts.template +6 -1
  27. package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-value-template.ts.template +5 -0
  28. package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-value.ts.template +10 -2
  29. package/src/generators/ui/libs/navigation-menu/files/index.ts.template +14 -14
  30. package/src/generators/ui/libs/pagination/files/lib/hlm-numbered-pagination-query-params.ts.template +8 -9
  31. package/src/generators/ui/libs/pagination/files/lib/hlm-numbered-pagination.ts.template +8 -8
  32. package/src/generators/ui/libs/select/files/index.ts.template +21 -3
  33. package/src/generators/ui/libs/select/files/lib/hlm-select-content.ts.template +28 -16
  34. package/src/generators/ui/libs/select/files/lib/hlm-select-group.ts.template +11 -3
  35. package/src/generators/ui/libs/select/files/lib/hlm-select-item.ts.template +34 -0
  36. package/src/generators/ui/libs/select/files/lib/hlm-select-label.ts.template +7 -11
  37. package/src/generators/ui/libs/select/files/lib/hlm-select-multiple.ts.template +47 -0
  38. package/src/generators/ui/libs/select/files/lib/hlm-select-placeholder.ts.template +17 -0
  39. package/src/generators/ui/libs/select/files/lib/hlm-select-portal.ts.template +8 -0
  40. package/src/generators/ui/libs/select/files/lib/hlm-select-scroll-down.ts.template +8 -4
  41. package/src/generators/ui/libs/select/files/lib/hlm-select-scroll-up.ts.template +8 -4
  42. package/src/generators/ui/libs/select/files/lib/hlm-select-separator.ts.template +4 -2
  43. package/src/generators/ui/libs/select/files/lib/hlm-select-trigger.ts.template +21 -33
  44. package/src/generators/ui/libs/select/files/lib/hlm-select-value-template.ts.template +5 -0
  45. package/src/generators/ui/libs/select/files/lib/hlm-select-value.ts.template +10 -3
  46. package/src/generators/ui/libs/select/files/lib/hlm-select-values-content.ts.template +9 -0
  47. package/src/generators/ui/libs/select/files/lib/hlm-select-values.ts.template +5 -0
  48. package/src/generators/ui/libs/select/files/lib/hlm-select.ts.template +38 -2
  49. package/src/generators/ui/supported-ui-libraries.json +40 -42
  50. package/src/index.d.ts +1 -0
  51. package/src/index.js +1 -0
  52. package/src/index.js.map +1 -1
  53. package/src/registry/schema.d.ts +14 -14
  54. package/src/generators/ui/libs/select/files/lib/hlm-select-option.ts.template +0 -32
  55. /package/src/generators/ui/libs/navigation-menu/files/{hlm-navigation-menu-content.ts.template → lib/hlm-navigation-menu-content.ts.template} +0 -0
  56. /package/src/generators/ui/libs/navigation-menu/files/{hlm-navigation-menu-item.ts.template → lib/hlm-navigation-menu-item.ts.template} +0 -0
  57. /package/src/generators/ui/libs/navigation-menu/files/{hlm-navigation-menu-link.ts.template → lib/hlm-navigation-menu-link.ts.template} +0 -0
  58. /package/src/generators/ui/libs/navigation-menu/files/{hlm-navigation-menu-list.ts.template → lib/hlm-navigation-menu-list.ts.template} +0 -0
  59. /package/src/generators/ui/libs/navigation-menu/files/{hlm-navigation-menu-portal.ts.template → lib/hlm-navigation-menu-portal.ts.template} +0 -0
  60. /package/src/generators/ui/libs/navigation-menu/files/{hlm-navigation-menu-trigger.ts.template → lib/hlm-navigation-menu-trigger.ts.template} +0 -0
  61. /package/src/generators/ui/libs/navigation-menu/files/{hlm-navigation-menu.ts.template → lib/hlm-navigation-menu.ts.template} +0 -0
@@ -10,7 +10,6 @@ import {
10
10
  untracked,
11
11
  } from '@angular/core';
12
12
  import { FormsModule } from '@angular/forms';
13
- import { BrnSelectImports } from '@spartan-ng/brain/select';
14
13
  import { HlmSelectImports } from '<%- importAlias %>/select';
15
14
  import { createPageArray, outOfBoundCorrection } from './hlm-numbered-pagination';
16
15
  import { HlmPagination } from './hlm-pagination';
@@ -32,8 +31,6 @@ import { HlmPaginationPrevious } from './hlm-pagination-previous';
32
31
  HlmPaginationNext,
33
32
  HlmPaginationLink,
34
33
  HlmPaginationEllipsis,
35
-
36
- BrnSelectImports,
37
34
  HlmSelectImports,
38
35
  ],
39
36
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -89,16 +86,18 @@ import { HlmPaginationPrevious } from './hlm-pagination-previous';
89
86
  </nav>
90
87
 
91
88
  <!-- Show Page Size selector -->
92
- <brn-select [(ngModel)]="itemsPerPage" class="ml-auto" placeholder="Page size">
89
+ <hlm-select [(ngModel)]="itemsPerPage" class="ml-auto">
93
90
  <hlm-select-trigger class="w-fit">
94
91
  <hlm-select-value />
95
92
  </hlm-select-trigger>
96
- <hlm-select-content>
97
- @for (pageSize of _pageSizesWithCurrent(); track pageSize) {
98
- <hlm-option [value]="pageSize">{{ pageSize }} / page</hlm-option>
99
- }
93
+ <hlm-select-content *hlmSelectPortal>
94
+ <hlm-select-group>
95
+ @for (pageSize of _pageSizesWithCurrent(); track pageSize) {
96
+ <hlm-select-item [value]="pageSize">{{ pageSize }}</hlm-select-item>
97
+ }
98
+ </hlm-select-group>
100
99
  </hlm-select-content>
101
- </brn-select>
100
+ </hlm-select>
102
101
  </div>
103
102
  `,
104
103
  })
@@ -10,7 +10,6 @@ import {
10
10
  untracked,
11
11
  } from '@angular/core';
12
12
  import { FormsModule } from '@angular/forms';
13
- import { BrnSelectImports } from '@spartan-ng/brain/select';
14
13
  import { HlmSelectImports } from '<%- importAlias %>/select';
15
14
  import { HlmPagination } from './hlm-pagination';
16
15
  import { HlmPaginationContent } from './hlm-pagination-content';
@@ -31,7 +30,6 @@ import { HlmPaginationPrevious } from './hlm-pagination-previous';
31
30
  HlmPaginationNext,
32
31
  HlmPaginationLink,
33
32
  HlmPaginationEllipsis,
34
- BrnSelectImports,
35
33
  HlmSelectImports,
36
34
  ],
37
35
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -73,16 +71,18 @@ import { HlmPaginationPrevious } from './hlm-pagination-previous';
73
71
  </nav>
74
72
 
75
73
  <!-- Show Page Size selector -->
76
- <brn-select [(ngModel)]="itemsPerPage" class="ml-auto" placeholder="Page size">
74
+ <hlm-select [(ngModel)]="itemsPerPage" class="ml-auto">
77
75
  <hlm-select-trigger class="w-fit">
78
76
  <hlm-select-value />
79
77
  </hlm-select-trigger>
80
- <hlm-select-content>
81
- @for (pageSize of _pageSizesWithCurrent(); track pageSize) {
82
- <hlm-option [value]="pageSize">{{ pageSize }} / page</hlm-option>
83
- }
78
+ <hlm-select-content *hlmSelectPortal>
79
+ <hlm-select-group>
80
+ @for (pageSize of _pageSizesWithCurrent(); track pageSize) {
81
+ <hlm-select-item [value]="pageSize">{{ pageSize }}</hlm-select-item>
82
+ }
83
+ </hlm-select-group>
84
84
  </hlm-select-content>
85
- </brn-select>
85
+ </hlm-select>
86
86
  </div>
87
87
  `,
88
88
  })
@@ -1,34 +1,52 @@
1
1
  import { HlmSelect } from './lib/hlm-select';
2
2
  import { HlmSelectContent } from './lib/hlm-select-content';
3
3
  import { HlmSelectGroup } from './lib/hlm-select-group';
4
+ import { HlmSelectItem } from './lib/hlm-select-item';
4
5
  import { HlmSelectLabel } from './lib/hlm-select-label';
5
- import { HlmSelectOption } from './lib/hlm-select-option';
6
+ import { HlmSelectMultiple } from './lib/hlm-select-multiple';
7
+ import { HlmSelectPlaceholder } from './lib/hlm-select-placeholder';
8
+ import { HlmSelectPortal } from './lib/hlm-select-portal';
6
9
  import { HlmSelectScrollDown } from './lib/hlm-select-scroll-down';
7
10
  import { HlmSelectScrollUp } from './lib/hlm-select-scroll-up';
8
11
  import { HlmSelectSeparator } from './lib/hlm-select-separator';
9
12
  import { HlmSelectTrigger } from './lib/hlm-select-trigger';
10
13
  import { HlmSelectValue } from './lib/hlm-select-value';
14
+ import { HlmSelectValueTemplate } from './lib/hlm-select-value-template';
15
+ import { HlmSelectValues } from './lib/hlm-select-values';
16
+ import { HlmSelectValuesContent } from './lib/hlm-select-values-content';
11
17
 
12
18
  export * from './lib/hlm-select';
13
19
  export * from './lib/hlm-select-content';
14
20
  export * from './lib/hlm-select-group';
21
+ export * from './lib/hlm-select-item';
15
22
  export * from './lib/hlm-select-label';
16
- export * from './lib/hlm-select-option';
23
+ export * from './lib/hlm-select-multiple';
24
+ export * from './lib/hlm-select-placeholder';
25
+ export * from './lib/hlm-select-portal';
17
26
  export * from './lib/hlm-select-scroll-down';
18
27
  export * from './lib/hlm-select-scroll-up';
19
28
  export * from './lib/hlm-select-separator';
20
29
  export * from './lib/hlm-select-trigger';
21
30
  export * from './lib/hlm-select-value';
31
+ export * from './lib/hlm-select-value-template';
32
+ export * from './lib/hlm-select-values';
33
+ export * from './lib/hlm-select-values-content';
22
34
 
23
35
  export const HlmSelectImports = [
24
36
  HlmSelect,
25
37
  HlmSelectContent,
26
38
  HlmSelectGroup,
39
+ HlmSelectItem,
27
40
  HlmSelectLabel,
28
- HlmSelectOption,
41
+ HlmSelectMultiple,
42
+ HlmSelectPlaceholder,
43
+ HlmSelectPortal,
29
44
  HlmSelectScrollDown,
30
45
  HlmSelectScrollUp,
31
46
  HlmSelectSeparator,
32
47
  HlmSelectTrigger,
33
48
  HlmSelectValue,
49
+ HlmSelectValues,
50
+ HlmSelectValuesContent,
51
+ HlmSelectValueTemplate,
34
52
  ] as const;
@@ -1,26 +1,38 @@
1
- import type { BooleanInput } from '@angular/cdk/coercion';
2
- import { Directive, booleanAttribute, input } from '@angular/core';
3
- import { injectExposedSideProvider, injectExposesStateProvider } from '@spartan-ng/brain/core';
4
- import { classes } from '<%- importAlias %>/utils';
1
+ import { BooleanInput } from '@angular/cdk/coercion';
2
+ import { booleanAttribute, ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
3
+ import { BrnSelectContent } from '@spartan-ng/brain/select';
4
+ import { classes, hlm } from '<%- importAlias %>/utils';
5
+ import { HlmSelectScrollDown } from './hlm-select-scroll-down';
6
+ import { HlmSelectScrollUp } from './hlm-select-scroll-up';
5
7
 
6
- @Directive({
7
- selector: '[hlmSelectContent], hlm-select-content',
8
- host: {
9
- '[attr.data-state]': '_stateProvider?.state() ?? "open"',
10
- '[attr.data-side]': '_sideProvider?.side() ?? "bottom"',
11
- },
8
+ @Component({
9
+ selector: 'hlm-select-content',
10
+ imports: [HlmSelectScrollUp, HlmSelectScrollDown],
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ hostDirectives: [BrnSelectContent],
13
+ template: `
14
+ @if (showScroll()) {
15
+ <hlm-select-scroll-up />
16
+ }
17
+
18
+ <div role="listbox" [class]="_computedListboxClasses()">
19
+ <ng-content />
20
+ </div>
21
+
22
+ @if (showScroll()) {
23
+ <hlm-select-scroll-down />
24
+ }
25
+ `,
12
26
  })
13
27
  export class HlmSelectContent {
14
- public readonly stickyLabels = input<boolean, BooleanInput>(false, {
15
- transform: booleanAttribute,
16
- });
17
- protected readonly _stateProvider = injectExposesStateProvider({ optional: true });
18
- protected readonly _sideProvider = injectExposedSideProvider({ optional: true });
28
+ protected readonly _computedListboxClasses = computed(() => hlm('flex flex-col'));
29
+
30
+ public readonly showScroll = input<boolean, BooleanInput>(false, { transform: booleanAttribute });
19
31
 
20
32
  constructor() {
21
33
  classes(
22
34
  () =>
23
- 'border-border 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 relative z-50 w-full min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md data-[side=bottom]:top-[2px] data-[side=top]:bottom-[2px]',
35
+ 'bg-popover no-scrollbar text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 relative isolate flex max-h-72 w-(--brn-select-width) min-w-36 flex-col overflow-x-hidden overflow-y-auto rounded-md shadow-md ring-1 duration-100',
24
36
  );
25
37
  }
26
38
  }
@@ -1,8 +1,16 @@
1
1
  import { Directive } from '@angular/core';
2
2
  import { BrnSelectGroup } from '@spartan-ng/brain/select';
3
+ import { classes } from '<%- importAlias %>/utils';
3
4
 
4
5
  @Directive({
5
- selector: '[hlmSelectGroup], hlm-select-group',
6
- hostDirectives: [BrnSelectGroup],
6
+ selector: '[hlmSelectGroup],hlm-select-group',
7
+ hostDirectives: [{ directive: BrnSelectGroup }],
8
+ host: {
9
+ 'data-slot': 'select-group',
10
+ },
7
11
  })
8
- export class HlmSelectGroup {}
12
+ export class HlmSelectGroup {
13
+ constructor() {
14
+ classes(() => 'scroll-my-1 p-1');
15
+ }
16
+ }
@@ -0,0 +1,34 @@
1
+ import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
2
+ import { NgIcon, provideIcons } from '@ng-icons/core';
3
+ import { lucideCheck } from '@ng-icons/lucide';
4
+ import { BrnSelectItem } from '@spartan-ng/brain/select';
5
+ import { classes } from '<%- importAlias %>/utils';
6
+
7
+ @Component({
8
+ selector: 'hlm-select-item',
9
+ imports: [NgIcon],
10
+ providers: [provideIcons({ lucideCheck })],
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ hostDirectives: [{ directive: BrnSelectItem, inputs: ['id', 'disabled', 'value'] }],
13
+ host: {
14
+ 'data-slot': 'select-item',
15
+ },
16
+ template: `
17
+ <ng-content />
18
+ @if (_active()) {
19
+ <ng-icon name="lucideCheck" class="absolute right-2 flex items-center justify-center" aria-hidden="true" />
20
+ }
21
+ `,
22
+ })
23
+ export class HlmSelectItem {
24
+ private readonly _brnSelectItem = inject(BrnSelectItem);
25
+
26
+ protected readonly _active = this._brnSelectItem.active;
27
+
28
+ constructor() {
29
+ classes(
30
+ () =>
31
+ "data-highlighted:bg-accent data-highlighted::text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0 [&_ng-icon:not([class*='text-'])]:text-base *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
32
+ );
33
+ }
34
+ }
@@ -1,20 +1,16 @@
1
- import { computed, Directive, inject } from '@angular/core';
1
+ import { Directive } from '@angular/core';
2
2
  import { BrnSelectLabel } from '@spartan-ng/brain/select';
3
3
  import { classes } from '<%- importAlias %>/utils';
4
- import { HlmSelectContent } from './hlm-select-content';
5
4
 
6
5
  @Directive({
7
- selector: '[hlmSelectLabel], hlm-select-label',
8
- hostDirectives: [BrnSelectLabel],
6
+ selector: '[hlmSelectLabel],hlm-select-label',
7
+ hostDirectives: [{ directive: BrnSelectLabel, inputs: ['id'] }],
8
+ host: {
9
+ 'data-slot': 'select-label',
10
+ },
9
11
  })
10
12
  export class HlmSelectLabel {
11
- private readonly _selectContent = inject(HlmSelectContent);
12
- private readonly _stickyLabels = computed(() => this._selectContent.stickyLabels());
13
-
14
13
  constructor() {
15
- classes(() => [
16
- 'text-muted-foreground px-2 py-1.5 text-xs',
17
- this._stickyLabels() ? 'bg-popover sticky top-0 z-[2] block' : '',
18
- ]);
14
+ classes(() => 'text-muted-foreground block px-2 py-1.5 text-xs');
19
15
  }
20
16
  }
@@ -0,0 +1,47 @@
1
+ import { Directive } from '@angular/core';
2
+ import { provideBrnDialogDefaultOptions } from '@spartan-ng/brain/dialog';
3
+ import { BrnPopover, provideBrnPopoverConfig } from '@spartan-ng/brain/popover';
4
+ import { BrnSelectMultiple } from '@spartan-ng/brain/select';
5
+ import { classes } from '<%- importAlias %>/utils';
6
+
7
+ @Directive({
8
+ selector: '[hlmSelectMultiple],hlm-select-multiple',
9
+ providers: [
10
+ provideBrnPopoverConfig({
11
+ align: 'start',
12
+ sideOffset: 6,
13
+ }),
14
+ provideBrnDialogDefaultOptions({
15
+ autoFocus: 'first-heading',
16
+ }),
17
+ ],
18
+ hostDirectives: [
19
+ {
20
+ directive: BrnSelectMultiple,
21
+ inputs: ['disabled', 'value', 'isItemEqualToValue', 'itemToString'],
22
+ outputs: ['valueChange'],
23
+ },
24
+ {
25
+ directive: BrnPopover,
26
+ inputs: [
27
+ 'align',
28
+ 'autoFocus',
29
+ 'closeDelay',
30
+ 'closeOnOutsidePointerEvents',
31
+ 'sideOffset',
32
+ 'state',
33
+ 'offsetX',
34
+ 'restoreFocus',
35
+ ],
36
+ outputs: ['stateChanged', 'closed'],
37
+ },
38
+ ],
39
+ host: {
40
+ 'data-slot': 'select',
41
+ },
42
+ })
43
+ export class HlmSelectMultiple {
44
+ constructor() {
45
+ classes(() => 'block');
46
+ }
47
+ }
@@ -0,0 +1,17 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnSelectPlaceholder } from '@spartan-ng/brain/select';
3
+ import { classes } from '<%- importAlias %>/utils';
4
+
5
+ @Directive({
6
+ selector: '[hlmSelectPlaceholder],hlm-select-placeholder',
7
+ hostDirectives: [BrnSelectPlaceholder],
8
+ host: { 'data-slot': 'select-placeholder' },
9
+ })
10
+ export class HlmSelectPlaceholder {
11
+ constructor() {
12
+ classes(
13
+ () =>
14
+ "flex items-center gap-2 data-hidden:hidden [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0 [&_ng-icon:not([class*='text-'])]:text-base",
15
+ );
16
+ }
17
+ }
@@ -0,0 +1,8 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnPopoverContent } from '@spartan-ng/brain/popover';
3
+
4
+ @Directive({
5
+ selector: '[hlmSelectPortal]',
6
+ hostDirectives: [{ directive: BrnPopoverContent, inputs: ['context', 'class'] }],
7
+ })
8
+ export class HlmSelectPortal {}
@@ -1,20 +1,24 @@
1
1
  import { ChangeDetectionStrategy, Component } from '@angular/core';
2
2
  import { NgIcon, provideIcons } from '@ng-icons/core';
3
3
  import { lucideChevronDown } from '@ng-icons/lucide';
4
- import { HlmIcon } from '<%- importAlias %>/icon';
4
+ import { BrnSelectScrollDown } from '@spartan-ng/brain/select';
5
5
  import { classes } from '<%- importAlias %>/utils';
6
6
 
7
7
  @Component({
8
8
  selector: 'hlm-select-scroll-down',
9
- imports: [NgIcon, HlmIcon],
9
+ imports: [NgIcon],
10
10
  providers: [provideIcons({ lucideChevronDown })],
11
11
  changeDetection: ChangeDetectionStrategy.OnPush,
12
+ hostDirectives: [BrnSelectScrollDown],
12
13
  template: `
13
- <ng-icon hlm size="sm" class="ml-2" name="lucideChevronDown" />
14
+ <ng-icon name="lucideChevronDown" />
14
15
  `,
15
16
  })
16
17
  export class HlmSelectScrollDown {
17
18
  constructor() {
18
- classes(() => 'flex cursor-default items-center justify-center py-1');
19
+ classes(
20
+ () =>
21
+ "bg-popover sticky bottom-0 z-10 flex w-full cursor-default items-center justify-center py-1 data-hidden:hidden [&_ng-icon:not([class*='text-'])]:text-base",
22
+ );
19
23
  }
20
24
  }
@@ -1,20 +1,24 @@
1
1
  import { ChangeDetectionStrategy, Component } from '@angular/core';
2
2
  import { NgIcon, provideIcons } from '@ng-icons/core';
3
3
  import { lucideChevronUp } from '@ng-icons/lucide';
4
- import { HlmIcon } from '<%- importAlias %>/icon';
4
+ import { BrnSelectScrollUp } from '@spartan-ng/brain/select';
5
5
  import { classes } from '<%- importAlias %>/utils';
6
6
 
7
7
  @Component({
8
8
  selector: 'hlm-select-scroll-up',
9
- imports: [NgIcon, HlmIcon],
9
+ imports: [NgIcon],
10
10
  providers: [provideIcons({ lucideChevronUp })],
11
11
  changeDetection: ChangeDetectionStrategy.OnPush,
12
+ hostDirectives: [BrnSelectScrollUp],
12
13
  template: `
13
- <ng-icon hlm size="sm" class="ml-2" name="lucideChevronUp" />
14
+ <ng-icon name="lucideChevronUp" />
14
15
  `,
15
16
  })
16
17
  export class HlmSelectScrollUp {
17
18
  constructor() {
18
- classes(() => 'flex cursor-default items-center justify-center py-1');
19
+ classes(
20
+ () =>
21
+ "bg-popover sticky top-0 z-10 flex w-full cursor-default items-center justify-center py-1 data-hidden:hidden [&_ng-icon:not([class*='text-'])]:text-base",
22
+ );
19
23
  }
20
24
  }
@@ -1,14 +1,16 @@
1
1
  import { Directive } from '@angular/core';
2
+ import { BrnSelectSeparator } from '@spartan-ng/brain/select';
2
3
  import { classes } from '<%- importAlias %>/utils';
3
4
 
4
5
  @Directive({
5
- selector: '[hlmSelectSeparator]',
6
+ selector: '[hlmSelectSeparator],hlm-select-separator',
7
+ hostDirectives: [{ directive: BrnSelectSeparator, inputs: ['orientation'] }],
6
8
  host: {
7
9
  'data-slot': 'select-separator',
8
10
  },
9
11
  })
10
12
  export class HlmSelectSeparator {
11
13
  constructor() {
12
- classes(() => 'bg-border pointer-events-none -mx-1 my-1 h-px');
14
+ classes(() => 'bg-border pointer-events-none -mx-1 my-1 h-px shrink-0');
13
15
  }
14
16
  }
@@ -1,53 +1,41 @@
1
- import { ChangeDetectionStrategy, Component, computed, contentChild, inject, input } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
2
2
  import { NgIcon, provideIcons } from '@ng-icons/core';
3
3
  import { lucideChevronDown } from '@ng-icons/lucide';
4
- import { BrnSelect, BrnSelectTrigger } from '@spartan-ng/brain/select';
5
- import { HlmIcon } from '<%- importAlias %>/icon';
4
+ import { BrnSelectTrigger, BrnSelectTriggerWrapper } from '@spartan-ng/brain/select';
6
5
  import { hlm } from '<%- importAlias %>/utils';
7
- import { cva } from 'class-variance-authority';
8
6
  import type { ClassValue } from 'clsx';
9
7
 
10
- export const selectTriggerVariants = cva(
11
- `border-input [&>ng-icon:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 [&>ng-icon]:pointer-events-none [&>ng-icon]:size-4 [&>ng-icon]:shrink-0`,
12
- {
13
- variants: {
14
- error: {
15
- auto: '[&.ng-invalid.ng-touched]:text-destructive [&.ng-invalid.ng-touched]:border-destructive [&.ng-invalid.ng-touched]:focus-visible:ring-destructive/20 dark:[&.ng-invalid.ng-touched]:focus-visible:ring-destructive/40',
16
- true: 'text-destructive border-destructive focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',
17
- },
18
- },
19
- defaultVariants: {
20
- error: 'auto',
21
- },
22
- },
23
- );
24
-
25
8
  @Component({
26
9
  selector: 'hlm-select-trigger',
27
- imports: [BrnSelectTrigger, NgIcon, HlmIcon],
10
+ imports: [NgIcon, BrnSelectTrigger],
28
11
  providers: [provideIcons({ lucideChevronDown })],
29
12
  changeDetection: ChangeDetectionStrategy.OnPush,
13
+ hostDirectives: [BrnSelectTriggerWrapper],
30
14
  template: `
31
- <button [class]="_computedClass()" #button hlmInput brnSelectTrigger type="button" [attr.data-size]="size()">
15
+ <button
16
+ brnSelectTrigger
17
+ [id]="buttonId()"
18
+ [class]="_computedClass()"
19
+ [attr.data-size]="size()"
20
+ data-slot="select-trigger"
21
+ >
32
22
  <ng-content />
33
- @if (_icon()) {
34
- <ng-content select="ng-icon" />
35
- } @else {
36
- <ng-icon hlm size="sm" class="ml-2 flex-none" name="lucideChevronDown" />
37
- }
23
+ <ng-icon name="lucideChevronDown" class="text-muted-foreground pointer-events-none text-base" />
38
24
  </button>
39
25
  `,
40
26
  })
41
27
  export class HlmSelectTrigger {
42
- protected readonly _icon = contentChild(HlmIcon);
43
-
44
- protected readonly _brnSelect = inject(BrnSelect, { optional: true });
28
+ private static _id = 0;
45
29
 
46
30
  public readonly userClass = input<ClassValue>('', { alias: 'class' });
47
-
48
- public readonly size = input<'default' | 'sm'>('default');
49
-
50
31
  protected readonly _computedClass = computed(() =>
51
- hlm(selectTriggerVariants({ error: this._brnSelect?.errorState() }), this.userClass()),
32
+ hlm(
33
+ "border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 flex w-full items-center justify-between gap-1.5 rounded-md border bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0 [&_ng-icon:not([class*='text-'])]:text-base",
34
+ this.userClass(),
35
+ ),
52
36
  );
37
+
38
+ public readonly buttonId = input<string>(`hlm-select-trigger-${HlmSelectTrigger._id++}`);
39
+
40
+ public readonly size = input<'default' | 'sm'>('default');
53
41
  }
@@ -0,0 +1,5 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnSelectValueTemplate } from '@spartan-ng/brain/select';
3
+
4
+ @Directive({ selector: '[hlmSelectValueTemplate]', hostDirectives: [BrnSelectValueTemplate] })
5
+ export class HlmSelectValueTemplate {}
@@ -1,11 +1,18 @@
1
- import { Directive } from '@angular/core';
1
+ import { Directive, inject } from '@angular/core';
2
+ import { BrnSelectValue } from '@spartan-ng/brain/select';
2
3
  import { classes } from '<%- importAlias %>/utils';
3
4
 
4
5
  @Directive({
5
- selector: 'hlm-select-value,[hlmSelectValue], brn-select-value[hlm]',
6
+ selector: '[hlmSelectValue],hlm-select-value',
7
+ hostDirectives: [{ directive: BrnSelectValue, inputs: ['placeholder'] }],
8
+ host: { '[attr.data-slot]': '!_hidden() ? "select-value" : null' },
6
9
  })
7
10
  export class HlmSelectValue {
11
+ private readonly _brnSelectValue = inject(BrnSelectValue);
12
+
13
+ protected readonly _hidden = this._brnSelectValue.hidden;
14
+
8
15
  constructor() {
9
- classes(() => 'data-[placeholder]:text-muted-foreground line-clamp-1 flex items-center gap-2 truncate');
16
+ classes(() => 'data-hidden:hidden');
10
17
  }
11
18
  }
@@ -0,0 +1,9 @@
1
+ import { Directive } from '@angular/core';
2
+ import { classes } from '<%- importAlias %>/utils';
3
+
4
+ @Directive({ selector: '[hlmSelectValuesContent],hlm-select-values-content' })
5
+ export class HlmSelectValuesContent {
6
+ constructor() {
7
+ classes(() => 'flex gap-1');
8
+ }
9
+ }
@@ -0,0 +1,5 @@
1
+ import { Directive } from '@angular/core';
2
+ import { BrnSelectValues } from '@spartan-ng/brain/select';
3
+
4
+ @Directive({ selector: '[hlmSelectValues]', hostDirectives: [BrnSelectValues] })
5
+ export class HlmSelectValues {}
@@ -1,11 +1,47 @@
1
1
  import { Directive } from '@angular/core';
2
+ import { provideBrnDialogDefaultOptions } from '@spartan-ng/brain/dialog';
3
+ import { BrnPopover, provideBrnPopoverConfig } from '@spartan-ng/brain/popover';
4
+ import { BrnSelect } from '@spartan-ng/brain/select';
2
5
  import { classes } from '<%- importAlias %>/utils';
3
6
 
4
7
  @Directive({
5
- selector: 'hlm-select,[hlmSelect],brn-select[hlm]',
8
+ selector: '[hlmSelect],hlm-select',
9
+ providers: [
10
+ provideBrnPopoverConfig({
11
+ align: 'start',
12
+ sideOffset: 6,
13
+ }),
14
+ provideBrnDialogDefaultOptions({
15
+ autoFocus: 'first-heading',
16
+ }),
17
+ ],
18
+ hostDirectives: [
19
+ {
20
+ directive: BrnSelect,
21
+ inputs: ['disabled', 'value', 'isItemEqualToValue', 'itemToString'],
22
+ outputs: ['valueChange'],
23
+ },
24
+ {
25
+ directive: BrnPopover,
26
+ inputs: [
27
+ 'align',
28
+ 'autoFocus',
29
+ 'closeDelay',
30
+ 'closeOnOutsidePointerEvents',
31
+ 'sideOffset',
32
+ 'state',
33
+ 'offsetX',
34
+ 'restoreFocus',
35
+ ],
36
+ outputs: ['stateChanged', 'closed'],
37
+ },
38
+ ],
39
+ host: {
40
+ 'data-slot': 'select',
41
+ },
6
42
  })
7
43
  export class HlmSelect {
8
44
  constructor() {
9
- classes(() => 'space-y-2');
45
+ classes(() => 'block');
10
46
  }
11
47
  }