@r2digisolutions/components 0.19.2 → 0.19.4
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.
|
@@ -16,11 +16,20 @@
|
|
|
16
16
|
priceLabel: string;
|
|
17
17
|
categoryLabel?: string;
|
|
18
18
|
installed?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Estado legible en el listado (p. ej. «Activo», «En licencia», «No incluido»).
|
|
21
|
+
* Si no se pasa y `installed`, se usa «Activo».
|
|
22
|
+
*/
|
|
23
|
+
statusLabel?: string;
|
|
19
24
|
/** landscape promotional card */
|
|
20
25
|
featured?: boolean;
|
|
26
|
+
/** Compact row for list view (ignored when featured). */
|
|
27
|
+
layout?: 'grid' | 'list';
|
|
21
28
|
tags?: StoreProductTag[];
|
|
22
29
|
icon: Component;
|
|
23
30
|
accentClass?: string;
|
|
31
|
+
/** Prefer link navigation when set (store detail URLs). */
|
|
32
|
+
href?: string;
|
|
24
33
|
onclick?: () => void;
|
|
25
34
|
/** Optional custom badge area */
|
|
26
35
|
badge?: Snippet;
|
|
@@ -32,10 +41,13 @@
|
|
|
32
41
|
priceLabel,
|
|
33
42
|
categoryLabel = '',
|
|
34
43
|
installed = false,
|
|
44
|
+
statusLabel = '',
|
|
35
45
|
featured = false,
|
|
46
|
+
layout = 'grid',
|
|
36
47
|
tags = [],
|
|
37
48
|
icon: Icon,
|
|
38
49
|
accentClass = 'from-neutral-800 to-neutral-600',
|
|
50
|
+
href = '',
|
|
39
51
|
onclick,
|
|
40
52
|
badge
|
|
41
53
|
}: Props = $props();
|
|
@@ -51,9 +63,25 @@
|
|
|
51
63
|
TAG_PRIORITY.filter((t) => visibleTags.includes(t)).slice(0, installed ? 1 : 2)
|
|
52
64
|
);
|
|
53
65
|
|
|
66
|
+
const resolvedStatus = $derived(
|
|
67
|
+
statusLabel.trim() || (installed ? 'Activo' : '')
|
|
68
|
+
);
|
|
69
|
+
const statusToneOk = $derived(
|
|
70
|
+
installed || resolvedStatus === 'Activo' || resolvedStatus === 'Instalado'
|
|
71
|
+
);
|
|
72
|
+
const isList = $derived(!featured && layout === 'list');
|
|
73
|
+
const rootClass = $derived(
|
|
74
|
+
[
|
|
75
|
+
'group ms-tile',
|
|
76
|
+
featured && 'ms-tile--featured',
|
|
77
|
+
isList && 'ms-tile--list'
|
|
78
|
+
]
|
|
79
|
+
.filter(Boolean)
|
|
80
|
+
.join(' ')
|
|
81
|
+
);
|
|
82
|
+
|
|
54
83
|
function tagVariant(tag: StoreProductTag): 'info' | 'warning' | 'default' {
|
|
55
84
|
if (tag === 'new') return 'info';
|
|
56
|
-
// Featured uses custom amber + white via tagClass (avoid warning’s amber text).
|
|
57
85
|
if (tag === 'featured') return 'default';
|
|
58
86
|
return 'default';
|
|
59
87
|
}
|
|
@@ -67,18 +95,19 @@
|
|
|
67
95
|
}
|
|
68
96
|
return '';
|
|
69
97
|
}
|
|
98
|
+
|
|
99
|
+
function onActivate(e: MouseEvent) {
|
|
100
|
+
if (href) return;
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
onclick?.();
|
|
103
|
+
}
|
|
70
104
|
</script>
|
|
71
105
|
|
|
72
|
-
|
|
73
|
-
type="button"
|
|
74
|
-
class="group ms-tile"
|
|
75
|
-
class:ms-tile--featured={featured}
|
|
76
|
-
{onclick}
|
|
77
|
-
>
|
|
106
|
+
{#snippet body()}
|
|
78
107
|
{#if featured}
|
|
79
108
|
<div class="ms-tile__promo bg-gradient-to-br {accentClass}">
|
|
80
109
|
<div class="ms-tile__promo-mesh" aria-hidden="true"></div>
|
|
81
|
-
{#if displayTags.length ||
|
|
110
|
+
{#if displayTags.length || resolvedStatus || badge}
|
|
82
111
|
<div class="ms-tile__tags">
|
|
83
112
|
{#if badge}
|
|
84
113
|
{@render badge()}
|
|
@@ -88,8 +117,10 @@
|
|
|
88
117
|
{TAG_LABELS[tag]}
|
|
89
118
|
</Badge>
|
|
90
119
|
{/each}
|
|
91
|
-
{#if
|
|
92
|
-
<Badge variant=
|
|
120
|
+
{#if resolvedStatus}
|
|
121
|
+
<Badge variant={statusToneOk ? 'success' : 'secondary'} size="sm">
|
|
122
|
+
{resolvedStatus}
|
|
123
|
+
</Badge>
|
|
93
124
|
{/if}
|
|
94
125
|
{/if}
|
|
95
126
|
</div>
|
|
@@ -102,19 +133,64 @@
|
|
|
102
133
|
{#if description}
|
|
103
134
|
<span class="ms-tile__promo-desc">{description}</span>
|
|
104
135
|
{/if}
|
|
105
|
-
<span class="ms-tile__promo-price">
|
|
136
|
+
<span class="ms-tile__promo-price">
|
|
137
|
+
{#if resolvedStatus && statusToneOk}
|
|
138
|
+
{resolvedStatus}
|
|
139
|
+
<span class="ms-tile__promo-sep" aria-hidden="true">·</span>
|
|
140
|
+
{/if}
|
|
141
|
+
{priceLabel}
|
|
142
|
+
</span>
|
|
106
143
|
</div>
|
|
107
144
|
<div class="ms-tile__promo-icon bg-gradient-to-br {accentClass}">
|
|
108
145
|
<Icon class="size-10 text-white drop-shadow" />
|
|
109
146
|
</div>
|
|
110
147
|
</div>
|
|
148
|
+
{:else if isList}
|
|
149
|
+
<div class="ms-tile__list-icon bg-gradient-to-br {accentClass}">
|
|
150
|
+
<div class="ms-tile__icon-shine" aria-hidden="true"></div>
|
|
151
|
+
<Icon class="relative size-7 text-white drop-shadow-sm" />
|
|
152
|
+
</div>
|
|
153
|
+
<div class="ms-tile__list-body">
|
|
154
|
+
<div class="ms-tile__list-top">
|
|
155
|
+
<span class="ms-tile__name">{name}</span>
|
|
156
|
+
{#if resolvedStatus}
|
|
157
|
+
<Badge variant={statusToneOk ? 'success' : 'secondary'} size="sm">
|
|
158
|
+
{resolvedStatus}
|
|
159
|
+
</Badge>
|
|
160
|
+
{:else if displayTags[0]}
|
|
161
|
+
<Badge
|
|
162
|
+
variant={tagVariant(displayTags[0])}
|
|
163
|
+
size="sm"
|
|
164
|
+
class={tagClass(displayTags[0])}
|
|
165
|
+
>
|
|
166
|
+
{TAG_LABELS[displayTags[0]]}
|
|
167
|
+
</Badge>
|
|
168
|
+
{/if}
|
|
169
|
+
</div>
|
|
170
|
+
{#if description}
|
|
171
|
+
<span class="ms-tile__list-desc">{description}</span>
|
|
172
|
+
{/if}
|
|
173
|
+
<div class="ms-tile__list-meta">
|
|
174
|
+
{#if categoryLabel}
|
|
175
|
+
<span>{categoryLabel}</span>
|
|
176
|
+
<span aria-hidden="true">·</span>
|
|
177
|
+
{/if}
|
|
178
|
+
<span class="ms-tile__price">{priceLabel}</span>
|
|
179
|
+
<span aria-hidden="true">·</span>
|
|
180
|
+
<span class="ms-tile__publisher">Evoteg</span>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
111
183
|
{:else}
|
|
112
184
|
<div class="ms-tile__icon-shell">
|
|
113
185
|
<div class="ms-tile__icon bg-gradient-to-br {accentClass}">
|
|
114
186
|
<div class="ms-tile__icon-shine" aria-hidden="true"></div>
|
|
115
187
|
<Icon class="relative size-9 text-white drop-shadow-sm sm:size-10" />
|
|
116
188
|
</div>
|
|
117
|
-
{#if
|
|
189
|
+
{#if statusToneOk}
|
|
190
|
+
<span class="ms-tile__corner">
|
|
191
|
+
<Badge variant="success" size="sm">{resolvedStatus || 'Activo'}</Badge>
|
|
192
|
+
</span>
|
|
193
|
+
{:else if displayTags[0]}
|
|
118
194
|
<span class="ms-tile__corner">
|
|
119
195
|
<Badge
|
|
120
196
|
variant={tagVariant(displayTags[0])}
|
|
@@ -124,17 +200,37 @@
|
|
|
124
200
|
{TAG_LABELS[displayTags[0]]}
|
|
125
201
|
</Badge>
|
|
126
202
|
</span>
|
|
127
|
-
{:else if
|
|
128
|
-
<span class="ms-
|
|
203
|
+
{:else if resolvedStatus}
|
|
204
|
+
<span class="ms-tile__corner">
|
|
205
|
+
<Badge variant="secondary" size="sm">{resolvedStatus}</Badge>
|
|
206
|
+
</span>
|
|
129
207
|
{/if}
|
|
130
208
|
</div>
|
|
131
209
|
<div class="ms-tile__meta">
|
|
132
210
|
<span class="ms-tile__name">{name}</span>
|
|
133
211
|
<span class="ms-tile__publisher">Evoteg</span>
|
|
212
|
+
{#if resolvedStatus}
|
|
213
|
+
<span
|
|
214
|
+
class="ms-tile__status"
|
|
215
|
+
class:ms-tile__status--ok={statusToneOk}
|
|
216
|
+
>
|
|
217
|
+
{resolvedStatus}
|
|
218
|
+
</span>
|
|
219
|
+
{/if}
|
|
134
220
|
<span class="ms-tile__price">{priceLabel}</span>
|
|
135
221
|
</div>
|
|
136
222
|
{/if}
|
|
137
|
-
|
|
223
|
+
{/snippet}
|
|
224
|
+
|
|
225
|
+
{#if href}
|
|
226
|
+
<a class={rootClass} {href} data-sveltekit-preload-data="hover">
|
|
227
|
+
{@render body()}
|
|
228
|
+
</a>
|
|
229
|
+
{:else}
|
|
230
|
+
<button type="button" class={rootClass} onclick={onActivate}>
|
|
231
|
+
{@render body()}
|
|
232
|
+
</button>
|
|
233
|
+
{/if}
|
|
138
234
|
|
|
139
235
|
<style>
|
|
140
236
|
.ms-tile {
|
|
@@ -149,6 +245,8 @@
|
|
|
149
245
|
padding: 0;
|
|
150
246
|
cursor: pointer;
|
|
151
247
|
border-radius: 1rem;
|
|
248
|
+
text-decoration: none;
|
|
249
|
+
color: inherit;
|
|
152
250
|
transition:
|
|
153
251
|
transform 200ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
154
252
|
filter 200ms ease;
|
|
@@ -160,6 +258,71 @@
|
|
|
160
258
|
outline: 2px solid var(--color-brand-500, #2563eb);
|
|
161
259
|
outline-offset: 4px;
|
|
162
260
|
}
|
|
261
|
+
.ms-tile--list {
|
|
262
|
+
flex-direction: row;
|
|
263
|
+
align-items: center;
|
|
264
|
+
gap: 0.9rem;
|
|
265
|
+
padding: 0.75rem 0.85rem;
|
|
266
|
+
border-radius: 1rem;
|
|
267
|
+
background: rgb(255 255 255 / 0.78);
|
|
268
|
+
border: 1px solid rgb(0 0 0 / 0.06);
|
|
269
|
+
box-shadow: 0 6px 18px rgb(0 0 0 / 0.04);
|
|
270
|
+
}
|
|
271
|
+
.ms-tile--list:hover {
|
|
272
|
+
transform: translateY(-1px);
|
|
273
|
+
border-color: rgb(0 0 0 / 0.1);
|
|
274
|
+
}
|
|
275
|
+
:global(.dark) .ms-tile--list {
|
|
276
|
+
background: rgb(23 23 23 / 0.88);
|
|
277
|
+
border-color: rgb(255 255 255 / 0.06);
|
|
278
|
+
}
|
|
279
|
+
.ms-tile__list-icon {
|
|
280
|
+
position: relative;
|
|
281
|
+
display: grid;
|
|
282
|
+
place-items: center;
|
|
283
|
+
width: 3.25rem;
|
|
284
|
+
height: 3.25rem;
|
|
285
|
+
border-radius: 22%;
|
|
286
|
+
flex-shrink: 0;
|
|
287
|
+
overflow: hidden;
|
|
288
|
+
box-shadow:
|
|
289
|
+
0 8px 18px rgb(0 0 0 / 0.2),
|
|
290
|
+
0 1px 0 rgb(255 255 255 / 0.2) inset;
|
|
291
|
+
}
|
|
292
|
+
.ms-tile__list-body {
|
|
293
|
+
min-width: 0;
|
|
294
|
+
flex: 1;
|
|
295
|
+
display: flex;
|
|
296
|
+
flex-direction: column;
|
|
297
|
+
gap: 0.2rem;
|
|
298
|
+
}
|
|
299
|
+
.ms-tile__list-top {
|
|
300
|
+
display: flex;
|
|
301
|
+
align-items: center;
|
|
302
|
+
justify-content: space-between;
|
|
303
|
+
gap: 0.75rem;
|
|
304
|
+
}
|
|
305
|
+
.ms-tile__list-desc {
|
|
306
|
+
font-size: 0.8rem;
|
|
307
|
+
line-height: 1.35;
|
|
308
|
+
color: var(--color-neutral-600, #525252);
|
|
309
|
+
display: -webkit-box;
|
|
310
|
+
-webkit-line-clamp: 1;
|
|
311
|
+
line-clamp: 1;
|
|
312
|
+
-webkit-box-orient: vertical;
|
|
313
|
+
overflow: hidden;
|
|
314
|
+
}
|
|
315
|
+
:global(.dark) .ms-tile__list-desc {
|
|
316
|
+
color: var(--color-neutral-400, #a3a3a3);
|
|
317
|
+
}
|
|
318
|
+
.ms-tile__list-meta {
|
|
319
|
+
display: flex;
|
|
320
|
+
flex-wrap: wrap;
|
|
321
|
+
align-items: center;
|
|
322
|
+
gap: 0.35rem;
|
|
323
|
+
font-size: 0.75rem;
|
|
324
|
+
color: var(--color-neutral-500, #737373);
|
|
325
|
+
}
|
|
163
326
|
.ms-tile__icon-shell {
|
|
164
327
|
position: relative;
|
|
165
328
|
width: 100%;
|
|
@@ -208,19 +371,6 @@
|
|
|
208
371
|
left: 0.45rem;
|
|
209
372
|
z-index: 2;
|
|
210
373
|
}
|
|
211
|
-
.ms-tile__dot {
|
|
212
|
-
position: absolute;
|
|
213
|
-
top: 0.55rem;
|
|
214
|
-
right: 0.55rem;
|
|
215
|
-
width: 0.55rem;
|
|
216
|
-
height: 0.55rem;
|
|
217
|
-
border-radius: 999px;
|
|
218
|
-
background: #16a34a;
|
|
219
|
-
box-shadow: 0 0 0 3px rgb(255 255 255 / 0.9);
|
|
220
|
-
}
|
|
221
|
-
:global(.dark) .ms-tile__dot {
|
|
222
|
-
box-shadow: 0 0 0 3px rgb(28 28 28);
|
|
223
|
-
}
|
|
224
374
|
.ms-tile__meta {
|
|
225
375
|
display: flex;
|
|
226
376
|
flex-direction: column;
|
|
@@ -240,13 +390,27 @@
|
|
|
240
390
|
color: var(--color-neutral-50, #fafafa);
|
|
241
391
|
}
|
|
242
392
|
.ms-tile__publisher,
|
|
243
|
-
.ms-tile__price
|
|
393
|
+
.ms-tile__price,
|
|
394
|
+
.ms-tile__status {
|
|
244
395
|
color: var(--color-neutral-500, #737373);
|
|
245
396
|
font-size: 0.75rem;
|
|
246
397
|
overflow: hidden;
|
|
247
398
|
text-overflow: ellipsis;
|
|
248
399
|
white-space: nowrap;
|
|
249
400
|
}
|
|
401
|
+
.ms-tile__status {
|
|
402
|
+
font-weight: 600;
|
|
403
|
+
color: var(--color-neutral-600, #525252);
|
|
404
|
+
}
|
|
405
|
+
.ms-tile__status--ok {
|
|
406
|
+
color: #15803d;
|
|
407
|
+
}
|
|
408
|
+
:global(.dark) .ms-tile__status {
|
|
409
|
+
color: var(--color-neutral-400, #a3a3a3);
|
|
410
|
+
}
|
|
411
|
+
:global(.dark) .ms-tile__status--ok {
|
|
412
|
+
color: #4ade80;
|
|
413
|
+
}
|
|
250
414
|
.ms-tile__price {
|
|
251
415
|
font-weight: 550;
|
|
252
416
|
color: var(--color-neutral-700, #404040);
|
|
@@ -254,6 +418,10 @@
|
|
|
254
418
|
:global(.dark) .ms-tile__price {
|
|
255
419
|
color: var(--color-neutral-300, #d4d4d4);
|
|
256
420
|
}
|
|
421
|
+
.ms-tile__promo-sep {
|
|
422
|
+
margin-inline: 0.25rem;
|
|
423
|
+
opacity: 0.65;
|
|
424
|
+
}
|
|
257
425
|
|
|
258
426
|
.ms-tile--featured {
|
|
259
427
|
height: 100%;
|
|
@@ -6,11 +6,20 @@ type Props = {
|
|
|
6
6
|
priceLabel: string;
|
|
7
7
|
categoryLabel?: string;
|
|
8
8
|
installed?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Estado legible en el listado (p. ej. «Activo», «En licencia», «No incluido»).
|
|
11
|
+
* Si no se pasa y `installed`, se usa «Activo».
|
|
12
|
+
*/
|
|
13
|
+
statusLabel?: string;
|
|
9
14
|
/** landscape promotional card */
|
|
10
15
|
featured?: boolean;
|
|
16
|
+
/** Compact row for list view (ignored when featured). */
|
|
17
|
+
layout?: 'grid' | 'list';
|
|
11
18
|
tags?: StoreProductTag[];
|
|
12
19
|
icon: Component;
|
|
13
20
|
accentClass?: string;
|
|
21
|
+
/** Prefer link navigation when set (store detail URLs). */
|
|
22
|
+
href?: string;
|
|
14
23
|
onclick?: () => void;
|
|
15
24
|
/** Optional custom badge area */
|
|
16
25
|
badge?: Snippet;
|