@egose/shadcn-theme-ng 0.0.18 → 0.0.20

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 (37) hide show
  1. package/autocomplete/fesm2022/autocomplete.mjs +1 -1
  2. package/autocomplete/fesm2022/autocomplete.mjs.map +1 -1
  3. package/autocomplete/index.d.ts +3 -3
  4. package/button/fesm2022/button.mjs +4 -4
  5. package/button/fesm2022/button.mjs.map +1 -1
  6. package/button/index.d.ts +11 -11
  7. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +1 -1
  8. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +1 -1
  9. package/exports.json +1 -1
  10. package/form-checkbox/fesm2022/form-checkbox.mjs +2 -2
  11. package/form-checkbox/fesm2022/form-checkbox.mjs.map +1 -1
  12. package/form-date-picker/fesm2022/form-date-picker.mjs +10 -9
  13. package/form-date-picker/fesm2022/form-date-picker.mjs.map +1 -1
  14. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +28 -26
  15. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +1 -1
  16. package/form-select/fesm2022/form-select.mjs +26 -25
  17. package/form-select/fesm2022/form-select.mjs.map +1 -1
  18. package/form-text-input/fesm2022/form-text-input.mjs +10 -9
  19. package/form-text-input/fesm2022/form-text-input.mjs.map +1 -1
  20. package/form-textarea/fesm2022/form-textarea.mjs +10 -9
  21. package/form-textarea/fesm2022/form-textarea.mjs.map +1 -1
  22. package/layout-simple/README.md +64 -0
  23. package/layout-simple/fesm2022/layout-simple.mjs +330 -0
  24. package/layout-simple/fesm2022/layout-simple.mjs.map +1 -0
  25. package/layout-simple/index.d.ts +111 -0
  26. package/menu/README.md +64 -0
  27. package/menu/fesm2022/menu.mjs +449 -0
  28. package/menu/fesm2022/menu.mjs.map +1 -0
  29. package/menu/index.d.ts +137 -0
  30. package/package.json +13 -1
  31. package/spinner/fesm2022/spinner.mjs +4 -10
  32. package/spinner/fesm2022/spinner.mjs.map +1 -1
  33. package/spinner/index.d.ts +1 -3
  34. package/switch/README.md +64 -0
  35. package/switch/fesm2022/switch.mjs +143 -0
  36. package/switch/fesm2022/switch.mjs.map +1 -0
  37. package/switch/index.d.ts +56 -0
@@ -0,0 +1,330 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, Component, viewChild, output, inject, signal, resource, ChangeDetectionStrategy, computed } from '@angular/core';
3
+ import { RouterLink } from '@angular/router';
4
+ import * as i1$1 from '@angular/cdk/layout';
5
+ import { Breakpoints } from '@angular/cdk/layout';
6
+ import { hlm } from '@egose/shadcn-theme-ng/utils';
7
+ import { NgIcon, provideIcons } from '@ng-icons/core';
8
+ import { lucideUser } from '@ng-icons/lucide';
9
+ import { BrnMenuTrigger } from '@spartan-ng/brain/menu';
10
+ import { HlmButton } from '@egose/shadcn-theme-ng/button';
11
+ import { HlmMenu, HlmMenuItem, HlmMenuLabel, HlmMenuSeparator, HlmMenuGroup } from '@egose/shadcn-theme-ng/menu';
12
+ import * as i2 from '@angular/forms';
13
+ import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
14
+ import * as i1 from '@egose/shadcn-theme-ng/autocomplete';
15
+ import { provideHlmAutocompleteConfig, HlmAutocompleteImports } from '@egose/shadcn-theme-ng/autocomplete';
16
+ import { HlmSpinner } from '@egose/shadcn-theme-ng/spinner';
17
+
18
+ class EgLayoutSimpleUserMenu {
19
+ menus = input([], ...(ngDevMode ? [{ debugName: "menus" }] : []));
20
+ hlm = hlm;
21
+ lucideUser = lucideUser;
22
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgLayoutSimpleUserMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
23
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.1", type: EgLayoutSimpleUserMenu, isStandalone: true, selector: "eg-layout-simple-user-menu", inputs: { menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
24
+ provideIcons({
25
+ lucideUser,
26
+ }),
27
+ ], ngImport: i0, template: `
28
+ <ng-template #iconTemplate>
29
+ <ng-icon [svg]="lucideUser" size="1.5rem" />
30
+ </ng-template>
31
+
32
+ <div class="flex w-full items-center justify-center pt-[20%]">
33
+ <button
34
+ hlmButton
35
+ variant="primary"
36
+ size="icon"
37
+ align="end"
38
+ [brnMenuTriggerFor]="menu"
39
+ [icon]="iconTemplate"
40
+ class="rounded-full border border-gray-400"
41
+ ></button>
42
+ </div>
43
+
44
+ <ng-template #menu>
45
+ <hlm-menu class="w-56">
46
+ @for (section of menus(); track section) {
47
+ @if (section.label) {
48
+ <hlm-menu-label>{{ section.label }}</hlm-menu-label>
49
+ }
50
+ @if (section.items?.length) {
51
+ <hlm-menu-group>
52
+ @for (item of section.items; track item) {
53
+ @if (item.link) {
54
+ <a hlmMenuItem [routerLink]="item.link" [class]="hlm(item.class, 'cursor-pointer')">
55
+ @if (item.icon) {
56
+ <ng-icon [svg]="item.icon" size="1rem" [class]="hlm(item.class, 'cursor-pointer mr-2')" />
57
+ }
58
+ <span>{{ item.label }}</span>
59
+ </a>
60
+ } @else {
61
+ <button hlmMenuItem (click)="item.action?.()" [class]="hlm(item.class, 'cursor-pointer')">
62
+ @if (item.icon) {
63
+ <ng-icon [svg]="item.icon" size="1rem" [class]="hlm(item.class, 'cursor-pointer mr-2')" />
64
+ }
65
+ <span>{{ item.label }}</span>
66
+ </button>
67
+ }
68
+ }
69
+ </hlm-menu-group>
70
+ }
71
+ @if (section.separator) {
72
+ <hlm-menu-separator />
73
+ }
74
+ }
75
+ </hlm-menu>
76
+ </ng-template>
77
+ `, isInline: true, dependencies: [{ kind: "directive", type: BrnMenuTrigger, selector: "[brnMenuTriggerFor]", inputs: ["align"] }, { kind: "component", type: HlmMenu, selector: "hlm-menu", inputs: ["class", "variant"] }, { kind: "directive", type: HlmMenuItem, selector: "[hlmMenuItem]", inputs: ["variant", "inset", "class"] }, { kind: "component", type: HlmMenuLabel, selector: "hlm-menu-label", inputs: ["inset", "class"] }, { kind: "component", type: HlmMenuSeparator, selector: "hlm-menu-separator", inputs: ["class"] }, { kind: "component", type: HlmMenuGroup, selector: "hlm-menu-group" }, { kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
78
+ }
79
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgLayoutSimpleUserMenu, decorators: [{
80
+ type: Component,
81
+ args: [{
82
+ selector: 'eg-layout-simple-user-menu',
83
+ imports: [
84
+ BrnMenuTrigger,
85
+ HlmMenu,
86
+ HlmMenuItem,
87
+ HlmMenuLabel,
88
+ HlmMenuSeparator,
89
+ HlmMenuGroup,
90
+ HlmButton,
91
+ NgIcon,
92
+ RouterLink,
93
+ ],
94
+ providers: [
95
+ provideIcons({
96
+ lucideUser,
97
+ }),
98
+ ],
99
+ template: `
100
+ <ng-template #iconTemplate>
101
+ <ng-icon [svg]="lucideUser" size="1.5rem" />
102
+ </ng-template>
103
+
104
+ <div class="flex w-full items-center justify-center pt-[20%]">
105
+ <button
106
+ hlmButton
107
+ variant="primary"
108
+ size="icon"
109
+ align="end"
110
+ [brnMenuTriggerFor]="menu"
111
+ [icon]="iconTemplate"
112
+ class="rounded-full border border-gray-400"
113
+ ></button>
114
+ </div>
115
+
116
+ <ng-template #menu>
117
+ <hlm-menu class="w-56">
118
+ @for (section of menus(); track section) {
119
+ @if (section.label) {
120
+ <hlm-menu-label>{{ section.label }}</hlm-menu-label>
121
+ }
122
+ @if (section.items?.length) {
123
+ <hlm-menu-group>
124
+ @for (item of section.items; track item) {
125
+ @if (item.link) {
126
+ <a hlmMenuItem [routerLink]="item.link" [class]="hlm(item.class, 'cursor-pointer')">
127
+ @if (item.icon) {
128
+ <ng-icon [svg]="item.icon" size="1rem" [class]="hlm(item.class, 'cursor-pointer mr-2')" />
129
+ }
130
+ <span>{{ item.label }}</span>
131
+ </a>
132
+ } @else {
133
+ <button hlmMenuItem (click)="item.action?.()" [class]="hlm(item.class, 'cursor-pointer')">
134
+ @if (item.icon) {
135
+ <ng-icon [svg]="item.icon" size="1rem" [class]="hlm(item.class, 'cursor-pointer mr-2')" />
136
+ }
137
+ <span>{{ item.label }}</span>
138
+ </button>
139
+ }
140
+ }
141
+ </hlm-menu-group>
142
+ }
143
+ @if (section.separator) {
144
+ <hlm-menu-separator />
145
+ }
146
+ }
147
+ </hlm-menu>
148
+ </ng-template>
149
+ `,
150
+ }]
151
+ }] });
152
+
153
+ const transformValueToSearchMap = {};
154
+ class EgGenericAutocomplete {
155
+ defaultOptionTemplate = viewChild('defaultOption', ...(ngDevMode ? [{ debugName: "defaultOptionTemplate" }] : []));
156
+ controlId = input(crypto.randomUUID(), ...(ngDevMode ? [{ debugName: "controlId" }] : []));
157
+ placeholderText = input('Select an option', ...(ngDevMode ? [{ debugName: "placeholderText" }] : []));
158
+ emptyText = input('No options found', ...(ngDevMode ? [{ debugName: "emptyText" }] : []));
159
+ optionTemplate = input(this.defaultOptionTemplate, ...(ngDevMode ? [{ debugName: "optionTemplate" }] : []));
160
+ loaderFn = input(async () => [], ...(ngDevMode ? [{ debugName: "loaderFn" }] : []));
161
+ transformValueToSearch = input((value) => String(value), ...(ngDevMode ? [{ debugName: "transformValueToSearch" }] : []));
162
+ optionChange = output();
163
+ _formBuilder = inject(FormBuilder);
164
+ form = this._formBuilder.group({
165
+ option: [null, Validators.required],
166
+ });
167
+ search = signal('', ...(ngDevMode ? [{ debugName: "search" }] : []));
168
+ options = resource({
169
+ defaultValue: [],
170
+ params: () => ({ search: this.search(), negajjang: '1111' }),
171
+ loader: async ({ params }) => {
172
+ const fn = this.loaderFn();
173
+ if (!fn) {
174
+ return [];
175
+ }
176
+ return fn(params);
177
+ },
178
+ });
179
+ ngOnInit() {
180
+ transformValueToSearchMap[this.controlId()] = this.transformValueToSearch();
181
+ this.form.controls['option'].valueChanges.subscribe((value) => {
182
+ if (value !== null) {
183
+ this.optionChange.emit(value);
184
+ }
185
+ });
186
+ }
187
+ ngOnDestroy() {
188
+ delete transformValueToSearchMap[this.controlId()];
189
+ }
190
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgGenericAutocomplete, deps: [], target: i0.ɵɵFactoryTarget.Component });
191
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.1", type: EgGenericAutocomplete, isStandalone: true, selector: "eg-generic-autocomplete", inputs: { controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null }, placeholderText: { classPropertyName: "placeholderText", publicName: "placeholderText", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, optionTemplate: { classPropertyName: "optionTemplate", publicName: "optionTemplate", isSignal: true, isRequired: false, transformFunction: null }, loaderFn: { classPropertyName: "loaderFn", publicName: "loaderFn", isSignal: true, isRequired: false, transformFunction: null }, transformValueToSearch: { classPropertyName: "transformValueToSearch", publicName: "transformValueToSearch", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionChange: "optionChange" }, viewQueries: [{ propertyName: "defaultOptionTemplate", first: true, predicate: ["defaultOption"], descendants: true, isSignal: true }], ngImport: i0, template: `
192
+ <form [formGroup]="form" class="space-y-8">
193
+ <hlm-autocomplete
194
+ [inputId]="controlId()"
195
+ [filteredOptions]="options.value()"
196
+ [optionTemplate]="optionTemplate()"
197
+ [loading]="options.isLoading()"
198
+ [(search)]="search"
199
+ [searchPlaceholderText]="placeholderText()"
200
+ [emptyText]="emptyText()"
201
+ formControlName="option"
202
+ class="bg-white"
203
+ >
204
+ <hlm-spinner loading />
205
+ </hlm-autocomplete>
206
+ </form>
207
+ <ng-template #defaultOption let-option>
208
+ {{ option }}
209
+ </ng-template>
210
+ `, isInline: true, dependencies: [{ kind: "component", type: HlmSpinner, selector: "hlm-spinner", inputs: ["size", "show", "class", "spinnerClass"] }, { kind: "component", type: i1.HlmAutocomplete, selector: "hlm-autocomplete", inputs: ["onSelect", "class", "autocompleteListClass", "autocompleteEmptyClass", "filteredOptions", "value", "search", "transformValueToSearch", "optionTemplate", "loading", "searchPlaceholderText", "loadingText", "emptyText", "ariaLabelToggleButton", "inputId", "disabled"], outputs: ["valueChange", "searchChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], viewProviders: [
211
+ provideHlmAutocompleteConfig({
212
+ transformValueToSearch: (params, inputId) => {
213
+ const fn = transformValueToSearchMap[inputId];
214
+ return fn(params);
215
+ },
216
+ }),
217
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
218
+ }
219
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgGenericAutocomplete, decorators: [{
220
+ type: Component,
221
+ args: [{
222
+ selector: 'eg-generic-autocomplete',
223
+ imports: [HlmSpinner, HlmAutocompleteImports, ReactiveFormsModule],
224
+ template: `
225
+ <form [formGroup]="form" class="space-y-8">
226
+ <hlm-autocomplete
227
+ [inputId]="controlId()"
228
+ [filteredOptions]="options.value()"
229
+ [optionTemplate]="optionTemplate()"
230
+ [loading]="options.isLoading()"
231
+ [(search)]="search"
232
+ [searchPlaceholderText]="placeholderText()"
233
+ [emptyText]="emptyText()"
234
+ formControlName="option"
235
+ class="bg-white"
236
+ >
237
+ <hlm-spinner loading />
238
+ </hlm-autocomplete>
239
+ </form>
240
+ <ng-template #defaultOption let-option>
241
+ {{ option }}
242
+ </ng-template>
243
+ `,
244
+ changeDetection: ChangeDetectionStrategy.OnPush,
245
+ viewProviders: [
246
+ provideHlmAutocompleteConfig({
247
+ transformValueToSearch: (params, inputId) => {
248
+ const fn = transformValueToSearchMap[inputId];
249
+ return fn(params);
250
+ },
251
+ }),
252
+ ],
253
+ }]
254
+ }] });
255
+
256
+ const commonLinkGroupClasses = 'hidden md:flex space-x-4 items-center';
257
+ const commonLinkClasses = 'text-left text-secondary visited:text-secondary hover:text-primary cursor-pointer no-underline';
258
+ class EgLayoutSimple {
259
+ breakpointObserver;
260
+ /** Menu data inputs */
261
+ leftMenus = input([], ...(ngDevMode ? [{ debugName: "leftMenus" }] : []));
262
+ rightMenus = input([], ...(ngDevMode ? [{ debugName: "rightMenus" }] : []));
263
+ userMenus = input([], ...(ngDevMode ? [{ debugName: "userMenus" }] : []));
264
+ logo = input('assets/logo.png', ...(ngDevMode ? [{ debugName: "logo" }] : []));
265
+ logoLink = input('/', ...(ngDevMode ? [{ debugName: "logoLink" }] : []));
266
+ hlm = hlm;
267
+ headerClass = input('', ...(ngDevMode ? [{ debugName: "headerClass", alias: 'headerClass' }] : [{ alias: 'headerClass' }]));
268
+ /** Container class inputs */
269
+ leftMenuClass = input('', ...(ngDevMode ? [{ debugName: "leftMenuClass", alias: 'leftClass' }] : [{ alias: 'leftClass' }]));
270
+ rightMenuClass = input('', ...(ngDevMode ? [{ debugName: "rightMenuClass", alias: 'rightClass' }] : [{ alias: 'rightClass' }]));
271
+ /** Link/button base class inputs */
272
+ leftLinkClass = input('', ...(ngDevMode ? [{ debugName: "leftLinkClass", alias: 'leftLinkClass' }] : [{ alias: 'leftLinkClass' }]));
273
+ rightLinkClass = input('', ...(ngDevMode ? [{ debugName: "rightLinkClass", alias: 'rightLinkClass' }] : [{ alias: 'rightLinkClass' }]));
274
+ searchEnabled = input(false, ...(ngDevMode ? [{ debugName: "searchEnabled" }] : []));
275
+ searchPlaceholderText = input('Select an page', ...(ngDevMode ? [{ debugName: "searchPlaceholderText" }] : []));
276
+ searchEmptyText = input('No pages found', ...(ngDevMode ? [{ debugName: "searchEmptyText" }] : []));
277
+ searchOptionTemplate = input(...(ngDevMode ? [undefined, { debugName: "searchOptionTemplate" }] : []));
278
+ searchLoaderFn = input(...(ngDevMode ? [undefined, { debugName: "searchLoaderFn" }] : []));
279
+ searchTransformValueToSearch = input(...(ngDevMode ? [undefined, { debugName: "searchTransformValueToSearch" }] : []));
280
+ searchOptionChange = output();
281
+ _headerClass = computed(() => hlm('px-4 py-2 flex items-center justify-between bg-gray-100 border-b border-gray-300', this.headerClass()), ...(ngDevMode ? [{ debugName: "_headerClass" }] : []));
282
+ /** Computed merged classes for containers */
283
+ _computedLeftClass = computed(() => hlm(commonLinkGroupClasses, this.leftMenuClass()), ...(ngDevMode ? [{ debugName: "_computedLeftClass" }] : []));
284
+ _computedRightClass = computed(() => hlm(commonLinkGroupClasses, this.rightMenuClass()), ...(ngDevMode ? [{ debugName: "_computedRightClass" }] : []));
285
+ /** Computed merged classes for link/button elements */
286
+ _computedLeftLinkClass = computed(() => hlm(commonLinkClasses, this.leftLinkClass()), ...(ngDevMode ? [{ debugName: "_computedLeftLinkClass" }] : []));
287
+ _computedRightLinkClass = computed(() => hlm(commonLinkClasses, this.rightLinkClass()), ...(ngDevMode ? [{ debugName: "_computedRightLinkClass" }] : []));
288
+ mobileMenuItemClass = commonLinkClasses;
289
+ footerEnabled = input(false, ...(ngDevMode ? [{ debugName: "footerEnabled" }] : []));
290
+ footerMenus = input([], ...(ngDevMode ? [{ debugName: "footerMenus" }] : []));
291
+ footerMenuClass = input('', ...(ngDevMode ? [{ debugName: "footerMenuClass", alias: 'footerMenuClass' }] : [{ alias: 'footerMenuClass' }]));
292
+ footerLinkClass = input('', ...(ngDevMode ? [{ debugName: "footerLinkClass", alias: 'footerLinkClass' }] : [{ alias: 'footerLinkClass' }]));
293
+ footerContent = input('© 2024 My Company', ...(ngDevMode ? [{ debugName: "footerContent" }] : []));
294
+ footerClass = input('', ...(ngDevMode ? [{ debugName: "footerClass", alias: 'footerClass' }] : [{ alias: 'footerClass' }]));
295
+ _footerClass = computed(() => hlm('px-4 py-4 bg-gray-100 border-t border-gray-300 text-sm text-gray-600', this.footerClass()), ...(ngDevMode ? [{ debugName: "_footerClass" }] : []));
296
+ _computedFooterMenuClass = computed(() => hlm('flex flex-wrap justify-center space-x-4', this.footerMenuClass()), ...(ngDevMode ? [{ debugName: "_computedFooterMenuClass" }] : []));
297
+ _computedFooterLinkClass = computed(() => hlm('text-secondary hover:text-primary cursor-pointer no-underline', this.footerLinkClass()), ...(ngDevMode ? [{ debugName: "_computedFooterLinkClass" }] : []));
298
+ /** Mobile menu state */
299
+ mobileMenuOpen = false;
300
+ isMobile = signal(false, ...(ngDevMode ? [{ debugName: "isMobile" }] : []));
301
+ constructor(breakpointObserver) {
302
+ this.breakpointObserver = breakpointObserver;
303
+ this.breakpointObserver.observe([Breakpoints.Handset]).subscribe((result) => {
304
+ this.isMobile.set(result.matches);
305
+ });
306
+ }
307
+ toggleMobileMenu() {
308
+ this.mobileMenuOpen = !this.mobileMenuOpen;
309
+ }
310
+ onSearchOptionChange(value) {
311
+ this.searchOptionChange.emit(value);
312
+ }
313
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgLayoutSimple, deps: [{ token: i1$1.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component });
314
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.1", type: EgLayoutSimple, isStandalone: true, selector: "eg-layout-simple", inputs: { leftMenus: { classPropertyName: "leftMenus", publicName: "leftMenus", isSignal: true, isRequired: false, transformFunction: null }, rightMenus: { classPropertyName: "rightMenus", publicName: "rightMenus", isSignal: true, isRequired: false, transformFunction: null }, userMenus: { classPropertyName: "userMenus", publicName: "userMenus", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, logoLink: { classPropertyName: "logoLink", publicName: "logoLink", isSignal: true, isRequired: false, transformFunction: null }, headerClass: { classPropertyName: "headerClass", publicName: "headerClass", isSignal: true, isRequired: false, transformFunction: null }, leftMenuClass: { classPropertyName: "leftMenuClass", publicName: "leftClass", isSignal: true, isRequired: false, transformFunction: null }, rightMenuClass: { classPropertyName: "rightMenuClass", publicName: "rightClass", isSignal: true, isRequired: false, transformFunction: null }, leftLinkClass: { classPropertyName: "leftLinkClass", publicName: "leftLinkClass", isSignal: true, isRequired: false, transformFunction: null }, rightLinkClass: { classPropertyName: "rightLinkClass", publicName: "rightLinkClass", isSignal: true, isRequired: false, transformFunction: null }, searchEnabled: { classPropertyName: "searchEnabled", publicName: "searchEnabled", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholderText: { classPropertyName: "searchPlaceholderText", publicName: "searchPlaceholderText", isSignal: true, isRequired: false, transformFunction: null }, searchEmptyText: { classPropertyName: "searchEmptyText", publicName: "searchEmptyText", isSignal: true, isRequired: false, transformFunction: null }, searchOptionTemplate: { classPropertyName: "searchOptionTemplate", publicName: "searchOptionTemplate", isSignal: true, isRequired: false, transformFunction: null }, searchLoaderFn: { classPropertyName: "searchLoaderFn", publicName: "searchLoaderFn", isSignal: true, isRequired: false, transformFunction: null }, searchTransformValueToSearch: { classPropertyName: "searchTransformValueToSearch", publicName: "searchTransformValueToSearch", isSignal: true, isRequired: false, transformFunction: null }, footerEnabled: { classPropertyName: "footerEnabled", publicName: "footerEnabled", isSignal: true, isRequired: false, transformFunction: null }, footerMenus: { classPropertyName: "footerMenus", publicName: "footerMenus", isSignal: true, isRequired: false, transformFunction: null }, footerMenuClass: { classPropertyName: "footerMenuClass", publicName: "footerMenuClass", isSignal: true, isRequired: false, transformFunction: null }, footerLinkClass: { classPropertyName: "footerLinkClass", publicName: "footerLinkClass", isSignal: true, isRequired: false, transformFunction: null }, footerContent: { classPropertyName: "footerContent", publicName: "footerContent", isSignal: true, isRequired: false, transformFunction: null }, footerClass: { classPropertyName: "footerClass", publicName: "footerClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchOptionChange: "searchOptionChange" }, ngImport: i0, template: "<div class=\"flex flex-col min-h-screen\">\n <!-- Header -->\n <header [class]=\"_headerClass()\">\n <!-- Left side: Logo + Left menus -->\n <div class=\"flex items-center space-x-6\">\n <div class=\"logo\">\n <a [routerLink]=\"logoLink()\">\n <img [src]=\"logo()\" alt=\"Logo\" class=\"h-10\" />\n </a>\n </div>\n <!-- Left menus (desktop) -->\n <nav [class]=\"_computedLeftClass()\">\n @for (item of leftMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n </nav>\n </div>\n\n <!-- Right menus (desktop) -->\n <nav [class]=\"_computedRightClass()\">\n @if (searchEnabled()) {\n <eg-generic-autocomplete\n [optionTemplate]=\"searchOptionTemplate()\"\n [loaderFn]=\"searchLoaderFn()\"\n [transformValueToSearch]=\"searchTransformValueToSearch()\"\n [placeholderText]=\"searchPlaceholderText()\"\n [emptyText]=\"searchEmptyText()\"\n (optionChange)=\"onSearchOptionChange($event)\"\n ></eg-generic-autocomplete>\n }\n\n @for (item of rightMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n\n @let uMenus = userMenus();\n @if (uMenus && uMenus.length > 0) {\n <eg-layout-simple-user-menu [menus]=\"uMenus\"></eg-layout-simple-user-menu>\n }\n </nav>\n\n <!-- Mobile menu button -->\n <button\n (click)=\"toggleMobileMenu()\"\n class=\"md:hidden p-2 text-gray-700 hover:text-primary focus:outline-none cursor-pointer\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-6 w-6\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n </header>\n\n <!-- Mobile menu -->\n @if (isMobile() && mobileMenuOpen) {\n <div class=\"bg-gray-100 border-b border-gray-300 px-4 py-2\">\n <nav class=\"flex flex-col space-y-2\">\n <!-- Left menus -->\n @for (item of leftMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n\n <!-- Right menus -->\n @for (item of rightMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n\n <!-- User menus (flattened for mobile) -->\n @for (section of userMenus(); track section.label) {\n @if (section.label) {\n <div class=\"font-bold mt-2\">{{ section.label }}</div>\n }\n @if (section.items?.length) {\n @for (item of section.items; track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n }\n @if (section.separator) {\n <hr class=\"border-gray-300 my-2\" />\n }\n }\n </nav>\n </div>\n }\n\n <!-- Main content -->\n <main class=\"flex-1 p-4\">\n <ng-content />\n </main>\n\n @if (footerEnabled()) {\n <footer [class]=\"_footerClass()\">\n <nav [class]=\"_computedFooterMenuClass()\">\n @for (item of footerMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n </nav>\n\n <div class=\"mt-2 text-center\">\n {{ footerContent() }}\n </div>\n </footer>\n }\n</div>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EgLayoutSimpleUserMenu, selector: "eg-layout-simple-user-menu", inputs: ["menus"] }, { kind: "component", type: EgGenericAutocomplete, selector: "eg-generic-autocomplete", inputs: ["controlId", "placeholderText", "emptyText", "optionTemplate", "loaderFn", "transformValueToSearch"], outputs: ["optionChange"] }] });
315
+ }
316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgLayoutSimple, decorators: [{
317
+ type: Component,
318
+ args: [{ selector: 'eg-layout-simple', standalone: true, imports: [RouterLink, EgLayoutSimpleUserMenu, EgGenericAutocomplete], template: "<div class=\"flex flex-col min-h-screen\">\n <!-- Header -->\n <header [class]=\"_headerClass()\">\n <!-- Left side: Logo + Left menus -->\n <div class=\"flex items-center space-x-6\">\n <div class=\"logo\">\n <a [routerLink]=\"logoLink()\">\n <img [src]=\"logo()\" alt=\"Logo\" class=\"h-10\" />\n </a>\n </div>\n <!-- Left menus (desktop) -->\n <nav [class]=\"_computedLeftClass()\">\n @for (item of leftMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n </nav>\n </div>\n\n <!-- Right menus (desktop) -->\n <nav [class]=\"_computedRightClass()\">\n @if (searchEnabled()) {\n <eg-generic-autocomplete\n [optionTemplate]=\"searchOptionTemplate()\"\n [loaderFn]=\"searchLoaderFn()\"\n [transformValueToSearch]=\"searchTransformValueToSearch()\"\n [placeholderText]=\"searchPlaceholderText()\"\n [emptyText]=\"searchEmptyText()\"\n (optionChange)=\"onSearchOptionChange($event)\"\n ></eg-generic-autocomplete>\n }\n\n @for (item of rightMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n\n @let uMenus = userMenus();\n @if (uMenus && uMenus.length > 0) {\n <eg-layout-simple-user-menu [menus]=\"uMenus\"></eg-layout-simple-user-menu>\n }\n </nav>\n\n <!-- Mobile menu button -->\n <button\n (click)=\"toggleMobileMenu()\"\n class=\"md:hidden p-2 text-gray-700 hover:text-primary focus:outline-none cursor-pointer\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-6 w-6\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n </header>\n\n <!-- Mobile menu -->\n @if (isMobile() && mobileMenuOpen) {\n <div class=\"bg-gray-100 border-b border-gray-300 px-4 py-2\">\n <nav class=\"flex flex-col space-y-2\">\n <!-- Left menus -->\n @for (item of leftMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n\n <!-- Right menus -->\n @for (item of rightMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n\n <!-- User menus (flattened for mobile) -->\n @for (section of userMenus(); track section.label) {\n @if (section.label) {\n <div class=\"font-bold mt-2\">{{ section.label }}</div>\n }\n @if (section.items?.length) {\n @for (item of section.items; track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n }\n @if (section.separator) {\n <hr class=\"border-gray-300 my-2\" />\n }\n }\n </nav>\n </div>\n }\n\n <!-- Main content -->\n <main class=\"flex-1 p-4\">\n <ng-content />\n </main>\n\n @if (footerEnabled()) {\n <footer [class]=\"_footerClass()\">\n <nav [class]=\"_computedFooterMenuClass()\">\n @for (item of footerMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n </nav>\n\n <div class=\"mt-2 text-center\">\n {{ footerContent() }}\n </div>\n </footer>\n }\n</div>\n" }]
319
+ }], ctorParameters: () => [{ type: i1$1.BreakpointObserver }] });
320
+
321
+ /*
322
+ * Public API Surface of layout-simple
323
+ */
324
+
325
+ /**
326
+ * Generated bundle index. Do not edit.
327
+ */
328
+
329
+ export { EgGenericAutocomplete, EgLayoutSimple, EgLayoutSimpleUserMenu };
330
+ //# sourceMappingURL=layout-simple.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout-simple.mjs","sources":["../../../projects/layout-simple/src/lib/user-menu.ts","../../../projects/layout-simple/src/lib/search.ts","../../../projects/layout-simple/src/lib/layout.ts","../../../projects/layout-simple/src/lib/layout.html","../../../projects/layout-simple/src/public-api.ts","../../../projects/layout-simple/src/layout-simple.ts"],"sourcesContent":["import { Component, input } from '@angular/core';\nimport { provideIcons } from '@ng-icons/core';\nimport { lucideUser } from '@ng-icons/lucide';\nimport { RouterLink } from '@angular/router';\nimport { BrnMenuTrigger } from '@spartan-ng/brain/menu';\nimport { hlm } from '@egose/shadcn-theme-ng/utils';\nimport { HlmButton } from '@egose/shadcn-theme-ng/button';\nimport { HlmMenu, HlmMenuGroup, HlmMenuItem, HlmMenuLabel, HlmMenuSeparator } from '@egose/shadcn-theme-ng/menu';\nimport { NgIcon } from '@ng-icons/core';\n\n// Interface for menu items\nexport interface UserMenuItem {\n label: string;\n icon?: any;\n action?: () => void;\n link?: string;\n class?: string;\n}\n\n// Interface for menu sections\nexport interface UserMenuSection {\n label?: string;\n separator?: boolean;\n items?: UserMenuItem[];\n}\n\n@Component({\n selector: 'eg-layout-simple-user-menu',\n imports: [\n BrnMenuTrigger,\n HlmMenu,\n HlmMenuItem,\n HlmMenuLabel,\n HlmMenuSeparator,\n HlmMenuGroup,\n HlmButton,\n NgIcon,\n RouterLink,\n ],\n providers: [\n provideIcons({\n lucideUser,\n }),\n ],\n template: `\n <ng-template #iconTemplate>\n <ng-icon [svg]=\"lucideUser\" size=\"1.5rem\" />\n </ng-template>\n\n <div class=\"tw:flex tw:w-full tw:items-center tw:justify-center tw:pt-[20%]\">\n <button\n hlmButton\n variant=\"primary\"\n size=\"icon\"\n align=\"end\"\n [brnMenuTriggerFor]=\"menu\"\n [icon]=\"iconTemplate\"\n class=\"tw:rounded-full tw:border tw:border-gray-400\"\n ></button>\n </div>\n\n <ng-template #menu>\n <hlm-menu class=\"tw:w-56\">\n @for (section of menus(); track section) {\n @if (section.label) {\n <hlm-menu-label>{{ section.label }}</hlm-menu-label>\n }\n @if (section.items?.length) {\n <hlm-menu-group>\n @for (item of section.items; track item) {\n @if (item.link) {\n <a hlmMenuItem [routerLink]=\"item.link\" [class]=\"hlm(item.class, 'tw:cursor-pointer')\">\n @if (item.icon) {\n <ng-icon [svg]=\"item.icon\" size=\"1rem\" [class]=\"hlm(item.class, 'tw:cursor-pointer tw:mr-2')\" />\n }\n <span>{{ item.label }}</span>\n </a>\n } @else {\n <button hlmMenuItem (click)=\"item.action?.()\" [class]=\"hlm(item.class, 'tw:cursor-pointer')\">\n @if (item.icon) {\n <ng-icon [svg]=\"item.icon\" size=\"1rem\" [class]=\"hlm(item.class, 'tw:cursor-pointer tw:mr-2')\" />\n }\n <span>{{ item.label }}</span>\n </button>\n }\n }\n </hlm-menu-group>\n }\n @if (section.separator) {\n <hlm-menu-separator />\n }\n }\n </hlm-menu>\n </ng-template>\n `,\n})\nexport class EgLayoutSimpleUserMenu {\n menus = input<UserMenuSection[]>([]);\n\n hlm = hlm;\n lucideUser = lucideUser;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n TemplateRef,\n signal,\n input,\n output,\n viewChild,\n inject,\n resource,\n} from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';\nimport {\n HlmAutocompleteImports,\n provideHlmAutocompleteConfig,\n HlmAutocompleteOption,\n} from '@egose/shadcn-theme-ng/autocomplete';\nimport { HlmSpinner } from '@egose/shadcn-theme-ng/spinner';\n\nconst transformValueToSearchMap: Record<string, any> = {};\n\n@Component({\n selector: 'eg-generic-autocomplete',\n imports: [HlmSpinner, HlmAutocompleteImports, ReactiveFormsModule],\n template: `\n <form [formGroup]=\"form\" class=\"space-y-8\">\n <hlm-autocomplete\n [inputId]=\"controlId()\"\n [filteredOptions]=\"options.value()\"\n [optionTemplate]=\"optionTemplate()\"\n [loading]=\"options.isLoading()\"\n [(search)]=\"search\"\n [searchPlaceholderText]=\"placeholderText()\"\n [emptyText]=\"emptyText()\"\n formControlName=\"option\"\n class=\"tw:bg-white\"\n >\n <hlm-spinner loading />\n </hlm-autocomplete>\n </form>\n <ng-template #defaultOption let-option>\n {{ option }}\n </ng-template>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n viewProviders: [\n provideHlmAutocompleteConfig({\n transformValueToSearch: (params, inputId) => {\n const fn = transformValueToSearchMap[inputId];\n return fn(params);\n },\n }),\n ],\n})\nexport class EgGenericAutocomplete<TItem, TParams extends object = { search: string }> {\n defaultOptionTemplate = viewChild<TemplateRef<HlmAutocompleteOption<TItem>>>('defaultOption');\n controlId = input<string>(crypto.randomUUID());\n placeholderText = input<string>('Select an option');\n emptyText = input<string>('No options found');\n\n optionTemplate = input<TemplateRef<HlmAutocompleteOption<TItem>> | undefined>(this.defaultOptionTemplate as any);\n loaderFn = input<((params: TParams) => Promise<TItem[]>) | undefined>(async () => []);\n transformValueToSearch = input<((value: TItem) => string) | undefined>((value: TItem) => String(value));\n\n public readonly optionChange = output<TItem>();\n private readonly _formBuilder = inject(FormBuilder);\n public form = this._formBuilder.group({\n option: [null, Validators.required],\n });\n\n public readonly search = signal<string>('');\n\n public options = resource<TItem[], TParams>({\n defaultValue: [] as TItem[],\n params: () => ({ search: this.search(), negajjang: '1111' }) as TParams,\n loader: async ({ params }) => {\n const fn = this.loaderFn();\n if (!fn) {\n return [];\n }\n\n return fn(params);\n },\n });\n\n ngOnInit() {\n transformValueToSearchMap[this.controlId()] = this.transformValueToSearch();\n\n this.form.controls['option'].valueChanges.subscribe((value) => {\n if (value !== null) {\n this.optionChange.emit(value);\n }\n });\n }\n\n ngOnDestroy() {\n delete transformValueToSearchMap[this.controlId()];\n }\n}\n","import { Component, input, output, computed, signal, viewChild, TemplateRef } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';\nimport { ClassValue } from 'clsx';\nimport { hlm } from '@egose/shadcn-theme-ng/utils';\nimport { HlmAutocompleteOption } from '@egose/shadcn-theme-ng/autocomplete';\nimport { EgLayoutSimpleUserMenu, type UserMenuSection } from './user-menu';\nimport { EgGenericAutocomplete } from './search';\n\n// Updated interface for left/right menu items\nexport interface MenuItem {\n label: string;\n link?: string; // optional router link\n action?: () => void; // optional click handler\n class?: string; // optional per-item CSS/Tailwind classes\n}\n\nconst commonLinkGroupClasses = 'tw:hidden tw:md:flex tw:space-x-4 tw:items-center';\nconst commonLinkClasses =\n 'tw:text-left tw:text-secondary tw:visited:text-secondary tw:hover:text-primary tw:cursor-pointer tw:no-underline';\n\n@Component({\n selector: 'eg-layout-simple',\n standalone: true,\n imports: [RouterLink, EgLayoutSimpleUserMenu, EgGenericAutocomplete],\n templateUrl: './layout.html',\n})\nexport class EgLayoutSimple<TItem, TParams extends object = { search: string }> {\n /** Menu data inputs */\n leftMenus = input<MenuItem[]>([]);\n rightMenus = input<MenuItem[]>([]);\n userMenus = input<UserMenuSection[]>([]);\n logo = input<string>('assets/logo.png');\n logoLink = input<string>('/');\n hlm = hlm;\n\n headerClass = input<ClassValue>('', { alias: 'headerClass' });\n\n /** Container class inputs */\n leftMenuClass = input<ClassValue>('', { alias: 'leftClass' });\n rightMenuClass = input<ClassValue>('', { alias: 'rightClass' });\n\n /** Link/button base class inputs */\n leftLinkClass = input<ClassValue>('', { alias: 'leftLinkClass' });\n rightLinkClass = input<ClassValue>('', { alias: 'rightLinkClass' });\n\n searchEnabled = input<boolean>(false);\n searchPlaceholderText = input<string>('Select an page');\n searchEmptyText = input<string>('No pages found');\n searchOptionTemplate = input<TemplateRef<HlmAutocompleteOption<TItem>>>();\n searchLoaderFn = input<(params: TParams) => Promise<TItem[]>>();\n searchTransformValueToSearch = input<(value: TItem) => string>();\n\n public readonly searchOptionChange = output<TItem>();\n\n protected readonly _headerClass = computed(() =>\n hlm(\n 'tw:px-4 tw:py-2 tw:flex tw:items-center tw:justify-between tw:bg-gray-100 tw:border-b tw:border-gray-300',\n this.headerClass(),\n ),\n );\n\n /** Computed merged classes for containers */\n protected readonly _computedLeftClass = computed(() => hlm(commonLinkGroupClasses, this.leftMenuClass()));\n protected readonly _computedRightClass = computed(() => hlm(commonLinkGroupClasses, this.rightMenuClass()));\n\n /** Computed merged classes for link/button elements */\n protected readonly _computedLeftLinkClass = computed(() => hlm(commonLinkClasses, this.leftLinkClass()));\n protected readonly _computedRightLinkClass = computed(() => hlm(commonLinkClasses, this.rightLinkClass()));\n\n mobileMenuItemClass = commonLinkClasses;\n\n footerEnabled = input<boolean>(false);\n footerMenus = input<MenuItem[]>([]);\n footerMenuClass = input<ClassValue>('', { alias: 'footerMenuClass' });\n footerLinkClass = input<ClassValue>('', { alias: 'footerLinkClass' });\n footerContent = input<string>('© 2024 My Company');\n footerClass = input<ClassValue>('', { alias: 'footerClass' });\n\n protected readonly _footerClass = computed(() =>\n hlm(\n 'tw:px-4 tw:py-4 tw:bg-gray-100 tw:border-t tw:border-gray-300 tw:text-sm tw:text-gray-600',\n this.footerClass(),\n ),\n );\n\n protected readonly _computedFooterMenuClass = computed(() =>\n hlm('tw:flex tw:flex-wrap tw:justify-center tw:space-x-4', this.footerMenuClass()),\n );\n\n protected readonly _computedFooterLinkClass = computed(() =>\n hlm('tw:text-secondary tw:hover:text-primary tw:cursor-pointer tw:no-underline', this.footerLinkClass()),\n );\n\n /** Mobile menu state */\n mobileMenuOpen = false;\n isMobile = signal(false);\n\n constructor(private breakpointObserver: BreakpointObserver) {\n this.breakpointObserver.observe([Breakpoints.Handset]).subscribe((result) => {\n this.isMobile.set(result.matches);\n });\n }\n\n toggleMobileMenu() {\n this.mobileMenuOpen = !this.mobileMenuOpen;\n }\n\n onSearchOptionChange(value: TItem) {\n this.searchOptionChange.emit(value);\n }\n}\n","<div class=\"tw:flex tw:flex-col tw:min-h-screen\">\n <!-- Header -->\n <header [class]=\"_headerClass()\">\n <!-- Left side: Logo + Left menus -->\n <div class=\"tw:flex tw:items-center tw:space-x-6\">\n <div class=\"logo\">\n <a [routerLink]=\"logoLink()\">\n <img [src]=\"logo()\" alt=\"Logo\" class=\"tw:h-10\" />\n </a>\n </div>\n <!-- Left menus (desktop) -->\n <nav [class]=\"_computedLeftClass()\">\n @for (item of leftMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedLeftLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n </nav>\n </div>\n\n <!-- Right menus (desktop) -->\n <nav [class]=\"_computedRightClass()\">\n @if (searchEnabled()) {\n <eg-generic-autocomplete\n [optionTemplate]=\"searchOptionTemplate()\"\n [loaderFn]=\"searchLoaderFn()\"\n [transformValueToSearch]=\"searchTransformValueToSearch()\"\n [placeholderText]=\"searchPlaceholderText()\"\n [emptyText]=\"searchEmptyText()\"\n (optionChange)=\"onSearchOptionChange($event)\"\n ></eg-generic-autocomplete>\n }\n\n @for (item of rightMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\"> {{ item.label }} </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedRightLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n\n @let uMenus = userMenus();\n @if (uMenus && uMenus.length > 0) {\n <eg-layout-simple-user-menu [menus]=\"uMenus\"></eg-layout-simple-user-menu>\n }\n </nav>\n\n <!-- Mobile menu button -->\n <button\n (click)=\"toggleMobileMenu()\"\n class=\"tw:md:hidden tw:p-2 tw:text-gray-700 tw:hover:text-primary tw:focus:outline-none tw:cursor-pointer\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"tw:h-6 tw:w-6\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n </header>\n\n <!-- Mobile menu -->\n @if (isMobile() && mobileMenuOpen) {\n <div class=\"tw:bg-gray-100 tw:border-b tw:border-gray-300 tw:px-4 tw:py-2\">\n <nav class=\"tw:flex tw:flex-col tw:space-y-2\">\n <!-- Left menus -->\n @for (item of leftMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n\n <!-- Right menus -->\n @for (item of rightMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n\n <!-- User menus (flattened for mobile) -->\n @for (section of userMenus(); track section.label) {\n @if (section.label) {\n <div class=\"tw:font-bold tw:mt-2\">{{ section.label }}</div>\n }\n @if (section.items?.length) {\n @for (item of section.items; track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"mobileMenuItemClass\">\n {{ item.label }}\n </button>\n }\n }\n }\n @if (section.separator) {\n <hr class=\"tw:border-gray-300 tw:my-2\" />\n }\n }\n </nav>\n </div>\n }\n\n <!-- Main content -->\n <main class=\"tw:flex-1 tw:p-4\">\n <ng-content />\n </main>\n\n @if (footerEnabled()) {\n <footer [class]=\"_footerClass()\">\n <nav [class]=\"_computedFooterMenuClass()\">\n @for (item of footerMenus(); track item.label) {\n @if (item.link) {\n <a [routerLink]=\"item.link\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </a>\n } @else {\n <button type=\"button\" (click)=\"item.action?.()\" [class]=\"hlm(_computedFooterLinkClass(), item.class || '')\">\n {{ item.label }}\n </button>\n }\n }\n </nav>\n\n <div class=\"tw:mt-2 tw:text-center\">\n {{ footerContent() }}\n </div>\n </footer>\n }\n</div>\n","/*\n * Public API Surface of layout-simple\n */\n\nexport * from './lib/layout';\nexport * from './lib/user-menu';\nexport * from './lib/search';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1"],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { TemplateRef } from '@angular/core';
3
+ import { BreakpointObserver } from '@angular/cdk/layout';
4
+ import { ClassValue } from 'clsx';
5
+ import { hlm } from '@egose/shadcn-theme-ng/utils';
6
+ import { HlmAutocompleteOption } from '@egose/shadcn-theme-ng/autocomplete';
7
+ import * as _angular_forms from '@angular/forms';
8
+
9
+ interface UserMenuItem {
10
+ label: string;
11
+ icon?: any;
12
+ action?: () => void;
13
+ link?: string;
14
+ class?: string;
15
+ }
16
+ interface UserMenuSection {
17
+ label?: string;
18
+ separator?: boolean;
19
+ items?: UserMenuItem[];
20
+ }
21
+ declare class EgLayoutSimpleUserMenu {
22
+ menus: _angular_core.InputSignal<UserMenuSection[]>;
23
+ hlm: typeof hlm;
24
+ lucideUser: string;
25
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgLayoutSimpleUserMenu, never>;
26
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgLayoutSimpleUserMenu, "eg-layout-simple-user-menu", never, { "menus": { "alias": "menus"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
27
+ }
28
+
29
+ interface MenuItem {
30
+ label: string;
31
+ link?: string;
32
+ action?: () => void;
33
+ class?: string;
34
+ }
35
+ declare class EgLayoutSimple<TItem, TParams extends object = {
36
+ search: string;
37
+ }> {
38
+ private breakpointObserver;
39
+ /** Menu data inputs */
40
+ leftMenus: _angular_core.InputSignal<MenuItem[]>;
41
+ rightMenus: _angular_core.InputSignal<MenuItem[]>;
42
+ userMenus: _angular_core.InputSignal<UserMenuSection[]>;
43
+ logo: _angular_core.InputSignal<string>;
44
+ logoLink: _angular_core.InputSignal<string>;
45
+ hlm: typeof hlm;
46
+ headerClass: _angular_core.InputSignal<ClassValue>;
47
+ /** Container class inputs */
48
+ leftMenuClass: _angular_core.InputSignal<ClassValue>;
49
+ rightMenuClass: _angular_core.InputSignal<ClassValue>;
50
+ /** Link/button base class inputs */
51
+ leftLinkClass: _angular_core.InputSignal<ClassValue>;
52
+ rightLinkClass: _angular_core.InputSignal<ClassValue>;
53
+ searchEnabled: _angular_core.InputSignal<boolean>;
54
+ searchPlaceholderText: _angular_core.InputSignal<string>;
55
+ searchEmptyText: _angular_core.InputSignal<string>;
56
+ searchOptionTemplate: _angular_core.InputSignal<TemplateRef<HlmAutocompleteOption<TItem>> | undefined>;
57
+ searchLoaderFn: _angular_core.InputSignal<((params: TParams) => Promise<TItem[]>) | undefined>;
58
+ searchTransformValueToSearch: _angular_core.InputSignal<((value: TItem) => string) | undefined>;
59
+ readonly searchOptionChange: _angular_core.OutputEmitterRef<TItem>;
60
+ protected readonly _headerClass: _angular_core.Signal<string>;
61
+ /** Computed merged classes for containers */
62
+ protected readonly _computedLeftClass: _angular_core.Signal<string>;
63
+ protected readonly _computedRightClass: _angular_core.Signal<string>;
64
+ /** Computed merged classes for link/button elements */
65
+ protected readonly _computedLeftLinkClass: _angular_core.Signal<string>;
66
+ protected readonly _computedRightLinkClass: _angular_core.Signal<string>;
67
+ mobileMenuItemClass: string;
68
+ footerEnabled: _angular_core.InputSignal<boolean>;
69
+ footerMenus: _angular_core.InputSignal<MenuItem[]>;
70
+ footerMenuClass: _angular_core.InputSignal<ClassValue>;
71
+ footerLinkClass: _angular_core.InputSignal<ClassValue>;
72
+ footerContent: _angular_core.InputSignal<string>;
73
+ footerClass: _angular_core.InputSignal<ClassValue>;
74
+ protected readonly _footerClass: _angular_core.Signal<string>;
75
+ protected readonly _computedFooterMenuClass: _angular_core.Signal<string>;
76
+ protected readonly _computedFooterLinkClass: _angular_core.Signal<string>;
77
+ /** Mobile menu state */
78
+ mobileMenuOpen: boolean;
79
+ isMobile: _angular_core.WritableSignal<boolean>;
80
+ constructor(breakpointObserver: BreakpointObserver);
81
+ toggleMobileMenu(): void;
82
+ onSearchOptionChange(value: TItem): void;
83
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgLayoutSimple<any, any>, never>;
84
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgLayoutSimple<any, any>, "eg-layout-simple", never, { "leftMenus": { "alias": "leftMenus"; "required": false; "isSignal": true; }; "rightMenus": { "alias": "rightMenus"; "required": false; "isSignal": true; }; "userMenus": { "alias": "userMenus"; "required": false; "isSignal": true; }; "logo": { "alias": "logo"; "required": false; "isSignal": true; }; "logoLink": { "alias": "logoLink"; "required": false; "isSignal": true; }; "headerClass": { "alias": "headerClass"; "required": false; "isSignal": true; }; "leftMenuClass": { "alias": "leftClass"; "required": false; "isSignal": true; }; "rightMenuClass": { "alias": "rightClass"; "required": false; "isSignal": true; }; "leftLinkClass": { "alias": "leftLinkClass"; "required": false; "isSignal": true; }; "rightLinkClass": { "alias": "rightLinkClass"; "required": false; "isSignal": true; }; "searchEnabled": { "alias": "searchEnabled"; "required": false; "isSignal": true; }; "searchPlaceholderText": { "alias": "searchPlaceholderText"; "required": false; "isSignal": true; }; "searchEmptyText": { "alias": "searchEmptyText"; "required": false; "isSignal": true; }; "searchOptionTemplate": { "alias": "searchOptionTemplate"; "required": false; "isSignal": true; }; "searchLoaderFn": { "alias": "searchLoaderFn"; "required": false; "isSignal": true; }; "searchTransformValueToSearch": { "alias": "searchTransformValueToSearch"; "required": false; "isSignal": true; }; "footerEnabled": { "alias": "footerEnabled"; "required": false; "isSignal": true; }; "footerMenus": { "alias": "footerMenus"; "required": false; "isSignal": true; }; "footerMenuClass": { "alias": "footerMenuClass"; "required": false; "isSignal": true; }; "footerLinkClass": { "alias": "footerLinkClass"; "required": false; "isSignal": true; }; "footerContent": { "alias": "footerContent"; "required": false; "isSignal": true; }; "footerClass": { "alias": "footerClass"; "required": false; "isSignal": true; }; }, { "searchOptionChange": "searchOptionChange"; }, never, ["*"], true, never>;
85
+ }
86
+
87
+ declare class EgGenericAutocomplete<TItem, TParams extends object = {
88
+ search: string;
89
+ }> {
90
+ defaultOptionTemplate: _angular_core.Signal<TemplateRef<HlmAutocompleteOption<TItem>> | undefined>;
91
+ controlId: _angular_core.InputSignal<string>;
92
+ placeholderText: _angular_core.InputSignal<string>;
93
+ emptyText: _angular_core.InputSignal<string>;
94
+ optionTemplate: _angular_core.InputSignal<TemplateRef<HlmAutocompleteOption<TItem>> | undefined>;
95
+ loaderFn: _angular_core.InputSignal<((params: TParams) => Promise<TItem[]>) | undefined>;
96
+ transformValueToSearch: _angular_core.InputSignal<((value: TItem) => string) | undefined>;
97
+ readonly optionChange: _angular_core.OutputEmitterRef<TItem>;
98
+ private readonly _formBuilder;
99
+ form: _angular_forms.FormGroup<{
100
+ option: _angular_forms.FormControl<null>;
101
+ }>;
102
+ readonly search: _angular_core.WritableSignal<string>;
103
+ options: _angular_core.ResourceRef<TItem[]>;
104
+ ngOnInit(): void;
105
+ ngOnDestroy(): void;
106
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgGenericAutocomplete<any, any>, never>;
107
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgGenericAutocomplete<any, any>, "eg-generic-autocomplete", never, { "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; "placeholderText": { "alias": "placeholderText"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "optionTemplate": { "alias": "optionTemplate"; "required": false; "isSignal": true; }; "loaderFn": { "alias": "loaderFn"; "required": false; "isSignal": true; }; "transformValueToSearch": { "alias": "transformValueToSearch"; "required": false; "isSignal": true; }; }, { "optionChange": "optionChange"; }, never, never, true, never>;
108
+ }
109
+
110
+ export { EgGenericAutocomplete, EgLayoutSimple, EgLayoutSimpleUserMenu };
111
+ export type { MenuItem, UserMenuItem, UserMenuSection };
package/menu/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Menu
2
+
3
+ This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.3.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
8
+
9
+ ```bash
10
+ ng generate component component-name
11
+ ```
12
+
13
+ For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
14
+
15
+ ```bash
16
+ ng generate --help
17
+ ```
18
+
19
+ ## Building
20
+
21
+ To build the library, run:
22
+
23
+ ```bash
24
+ ng build menu
25
+ ```
26
+
27
+ This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
28
+
29
+ ### Publishing the Library
30
+
31
+ Once the project is built, you can publish your library by following these steps:
32
+
33
+ 1. Navigate to the `dist` directory:
34
+
35
+ ```bash
36
+ cd dist/menu
37
+ ```
38
+
39
+ 2. Run the `npm publish` command to publish your library to the npm registry:
40
+ ```bash
41
+ npm publish
42
+ ```
43
+
44
+ ## Running unit tests
45
+
46
+ To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
47
+
48
+ ```bash
49
+ ng test
50
+ ```
51
+
52
+ ## Running end-to-end tests
53
+
54
+ For end-to-end (e2e) testing, run:
55
+
56
+ ```bash
57
+ ng e2e
58
+ ```
59
+
60
+ Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
61
+
62
+ ## Additional Resources
63
+
64
+ For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.