ng-magary 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE.md +21 -0
  2. package/bun.lock +290 -0
  3. package/ng-package.json +7 -0
  4. package/package.json +11 -12
  5. package/src/lib/Button/button/button.html +29 -0
  6. package/src/lib/Button/button/button.module.ts +9 -0
  7. package/src/lib/Button/button/button.scss +196 -0
  8. package/src/lib/Button/button/button.spec.ts +18 -0
  9. package/src/lib/Button/button/button.ts +72 -0
  10. package/src/lib/Button/speed-dial/speed-dial-item.interface.ts +9 -0
  11. package/src/lib/Button/speed-dial/speed-dial.html +57 -0
  12. package/src/lib/Button/speed-dial/speed-dial.module.ts +8 -0
  13. package/src/lib/Button/speed-dial/speed-dial.scss +247 -0
  14. package/src/lib/Button/speed-dial/speed-dial.spec.ts +18 -0
  15. package/src/lib/Button/speed-dial/speed-dial.ts +106 -0
  16. package/src/lib/Form/cascade-select/cascade-select.html +1 -0
  17. package/src/lib/Form/cascade-select/cascade-select.module.ts +8 -0
  18. package/src/lib/Form/cascade-select/cascade-select.scss +0 -0
  19. package/src/lib/Form/cascade-select/cascade-select.spec.ts +18 -0
  20. package/src/lib/Form/cascade-select/cascade-select.ts +9 -0
  21. package/src/lib/Form/input/input.html +66 -0
  22. package/src/lib/Form/input/input.module.ts +9 -0
  23. package/src/lib/Form/input/input.scss +193 -0
  24. package/src/lib/Form/input/input.spec.ts +22 -0
  25. package/src/lib/Form/input/input.ts +132 -0
  26. package/src/lib/Menu/panelmenu/panelmenu.html +259 -0
  27. package/src/lib/Menu/panelmenu/panelmenu.interface.ts +13 -0
  28. package/src/lib/Menu/panelmenu/panelmenu.module.ts +9 -0
  29. package/src/lib/Menu/panelmenu/panelmenu.scss +177 -0
  30. package/src/lib/Menu/panelmenu/panelmenu.spec.ts +18 -0
  31. package/src/lib/Menu/panelmenu/panelmenu.ts +134 -0
  32. package/src/lib/Menu/sidebar/sidebar.html +85 -0
  33. package/src/lib/Menu/sidebar/sidebar.module.ts +9 -0
  34. package/src/lib/Menu/sidebar/sidebar.scss +153 -0
  35. package/src/lib/Menu/sidebar/sidebar.spec.ts +18 -0
  36. package/src/lib/Menu/sidebar/sidebar.ts +64 -0
  37. package/src/lib/Misc/avatar/avatar.html +44 -0
  38. package/src/lib/Misc/avatar/avatar.module.ts +9 -0
  39. package/src/lib/Misc/avatar/avatar.scss +167 -0
  40. package/src/lib/Misc/avatar/avatar.spec.ts +18 -0
  41. package/src/lib/Misc/avatar/avatar.ts +93 -0
  42. package/src/lib/Panel/card/card.html +58 -0
  43. package/src/lib/Panel/card/card.module.ts +9 -0
  44. package/src/lib/Panel/card/card.scss +290 -0
  45. package/src/lib/Panel/card/card.spec.ts +18 -0
  46. package/src/lib/Panel/card/card.ts +126 -0
  47. package/src/lib/Panel/tabs/tab/tab.spec.ts +18 -0
  48. package/src/lib/Panel/tabs/tab/tab.ts +12 -0
  49. package/src/lib/Panel/tabs/tabs.html +26 -0
  50. package/src/lib/Panel/tabs/tabs.module.ts +10 -0
  51. package/src/lib/Panel/tabs/tabs.scss +58 -0
  52. package/src/lib/Panel/tabs/tabs.spec.ts +18 -0
  53. package/src/lib/Panel/tabs/tabs.ts +57 -0
  54. package/src/lib/ng-magary.spec.ts +18 -0
  55. package/src/lib/ng-magary.ts +43 -0
  56. package/src/public-api.ts +5 -0
  57. package/tsconfig.lib.json +22 -0
  58. package/tsconfig.lib.prod.json +11 -0
  59. package/tsconfig.spec.json +14 -0
  60. package/fesm2022/ng-magary.mjs +0 -811
  61. package/fesm2022/ng-magary.mjs.map +0 -1
  62. package/index.d.ts +0 -422
  63. package/index.d.ts.map +0 -1
@@ -0,0 +1,126 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, computed, input } from '@angular/core';
3
+ type ImagePosition = 'left' | 'right' | 'top' | 'bottom';
4
+ type ShadowLevel = 0 | 1 | 2 | 3 | 4 | 5;
5
+ type CardVariant = 'elevated' | 'outlined' | 'filled';
6
+ @Component({
7
+ selector: 'magary-card',
8
+ standalone: true,
9
+ imports: [CommonModule],
10
+ templateUrl: './card.html',
11
+ styleUrl: './card.scss',
12
+ })
13
+ export class MagaryCard {
14
+ readonly img = input<string>();
15
+ readonly positionImage = input<ImagePosition>('top');
16
+ readonly shadow = input<ShadowLevel>(1);
17
+ readonly width = input<string>('250px');
18
+ readonly height = input<string>('auto');
19
+ readonly padding = input<string>('1rem');
20
+ readonly gap = input<string>('1rem');
21
+ readonly borderRadius = input<string>('0.75rem');
22
+ readonly imageSize = input<string>('500px');
23
+ readonly backgroundColor = input<string>('#fff');
24
+ readonly responsive = input<boolean>(true);
25
+ readonly altText = input<string>('Card image');
26
+ readonly imageFit = input<
27
+ 'cover' | 'contain' | 'fill' | 'scale-down' | 'none'
28
+ >('cover');
29
+ readonly clickable = input<boolean>(false);
30
+ readonly loading = input<boolean>(false);
31
+ readonly disabled = input<boolean>(false);
32
+ readonly variant = input<CardVariant>('elevated');
33
+ readonly loadingText = input<string>('Cargando...');
34
+ readonly cardClasses = computed(() =>
35
+ [
36
+ 'card',
37
+ `shadow-${this.shadow()}`,
38
+ `layout-${this.positionImage()}`,
39
+ `variant-${this.variant()}`,
40
+ this.responsive() ? 'responsive' : '',
41
+ this.clickable() ? 'clickable' : '',
42
+ this.loading() ? 'loading' : '',
43
+ this.disabled() ? 'disabled' : '',
44
+ ].filter(Boolean),
45
+ );
46
+ readonly cardStyles = computed(() => ({
47
+ width: this.width(),
48
+ height: this.height(),
49
+ 'border-radius': this.borderRadius(),
50
+ 'background-color': this.backgroundColor(),
51
+ '--border-radius': this.borderRadius(),
52
+ '--gap': this.gap(),
53
+ '--padding': this.padding(),
54
+ cursor: this.clickable() && !this.disabled() ? 'pointer' : 'default',
55
+ opacity: this.disabled() ? '0.6' : '1',
56
+ 'pointer-events': this.disabled() ? 'none' : 'auto',
57
+ }));
58
+ readonly imageWidth = computed((): string => {
59
+ if (this.positionImage() === 'left' || this.positionImage() === 'right') {
60
+ return `calc(${this.width()} / 2)`;
61
+ }
62
+ return '100%';
63
+ });
64
+ readonly imageHeight = computed((): string => {
65
+ if (this.positionImage() === 'top' || this.positionImage() === 'bottom') {
66
+ return `calc(${this.imageSize()} / 2)`;
67
+ }
68
+ return '100%';
69
+ });
70
+ readonly imageClasses = computed(() => [
71
+ 'card-img',
72
+ `img-${this.positionImage()}`,
73
+ ]);
74
+ readonly imageBorderRadius = computed((): Record<string, string> => {
75
+ const radius = this.borderRadius();
76
+ const pos = this.positionImage();
77
+ const radiusMap: Record<ImagePosition, Record<string, string>> = {
78
+ top: {
79
+ 'border-top-left-radius': radius,
80
+ 'border-top-right-radius': radius,
81
+ },
82
+ bottom: {
83
+ 'border-bottom-left-radius': radius,
84
+ 'border-bottom-right-radius': radius,
85
+ },
86
+ left: {
87
+ 'border-top-left-radius': radius,
88
+ 'border-bottom-left-radius': radius,
89
+ },
90
+ right: {
91
+ 'border-top-right-radius': radius,
92
+ 'border-bottom-right-radius': radius,
93
+ },
94
+ };
95
+ return radiusMap[pos] || {};
96
+ });
97
+ readonly imageStyles = computed(() => ({
98
+ width: this.imageWidth(),
99
+ height: this.imageHeight(),
100
+ 'object-fit': this.imageFit(),
101
+ ...this.imageBorderRadius(),
102
+ }));
103
+ readonly hasImage = computed(() => Boolean(this.img()));
104
+ readonly isHorizontalLayout = computed(
105
+ () => this.positionImage() === 'left' || this.positionImage() === 'right',
106
+ );
107
+ readonly isInteractive = computed(
108
+ () => this.clickable() && !this.disabled() && !this.loading(),
109
+ );
110
+ readonly showLoadingOverlay = computed(() => this.loading());
111
+ onCardClick(event: Event) {
112
+ if (this.isInteractive()) {
113
+ const cardClickEvent = new CustomEvent('cardClick', {
114
+ detail: { event },
115
+ bubbles: true,
116
+ });
117
+ (event.target as HTMLElement).dispatchEvent(cardClickEvent);
118
+ }
119
+ }
120
+ onCardKeydown(event: KeyboardEvent) {
121
+ if (this.isInteractive() && (event.key === 'Enter' || event.key === ' ')) {
122
+ event.preventDefault();
123
+ this.onCardClick(event);
124
+ }
125
+ }
126
+ }
@@ -0,0 +1,18 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { Tab } from './tab';
3
+ describe('Tab', () => {
4
+ let component: Tab;
5
+ let fixture: ComponentFixture<Tab>;
6
+ beforeEach(async () => {
7
+ await TestBed.configureTestingModule({
8
+ imports: [Tab]
9
+ })
10
+ .compileComponents();
11
+ fixture = TestBed.createComponent(Tab);
12
+ component = fixture.componentInstance;
13
+ fixture.detectChanges();
14
+ });
15
+ it('should create', () => {
16
+ expect(component).toBeTruthy();
17
+ });
18
+ });
@@ -0,0 +1,12 @@
1
+ import { Component, input, signal } from '@angular/core';
2
+ @Component({
3
+ selector: 'magary-tab',
4
+ standalone: true,
5
+ template: `@if (active()) {
6
+ <ng-content style="width: 100%;" />
7
+ }`,
8
+ })
9
+ export class MagaryTab {
10
+ public label = input<string>('');
11
+ public active = signal(false);
12
+ }
@@ -0,0 +1,26 @@
1
+ <div class="tabs">
2
+ <div
3
+ class="tab-headers"
4
+ #tabHeaders
5
+ [style.--background-color-line]="backgroundLine()"
6
+ [style.--height-line]="heightLine()"
7
+ >
8
+ @for (tab of tabs.toArray(); track $index) {
9
+ <button
10
+ #tabButton
11
+ (click)="selectTab($index)"
12
+ [class.active]="activeIndex() === $index"
13
+ >
14
+ {{ tab.label() }}
15
+ </button>
16
+ }
17
+ </div>
18
+ <div
19
+ class="tab-content"
20
+ [style.--position-content]="positionContent()"
21
+ [style.--background]="background()"
22
+ [style.--padding]="padding()"
23
+ >
24
+ <ng-content></ng-content>
25
+ </div>
26
+ </div>
@@ -0,0 +1,10 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { MagaryTabs } from './tabs';
4
+ import { MagaryTab } from './tab/tab';
5
+ @NgModule({
6
+ declarations: [],
7
+ imports: [CommonModule, MagaryTabs, MagaryTab],
8
+ exports: [MagaryTabs, MagaryTab],
9
+ })
10
+ export class TabsModule {}
@@ -0,0 +1,58 @@
1
+ .tabs {
2
+ border: 1px solid #ccc;
3
+ border-radius: 8px;
4
+ overflow: hidden;
5
+ background: #fff;
6
+ }
7
+ .tab-headers {
8
+ display: flex;
9
+ border-bottom: 1px solid #ddd;
10
+ position: relative;
11
+ &::after {
12
+ content: '';
13
+ position: absolute;
14
+ bottom: -1px;
15
+ height: var(--height-line);;
16
+ background-color: var(--background-color-line);
17
+ transition: left 0.4s ease-in-out, width 0.4s ease-in-out;
18
+ left: var(--underline-left, 0);
19
+ width: var(--underline-width, 0);
20
+ }
21
+ button {
22
+ flex: 1;
23
+ padding: 1rem;
24
+ background: none;
25
+ border: none;
26
+ cursor: pointer;
27
+ font-weight: bold;
28
+ transition: background 0.3s;
29
+ z-index: 1;
30
+ &:hover {
31
+ background: #f0f0f0;
32
+ }
33
+ &.active {
34
+ background: #f9f9f9;
35
+ color: #000;
36
+ height: 4px;
37
+ }
38
+ }
39
+ }
40
+ .tab-content {
41
+ padding: var(--padding);
42
+ display: flex;
43
+ justify-content: var(--position-content);
44
+ background: var(--background);
45
+ &.animated {
46
+ animation: slideIn 0.7s ease-out;
47
+ }
48
+ @keyframes slideIn {
49
+ from {
50
+ opacity: 0;
51
+ transform: translateX(10px);
52
+ }
53
+ to {
54
+ opacity: 1;
55
+ transform: translateX(0);
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,18 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { Tabs } from './tabs';
3
+ describe('Tabs', () => {
4
+ let component: Tabs;
5
+ let fixture: ComponentFixture<Tabs>;
6
+ beforeEach(async () => {
7
+ await TestBed.configureTestingModule({
8
+ imports: [Tabs]
9
+ })
10
+ .compileComponents();
11
+ fixture = TestBed.createComponent(Tabs);
12
+ component = fixture.componentInstance;
13
+ fixture.detectChanges();
14
+ });
15
+ it('should create', () => {
16
+ expect(component).toBeTruthy();
17
+ });
18
+ });
@@ -0,0 +1,57 @@
1
+ import {
2
+ AfterContentInit,
3
+ Component,
4
+ ContentChildren,
5
+ ElementRef,
6
+ input,
7
+ OnInit,
8
+ QueryList,
9
+ signal,
10
+ ViewChild,
11
+ ViewChildren,
12
+ } from '@angular/core';
13
+ import { MagaryTab } from './tab/tab';
14
+ @Component({
15
+ selector: 'magary-tabs',
16
+ imports: [],
17
+ templateUrl: './tabs.html',
18
+ styleUrl: './tabs.scss',
19
+ })
20
+ export class MagaryTabs implements OnInit, AfterContentInit {
21
+ @ContentChildren(MagaryTab) tabs!: QueryList<MagaryTab>;
22
+ @ViewChild('tabHeaders') headersRef!: ElementRef<HTMLElement>;
23
+ @ViewChildren('tabButton') buttonsRef!: QueryList<ElementRef<HTMLElement>>;
24
+ public activeIndex = signal(0);
25
+ public backgroundLine = input<string>('#000');
26
+ public positionContent = input<string>('center');
27
+ public background = input<string>('#fff');
28
+ public padding = input<string>('0');
29
+ public heightLine = input<string>('5px');
30
+ ngOnInit(): void {
31
+ this.activeIndex.set(0);
32
+ this.updateUnderlinePosition(0);
33
+ }
34
+ ngAfterContentInit() {
35
+ const tabsArray = this.tabs.toArray();
36
+ if (tabsArray.length > 0) {
37
+ tabsArray[0].active.set(true);
38
+ }
39
+ }
40
+ public selectTab(index: number) {
41
+ this.tabs.forEach((tab, i) => tab.active.set(i === index));
42
+ this.activeIndex.set(index);
43
+ this.updateUnderlinePosition(index);
44
+ }
45
+ private updateUnderlinePosition(index: number) {
46
+ setTimeout(() => {
47
+ const activeBtn = this.buttonsRef.toArray()[index]?.nativeElement;
48
+ const headersEl = this.headersRef.nativeElement;
49
+ if (activeBtn && headersEl) {
50
+ const left = activeBtn.offsetLeft;
51
+ const width = activeBtn.offsetWidth;
52
+ headersEl.style.setProperty('--underline-left', `${left}px`);
53
+ headersEl.style.setProperty('--underline-width', `${width}px`);
54
+ }
55
+ }, 0);
56
+ }
57
+ }
@@ -0,0 +1,18 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { NgMagary } from './ng-magary';
3
+ describe('NgMagary', () => {
4
+ let component: NgMagary;
5
+ let fixture: ComponentFixture<NgMagary>;
6
+ beforeEach(async () => {
7
+ await TestBed.configureTestingModule({
8
+ imports: [NgMagary]
9
+ })
10
+ .compileComponents();
11
+ fixture = TestBed.createComponent(NgMagary);
12
+ component = fixture.componentInstance;
13
+ fixture.detectChanges();
14
+ });
15
+ it('should create', () => {
16
+ expect(component).toBeTruthy();
17
+ });
18
+ });
@@ -0,0 +1,43 @@
1
+ // 🔘 Button //
2
+ export * from './Button/button/button';
3
+ export * from './Button/button/button.module';
4
+ export * from './Button/speed-dial/speed-dial';
5
+ export * from './Button/speed-dial/speed-dial.module';
6
+
7
+ // 🗄️ Data //
8
+ // (por ahora vacío)
9
+
10
+ // 📂 File //
11
+ // (por ahora vacío)
12
+
13
+ // 📝 Form //
14
+ export * from './Form/cascade-select/cascade-select';
15
+ export * from './Form/cascade-select/cascade-select.module';
16
+ export * from './Form/input/input';
17
+ export * from './Form/input/input.module';
18
+
19
+ // 🖼️ Media //
20
+ // (por ahora vacío)
21
+
22
+ // 📋 Menu //
23
+ export * from './Menu/panelmenu/panelmenu';
24
+ export * from './Menu/panelmenu/panelmenu.module';
25
+ export * from './Menu/sidebar/sidebar';
26
+ export * from './Menu/sidebar/sidebar.module';
27
+
28
+ // 💬 Messages //
29
+ // (por ahora vacío)
30
+
31
+ // 👤 Misc //
32
+ export * from './Misc/avatar/avatar';
33
+ export * from './Misc/avatar/avatar.module';
34
+
35
+ // 🗂️ Overlay //
36
+ // (por ahora vacío)
37
+
38
+ // 📦 Panel //
39
+ export * from './Panel/card/card';
40
+ export * from './Panel/card/card.module';
41
+ export * from './Panel/tabs/tabs';
42
+ export * from './Panel/tabs/tabs.module';
43
+ export * from './Panel/tabs/tab/tab';
@@ -0,0 +1,5 @@
1
+ /*
2
+ * Public API Surface of ng-magary
3
+ */
4
+
5
+ export * from './lib/ng-magary';
@@ -0,0 +1,22 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../out-tsc/lib",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "sourceMap": true,
8
+ "inlineSources": true,
9
+ "types": []
10
+ },
11
+ "angularCompilerOptions": {
12
+ "compilationMode": "partial"
13
+ },
14
+ "include": [
15
+ "src/**/*.ts"
16
+ ],
17
+ "exclude": [
18
+ "dist",
19
+ "node_modules",
20
+ "**/*.spec.ts"
21
+ ]
22
+ }
@@ -0,0 +1,11 @@
1
+ /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2
+ /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3
+ {
4
+ "extends": "./tsconfig.lib.json",
5
+ "compilerOptions": {
6
+ "declarationMap": false
7
+ },
8
+ "angularCompilerOptions": {
9
+ "compilationMode": "partial"
10
+ }
11
+ }
@@ -0,0 +1,14 @@
1
+ /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2
+ /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3
+ {
4
+ "extends": "../../tsconfig.json",
5
+ "compilerOptions": {
6
+ "outDir": "../../out-tsc/spec",
7
+ "types": [
8
+ "jasmine"
9
+ ]
10
+ },
11
+ "include": [
12
+ "src/**/*.ts"
13
+ ]
14
+ }