@lit-roa/tarjeta-producto 0.1.0 → 0.1.1

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 CHANGED
@@ -1,55 +1,55 @@
1
- # @lit-roa/tarjeta-producto
2
-
3
- Tarjeta de producto con imagen, nombre, precio (con precio anterior tachado
4
- si hay descuento) y botón para agregar al carrito.
5
-
6
- ```bash
7
- npm install @lit-roa/tarjeta-producto
8
- ```
9
-
10
- ```ts
11
- import '@lit-roa/tarjeta-producto';
12
- ```
13
-
14
- ```html
15
- <lr-tarjeta-producto
16
- id-producto="cafe-250"
17
- nombre="Café de Chiapas 250 g"
18
- precio="189"
19
- precio-antes="220"
20
- imagen="https://…/cafe.jpg"
21
- href="/productos/cafe-250"
22
- ></lr-tarjeta-producto>
23
- ```
24
-
25
- ## Atributos
26
-
27
- | Atributo | Propiedad | Tipo | Por omisión |
28
- | --- | --- | --- | --- |
29
- | `id-producto` | `idProducto` | `string` | `''` |
30
- | `nombre` | `nombre` | `string` | `''` |
31
- | `precio` | `precio` | `number` | `0` |
32
- | `precio-antes` | `precioAntes` | `number` | — |
33
- | `moneda` | `moneda` | `string` | `'MXN'` |
34
- | `imagen` | `imagen` | `string` | `''` |
35
- | `href` | `href` | `string` | `''` |
36
- | `agotado` | `agotado` | `boolean` | `false` |
37
- | `texto-boton` | `textoBoton` | `string` | `'Agregar al carrito'` |
38
-
39
- ## Eventos
40
-
41
- | Evento | `detail` |
42
- | --- | --- |
43
- | `agregar-al-carrito` | `{ id: string, cantidad: number }` |
44
-
45
- ## Slots
46
-
47
- | Slot | Uso |
48
- | --- | --- |
49
- | `etiqueta` | Contenido sobre la imagen ("Nuevo", "Oferta") |
50
-
51
- ## Desarrollo
52
-
53
- ```bash
54
- npm run dev -w @lit-roa/tarjeta-producto
55
- ```
1
+ # @lit-roa/tarjeta-producto
2
+
3
+ Tarjeta de producto con imagen, nombre, precio (con precio anterior tachado
4
+ si hay descuento) y botón para agregar al carrito.
5
+
6
+ ```bash
7
+ npm install @lit-roa/tarjeta-producto
8
+ ```
9
+
10
+ ```ts
11
+ import '@lit-roa/tarjeta-producto';
12
+ ```
13
+
14
+ ```html
15
+ <lr-tarjeta-producto
16
+ id-producto="cafe-250"
17
+ nombre="Café de Chiapas 250 g"
18
+ precio="189"
19
+ precio-antes="220"
20
+ imagen="https://…/cafe.jpg"
21
+ href="/productos/cafe-250"
22
+ ></lr-tarjeta-producto>
23
+ ```
24
+
25
+ ## Atributos
26
+
27
+ | Atributo | Propiedad | Tipo | Por omisión |
28
+ | --- | --- | --- | --- |
29
+ | `id-producto` | `idProducto` | `string` | `''` |
30
+ | `nombre` | `nombre` | `string` | `''` |
31
+ | `precio` | `precio` | `number` | `0` |
32
+ | `precio-antes` | `precioAntes` | `number` | — |
33
+ | `moneda` | `moneda` | `string` | `'MXN'` |
34
+ | `imagen` | `imagen` | `string` | `''` |
35
+ | `href` | `href` | `string` | `''` |
36
+ | `agotado` | `agotado` | `boolean` | `false` |
37
+ | `texto-boton` | `textoBoton` | `string` | `'Agregar al carrito'` |
38
+
39
+ ## Eventos
40
+
41
+ | Evento | `detail` |
42
+ | --- | --- |
43
+ | `agregar-al-carrito` | `{ id: string, cantidad: number }` |
44
+
45
+ ## Slots
46
+
47
+ | Slot | Uso |
48
+ | --- | --- |
49
+ | `etiqueta` | Contenido sobre la imagen ("Nuevo", "Oferta") |
50
+
51
+ ## Desarrollo
52
+
53
+ ```bash
54
+ npm run dev -w @lit-roa/tarjeta-producto
55
+ ```
@@ -1 +1 @@
1
- {"version":3,"file":"tarjeta-producto.d.ts","sourceRoot":"","sources":["../src/tarjeta-producto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAIrD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IAC/C,OAAgB,MAAM,4BAsFpB;IAEF,gEAAgE;IACxB,UAAU,SAAM;IAE5C,MAAM,SAAM;IAEI,MAAM,SAAK;IAEvC,oEAAoE;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAEhE,MAAM,SAAS;IAEf,MAAM,SAAM;IAExB,sEAAsE;IAC1D,IAAI,SAAM;IAEsB,OAAO,UAAS;IAEpB,UAAU,SAAwB;IAEjE,MAAM;IAyBf,OAAO,CAAC,OAAO;CAGhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,qBAAqB,EAAE,iBAAiB,CAAC;KAC1C;CACF"}
1
+ {"version":3,"file":"tarjeta-producto.d.ts","sourceRoot":"","sources":["../src/tarjeta-producto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAIrD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IAC/C,OAAgB,MAAM,4BAyFpB;IAEF,gEAAgE;IACxB,UAAU,SAAM;IAE5C,MAAM,SAAM;IAEI,MAAM,SAAK;IAEvC,oEAAoE;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAEhE,MAAM,SAAS;IAEf,MAAM,SAAM;IAExB,sEAAsE;IAC1D,IAAI,SAAM;IAEsB,OAAO,UAAS;IAEpB,UAAU,SAAM;IAE/C,MAAM;IAyBf,OAAO,CAAC,OAAO;CAGhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,qBAAqB,EAAE,iBAAiB,CAAC;KAC1C;CACF"}
@@ -25,117 +25,120 @@ let LrTarjetaProducto = class LrTarjetaProducto extends LitElement {
25
25
  /** Liga al detalle del producto; cada sitio arma sus propias URLs. */
26
26
  this.href = '';
27
27
  this.agotado = false;
28
- this.textoBoton = 'Agregar al carrito';
28
+ this.textoBoton = '';
29
29
  }
30
30
  static { this.styles = [
31
31
  tokens,
32
32
  estilosBase,
33
- css `
34
- :host {
35
- display: block;
36
- }
37
- article {
38
- display: flex;
39
- flex-direction: column;
40
- height: 100%;
41
- background: var(--_color-fondo);
42
- border: 1px solid var(--_color-borde);
43
- border-radius: var(--_radio);
44
- box-shadow: var(--_sombra);
45
- overflow: hidden;
46
- }
47
- .imagen {
48
- position: relative;
49
- aspect-ratio: 1;
50
- background: var(--_color-borde);
51
- }
52
- .imagen img {
53
- width: 100%;
54
- height: 100%;
55
- object-fit: cover;
56
- display: block;
57
- }
58
- .imagen ::slotted(*) {
59
- position: absolute;
60
- top: 0.5rem;
61
- left: 0.5rem;
62
- }
63
- .cuerpo {
64
- display: flex;
65
- flex-direction: column;
66
- gap: 0.5rem;
67
- flex: 1;
68
- padding: var(--_espacio);
69
- }
70
- h3 {
71
- margin: 0;
72
- font-size: 1rem;
73
- font-weight: 600;
74
- }
75
- a {
76
- color: inherit;
77
- text-decoration: none;
78
- }
79
- a:hover {
80
- text-decoration: underline;
81
- }
82
- .precios {
83
- display: flex;
84
- align-items: baseline;
85
- gap: 0.5rem;
86
- margin-top: auto;
87
- }
88
- .precio {
89
- font-size: 1.125rem;
90
- font-weight: 700;
91
- }
92
- .antes {
93
- color: var(--_color-texto-suave);
94
- text-decoration: line-through;
95
- font-size: 0.875rem;
96
- }
97
- button {
98
- font: inherit;
99
- font-weight: 600;
100
- padding: 0.625rem 1rem;
101
- border: 0;
102
- border-radius: calc(var(--_radio) / 1.5);
103
- background: var(--_color-primario);
104
- color: var(--_color-sobre-primario);
105
- cursor: pointer;
106
- }
107
- button:disabled {
108
- opacity: 0.5;
109
- cursor: not-allowed;
110
- }
111
- button:focus-visible {
112
- outline: 2px solid var(--_color-primario);
113
- outline-offset: 2px;
114
- }
33
+ css `
34
+ :host {
35
+ display: block;
36
+ }
37
+ article {
38
+ display: flex;
39
+ flex-direction: column;
40
+ height: 100%;
41
+ background: var(--_color-fondo);
42
+ border: 1px solid var(--_color-borde);
43
+ border-radius: var(--_radio);
44
+ box-shadow: var(--_sombra);
45
+ overflow: hidden;
46
+ }
47
+ .imagen {
48
+ position: relative;
49
+ aspect-ratio: 1;
50
+ background: var(--_color-borde);
51
+ }
52
+ .imagen img {
53
+ width: 100%;
54
+ height: 100%;
55
+ object-fit: cover;
56
+ display: block;
57
+ }
58
+ .imagen ::slotted(*) {
59
+ position: absolute;
60
+ top: 0.5rem;
61
+ left: 0.5rem;
62
+ }
63
+ .cuerpo {
64
+ display: flex;
65
+ flex-direction: column;
66
+ gap: 0.5rem;
67
+ flex: 1;
68
+ padding: var(--_espacio);
69
+ }
70
+ h3 {
71
+ margin: 0;
72
+ font-size: 1rem;
73
+ font-weight: 600;
74
+ }
75
+ a {
76
+ color: inherit;
77
+ text-decoration: none;
78
+ }
79
+ a:hover {
80
+ text-decoration: underline;
81
+ }
82
+ .precios {
83
+ display: flex;
84
+ align-items: baseline;
85
+ gap: 0.5rem;
86
+ margin-top: auto;
87
+ }
88
+ .precio {
89
+ font-size: 1.125rem;
90
+ font-weight: 700;
91
+ }
92
+ .antes {
93
+ color: var(--_color-texto-suave);
94
+ text-decoration: line-through;
95
+ font-size: 0.875rem;
96
+ }
97
+ button {
98
+ font: inherit;
99
+ font-weight: 600;
100
+ padding: 0.625rem 1rem;
101
+ border: 0;
102
+ border-radius: calc(var(--_radio) / 1.5);
103
+ background: var(--_color-primario);
104
+ color: var(--_color-sobre-primario);
105
+ cursor: pointer;
106
+ }
107
+ button:disabled {
108
+ opacity: 0.5;
109
+ cursor: not-allowed;
110
+ }
111
+ button:focus-visible {
112
+ outline: 2px solid var(--_color-primario);
113
+ outline-offset: 2px;
114
+ }
115
+ .hidden {
116
+ display: none;
117
+ }
115
118
  `,
116
119
  ]; }
117
120
  render() {
118
121
  const titulo = this.href ? html `<a href=${this.href}>${this.nombre}</a>` : this.nombre;
119
122
  const conDescuento = this.precioAntes !== undefined && this.precioAntes > this.precio;
120
- return html `
121
- <article>
122
- <div class="imagen">
123
- ${this.imagen ? html `<img src=${this.imagen} alt=${this.nombre} loading="lazy" />` : nothing}
124
- <slot name="etiqueta"></slot>
125
- </div>
126
- <div class="cuerpo">
127
- <h3>${titulo}</h3>
128
- <div class="precios">
129
- <span class="precio">${formatearPrecio(this.precio, this.moneda)}</span>
123
+ return html `
124
+ <article>
125
+ <div class="imagen">
126
+ ${this.imagen ? html `<img src=${this.imagen} alt=${this.nombre} loading="lazy" />` : nothing}
127
+ <slot name="etiqueta"></slot>
128
+ </div>
129
+ <div class="cuerpo">
130
+ <h3>${titulo}</h3>
131
+ <div class="precios">
132
+ <span class="precio">${formatearPrecio(this.precio, this.moneda)}</span>
130
133
  ${conDescuento
131
134
  ? html `<span class="antes">${formatearPrecio(this.precioAntes, this.moneda)}</span>`
132
- : nothing}
133
- </div>
134
- <button ?disabled=${this.agotado} @click=${this.agregar}>
135
- ${this.agotado ? 'Agotado' : this.textoBoton}
136
- </button>
137
- </div>
138
- </article>
135
+ : nothing}
136
+ </div>
137
+ <button ?disabled=${this.agotado} @click=${this.agregar} class="${this.textoBoton ? '' : 'hidden'}">
138
+ ${this.agotado ? 'Agotado' : this.textoBoton}
139
+ </button>
140
+ </div>
141
+ </article>
139
142
  `;
140
143
  }
141
144
  agregar() {
@@ -1 +1 @@
1
- {"version":3,"file":"tarjeta-producto.js","sourceRoot":"","sources":["../src/tarjeta-producto.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAO7E;;;;;GAKG;AAEI,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,UAAU;IAA1C;;QAyFL,gEAAgE;QACxB,eAAU,GAAG,EAAE,CAAC;QAE5C,WAAM,GAAG,EAAE,CAAC;QAEI,WAAM,GAAG,CAAC,CAAC;QAK3B,WAAM,GAAG,KAAK,CAAC;QAEf,WAAM,GAAG,EAAE,CAAC;QAExB,sEAAsE;QAC1D,SAAI,GAAG,EAAE,CAAC;QAEsB,YAAO,GAAG,KAAK,CAAC;QAEpB,eAAU,GAAG,oBAAoB,CAAC;IA8B5E,CAAC;aAzIiB,WAAM,GAAG;QACvB,MAAM;QACN,WAAW;QACX,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkFF;KACF,AAtFqB,CAsFpB;IAuBO,MAAM;QACb,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,WAAW,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACvF,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;QACtF,OAAO,IAAI,CAAA;;;YAGH,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA,YAAY,IAAI,CAAC,MAAM,QAAQ,IAAI,CAAC,MAAM,oBAAoB,CAAC,CAAC,CAAC,OAAO;;;;gBAItF,MAAM;;mCAEa,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;cAC9D,YAAY;YACZ,CAAC,CAAC,IAAI,CAAA,uBAAuB,eAAe,CAAC,IAAI,CAAC,WAAY,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YACrF,CAAC,CAAC,OAAO;;8BAEO,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,OAAO;cACnD,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU;;;;KAInD,CAAC;IACJ,CAAC;IAEO,OAAO;QACb,MAAM,CAAiB,IAAI,EAAE,oBAAoB,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;;AA/CuC;IAAvC,QAAQ,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;qDAAiB;AAE5C;IAAX,QAAQ,EAAE;iDAAa;AAEI;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;iDAAY;AAGgB;IAAtD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;sDAAsB;AAEhE;IAAX,QAAQ,EAAE;iDAAgB;AAEf;IAAX,QAAQ,EAAE;iDAAa;AAGZ;IAAX,QAAQ,EAAE;+CAAW;AAEsB;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;kDAAiB;AAEpB;IAAvC,QAAQ,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;qDAAmC;AA5G/D,iBAAiB;IAD7B,aAAa,CAAC,qBAAqB,CAAC;GACxB,iBAAiB,CA0I7B"}
1
+ {"version":3,"file":"tarjeta-producto.js","sourceRoot":"","sources":["../src/tarjeta-producto.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,30 +1,30 @@
1
- {
2
- "name": "@lit-roa/tarjeta-producto",
3
- "version": "0.1.0",
4
- "description": "Tarjeta de producto con imagen, nombre, precio y botón para agregar al carrito.",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "default": "./dist/index.js"
12
- }
13
- },
14
- "files": [
15
- "dist",
16
- "src"
17
- ],
18
- "sideEffects": [
19
- "./dist/index.js"
20
- ],
21
- "scripts": {
22
- "dev": "vite",
23
- "build": "tsc -b"
24
- },
25
- "dependencies": {
26
- "@lit-roa/base": "^0.1.0",
27
- "lit": "^3.3.3"
28
- },
29
- "license": "MIT"
30
- }
1
+ {
2
+ "name": "@lit-roa/tarjeta-producto",
3
+ "version": "0.1.1",
4
+ "description": "Tarjeta de producto con imagen, nombre, precio y botón para agregar al carrito.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src"
17
+ ],
18
+ "sideEffects": [
19
+ "./dist/index.js"
20
+ ],
21
+ "scripts": {
22
+ "dev": "vite",
23
+ "build": "tsc -b"
24
+ },
25
+ "dependencies": {
26
+ "@lit-roa/base": "^0.1.0",
27
+ "lit": "^3.3.3"
28
+ },
29
+ "license": "MIT"
30
+ }
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export { LrTarjetaProducto, type DetalleAgregar } from './tarjeta-producto.js';
1
+ export { LrTarjetaProducto, type DetalleAgregar } from './tarjeta-producto.js';
@@ -1,161 +1,164 @@
1
- import { LitElement, css, html, nothing } from 'lit';
2
- import { customElement, property } from 'lit/decorators.js';
3
- import { emitir, estilosBase, formatearPrecio, tokens } from '@lit-roa/base';
4
-
5
- export interface DetalleAgregar {
6
- id: string;
7
- cantidad: number;
8
- }
9
-
10
- /**
11
- * Tarjeta de producto.
12
- *
13
- * @fires agregar-al-carrito - Al tocar el botón. `detail`: `{ id, cantidad }`.
14
- * @slot etiqueta - Contenido sobre la imagen, por ejemplo "Nuevo" u "Oferta".
15
- */
16
- @customElement('lr-tarjeta-producto')
17
- export class LrTarjetaProducto extends LitElement {
18
- static override styles = [
19
- tokens,
20
- estilosBase,
21
- css`
22
- :host {
23
- display: block;
24
- }
25
- article {
26
- display: flex;
27
- flex-direction: column;
28
- height: 100%;
29
- background: var(--_color-fondo);
30
- border: 1px solid var(--_color-borde);
31
- border-radius: var(--_radio);
32
- box-shadow: var(--_sombra);
33
- overflow: hidden;
34
- }
35
- .imagen {
36
- position: relative;
37
- aspect-ratio: 1;
38
- background: var(--_color-borde);
39
- }
40
- .imagen img {
41
- width: 100%;
42
- height: 100%;
43
- object-fit: cover;
44
- display: block;
45
- }
46
- .imagen ::slotted(*) {
47
- position: absolute;
48
- top: 0.5rem;
49
- left: 0.5rem;
50
- }
51
- .cuerpo {
52
- display: flex;
53
- flex-direction: column;
54
- gap: 0.5rem;
55
- flex: 1;
56
- padding: var(--_espacio);
57
- }
58
- h3 {
59
- margin: 0;
60
- font-size: 1rem;
61
- font-weight: 600;
62
- }
63
- a {
64
- color: inherit;
65
- text-decoration: none;
66
- }
67
- a:hover {
68
- text-decoration: underline;
69
- }
70
- .precios {
71
- display: flex;
72
- align-items: baseline;
73
- gap: 0.5rem;
74
- margin-top: auto;
75
- }
76
- .precio {
77
- font-size: 1.125rem;
78
- font-weight: 700;
79
- }
80
- .antes {
81
- color: var(--_color-texto-suave);
82
- text-decoration: line-through;
83
- font-size: 0.875rem;
84
- }
85
- button {
86
- font: inherit;
87
- font-weight: 600;
88
- padding: 0.625rem 1rem;
89
- border: 0;
90
- border-radius: calc(var(--_radio) / 1.5);
91
- background: var(--_color-primario);
92
- color: var(--_color-sobre-primario);
93
- cursor: pointer;
94
- }
95
- button:disabled {
96
- opacity: 0.5;
97
- cursor: not-allowed;
98
- }
99
- button:focus-visible {
100
- outline: 2px solid var(--_color-primario);
101
- outline-offset: 2px;
102
- }
103
- `,
104
- ];
105
-
106
- /** Id del producto; viaja en el evento `agregar-al-carrito`. */
107
- @property({ attribute: 'id-producto' }) idProducto = '';
108
-
109
- @property() nombre = '';
110
-
111
- @property({ type: Number }) precio = 0;
112
-
113
- /** Precio anterior; si es mayor que `precio` se muestra tachado. */
114
- @property({ type: Number, attribute: 'precio-antes' }) precioAntes?: number;
115
-
116
- @property() moneda = 'MXN';
117
-
118
- @property() imagen = '';
119
-
120
- /** Liga al detalle del producto; cada sitio arma sus propias URLs. */
121
- @property() href = '';
122
-
123
- @property({ type: Boolean, reflect: true }) agotado = false;
124
-
125
- @property({ attribute: 'texto-boton' }) textoBoton = 'Agregar al carrito';
126
-
127
- override render() {
128
- const titulo = this.href ? html`<a href=${this.href}>${this.nombre}</a>` : this.nombre;
129
- const conDescuento = this.precioAntes !== undefined && this.precioAntes > this.precio;
130
- return html`
131
- <article>
132
- <div class="imagen">
133
- ${this.imagen ? html`<img src=${this.imagen} alt=${this.nombre} loading="lazy" />` : nothing}
134
- <slot name="etiqueta"></slot>
135
- </div>
136
- <div class="cuerpo">
137
- <h3>${titulo}</h3>
138
- <div class="precios">
139
- <span class="precio">${formatearPrecio(this.precio, this.moneda)}</span>
140
- ${conDescuento
141
- ? html`<span class="antes">${formatearPrecio(this.precioAntes!, this.moneda)}</span>`
142
- : nothing}
143
- </div>
144
- <button ?disabled=${this.agotado} @click=${this.agregar}>
145
- ${this.agotado ? 'Agotado' : this.textoBoton}
146
- </button>
147
- </div>
148
- </article>
149
- `;
150
- }
151
-
152
- private agregar() {
153
- emitir<DetalleAgregar>(this, 'agregar-al-carrito', { id: this.idProducto, cantidad: 1 });
154
- }
155
- }
156
-
157
- declare global {
158
- interface HTMLElementTagNameMap {
159
- 'lr-tarjeta-producto': LrTarjetaProducto;
160
- }
161
- }
1
+ import { LitElement, css, html, nothing } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+ import { emitir, estilosBase, formatearPrecio, tokens } from '@lit-roa/base';
4
+
5
+ export interface DetalleAgregar {
6
+ id: string;
7
+ cantidad: number;
8
+ }
9
+
10
+ /**
11
+ * Tarjeta de producto.
12
+ *
13
+ * @fires agregar-al-carrito - Al tocar el botón. `detail`: `{ id, cantidad }`.
14
+ * @slot etiqueta - Contenido sobre la imagen, por ejemplo "Nuevo" u "Oferta".
15
+ */
16
+ @customElement('lr-tarjeta-producto')
17
+ export class LrTarjetaProducto extends LitElement {
18
+ static override styles = [
19
+ tokens,
20
+ estilosBase,
21
+ css`
22
+ :host {
23
+ display: block;
24
+ }
25
+ article {
26
+ display: flex;
27
+ flex-direction: column;
28
+ height: 100%;
29
+ background: var(--_color-fondo);
30
+ border: 1px solid var(--_color-borde);
31
+ border-radius: var(--_radio);
32
+ box-shadow: var(--_sombra);
33
+ overflow: hidden;
34
+ }
35
+ .imagen {
36
+ position: relative;
37
+ aspect-ratio: 1;
38
+ background: var(--_color-borde);
39
+ }
40
+ .imagen img {
41
+ width: 100%;
42
+ height: 100%;
43
+ object-fit: cover;
44
+ display: block;
45
+ }
46
+ .imagen ::slotted(*) {
47
+ position: absolute;
48
+ top: 0.5rem;
49
+ left: 0.5rem;
50
+ }
51
+ .cuerpo {
52
+ display: flex;
53
+ flex-direction: column;
54
+ gap: 0.5rem;
55
+ flex: 1;
56
+ padding: var(--_espacio);
57
+ }
58
+ h3 {
59
+ margin: 0;
60
+ font-size: 1rem;
61
+ font-weight: 600;
62
+ }
63
+ a {
64
+ color: inherit;
65
+ text-decoration: none;
66
+ }
67
+ a:hover {
68
+ text-decoration: underline;
69
+ }
70
+ .precios {
71
+ display: flex;
72
+ align-items: baseline;
73
+ gap: 0.5rem;
74
+ margin-top: auto;
75
+ }
76
+ .precio {
77
+ font-size: 1.125rem;
78
+ font-weight: 700;
79
+ }
80
+ .antes {
81
+ color: var(--_color-texto-suave);
82
+ text-decoration: line-through;
83
+ font-size: 0.875rem;
84
+ }
85
+ button {
86
+ font: inherit;
87
+ font-weight: 600;
88
+ padding: 0.625rem 1rem;
89
+ border: 0;
90
+ border-radius: calc(var(--_radio) / 1.5);
91
+ background: var(--_color-primario);
92
+ color: var(--_color-sobre-primario);
93
+ cursor: pointer;
94
+ }
95
+ button:disabled {
96
+ opacity: 0.5;
97
+ cursor: not-allowed;
98
+ }
99
+ button:focus-visible {
100
+ outline: 2px solid var(--_color-primario);
101
+ outline-offset: 2px;
102
+ }
103
+ .hidden {
104
+ display: none;
105
+ }
106
+ `,
107
+ ];
108
+
109
+ /** Id del producto; viaja en el evento `agregar-al-carrito`. */
110
+ @property({ attribute: 'id-producto' }) idProducto = '';
111
+
112
+ @property() nombre = '';
113
+
114
+ @property({ type: Number }) precio = 0;
115
+
116
+ /** Precio anterior; si es mayor que `precio` se muestra tachado. */
117
+ @property({ type: Number, attribute: 'precio-antes' }) precioAntes?: number;
118
+
119
+ @property() moneda = 'MXN';
120
+
121
+ @property() imagen = '';
122
+
123
+ /** Liga al detalle del producto; cada sitio arma sus propias URLs. */
124
+ @property() href = '';
125
+
126
+ @property({ type: Boolean, reflect: true }) agotado = false;
127
+
128
+ @property({ attribute: 'texto-boton' }) textoBoton = '';
129
+
130
+ override render() {
131
+ const titulo = this.href ? html`<a href=${this.href}>${this.nombre}</a>` : this.nombre;
132
+ const conDescuento = this.precioAntes !== undefined && this.precioAntes > this.precio;
133
+ return html`
134
+ <article>
135
+ <div class="imagen">
136
+ ${this.imagen ? html`<img src=${this.imagen} alt=${this.nombre} loading="lazy" />` : nothing}
137
+ <slot name="etiqueta"></slot>
138
+ </div>
139
+ <div class="cuerpo">
140
+ <h3>${titulo}</h3>
141
+ <div class="precios">
142
+ <span class="precio">${formatearPrecio(this.precio, this.moneda)}</span>
143
+ ${conDescuento
144
+ ? html`<span class="antes">${formatearPrecio(this.precioAntes!, this.moneda)}</span>`
145
+ : nothing}
146
+ </div>
147
+ <button ?disabled=${this.agotado} @click=${this.agregar} class="${this.textoBoton ? '' : 'hidden'}">
148
+ ${this.agotado ? 'Agotado' : this.textoBoton}
149
+ </button>
150
+ </div>
151
+ </article>
152
+ `;
153
+ }
154
+
155
+ private agregar() {
156
+ emitir<DetalleAgregar>(this, 'agregar-al-carrito', { id: this.idProducto, cantidad: 1 });
157
+ }
158
+ }
159
+
160
+ declare global {
161
+ interface HTMLElementTagNameMap {
162
+ 'lr-tarjeta-producto': LrTarjetaProducto;
163
+ }
164
+ }