@mimi-ng/cli 0.2.0 → 0.3.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.
- package/README.md +15 -1
- package/dist/registry.json +274 -14
- package/dist/templates/components/calendar/calendar-texts.ts +72 -0
- package/dist/templates/components/calendar/calendar.ts +588 -0
- package/dist/templates/components/calendar/dates.ts +181 -0
- package/dist/templates/components/calendar/index.ts +3 -0
- package/dist/templates/components/chip/chip-texts.ts +40 -0
- package/dist/templates/components/chip/chip.ts +116 -0
- package/dist/templates/components/chip/index.ts +2 -0
- package/dist/templates/components/color-picker/color-picker-texts.ts +57 -0
- package/dist/templates/components/color-picker/color-picker.ts +718 -0
- package/dist/templates/components/color-picker/color.ts +157 -0
- package/dist/templates/components/color-picker/index.ts +3 -0
- package/dist/templates/components/combobox/combobox-texts.ts +70 -0
- package/dist/templates/components/combobox/combobox.ts +798 -0
- package/dist/templates/components/combobox/index.ts +2 -0
- package/dist/templates/components/date-picker/date-picker.ts +240 -0
- package/dist/templates/components/date-picker/index.ts +3 -0
- package/dist/templates/components/date-range/date-range.ts +308 -0
- package/dist/templates/components/date-range/index.ts +1 -0
- package/dist/templates/components/file-upload/file-upload-texts.ts +77 -0
- package/dist/templates/components/file-upload/file-upload.ts +698 -0
- package/dist/templates/components/file-upload/index.ts +2 -0
- package/dist/templates/components/input-mask/index.ts +1 -0
- package/dist/templates/components/input-mask/input-mask.ts +319 -0
- package/dist/templates/components/input-otp/index.ts +1 -0
- package/dist/templates/components/input-otp/input-otp.ts +212 -0
- package/dist/templates/components/number-input/index.ts +2 -0
- package/dist/templates/components/number-input/number-input-texts.ts +46 -0
- package/dist/templates/components/number-input/number-input.ts +450 -0
- package/dist/templates/components/option-list/index.ts +11 -0
- package/dist/templates/components/option-list/option-list.ts +518 -0
- package/dist/templates/components/password/index.ts +2 -0
- package/dist/templates/components/password/password-texts.ts +68 -0
- package/dist/templates/components/password/password.ts +363 -0
- package/dist/templates/components/popover/popover.ts +12 -4
- package/dist/templates/components/progress/index.ts +1 -0
- package/dist/templates/components/progress/progress.ts +217 -0
- package/dist/templates/components/select/select.ts +3 -2
- package/dist/templates/components/slider/index.ts +2 -0
- package/dist/templates/components/slider/slider-texts.ts +26 -0
- package/dist/templates/components/slider/slider.ts +425 -0
- package/dist/templates/components/tags-input/index.ts +2 -0
- package/dist/templates/components/tags-input/tags-input-texts.ts +44 -0
- package/dist/templates/components/tags-input/tags-input.ts +303 -0
- package/dist/templates/components/toggle-group/index.ts +1 -0
- package/dist/templates/components/toggle-group/toggle-group.ts +406 -0
- package/dist/templates/theme/provider.ts +13 -0
- package/dist/templates/theme/theme-base.css +103 -0
- package/dist/templates/theme/types.ts +216 -0
- package/dist/templates/utils/overlay.ts +17 -4
- package/dist/ui/index.js +105 -1
- package/dist/ui/schema.json +56 -0
- package/dist/utils/write-files.js +12 -2
- package/package.json +1 -1
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Conversiones de color del Color Picker (G2.12). El valor es siempre hex de 6 dígitos en
|
|
3
|
+
* minúsculas (decidido por defecto, opción (a)); se elige en HSV (como el diseño) y se puede ver
|
|
4
|
+
* y escribir en OKLCH, recortado a sRGB.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface MimiRgb {
|
|
8
|
+
r: number;
|
|
9
|
+
g: number;
|
|
10
|
+
b: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface MimiHsv {
|
|
14
|
+
/** Tono, 0–360. */
|
|
15
|
+
h: number;
|
|
16
|
+
/** Saturación y brillo, 0–1. */
|
|
17
|
+
s: number;
|
|
18
|
+
v: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Formato en el que se ve y se escribe el color. */
|
|
22
|
+
export type MimiColorFormat = 'hex' | 'oklch';
|
|
23
|
+
|
|
24
|
+
const clamp = (n: number, min = 0, max = 1) => Math.min(max, Math.max(min, n));
|
|
25
|
+
|
|
26
|
+
/** `#4f46e5`, `#fff` (con o sin `#`, mayúsculas o minúsculas) → hex de 6 dígitos, o null. */
|
|
27
|
+
export function mimiNormalizeHex(text: string | null | undefined): string | null {
|
|
28
|
+
// Un formulario puede mandar `null` o `undefined` (ngModel antes de escribir el valor).
|
|
29
|
+
const match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec((text ?? '').trim());
|
|
30
|
+
if (!match) return null;
|
|
31
|
+
const hex = match[1].toLowerCase();
|
|
32
|
+
return '#' + (hex.length === 3 ? [...hex].map((c) => c + c).join('') : hex);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function mimiHexToRgb(hex: string): MimiRgb | null {
|
|
36
|
+
const normal = mimiNormalizeHex(hex);
|
|
37
|
+
if (!normal) return null;
|
|
38
|
+
const n = parseInt(normal.slice(1), 16);
|
|
39
|
+
return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function mimiRgbToHex({ r, g, b }: MimiRgb): string {
|
|
43
|
+
return (
|
|
44
|
+
'#' +
|
|
45
|
+
[r, g, b]
|
|
46
|
+
.map((c) =>
|
|
47
|
+
Math.round(clamp(c, 0, 255))
|
|
48
|
+
.toString(16)
|
|
49
|
+
.padStart(2, '0'),
|
|
50
|
+
)
|
|
51
|
+
.join('')
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function mimiRgbToHsv({ r, g, b }: MimiRgb): MimiHsv {
|
|
56
|
+
const [rn, gn, bn] = [r / 255, g / 255, b / 255];
|
|
57
|
+
const max = Math.max(rn, gn, bn);
|
|
58
|
+
const min = Math.min(rn, gn, bn);
|
|
59
|
+
const d = max - min;
|
|
60
|
+
let h = 0;
|
|
61
|
+
if (d) {
|
|
62
|
+
if (max === rn) h = ((gn - bn) / d) % 6;
|
|
63
|
+
else if (max === gn) h = (bn - rn) / d + 2;
|
|
64
|
+
else h = (rn - gn) / d + 4;
|
|
65
|
+
h *= 60;
|
|
66
|
+
if (h < 0) h += 360;
|
|
67
|
+
}
|
|
68
|
+
return { h, s: max ? d / max : 0, v: max };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function mimiHsvToRgb({ h, s, v }: MimiHsv): MimiRgb {
|
|
72
|
+
const c = v * s;
|
|
73
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
74
|
+
const m = v - c;
|
|
75
|
+
const [r, g, b] =
|
|
76
|
+
h < 60
|
|
77
|
+
? [c, x, 0]
|
|
78
|
+
: h < 120
|
|
79
|
+
? [x, c, 0]
|
|
80
|
+
: h < 180
|
|
81
|
+
? [0, c, x]
|
|
82
|
+
: h < 240
|
|
83
|
+
? [0, x, c]
|
|
84
|
+
: h < 300
|
|
85
|
+
? [x, 0, c]
|
|
86
|
+
: [c, 0, x];
|
|
87
|
+
return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const toLinear = (c: number) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
|
|
91
|
+
const fromLinear = (c: number) => (c <= 0.0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055);
|
|
92
|
+
|
|
93
|
+
/** sRGB → OKLCH (`l` 0–1, `c` ≥ 0, `h` 0–360). */
|
|
94
|
+
export function mimiRgbToOklch({ r, g, b }: MimiRgb): { l: number; c: number; h: number } {
|
|
95
|
+
const [lr, lg, lb] = [r / 255, g / 255, b / 255].map(toLinear);
|
|
96
|
+
const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);
|
|
97
|
+
const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);
|
|
98
|
+
const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);
|
|
99
|
+
const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
|
|
100
|
+
const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
|
|
101
|
+
const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
|
|
102
|
+
const C = Math.sqrt(A * A + B * B);
|
|
103
|
+
let H = (Math.atan2(B, A) * 180) / Math.PI;
|
|
104
|
+
if (H < 0) H += 360;
|
|
105
|
+
return { l: L, c: C, h: C < 1e-4 ? 0 : H };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** OKLCH → sRGB. `clipped` dice si estaba fuera de sRGB y se recortó. */
|
|
109
|
+
export function mimiOklchToRgb(
|
|
110
|
+
l: number,
|
|
111
|
+
c: number,
|
|
112
|
+
h: number,
|
|
113
|
+
): { rgb: MimiRgb; clipped: boolean } {
|
|
114
|
+
const hr = (h * Math.PI) / 180;
|
|
115
|
+
const A = c * Math.cos(hr);
|
|
116
|
+
const B = c * Math.sin(hr);
|
|
117
|
+
const l_ = (l + 0.3963377774 * A + 0.2158037573 * B) ** 3;
|
|
118
|
+
const m_ = (l - 0.1055613458 * A - 0.0638541728 * B) ** 3;
|
|
119
|
+
const s_ = (l - 0.0894841775 * A - 1.291485548 * B) ** 3;
|
|
120
|
+
const linear = [
|
|
121
|
+
4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_,
|
|
122
|
+
-1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_,
|
|
123
|
+
-0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_,
|
|
124
|
+
].map(fromLinear);
|
|
125
|
+
const clipped = linear.some((x) => x < -1e-4 || x > 1 + 1e-4);
|
|
126
|
+
const [r, g, b] = linear.map((x) => clamp(x) * 255);
|
|
127
|
+
return { rgb: { r, g, b }, clipped };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** `oklch(0.511 0.230 276.9)`. */
|
|
131
|
+
export function mimiFormatOklch(hex: string): string {
|
|
132
|
+
const rgb = mimiHexToRgb(hex);
|
|
133
|
+
if (!rgb) return '';
|
|
134
|
+
const { l, c, h } = mimiRgbToOklch(rgb);
|
|
135
|
+
return `oklch(${l.toFixed(3)} ${c.toFixed(3)} ${h.toFixed(1)})`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Lee un color escrito: hex (`#4f46e5`, `#fff`) u `oklch(L C H)` (L en 0–1 o en %). Devuelve el
|
|
140
|
+
* hex y si se recortó a sRGB, o null si no se entiende.
|
|
141
|
+
*/
|
|
142
|
+
export function mimiParseColor(
|
|
143
|
+
text: string | null | undefined,
|
|
144
|
+
): { hex: string; clipped: boolean } | null {
|
|
145
|
+
const hex = mimiNormalizeHex(text);
|
|
146
|
+
if (hex) return { hex, clipped: false };
|
|
147
|
+
const match = /^oklch\(\s*([\d.]+)(%?)\s+([\d.]+)\s+([\d.]+)(?:deg)?\s*\)$/i.exec(
|
|
148
|
+
(text ?? '').trim(),
|
|
149
|
+
);
|
|
150
|
+
if (!match) return null;
|
|
151
|
+
const l = +match[1] / (match[2] ? 100 : 1);
|
|
152
|
+
const c = +match[3];
|
|
153
|
+
const h = +match[4];
|
|
154
|
+
if ([l, c, h].some(Number.isNaN) || l > 1) return null;
|
|
155
|
+
const { rgb, clipped } = mimiOklchToRgb(l, c, h);
|
|
156
|
+
return { hex: mimiRgbToHex(rgb), clipped };
|
|
157
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { InjectionToken, type Provider } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Textos del Combobox, en archivo propio y sin @angular/aria ni @angular/cdk: así se pueden
|
|
5
|
+
* proveer en `app.config.ts` sin llevar el Combobox al chunk inicial. Los de Select no se tocan.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Textos que el Combobox muestra o anuncia. Los que dependen de un dato son funciones. */
|
|
9
|
+
export interface MimiComboboxText {
|
|
10
|
+
/** Fila para crear un valor nuevo: «Crear «Tokio»». */
|
|
11
|
+
create: (text: string) => string;
|
|
12
|
+
/** Título cuando lo escrito no coincide con ninguna opción. */
|
|
13
|
+
noResults: (text: string) => string;
|
|
14
|
+
/** Detalle debajo del título de «sin resultados» (vacío: no se muestra). */
|
|
15
|
+
noResultsHint: string;
|
|
16
|
+
/** Título cuando no hay ninguna opción (sin haber escrito). */
|
|
17
|
+
noOptions: string;
|
|
18
|
+
/** Estado de carga, en el panel. */
|
|
19
|
+
loading: string;
|
|
20
|
+
/** Anuncio con la cantidad de resultados al escribir. */
|
|
21
|
+
results: (count: number) => string;
|
|
22
|
+
/** Ayuda debajo del campo, en el múltiple. */
|
|
23
|
+
help: string;
|
|
24
|
+
/** Chips ocultos con el múltiple cerrado y sin foco: «+2». */
|
|
25
|
+
more: (count: number) => string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Textos predeterminados (inglés). */
|
|
29
|
+
export const MIMI_COMBOBOX_TEXT_EN: MimiComboboxText = {
|
|
30
|
+
create: (text) => `Create “${text}”`,
|
|
31
|
+
noResults: (text) => `No results for “${text}”`,
|
|
32
|
+
noResultsHint: 'Check the spelling or try another search.',
|
|
33
|
+
noOptions: 'No options',
|
|
34
|
+
loading: 'Searching…',
|
|
35
|
+
results: (count) => `${count} ${count === 1 ? 'result' : 'results'}`,
|
|
36
|
+
help: 'Enter adds · Backspace removes the last one',
|
|
37
|
+
more: (count) => `+${count}`,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** Textos en español: `provideMimiComboboxText(MIMI_COMBOBOX_TEXT_ES)`. */
|
|
41
|
+
export const MIMI_COMBOBOX_TEXT_ES: MimiComboboxText = {
|
|
42
|
+
create: (text) => `Crear «${text}»`,
|
|
43
|
+
noResults: (text) => `Sin resultados para «${text}»`,
|
|
44
|
+
noResultsHint: 'Revisa la ortografía o prueba otra búsqueda.',
|
|
45
|
+
noOptions: 'Sin opciones',
|
|
46
|
+
loading: 'Buscando…',
|
|
47
|
+
results: (count) => `${count} ${count === 1 ? 'resultado' : 'resultados'}`,
|
|
48
|
+
help: 'Enter agrega · Backspace quita el último chip',
|
|
49
|
+
more: (count) => `+${count}`,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** Textos activos. Sin `provideMimiComboboxText`, los predeterminados en inglés. */
|
|
53
|
+
export const MIMI_COMBOBOX_TEXT = new InjectionToken<MimiComboboxText>('MIMI_COMBOBOX_TEXT', {
|
|
54
|
+
providedIn: 'root',
|
|
55
|
+
factory: () => MIMI_COMBOBOX_TEXT_EN,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Cambia los textos del Combobox. Lo que no definas sigue en inglés:
|
|
60
|
+
*
|
|
61
|
+
* ```ts
|
|
62
|
+
* provideMimiComboboxText(MIMI_COMBOBOX_TEXT_ES)
|
|
63
|
+
* provideMimiComboboxText({ ...MIMI_COMBOBOX_TEXT_ES, loading: 'Buscando ciudades…' })
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Va en `app.config.ts` o en los `providers` de un componente o ruta.
|
|
67
|
+
*/
|
|
68
|
+
export function provideMimiComboboxText(text: Partial<MimiComboboxText>): Provider {
|
|
69
|
+
return { provide: MIMI_COMBOBOX_TEXT, useValue: { ...MIMI_COMBOBOX_TEXT_EN, ...text } };
|
|
70
|
+
}
|