@lesterarte/sefin-ui 0.0.1 → 0.0.3-dev.0

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.
@@ -0,0 +1,808 @@
1
+ import * as i0 from '@angular/core';
2
+ import { EventEmitter, Output, Input, ChangeDetectionStrategy, Component, forwardRef } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i2 from '@angular/forms';
6
+ import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
7
+
8
+ /**
9
+ * Color design tokens as TypeScript constants
10
+ * Based on Secretaría de Finanzas brand guidelines
11
+ * These values are the source of truth for all color tokens
12
+ */
13
+ const COLOR_TOKENS = {
14
+ // Primary colors - Secretaría de Finanzas brand colors
15
+ primary: {
16
+ // Light Blue (Azul Claro) - Primary brand color
17
+ 50: '#e6f7fb',
18
+ 100: '#b3e5f0',
19
+ 200: '#80d3e5',
20
+ 300: '#4dc1da',
21
+ 400: '#2ab0cf',
22
+ 500: '#55C3D8', // Primary Light Blue from brand guidelines
23
+ 600: '#4aafc4',
24
+ 700: '#3f9bb0',
25
+ 800: '#34879c',
26
+ 900: '#297388',
27
+ },
28
+ // Secondary colors - Grays from brand guidelines
29
+ secondary: {
30
+ // Based on Dark Gray and Light Gray from brand
31
+ 50: '#f5f5f5',
32
+ 100: '#e8e8e8',
33
+ 200: '#cecece', // Light Gray from brand guidelines
34
+ 300: '#b5b5b5',
35
+ 400: '#9b9b9b',
36
+ 500: '#828282',
37
+ 600: '#686868',
38
+ 700: '#4f4f4f',
39
+ 800: '#383838', // Dark Gray from brand guidelines
40
+ 900: '#2a2a2a',
41
+ },
42
+ // Neutral colors - Based on brand grays
43
+ neutral: {
44
+ 50: '#ffffff', // White from brand guidelines
45
+ 100: '#f5f5f5',
46
+ 200: '#cecece', // Light Gray
47
+ 300: '#b5b5b5',
48
+ 400: '#9b9b9b',
49
+ 500: '#828282',
50
+ 600: '#686868',
51
+ 700: '#4f4f4f',
52
+ 800: '#383838', // Dark Gray
53
+ 900: '#2a2a2a',
54
+ },
55
+ // Semantic colors - Keeping standard semantic colors
56
+ success: {
57
+ 50: '#e8f5e9',
58
+ 100: '#c8e6c9',
59
+ 200: '#a5d6a7',
60
+ 300: '#81c784',
61
+ 400: '#66bb6a',
62
+ 500: '#4caf50',
63
+ 600: '#43a047',
64
+ 700: '#388e3c',
65
+ 800: '#2e7d32',
66
+ 900: '#1b5e20',
67
+ },
68
+ warning: {
69
+ 50: '#fff3e0',
70
+ 100: '#ffe0b2',
71
+ 200: '#ffcc80',
72
+ 300: '#ffb74d',
73
+ 400: '#ffa726',
74
+ 500: '#ff9800',
75
+ 600: '#fb8c00',
76
+ 700: '#f57c00',
77
+ 800: '#ef6c00',
78
+ 900: '#e65100',
79
+ },
80
+ error: {
81
+ 50: '#ffebee',
82
+ 100: '#ffcdd2',
83
+ 200: '#ef9a9a',
84
+ 300: '#e57373',
85
+ 400: '#ef5350',
86
+ 500: '#f44336',
87
+ 600: '#e53935',
88
+ 700: '#d32f2f',
89
+ 800: '#c62828',
90
+ 900: '#b71c1c',
91
+ },
92
+ info: {
93
+ 50: '#e0f2f1',
94
+ 100: '#b2dfdb',
95
+ 200: '#80cbc4',
96
+ 300: '#4db6ac',
97
+ 400: '#26a69a',
98
+ 500: '#009688',
99
+ 600: '#00897b',
100
+ 700: '#00796b',
101
+ 800: '#00695c',
102
+ 900: '#004d40',
103
+ },
104
+ // Brand-specific colors
105
+ brand: {
106
+ darkGray: '#383838', // Dark Gray from brand guidelines
107
+ lightGray: '#cecece', // Light Gray from brand guidelines
108
+ lightBlue: '#55C3D8', // Light Blue from brand guidelines
109
+ white: '#ffffff', // White from brand guidelines
110
+ },
111
+ };
112
+
113
+ var colors = /*#__PURE__*/Object.freeze({
114
+ __proto__: null,
115
+ COLOR_TOKENS: COLOR_TOKENS
116
+ });
117
+
118
+ /**
119
+ * Spacing design tokens
120
+ * Based on 8px grid system
121
+ */
122
+ const SPACING_TOKENS = {
123
+ xs: '4px',
124
+ sm: '8px',
125
+ md: '16px',
126
+ lg: '24px',
127
+ xl: '32px',
128
+ '2xl': '48px',
129
+ '3xl': '64px',
130
+ '4xl': '96px',
131
+ '5xl': '128px',
132
+ };
133
+
134
+ var spacing = /*#__PURE__*/Object.freeze({
135
+ __proto__: null,
136
+ SPACING_TOKENS: SPACING_TOKENS
137
+ });
138
+
139
+ /**
140
+ * Typography design tokens
141
+ * Based on Secretaría de Finanzas brand guidelines - Pluto typeface
142
+ */
143
+ const TYPOGRAPHY_TOKENS = {
144
+ fontFamily: {
145
+ base: "'Pluto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
146
+ mono: "'Fira Code', 'Courier New', monospace",
147
+ },
148
+ fontSize: {
149
+ xs: '0.75rem', // 12px
150
+ sm: '0.875rem', // 14px
151
+ base: '1rem', // 16px
152
+ lg: '1.125rem', // 18px
153
+ xl: '1.25rem', // 20px
154
+ '2xl': '1.5rem', // 24px
155
+ '3xl': '1.875rem', // 30px
156
+ '4xl': '2.25rem', // 36px
157
+ '5xl': '3rem', // 48px
158
+ },
159
+ fontWeight: {
160
+ light: 300, // Pluto-Light
161
+ normal: 400, // Pluto-Regular
162
+ medium: 500,
163
+ semibold: 600,
164
+ bold: 700, // Pluto-Bold
165
+ },
166
+ lineHeight: {
167
+ tight: 1.25,
168
+ normal: 1.5,
169
+ relaxed: 1.75,
170
+ },
171
+ };
172
+
173
+ var typography = /*#__PURE__*/Object.freeze({
174
+ __proto__: null,
175
+ TYPOGRAPHY_TOKENS: TYPOGRAPHY_TOKENS
176
+ });
177
+
178
+ /**
179
+ * Border radius design tokens
180
+ */
181
+ const BORDER_RADIUS_TOKENS = {
182
+ none: '0',
183
+ sm: '4px',
184
+ md: '8px',
185
+ lg: '12px',
186
+ xl: '16px',
187
+ '2xl': '24px',
188
+ full: '9999px',
189
+ };
190
+
191
+ var borderRadius = /*#__PURE__*/Object.freeze({
192
+ __proto__: null,
193
+ BORDER_RADIUS_TOKENS: BORDER_RADIUS_TOKENS
194
+ });
195
+
196
+ /**
197
+ * Shadow design tokens
198
+ */
199
+ const SHADOW_TOKENS = {
200
+ none: 'none',
201
+ sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
202
+ md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
203
+ lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
204
+ xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
205
+ '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
206
+ };
207
+
208
+ var shadow = /*#__PURE__*/Object.freeze({
209
+ __proto__: null,
210
+ SHADOW_TOKENS: SHADOW_TOKENS
211
+ });
212
+
213
+ /**
214
+ * Design tokens index
215
+ * Central export for all design tokens
216
+ */
217
+ /**
218
+ * All design tokens combined
219
+ */
220
+ const DESIGN_TOKENS = {
221
+ colors: () => Promise.resolve().then(function () { return colors; }).then(m => m.COLOR_TOKENS),
222
+ spacing: () => Promise.resolve().then(function () { return spacing; }).then(m => m.SPACING_TOKENS),
223
+ typography: () => Promise.resolve().then(function () { return typography; }).then(m => m.TYPOGRAPHY_TOKENS),
224
+ borderRadius: () => Promise.resolve().then(function () { return borderRadius; }).then(m => m.BORDER_RADIUS_TOKENS),
225
+ shadow: () => Promise.resolve().then(function () { return shadow; }).then(m => m.SHADOW_TOKENS),
226
+ };
227
+
228
+ /**
229
+ * Light theme configuration
230
+ * Based on Secretaría de Finanzas brand colors
231
+ */
232
+ const LIGHT_THEME = {
233
+ name: 'light',
234
+ colors: {
235
+ // Primary color is Light Blue from brand
236
+ primary: COLOR_TOKENS.brand.lightBlue,
237
+ 'primary-dark': COLOR_TOKENS.primary[700],
238
+ 'primary-light': COLOR_TOKENS.primary[300],
239
+ // Secondary uses Dark Gray
240
+ secondary: COLOR_TOKENS.brand.darkGray,
241
+ 'secondary-dark': COLOR_TOKENS.secondary[900],
242
+ 'secondary-light': COLOR_TOKENS.secondary[600],
243
+ // Background uses White and Light Gray
244
+ background: COLOR_TOKENS.brand.white,
245
+ 'background-elevated': COLOR_TOKENS.brand.white,
246
+ surface: COLOR_TOKENS.brand.white,
247
+ 'surface-hover': COLOR_TOKENS.brand.lightGray,
248
+ // Text uses Dark Gray
249
+ text: COLOR_TOKENS.brand.darkGray,
250
+ 'text-secondary': COLOR_TOKENS.secondary[600],
251
+ 'text-disabled': COLOR_TOKENS.secondary[400],
252
+ // Borders use Light Gray
253
+ border: COLOR_TOKENS.brand.lightGray,
254
+ 'border-focus': COLOR_TOKENS.brand.lightBlue,
255
+ // Semantic colors
256
+ success: COLOR_TOKENS.success[500],
257
+ warning: COLOR_TOKENS.warning[500],
258
+ error: COLOR_TOKENS.error[500],
259
+ info: COLOR_TOKENS.info[500],
260
+ },
261
+ };
262
+
263
+ /**
264
+ * Dark theme configuration
265
+ * Based on Secretaría de Finanzas brand colors (inverted)
266
+ */
267
+ const DARK_THEME = {
268
+ name: 'dark',
269
+ colors: {
270
+ // Primary color remains Light Blue
271
+ primary: COLOR_TOKENS.brand.lightBlue,
272
+ 'primary-dark': COLOR_TOKENS.primary[300],
273
+ 'primary-light': COLOR_TOKENS.primary[700],
274
+ // Secondary uses Light Gray for contrast
275
+ secondary: COLOR_TOKENS.brand.lightGray,
276
+ 'secondary-dark': COLOR_TOKENS.secondary[400],
277
+ 'secondary-light': COLOR_TOKENS.secondary[200],
278
+ // Background uses Dark Gray
279
+ background: COLOR_TOKENS.brand.darkGray,
280
+ 'background-elevated': COLOR_TOKENS.secondary[700],
281
+ surface: COLOR_TOKENS.secondary[700],
282
+ 'surface-hover': COLOR_TOKENS.secondary[600],
283
+ // Text uses White and Light Gray
284
+ text: COLOR_TOKENS.brand.white,
285
+ 'text-secondary': COLOR_TOKENS.brand.lightGray,
286
+ 'text-disabled': COLOR_TOKENS.secondary[500],
287
+ // Borders use medium gray
288
+ border: COLOR_TOKENS.secondary[600],
289
+ 'border-focus': COLOR_TOKENS.brand.lightBlue,
290
+ // Semantic colors
291
+ success: COLOR_TOKENS.success[400],
292
+ warning: COLOR_TOKENS.warning[400],
293
+ error: COLOR_TOKENS.error[400],
294
+ info: COLOR_TOKENS.info[400],
295
+ },
296
+ };
297
+
298
+ /**
299
+ * Brand theme configuration
300
+ * Exact colors from Secretaría de Finanzas brand guidelines
301
+ */
302
+ const BRAND_THEME = {
303
+ name: 'brand',
304
+ colors: {
305
+ // Primary: Light Blue from brand guidelines
306
+ primary: COLOR_TOKENS.brand.lightBlue, // #55C3D8
307
+ 'primary-dark': COLOR_TOKENS.primary[700],
308
+ 'primary-light': COLOR_TOKENS.primary[300],
309
+ // Secondary: Dark Gray from brand guidelines
310
+ secondary: COLOR_TOKENS.brand.darkGray, // #383838
311
+ 'secondary-dark': COLOR_TOKENS.secondary[900],
312
+ 'secondary-light': COLOR_TOKENS.secondary[600],
313
+ // Background: White from brand guidelines
314
+ background: COLOR_TOKENS.brand.white, // #ffffff
315
+ 'background-elevated': COLOR_TOKENS.brand.white,
316
+ surface: COLOR_TOKENS.brand.white,
317
+ 'surface-hover': COLOR_TOKENS.brand.lightGray, // #cecece
318
+ // Text: Dark Gray from brand guidelines
319
+ text: COLOR_TOKENS.brand.darkGray, // #383838
320
+ 'text-secondary': COLOR_TOKENS.secondary[600],
321
+ 'text-disabled': COLOR_TOKENS.secondary[400],
322
+ // Border: Light Gray from brand guidelines
323
+ border: COLOR_TOKENS.brand.lightGray, // #cecece
324
+ 'border-focus': COLOR_TOKENS.brand.lightBlue, // #55C3D8
325
+ // Semantic colors
326
+ success: COLOR_TOKENS.success[500],
327
+ warning: COLOR_TOKENS.warning[500],
328
+ error: COLOR_TOKENS.error[500],
329
+ info: COLOR_TOKENS.info[500],
330
+ },
331
+ };
332
+
333
+ /**
334
+ * Themes index
335
+ */
336
+
337
+ /**
338
+ * Theme loader utility
339
+ * Generates CSS variables from design tokens
340
+ */
341
+ class ThemeLoader {
342
+ /**
343
+ * Load a theme and apply it to the document root
344
+ */
345
+ static loadTheme(themeName = 'light') {
346
+ const theme = this.getTheme(themeName);
347
+ const root = document.documentElement;
348
+ // Apply color tokens
349
+ Object.entries(theme.colors).forEach(([key, value]) => {
350
+ root.style.setProperty(`--sefin-color-${key}`, value);
351
+ });
352
+ // Apply spacing tokens
353
+ Object.entries(SPACING_TOKENS).forEach(([key, value]) => {
354
+ root.style.setProperty(`--sefin-spacing-${key}`, value);
355
+ });
356
+ // Apply typography tokens
357
+ Object.entries(TYPOGRAPHY_TOKENS.fontFamily).forEach(([key, value]) => {
358
+ root.style.setProperty(`--sefin-font-family-${key}`, value);
359
+ });
360
+ Object.entries(TYPOGRAPHY_TOKENS.fontSize).forEach(([key, value]) => {
361
+ root.style.setProperty(`--sefin-font-size-${key}`, value);
362
+ });
363
+ Object.entries(TYPOGRAPHY_TOKENS.fontWeight).forEach(([key, value]) => {
364
+ root.style.setProperty(`--sefin-font-weight-${key}`, String(value));
365
+ });
366
+ Object.entries(TYPOGRAPHY_TOKENS.lineHeight).forEach(([key, value]) => {
367
+ root.style.setProperty(`--sefin-line-height-${key}`, String(value));
368
+ });
369
+ // Apply border radius tokens
370
+ Object.entries(BORDER_RADIUS_TOKENS).forEach(([key, value]) => {
371
+ root.style.setProperty(`--sefin-radius-${key}`, value);
372
+ });
373
+ // Apply shadow tokens
374
+ Object.entries(SHADOW_TOKENS).forEach(([key, value]) => {
375
+ root.style.setProperty(`--sefin-shadow-${key}`, value);
376
+ });
377
+ // Set theme attribute for CSS selectors
378
+ root.setAttribute('data-theme', themeName);
379
+ }
380
+ /**
381
+ * Get theme configuration by name
382
+ */
383
+ static getTheme(themeName) {
384
+ switch (themeName) {
385
+ case 'dark':
386
+ return DARK_THEME;
387
+ case 'brand':
388
+ return BRAND_THEME;
389
+ case 'light':
390
+ default:
391
+ return LIGHT_THEME;
392
+ }
393
+ }
394
+ /**
395
+ * Get all CSS variables as a string (useful for SSR or static generation)
396
+ */
397
+ static getThemeCSS(themeName = 'light') {
398
+ const theme = this.getTheme(themeName);
399
+ let css = ':root {\n';
400
+ // Color tokens
401
+ Object.entries(theme.colors).forEach(([key, value]) => {
402
+ css += ` --sefin-color-${key}: ${value};\n`;
403
+ });
404
+ // Spacing tokens
405
+ Object.entries(SPACING_TOKENS).forEach(([key, value]) => {
406
+ css += ` --sefin-spacing-${key}: ${value};\n`;
407
+ });
408
+ // Typography tokens
409
+ Object.entries(TYPOGRAPHY_TOKENS.fontFamily).forEach(([key, value]) => {
410
+ css += ` --sefin-font-family-${key}: ${value};\n`;
411
+ });
412
+ Object.entries(TYPOGRAPHY_TOKENS.fontSize).forEach(([key, value]) => {
413
+ css += ` --sefin-font-size-${key}: ${value};\n`;
414
+ });
415
+ Object.entries(TYPOGRAPHY_TOKENS.fontWeight).forEach(([key, value]) => {
416
+ css += ` --sefin-font-weight-${key}: ${value};\n`;
417
+ });
418
+ Object.entries(TYPOGRAPHY_TOKENS.lineHeight).forEach(([key, value]) => {
419
+ css += ` --sefin-line-height-${key}: ${value};\n`;
420
+ });
421
+ // Border radius tokens
422
+ Object.entries(BORDER_RADIUS_TOKENS).forEach(([key, value]) => {
423
+ css += ` --sefin-radius-${key}: ${value};\n`;
424
+ });
425
+ // Shadow tokens
426
+ Object.entries(SHADOW_TOKENS).forEach(([key, value]) => {
427
+ css += ` --sefin-shadow-${key}: ${value};\n`;
428
+ });
429
+ css += '}\n';
430
+ return css;
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Utilities index
436
+ */
437
+
438
+ /**
439
+ * Shared types and interfaces
440
+ */
441
+
442
+ /**
443
+ * Shared index
444
+ */
445
+
446
+ class ButtonComponent {
447
+ variant = 'primary';
448
+ size = 'md';
449
+ disabled = false;
450
+ type = 'button';
451
+ class = '';
452
+ clicked = new EventEmitter();
453
+ onClick(event) {
454
+ if (!this.disabled) {
455
+ this.clicked.emit(event);
456
+ }
457
+ }
458
+ get buttonClasses() {
459
+ return [
460
+ 'sefin-button',
461
+ `sefin-button--${this.variant}`,
462
+ `sefin-button--${this.size}`,
463
+ this.disabled ? 'sefin-button--disabled' : '',
464
+ this.class,
465
+ ]
466
+ .filter(Boolean)
467
+ .join(' ');
468
+ }
469
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
470
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ButtonComponent, isStandalone: true, selector: "sefin-button", inputs: { variant: "variant", size: "size", disabled: "disabled", type: "type", class: "class" }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<button [type]=\"type\" [disabled]=\"disabled\" [class]=\"buttonClasses\" (click)=\"onClick($event)\">\n <ng-content></ng-content>\n</button>\n", styles: [".sefin-button{display:inline-flex;align-items:center;justify-content:center;font-family:var(--sefin-font-family-base);font-weight:var(--sefin-font-weight-medium, 500);border-radius:var(--sefin-radius-md, 8px);transition:all .2s ease-in-out;cursor:pointer;outline:none;border:1px solid transparent}.sefin-button:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-button--sm{padding:var(--sefin-spacing-sm, 8px) var(--sefin-spacing-md, 16px);font-size:var(--sefin-font-size-sm, .875rem);min-height:32px}.sefin-button--md{padding:var(--sefin-spacing-md, 16px) var(--sefin-spacing-lg, 24px);font-size:var(--sefin-font-size-base, 1rem);min-height:40px}.sefin-button--lg{padding:var(--sefin-spacing-lg, 24px) var(--sefin-spacing-xl, 32px);font-size:var(--sefin-font-size-lg, 1.125rem);min-height:48px}.sefin-button--primary{background-color:var(--sefin-color-primary);color:#fff}.sefin-button--primary:hover:not(:disabled){background-color:var(--sefin-color-primary-dark)}.sefin-button--primary:active:not(:disabled){transform:translateY(1px)}.sefin-button--secondary{background-color:var(--sefin-color-secondary);color:#fff}.sefin-button--secondary:hover:not(:disabled){background-color:var(--sefin-color-secondary-dark)}.sefin-button--secondary:active:not(:disabled){transform:translateY(1px)}.sefin-button--outline{background-color:transparent;color:var(--sefin-color-primary);border-color:var(--sefin-color-primary)}.sefin-button--outline:hover:not(:disabled){background-color:var(--sefin-color-primary);color:#fff}.sefin-button--ghost{background-color:transparent;color:var(--sefin-color-primary)}.sefin-button--ghost:hover:not(:disabled){background-color:var(--sefin-color-surface-hover)}.sefin-button--danger{background-color:var(--sefin-color-error);color:#fff}.sefin-button--danger:hover:not(:disabled){background-color:var(--sefin-color-error);opacity:.9}.sefin-button--disabled{opacity:.6;cursor:not-allowed;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
471
+ }
472
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonComponent, decorators: [{
473
+ type: Component,
474
+ args: [{ selector: 'sefin-button', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button [type]=\"type\" [disabled]=\"disabled\" [class]=\"buttonClasses\" (click)=\"onClick($event)\">\n <ng-content></ng-content>\n</button>\n", styles: [".sefin-button{display:inline-flex;align-items:center;justify-content:center;font-family:var(--sefin-font-family-base);font-weight:var(--sefin-font-weight-medium, 500);border-radius:var(--sefin-radius-md, 8px);transition:all .2s ease-in-out;cursor:pointer;outline:none;border:1px solid transparent}.sefin-button:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-button--sm{padding:var(--sefin-spacing-sm, 8px) var(--sefin-spacing-md, 16px);font-size:var(--sefin-font-size-sm, .875rem);min-height:32px}.sefin-button--md{padding:var(--sefin-spacing-md, 16px) var(--sefin-spacing-lg, 24px);font-size:var(--sefin-font-size-base, 1rem);min-height:40px}.sefin-button--lg{padding:var(--sefin-spacing-lg, 24px) var(--sefin-spacing-xl, 32px);font-size:var(--sefin-font-size-lg, 1.125rem);min-height:48px}.sefin-button--primary{background-color:var(--sefin-color-primary);color:#fff}.sefin-button--primary:hover:not(:disabled){background-color:var(--sefin-color-primary-dark)}.sefin-button--primary:active:not(:disabled){transform:translateY(1px)}.sefin-button--secondary{background-color:var(--sefin-color-secondary);color:#fff}.sefin-button--secondary:hover:not(:disabled){background-color:var(--sefin-color-secondary-dark)}.sefin-button--secondary:active:not(:disabled){transform:translateY(1px)}.sefin-button--outline{background-color:transparent;color:var(--sefin-color-primary);border-color:var(--sefin-color-primary)}.sefin-button--outline:hover:not(:disabled){background-color:var(--sefin-color-primary);color:#fff}.sefin-button--ghost{background-color:transparent;color:var(--sefin-color-primary)}.sefin-button--ghost:hover:not(:disabled){background-color:var(--sefin-color-surface-hover)}.sefin-button--danger{background-color:var(--sefin-color-error);color:#fff}.sefin-button--danger:hover:not(:disabled){background-color:var(--sefin-color-error);opacity:.9}.sefin-button--disabled{opacity:.6;cursor:not-allowed;pointer-events:none}\n"] }]
475
+ }], propDecorators: { variant: [{
476
+ type: Input
477
+ }], size: [{
478
+ type: Input
479
+ }], disabled: [{
480
+ type: Input
481
+ }], type: [{
482
+ type: Input
483
+ }], class: [{
484
+ type: Input
485
+ }], clicked: [{
486
+ type: Output
487
+ }] } });
488
+
489
+ class IconComponent {
490
+ name = '';
491
+ size = 'md';
492
+ class = '';
493
+ get iconClasses() {
494
+ return [
495
+ 'sefin-icon',
496
+ `sefin-icon--${this.size}`,
497
+ this.class,
498
+ ]
499
+ .filter(Boolean)
500
+ .join(' ');
501
+ }
502
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
503
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: IconComponent, isStandalone: true, selector: "sefin-icon", inputs: { name: "name", size: "size", class: "class" }, ngImport: i0, template: "<span [class]=\"iconClasses\" [attr.aria-label]=\"name\">\n <ng-content></ng-content>\n</span>\n\n", styles: [".sefin-icon{display:inline-flex;align-items:center;justify-content:center;color:currentColor}.sefin-icon--sm{width:16px;height:16px;font-size:16px}.sefin-icon--md{width:24px;height:24px;font-size:24px}.sefin-icon--lg{width:32px;height:32px;font-size:32px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
504
+ }
505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IconComponent, decorators: [{
506
+ type: Component,
507
+ args: [{ selector: 'sefin-icon', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span [class]=\"iconClasses\" [attr.aria-label]=\"name\">\n <ng-content></ng-content>\n</span>\n\n", styles: [".sefin-icon{display:inline-flex;align-items:center;justify-content:center;color:currentColor}.sefin-icon--sm{width:16px;height:16px;font-size:16px}.sefin-icon--md{width:24px;height:24px;font-size:24px}.sefin-icon--lg{width:32px;height:32px;font-size:32px}\n"] }]
508
+ }], propDecorators: { name: [{
509
+ type: Input
510
+ }], size: [{
511
+ type: Input
512
+ }], class: [{
513
+ type: Input
514
+ }] } });
515
+
516
+ class InputComponent {
517
+ type = 'text';
518
+ placeholder = '';
519
+ size = 'md';
520
+ disabled = false;
521
+ required = false;
522
+ readonly = false;
523
+ class = '';
524
+ id = '';
525
+ blur = new EventEmitter();
526
+ focus = new EventEmitter();
527
+ value = '';
528
+ onChange = (value) => { };
529
+ onTouched = () => { };
530
+ onInput(event) {
531
+ const target = event.target;
532
+ this.value = target.value;
533
+ this.onChange(this.value);
534
+ }
535
+ onBlur(event) {
536
+ this.onTouched();
537
+ this.blur.emit(event);
538
+ }
539
+ onFocus(event) {
540
+ this.focus.emit(event);
541
+ }
542
+ writeValue(value) {
543
+ this.value = value || '';
544
+ }
545
+ registerOnChange(fn) {
546
+ this.onChange = fn;
547
+ }
548
+ registerOnTouched(fn) {
549
+ this.onTouched = fn;
550
+ }
551
+ setDisabledState(isDisabled) {
552
+ this.disabled = isDisabled;
553
+ }
554
+ get inputClasses() {
555
+ return [
556
+ 'sefin-input',
557
+ `sefin-input--${this.size}`,
558
+ this.disabled ? 'sefin-input--disabled' : '',
559
+ this.class,
560
+ ]
561
+ .filter(Boolean)
562
+ .join(' ');
563
+ }
564
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: InputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
565
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: InputComponent, isStandalone: true, selector: "sefin-input", inputs: { type: "type", placeholder: "placeholder", size: "size", disabled: "disabled", required: "required", readonly: "readonly", class: "class", id: "id" }, outputs: { blur: "blur", focus: "focus" }, providers: [
566
+ {
567
+ provide: NG_VALUE_ACCESSOR,
568
+ useExisting: forwardRef(() => InputComponent),
569
+ multi: true,
570
+ },
571
+ ], ngImport: i0, template: "<input\n [type]=\"type\"\n [id]=\"id\"\n [class]=\"inputClasses\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur($event)\"\n (focus)=\"onFocus($event)\"\n/>\n\n", styles: [".sefin-input{width:100%;font-family:var(--sefin-font-family-base);color:var(--sefin-color-text);background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-md, 8px);transition:all .2s ease-in-out;outline:none}.sefin-input::placeholder{color:var(--sefin-color-text-secondary)}.sefin-input:focus{border-color:var(--sefin-color-border-focus);box-shadow:0 0 0 3px rgba(var(--sefin-color-primary-rgb, 33, 150, 243),.1)}.sefin-input:disabled{background-color:var(--sefin-color-surface-hover);color:var(--sefin-color-text-disabled);cursor:not-allowed}.sefin-input--sm{padding:var(--sefin-spacing-sm, 8px) var(--sefin-spacing-md, 16px);font-size:var(--sefin-font-size-sm, .875rem);min-height:32px}.sefin-input--md{padding:var(--sefin-spacing-md, 16px);font-size:var(--sefin-font-size-base, 1rem);min-height:40px}.sefin-input--lg{padding:var(--sefin-spacing-lg, 24px);font-size:var(--sefin-font-size-lg, 1.125rem);min-height:48px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
572
+ }
573
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: InputComponent, decorators: [{
574
+ type: Component,
575
+ args: [{ selector: 'sefin-input', standalone: true, imports: [CommonModule, FormsModule], providers: [
576
+ {
577
+ provide: NG_VALUE_ACCESSOR,
578
+ useExisting: forwardRef(() => InputComponent),
579
+ multi: true,
580
+ },
581
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<input\n [type]=\"type\"\n [id]=\"id\"\n [class]=\"inputClasses\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur($event)\"\n (focus)=\"onFocus($event)\"\n/>\n\n", styles: [".sefin-input{width:100%;font-family:var(--sefin-font-family-base);color:var(--sefin-color-text);background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-md, 8px);transition:all .2s ease-in-out;outline:none}.sefin-input::placeholder{color:var(--sefin-color-text-secondary)}.sefin-input:focus{border-color:var(--sefin-color-border-focus);box-shadow:0 0 0 3px rgba(var(--sefin-color-primary-rgb, 33, 150, 243),.1)}.sefin-input:disabled{background-color:var(--sefin-color-surface-hover);color:var(--sefin-color-text-disabled);cursor:not-allowed}.sefin-input--sm{padding:var(--sefin-spacing-sm, 8px) var(--sefin-spacing-md, 16px);font-size:var(--sefin-font-size-sm, .875rem);min-height:32px}.sefin-input--md{padding:var(--sefin-spacing-md, 16px);font-size:var(--sefin-font-size-base, 1rem);min-height:40px}.sefin-input--lg{padding:var(--sefin-spacing-lg, 24px);font-size:var(--sefin-font-size-lg, 1.125rem);min-height:48px}\n"] }]
582
+ }], propDecorators: { type: [{
583
+ type: Input
584
+ }], placeholder: [{
585
+ type: Input
586
+ }], size: [{
587
+ type: Input
588
+ }], disabled: [{
589
+ type: Input
590
+ }], required: [{
591
+ type: Input
592
+ }], readonly: [{
593
+ type: Input
594
+ }], class: [{
595
+ type: Input
596
+ }], id: [{
597
+ type: Input
598
+ }], blur: [{
599
+ type: Output
600
+ }], focus: [{
601
+ type: Output
602
+ }] } });
603
+
604
+ /**
605
+ * Atoms index
606
+ */
607
+
608
+ class FormFieldComponent {
609
+ label = '';
610
+ hint = '';
611
+ error = '';
612
+ required = false;
613
+ disabled = false;
614
+ inputId = '';
615
+ inputType = 'text';
616
+ placeholder = '';
617
+ size = 'md';
618
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: FormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
619
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: FormFieldComponent, isStandalone: true, selector: "sefin-form-field", inputs: { label: "label", hint: "hint", error: "error", required: "required", disabled: "disabled", inputId: "inputId", inputType: "inputType", placeholder: "placeholder", size: "size" }, ngImport: i0, template: "<div class=\"sefin-form-field\">\n <label *ngIf=\"label\" [for]=\"inputId\" class=\"sefin-form-field__label\">\n {{ label }}\n <span *ngIf=\"required\" class=\"sefin-form-field__required\">*</span>\n </label>\n <sefin-input\n [id]=\"inputId\"\n [type]=\"inputType\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n [size]=\"size\"\n [class.sefin-form-field__input--error]=\"!!error\"\n ></sefin-input>\n <div *ngIf=\"hint && !error\" class=\"sefin-form-field__hint\">{{ hint }}</div>\n <div *ngIf=\"error\" class=\"sefin-form-field__error\">{{ error }}</div>\n</div>\n\n", styles: [".sefin-form-field{display:flex;flex-direction:column;gap:var(--sefin-spacing-sm, 8px);width:100%}.sefin-form-field__label{font-size:var(--sefin-font-size-sm, .875rem);font-weight:var(--sefin-font-weight-medium, 500);color:var(--sefin-color-text)}.sefin-form-field__required{color:var(--sefin-color-error);margin-left:2px}.sefin-form-field__hint{font-size:var(--sefin-font-size-xs, .75rem);color:var(--sefin-color-text-secondary)}.sefin-form-field__error{font-size:var(--sefin-font-size-xs, .75rem);color:var(--sefin-color-error)}.sefin-form-field__input--error{border-color:var(--sefin-color-error)!important}.sefin-form-field__input--error:focus{box-shadow:0 0 0 3px #f443361a!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: InputComponent, selector: "sefin-input", inputs: ["type", "placeholder", "size", "disabled", "required", "readonly", "class", "id"], outputs: ["blur", "focus"] }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
620
+ }
621
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: FormFieldComponent, decorators: [{
622
+ type: Component,
623
+ args: [{ selector: 'sefin-form-field', standalone: true, imports: [CommonModule, InputComponent, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sefin-form-field\">\n <label *ngIf=\"label\" [for]=\"inputId\" class=\"sefin-form-field__label\">\n {{ label }}\n <span *ngIf=\"required\" class=\"sefin-form-field__required\">*</span>\n </label>\n <sefin-input\n [id]=\"inputId\"\n [type]=\"inputType\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n [size]=\"size\"\n [class.sefin-form-field__input--error]=\"!!error\"\n ></sefin-input>\n <div *ngIf=\"hint && !error\" class=\"sefin-form-field__hint\">{{ hint }}</div>\n <div *ngIf=\"error\" class=\"sefin-form-field__error\">{{ error }}</div>\n</div>\n\n", styles: [".sefin-form-field{display:flex;flex-direction:column;gap:var(--sefin-spacing-sm, 8px);width:100%}.sefin-form-field__label{font-size:var(--sefin-font-size-sm, .875rem);font-weight:var(--sefin-font-weight-medium, 500);color:var(--sefin-color-text)}.sefin-form-field__required{color:var(--sefin-color-error);margin-left:2px}.sefin-form-field__hint{font-size:var(--sefin-font-size-xs, .75rem);color:var(--sefin-color-text-secondary)}.sefin-form-field__error{font-size:var(--sefin-font-size-xs, .75rem);color:var(--sefin-color-error)}.sefin-form-field__input--error{border-color:var(--sefin-color-error)!important}.sefin-form-field__input--error:focus{box-shadow:0 0 0 3px #f443361a!important}\n"] }]
624
+ }], propDecorators: { label: [{
625
+ type: Input
626
+ }], hint: [{
627
+ type: Input
628
+ }], error: [{
629
+ type: Input
630
+ }], required: [{
631
+ type: Input
632
+ }], disabled: [{
633
+ type: Input
634
+ }], inputId: [{
635
+ type: Input
636
+ }], inputType: [{
637
+ type: Input
638
+ }], placeholder: [{
639
+ type: Input
640
+ }], size: [{
641
+ type: Input
642
+ }] } });
643
+
644
+ class DropdownComponent {
645
+ options = [];
646
+ placeholder = 'Select an option';
647
+ disabled = false;
648
+ size = 'md';
649
+ selectionChange = new EventEmitter();
650
+ isOpen = false;
651
+ selectedOption = null;
652
+ toggle() {
653
+ if (!this.disabled) {
654
+ this.isOpen = !this.isOpen;
655
+ }
656
+ }
657
+ selectOption(option) {
658
+ if (!option.disabled) {
659
+ this.selectedOption = option;
660
+ this.isOpen = false;
661
+ this.selectionChange.emit(option.value);
662
+ }
663
+ }
664
+ get displayText() {
665
+ return this.selectedOption?.label || this.placeholder;
666
+ }
667
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
668
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: DropdownComponent, isStandalone: true, selector: "sefin-dropdown", inputs: { options: "options", placeholder: "placeholder", disabled: "disabled", size: "size" }, outputs: { selectionChange: "selectionChange" }, ngImport: i0, template: "<div class=\"sefin-dropdown\" [class.sefin-dropdown--open]=\"isOpen\">\n <sefin-button\n [variant]=\"'outline'\"\n [size]=\"size\"\n [disabled]=\"disabled\"\n (clicked)=\"toggle()\"\n class=\"sefin-dropdown__trigger\"\n >\n {{ displayText }}\n <span class=\"sefin-dropdown__arrow\">\u25BC</span>\n </sefin-button>\n <div *ngIf=\"isOpen\" class=\"sefin-dropdown__menu\">\n <button\n *ngFor=\"let option of options\"\n [class.sefin-dropdown__option--disabled]=\"option.disabled\"\n [class.sefin-dropdown__option--selected]=\"selectedOption?.value === option.value\"\n class=\"sefin-dropdown__option\"\n (click)=\"selectOption(option)\"\n [disabled]=\"option.disabled\"\n >\n {{ option.label }}\n </button>\n </div>\n</div>\n\n", styles: [".sefin-dropdown{position:relative;width:100%}.sefin-dropdown__trigger{width:100%;justify-content:space-between}.sefin-dropdown__arrow{margin-left:var(--sefin-spacing-sm, 8px);transition:transform .2s ease-in-out}.sefin-dropdown--open .sefin-dropdown__arrow{transform:rotate(180deg)}.sefin-dropdown__menu{position:absolute;top:calc(100% + var(--sefin-spacing-xs, 4px));left:0;right:0;background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-md, 8px);box-shadow:var(--sefin-shadow-lg);z-index:1000;max-height:300px;overflow-y:auto}.sefin-dropdown__option{width:100%;padding:var(--sefin-spacing-md, 16px);text-align:left;background:none;border:none;cursor:pointer;color:var(--sefin-color-text);font-size:var(--sefin-font-size-base, 1rem);transition:background-color .2s ease-in-out}.sefin-dropdown__option:hover:not(:disabled){background-color:var(--sefin-color-surface-hover)}.sefin-dropdown__option--selected{background-color:var(--sefin-color-primary);color:#fff}.sefin-dropdown__option--disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ButtonComponent, selector: "sefin-button", inputs: ["variant", "size", "disabled", "type", "class"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
669
+ }
670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DropdownComponent, decorators: [{
671
+ type: Component,
672
+ args: [{ selector: 'sefin-dropdown', standalone: true, imports: [CommonModule, ButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sefin-dropdown\" [class.sefin-dropdown--open]=\"isOpen\">\n <sefin-button\n [variant]=\"'outline'\"\n [size]=\"size\"\n [disabled]=\"disabled\"\n (clicked)=\"toggle()\"\n class=\"sefin-dropdown__trigger\"\n >\n {{ displayText }}\n <span class=\"sefin-dropdown__arrow\">\u25BC</span>\n </sefin-button>\n <div *ngIf=\"isOpen\" class=\"sefin-dropdown__menu\">\n <button\n *ngFor=\"let option of options\"\n [class.sefin-dropdown__option--disabled]=\"option.disabled\"\n [class.sefin-dropdown__option--selected]=\"selectedOption?.value === option.value\"\n class=\"sefin-dropdown__option\"\n (click)=\"selectOption(option)\"\n [disabled]=\"option.disabled\"\n >\n {{ option.label }}\n </button>\n </div>\n</div>\n\n", styles: [".sefin-dropdown{position:relative;width:100%}.sefin-dropdown__trigger{width:100%;justify-content:space-between}.sefin-dropdown__arrow{margin-left:var(--sefin-spacing-sm, 8px);transition:transform .2s ease-in-out}.sefin-dropdown--open .sefin-dropdown__arrow{transform:rotate(180deg)}.sefin-dropdown__menu{position:absolute;top:calc(100% + var(--sefin-spacing-xs, 4px));left:0;right:0;background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-md, 8px);box-shadow:var(--sefin-shadow-lg);z-index:1000;max-height:300px;overflow-y:auto}.sefin-dropdown__option{width:100%;padding:var(--sefin-spacing-md, 16px);text-align:left;background:none;border:none;cursor:pointer;color:var(--sefin-color-text);font-size:var(--sefin-font-size-base, 1rem);transition:background-color .2s ease-in-out}.sefin-dropdown__option:hover:not(:disabled){background-color:var(--sefin-color-surface-hover)}.sefin-dropdown__option--selected{background-color:var(--sefin-color-primary);color:#fff}.sefin-dropdown__option--disabled{opacity:.5;cursor:not-allowed}\n"] }]
673
+ }], propDecorators: { options: [{
674
+ type: Input
675
+ }], placeholder: [{
676
+ type: Input
677
+ }], disabled: [{
678
+ type: Input
679
+ }], size: [{
680
+ type: Input
681
+ }], selectionChange: [{
682
+ type: Output
683
+ }] } });
684
+
685
+ class CardComponent {
686
+ variant = 'default';
687
+ class = '';
688
+ get cardClasses() {
689
+ return [
690
+ 'sefin-card',
691
+ `sefin-card--${this.variant}`,
692
+ this.class,
693
+ ]
694
+ .filter(Boolean)
695
+ .join(' ');
696
+ }
697
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
698
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: CardComponent, isStandalone: true, selector: "sefin-card", inputs: { variant: "variant", class: "class" }, ngImport: i0, template: "<div [class]=\"cardClasses\">\n <ng-content></ng-content>\n</div>\n\n", styles: [".sefin-card{background-color:var(--sefin-color-surface);border-radius:var(--sefin-radius-lg, 12px);padding:var(--sefin-spacing-lg, 24px);transition:all .2s ease-in-out}.sefin-card--default{background-color:var(--sefin-color-surface)}.sefin-card--elevated{background-color:var(--sefin-color-background-elevated);box-shadow:var(--sefin-shadow-md)}.sefin-card--outlined{background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
699
+ }
700
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CardComponent, decorators: [{
701
+ type: Component,
702
+ args: [{ selector: 'sefin-card', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"cardClasses\">\n <ng-content></ng-content>\n</div>\n\n", styles: [".sefin-card{background-color:var(--sefin-color-surface);border-radius:var(--sefin-radius-lg, 12px);padding:var(--sefin-spacing-lg, 24px);transition:all .2s ease-in-out}.sefin-card--default{background-color:var(--sefin-color-surface)}.sefin-card--elevated{background-color:var(--sefin-color-background-elevated);box-shadow:var(--sefin-shadow-md)}.sefin-card--outlined{background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border)}\n"] }]
703
+ }], propDecorators: { variant: [{
704
+ type: Input
705
+ }], class: [{
706
+ type: Input
707
+ }] } });
708
+
709
+ /**
710
+ * Molecules index
711
+ */
712
+
713
+ class HeaderComponent {
714
+ title = '';
715
+ logo = '';
716
+ showUserMenu = true;
717
+ userName = '';
718
+ logoClick = new EventEmitter();
719
+ menuClick = new EventEmitter();
720
+ userMenuClick = new EventEmitter();
721
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
722
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: HeaderComponent, isStandalone: true, selector: "sefin-header", inputs: { title: "title", logo: "logo", showUserMenu: "showUserMenu", userName: "userName" }, outputs: { logoClick: "logoClick", menuClick: "menuClick", userMenuClick: "userMenuClick" }, ngImport: i0, template: "<header class=\"sefin-header\">\n <div class=\"sefin-header__left\">\n <div *ngIf=\"logo\" class=\"sefin-header__logo\" (click)=\"logoClick.emit()\">\n <img [src]=\"logo\" [alt]=\"title\" />\n </div>\n <h1 *ngIf=\"title\" class=\"sefin-header__title\">{{ title }}</h1>\n </div>\n <div class=\"sefin-header__right\">\n <sefin-button\n *ngIf=\"showUserMenu\"\n variant=\"ghost\"\n size=\"md\"\n (clicked)=\"userMenuClick.emit()\"\n class=\"sefin-header__user-menu\"\n >\n <sefin-icon name=\"user\" size=\"md\"></sefin-icon>\n <span *ngIf=\"userName\">{{ userName }}</span>\n </sefin-button>\n <sefin-button\n variant=\"ghost\"\n size=\"md\"\n (clicked)=\"menuClick.emit()\"\n class=\"sefin-header__menu-button\"\n >\n <sefin-icon name=\"menu\" size=\"md\">\u2630</sefin-icon>\n </sefin-button>\n </div>\n</header>\n\n", styles: [".sefin-header{display:flex;align-items:center;justify-content:space-between;padding:var(--sefin-spacing-md, 16px) var(--sefin-spacing-lg, 24px);background-color:var(--sefin-color-surface);border-bottom:1px solid var(--sefin-color-border);box-shadow:var(--sefin-shadow-sm)}.sefin-header__left{display:flex;align-items:center;gap:var(--sefin-spacing-md, 16px)}.sefin-header__logo{cursor:pointer;display:flex;align-items:center}.sefin-header__logo img{height:40px;width:auto}.sefin-header__title{font-size:var(--sefin-font-size-xl, 1.25rem);font-weight:var(--sefin-font-weight-semibold, 600);color:var(--sefin-color-text);margin:0}.sefin-header__right,.sefin-header__user-menu{display:flex;align-items:center;gap:var(--sefin-spacing-sm, 8px)}.sefin-header__menu-button{display:flex;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ButtonComponent, selector: "sefin-button", inputs: ["variant", "size", "disabled", "type", "class"], outputs: ["clicked"] }, { kind: "component", type: IconComponent, selector: "sefin-icon", inputs: ["name", "size", "class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
723
+ }
724
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HeaderComponent, decorators: [{
725
+ type: Component,
726
+ args: [{ selector: 'sefin-header', standalone: true, imports: [CommonModule, ButtonComponent, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"sefin-header\">\n <div class=\"sefin-header__left\">\n <div *ngIf=\"logo\" class=\"sefin-header__logo\" (click)=\"logoClick.emit()\">\n <img [src]=\"logo\" [alt]=\"title\" />\n </div>\n <h1 *ngIf=\"title\" class=\"sefin-header__title\">{{ title }}</h1>\n </div>\n <div class=\"sefin-header__right\">\n <sefin-button\n *ngIf=\"showUserMenu\"\n variant=\"ghost\"\n size=\"md\"\n (clicked)=\"userMenuClick.emit()\"\n class=\"sefin-header__user-menu\"\n >\n <sefin-icon name=\"user\" size=\"md\"></sefin-icon>\n <span *ngIf=\"userName\">{{ userName }}</span>\n </sefin-button>\n <sefin-button\n variant=\"ghost\"\n size=\"md\"\n (clicked)=\"menuClick.emit()\"\n class=\"sefin-header__menu-button\"\n >\n <sefin-icon name=\"menu\" size=\"md\">\u2630</sefin-icon>\n </sefin-button>\n </div>\n</header>\n\n", styles: [".sefin-header{display:flex;align-items:center;justify-content:space-between;padding:var(--sefin-spacing-md, 16px) var(--sefin-spacing-lg, 24px);background-color:var(--sefin-color-surface);border-bottom:1px solid var(--sefin-color-border);box-shadow:var(--sefin-shadow-sm)}.sefin-header__left{display:flex;align-items:center;gap:var(--sefin-spacing-md, 16px)}.sefin-header__logo{cursor:pointer;display:flex;align-items:center}.sefin-header__logo img{height:40px;width:auto}.sefin-header__title{font-size:var(--sefin-font-size-xl, 1.25rem);font-weight:var(--sefin-font-weight-semibold, 600);color:var(--sefin-color-text);margin:0}.sefin-header__right,.sefin-header__user-menu{display:flex;align-items:center;gap:var(--sefin-spacing-sm, 8px)}.sefin-header__menu-button{display:flex;align-items:center}\n"] }]
727
+ }], propDecorators: { title: [{
728
+ type: Input
729
+ }], logo: [{
730
+ type: Input
731
+ }], showUserMenu: [{
732
+ type: Input
733
+ }], userName: [{
734
+ type: Input
735
+ }], logoClick: [{
736
+ type: Output
737
+ }], menuClick: [{
738
+ type: Output
739
+ }], userMenuClick: [{
740
+ type: Output
741
+ }] } });
742
+
743
+ class LoginFormComponent {
744
+ email = '';
745
+ password = '';
746
+ error = '';
747
+ submit = new EventEmitter();
748
+ onSubmit() {
749
+ if (this.email && this.password) {
750
+ this.error = '';
751
+ this.submit.emit({
752
+ email: this.email,
753
+ password: this.password,
754
+ });
755
+ }
756
+ else {
757
+ this.error = 'Please fill in all fields';
758
+ }
759
+ }
760
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LoginFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
761
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: LoginFormComponent, isStandalone: true, selector: "sefin-login-form", outputs: { submit: "submit" }, ngImport: i0, template: "<sefin-card variant=\"elevated\" class=\"sefin-login-form\">\n <h2 class=\"sefin-login-form__title\">Sign In</h2>\n <form (ngSubmit)=\"onSubmit()\" class=\"sefin-login-form__form\">\n <sefin-form-field\n label=\"Email\"\n inputId=\"email\"\n inputType=\"email\"\n placeholder=\"Enter your email\"\n [required]=\"true\"\n [(ngModel)]=\"email\"\n name=\"email\"\n ></sefin-form-field>\n <sefin-form-field\n label=\"Password\"\n inputId=\"password\"\n inputType=\"password\"\n placeholder=\"Enter your password\"\n [required]=\"true\"\n [(ngModel)]=\"password\"\n name=\"password\"\n ></sefin-form-field>\n <div *ngIf=\"error\" class=\"sefin-login-form__error\">{{ error }}</div>\n <sefin-button\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n class=\"sefin-login-form__submit\"\n >\n Sign In\n </sefin-button>\n </form>\n</sefin-card>\n\n", styles: [".sefin-login-form{max-width:400px;width:100%}.sefin-login-form__title{font-size:var(--sefin-font-size-2xl, 1.5rem);font-weight:var(--sefin-font-weight-semibold, 600);margin-bottom:var(--sefin-spacing-xl, 32px);text-align:center}.sefin-login-form__form{display:flex;flex-direction:column;gap:var(--sefin-spacing-lg, 24px)}.sefin-login-form__error{padding:var(--sefin-spacing-md, 16px);background-color:#f443361a;color:var(--sefin-color-error);border-radius:var(--sefin-radius-md, 8px);font-size:var(--sefin-font-size-sm, .875rem)}.sefin-login-form__submit{width:100%;margin-top:var(--sefin-spacing-md, 16px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { 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],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormFieldComponent, selector: "sefin-form-field", inputs: ["label", "hint", "error", "required", "disabled", "inputId", "inputType", "placeholder", "size"] }, { kind: "component", type: ButtonComponent, selector: "sefin-button", inputs: ["variant", "size", "disabled", "type", "class"], outputs: ["clicked"] }, { kind: "component", type: CardComponent, selector: "sefin-card", inputs: ["variant", "class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
762
+ }
763
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LoginFormComponent, decorators: [{
764
+ type: Component,
765
+ args: [{ selector: 'sefin-login-form', standalone: true, imports: [CommonModule, FormsModule, FormFieldComponent, ButtonComponent, CardComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<sefin-card variant=\"elevated\" class=\"sefin-login-form\">\n <h2 class=\"sefin-login-form__title\">Sign In</h2>\n <form (ngSubmit)=\"onSubmit()\" class=\"sefin-login-form__form\">\n <sefin-form-field\n label=\"Email\"\n inputId=\"email\"\n inputType=\"email\"\n placeholder=\"Enter your email\"\n [required]=\"true\"\n [(ngModel)]=\"email\"\n name=\"email\"\n ></sefin-form-field>\n <sefin-form-field\n label=\"Password\"\n inputId=\"password\"\n inputType=\"password\"\n placeholder=\"Enter your password\"\n [required]=\"true\"\n [(ngModel)]=\"password\"\n name=\"password\"\n ></sefin-form-field>\n <div *ngIf=\"error\" class=\"sefin-login-form__error\">{{ error }}</div>\n <sefin-button\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n class=\"sefin-login-form__submit\"\n >\n Sign In\n </sefin-button>\n </form>\n</sefin-card>\n\n", styles: [".sefin-login-form{max-width:400px;width:100%}.sefin-login-form__title{font-size:var(--sefin-font-size-2xl, 1.5rem);font-weight:var(--sefin-font-weight-semibold, 600);margin-bottom:var(--sefin-spacing-xl, 32px);text-align:center}.sefin-login-form__form{display:flex;flex-direction:column;gap:var(--sefin-spacing-lg, 24px)}.sefin-login-form__error{padding:var(--sefin-spacing-md, 16px);background-color:#f443361a;color:var(--sefin-color-error);border-radius:var(--sefin-radius-md, 8px);font-size:var(--sefin-font-size-sm, .875rem)}.sefin-login-form__submit{width:100%;margin-top:var(--sefin-spacing-md, 16px)}\n"] }]
766
+ }], propDecorators: { submit: [{
767
+ type: Output
768
+ }] } });
769
+
770
+ class ToolbarComponent {
771
+ title = '';
772
+ actions = [];
773
+ actionClick = new EventEmitter();
774
+ onActionClick(action) {
775
+ action.action();
776
+ this.actionClick.emit(action);
777
+ }
778
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
779
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ToolbarComponent, isStandalone: true, selector: "sefin-toolbar", inputs: { title: "title", actions: "actions" }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: "<div class=\"sefin-toolbar\">\n <h2 *ngIf=\"title\" class=\"sefin-toolbar__title\">{{ title }}</h2>\n <div class=\"sefin-toolbar__actions\">\n <sefin-button\n *ngFor=\"let action of actions\"\n [variant]=\"action.variant || 'primary'\"\n size=\"md\"\n (clicked)=\"onActionClick(action)\"\n >\n <sefin-icon *ngIf=\"action.icon\" [name]=\"action.icon\" size=\"sm\"></sefin-icon>\n {{ action.label }}\n </sefin-button>\n </div>\n</div>\n\n", styles: [".sefin-toolbar{display:flex;align-items:center;justify-content:space-between;padding:var(--sefin-spacing-lg, 24px);background-color:var(--sefin-color-background-elevated);border-bottom:1px solid var(--sefin-color-border)}.sefin-toolbar__title{font-size:var(--sefin-font-size-xl, 1.25rem);font-weight:var(--sefin-font-weight-semibold, 600);color:var(--sefin-color-text);margin:0}.sefin-toolbar__actions{display:flex;align-items:center;gap:var(--sefin-spacing-md, 16px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ButtonComponent, selector: "sefin-button", inputs: ["variant", "size", "disabled", "type", "class"], outputs: ["clicked"] }, { kind: "component", type: IconComponent, selector: "sefin-icon", inputs: ["name", "size", "class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
780
+ }
781
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ToolbarComponent, decorators: [{
782
+ type: Component,
783
+ args: [{ selector: 'sefin-toolbar', standalone: true, imports: [CommonModule, ButtonComponent, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sefin-toolbar\">\n <h2 *ngIf=\"title\" class=\"sefin-toolbar__title\">{{ title }}</h2>\n <div class=\"sefin-toolbar__actions\">\n <sefin-button\n *ngFor=\"let action of actions\"\n [variant]=\"action.variant || 'primary'\"\n size=\"md\"\n (clicked)=\"onActionClick(action)\"\n >\n <sefin-icon *ngIf=\"action.icon\" [name]=\"action.icon\" size=\"sm\"></sefin-icon>\n {{ action.label }}\n </sefin-button>\n </div>\n</div>\n\n", styles: [".sefin-toolbar{display:flex;align-items:center;justify-content:space-between;padding:var(--sefin-spacing-lg, 24px);background-color:var(--sefin-color-background-elevated);border-bottom:1px solid var(--sefin-color-border)}.sefin-toolbar__title{font-size:var(--sefin-font-size-xl, 1.25rem);font-weight:var(--sefin-font-weight-semibold, 600);color:var(--sefin-color-text);margin:0}.sefin-toolbar__actions{display:flex;align-items:center;gap:var(--sefin-spacing-md, 16px)}\n"] }]
784
+ }], propDecorators: { title: [{
785
+ type: Input
786
+ }], actions: [{
787
+ type: Input
788
+ }], actionClick: [{
789
+ type: Output
790
+ }] } });
791
+
792
+ /**
793
+ * Organisms index
794
+ */
795
+
796
+ /*
797
+ * Public API Surface of @sefin/sefin-ui
798
+ */
799
+ // Design Tokens
800
+ // Styles (for importing in consuming apps)
801
+ const STYLES_PATH = './styles/index.scss';
802
+
803
+ /**
804
+ * Generated bundle index. Do not edit.
805
+ */
806
+
807
+ export { BORDER_RADIUS_TOKENS, BRAND_THEME, ButtonComponent, COLOR_TOKENS, CardComponent, DARK_THEME, DESIGN_TOKENS, DropdownComponent, FormFieldComponent, HeaderComponent, IconComponent, InputComponent, LIGHT_THEME, LoginFormComponent, SHADOW_TOKENS, SPACING_TOKENS, STYLES_PATH, TYPOGRAPHY_TOKENS, ThemeLoader, ToolbarComponent };
808
+ //# sourceMappingURL=lesterarte-sefin-ui.mjs.map