@proyecto-viviana/ui 0.1.1 → 0.1.3
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/dist/index.d.ts +649 -51
- package/dist/index.js +232 -185
- package/dist/index.jsx +1533 -0
- package/package.json +9 -7
- package/dist/alert/index.d.ts +0 -12
- package/dist/alert/index.d.ts.map +0 -1
- package/dist/avatar/index.d.ts +0 -17
- package/dist/avatar/index.d.ts.map +0 -1
- package/dist/badge/index.d.ts +0 -12
- package/dist/badge/index.d.ts.map +0 -1
- package/dist/button/Button.d.ts +0 -19
- package/dist/button/Button.d.ts.map +0 -1
- package/dist/button/index.d.ts +0 -3
- package/dist/button/index.d.ts.map +0 -1
- package/dist/button/types.d.ts +0 -23
- package/dist/button/types.d.ts.map +0 -1
- package/dist/checkbox/index.d.ts +0 -43
- package/dist/checkbox/index.d.ts.map +0 -1
- package/dist/custom/calendar-card/index.d.ts +0 -12
- package/dist/custom/calendar-card/index.d.ts.map +0 -1
- package/dist/custom/chip/index.d.ts +0 -11
- package/dist/custom/chip/index.d.ts.map +0 -1
- package/dist/custom/conversation/index.d.ts +0 -32
- package/dist/custom/conversation/index.d.ts.map +0 -1
- package/dist/custom/event-card/index.d.ts +0 -26
- package/dist/custom/event-card/index.d.ts.map +0 -1
- package/dist/custom/lateral-nav/index.d.ts +0 -32
- package/dist/custom/lateral-nav/index.d.ts.map +0 -1
- package/dist/custom/logo/index.d.ts +0 -26
- package/dist/custom/logo/index.d.ts.map +0 -1
- package/dist/custom/nav-header/index.d.ts +0 -12
- package/dist/custom/nav-header/index.d.ts.map +0 -1
- package/dist/custom/page-layout/index.d.ts +0 -11
- package/dist/custom/page-layout/index.d.ts.map +0 -1
- package/dist/custom/profile-card/index.d.ts +0 -12
- package/dist/custom/profile-card/index.d.ts.map +0 -1
- package/dist/custom/project-card/index.d.ts +0 -24
- package/dist/custom/project-card/index.d.ts.map +0 -1
- package/dist/custom/timeline-item/index.d.ts +0 -18
- package/dist/custom/timeline-item/index.d.ts.map +0 -1
- package/dist/dialog/index.d.ts +0 -18
- package/dist/dialog/index.d.ts.map +0 -1
- package/dist/icon/icons/GitHubIcon.d.ts +0 -7
- package/dist/icon/icons/GitHubIcon.d.ts.map +0 -1
- package/dist/icon/index.d.ts +0 -28
- package/dist/icon/index.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/link/index.d.ts +0 -39
- package/dist/link/index.d.ts.map +0 -1
- package/dist/progress-bar/index.d.ts +0 -49
- package/dist/progress-bar/index.d.ts.map +0 -1
- package/dist/radio/index.d.ts +0 -43
- package/dist/radio/index.d.ts.map +0 -1
- package/dist/separator/index.d.ts +0 -42
- package/dist/separator/index.d.ts.map +0 -1
- package/dist/switch/ToggleSwitch.d.ts +0 -28
- package/dist/switch/ToggleSwitch.d.ts.map +0 -1
- package/dist/switch/index.d.ts +0 -26
- package/dist/switch/index.d.ts.map +0 -1
- package/dist/test-utils/index.d.ts +0 -44
- package/dist/test-utils/index.d.ts.map +0 -1
- package/dist/textfield/index.d.ts +0 -31
- package/dist/textfield/index.d.ts.map +0 -1
- package/dist/tooltip/index.d.ts +0 -17
- package/dist/tooltip/index.d.ts.map +0 -1
package/dist/index.jsx
ADDED
|
@@ -0,0 +1,1533 @@
|
|
|
1
|
+
// src/button/Button.tsx
|
|
2
|
+
import { splitProps, mergeProps as solidMergeProps } from "solid-js";
|
|
3
|
+
import { Button as HeadlessButton } from "@proyecto-viviana/solidaria-components";
|
|
4
|
+
function Button(props) {
|
|
5
|
+
const defaultProps = {
|
|
6
|
+
variant: "primary",
|
|
7
|
+
buttonStyle: "fill",
|
|
8
|
+
size: "md"
|
|
9
|
+
};
|
|
10
|
+
const merged = solidMergeProps(defaultProps, props);
|
|
11
|
+
const [local, headlessProps] = splitProps(merged, [
|
|
12
|
+
"children",
|
|
13
|
+
"variant",
|
|
14
|
+
"buttonStyle",
|
|
15
|
+
"size",
|
|
16
|
+
"fullWidth",
|
|
17
|
+
"staticColor",
|
|
18
|
+
"class"
|
|
19
|
+
]);
|
|
20
|
+
const getClassName = (renderProps) => {
|
|
21
|
+
const classList = [
|
|
22
|
+
"vui-button",
|
|
23
|
+
`vui-button--${local.buttonStyle}`,
|
|
24
|
+
`vui-button--${local.variant}`,
|
|
25
|
+
`vui-button--${local.size}`
|
|
26
|
+
];
|
|
27
|
+
if (renderProps.isPressed) {
|
|
28
|
+
classList.push("is-pressed");
|
|
29
|
+
}
|
|
30
|
+
if (local.fullWidth) {
|
|
31
|
+
classList.push("vui-button--full-width");
|
|
32
|
+
}
|
|
33
|
+
if (local.class) {
|
|
34
|
+
classList.push(local.class);
|
|
35
|
+
}
|
|
36
|
+
return classList.join(" ");
|
|
37
|
+
};
|
|
38
|
+
return <HeadlessButton
|
|
39
|
+
{...headlessProps}
|
|
40
|
+
class={getClassName}
|
|
41
|
+
data-variant={local.variant}
|
|
42
|
+
data-style={local.buttonStyle}
|
|
43
|
+
data-static-color={local.staticColor || void 0}
|
|
44
|
+
>
|
|
45
|
+
{local.children}
|
|
46
|
+
</HeadlessButton>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/badge/index.tsx
|
|
50
|
+
import { Show } from "solid-js";
|
|
51
|
+
var variantStyles = {
|
|
52
|
+
primary: "bg-primary-500 text-white",
|
|
53
|
+
secondary: "bg-bg-300 text-primary-300",
|
|
54
|
+
accent: "bg-accent-300 text-black",
|
|
55
|
+
success: "bg-success-400 text-white",
|
|
56
|
+
warning: "bg-warning-400 text-black",
|
|
57
|
+
danger: "bg-danger-400 text-white"
|
|
58
|
+
};
|
|
59
|
+
var sizeStyles = {
|
|
60
|
+
sm: "w-5 h-5 text-xs",
|
|
61
|
+
md: "w-7 h-7 text-xs",
|
|
62
|
+
lg: "w-9 h-9 text-sm"
|
|
63
|
+
};
|
|
64
|
+
function Badge(props) {
|
|
65
|
+
const variant = () => props.variant ?? "accent";
|
|
66
|
+
const size = () => props.size ?? "md";
|
|
67
|
+
return <div
|
|
68
|
+
class={`flex items-center justify-center rounded-full border-b border-white font-semibold ${variantStyles[variant()]} ${sizeStyles[size()]} ${props.class ?? ""}`}
|
|
69
|
+
>
|
|
70
|
+
<Show when={props.count !== void 0} fallback={props.children}>
|
|
71
|
+
<span>{props.count}</span>
|
|
72
|
+
</Show>
|
|
73
|
+
</div>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/alert/index.tsx
|
|
77
|
+
import { Show as Show2 } from "solid-js";
|
|
78
|
+
var variantStyles2 = {
|
|
79
|
+
info: "bg-primary-700 text-primary-200 border border-primary-500",
|
|
80
|
+
success: "bg-success-600 text-success-100 border border-success-400",
|
|
81
|
+
warning: "bg-warning-600 text-warning-100 border border-warning-400",
|
|
82
|
+
error: "bg-danger-600 text-danger-100 border border-danger-400"
|
|
83
|
+
};
|
|
84
|
+
function Alert(props) {
|
|
85
|
+
const variant = () => props.variant ?? "info";
|
|
86
|
+
return <div
|
|
87
|
+
class={`flex items-center min-h-[50px] font-normal rounded-lg px-4 py-2 ${variantStyles2[variant()]} ${props.class ?? ""}`}
|
|
88
|
+
role="alert"
|
|
89
|
+
>
|
|
90
|
+
<div class="flex items-center gap-3 flex-1">
|
|
91
|
+
<Show2 when={props.title}>
|
|
92
|
+
<span class="font-semibold font-jost">{props.title}</span>
|
|
93
|
+
<span class="opacity-50">|</span>
|
|
94
|
+
</Show2>
|
|
95
|
+
<div class="flex-1">{props.children}</div>
|
|
96
|
+
<Show2 when={props.dismissible}>
|
|
97
|
+
<button
|
|
98
|
+
class="hover:opacity-70 transition-opacity ml-2"
|
|
99
|
+
onClick={props.onDismiss}
|
|
100
|
+
aria-label="Dismiss"
|
|
101
|
+
>
|
|
102
|
+
✕
|
|
103
|
+
</button>
|
|
104
|
+
</Show2>
|
|
105
|
+
</div>
|
|
106
|
+
</div>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/avatar/index.tsx
|
|
110
|
+
import { Show as Show3 } from "solid-js";
|
|
111
|
+
var sizeStyles2 = {
|
|
112
|
+
xs: { container: "w-6 h-6", text: "text-xs", indicator: "w-1.5 h-1.5" },
|
|
113
|
+
sm: { container: "w-8 h-8", text: "text-sm", indicator: "w-2 h-2" },
|
|
114
|
+
md: { container: "w-10 h-10", text: "text-base", indicator: "w-2.5 h-2.5" },
|
|
115
|
+
lg: { container: "w-14 h-14", text: "text-lg", indicator: "w-3 h-3" },
|
|
116
|
+
xl: { container: "w-20 h-20", text: "text-xl", indicator: "w-4 h-4" }
|
|
117
|
+
};
|
|
118
|
+
function Avatar(props) {
|
|
119
|
+
const size = () => props.size ?? "md";
|
|
120
|
+
const styles = () => sizeStyles2[size()];
|
|
121
|
+
const initials = () => {
|
|
122
|
+
if (props.fallback) return props.fallback.slice(0, 2).toUpperCase();
|
|
123
|
+
if (props.alt) return props.alt.slice(0, 2).toUpperCase();
|
|
124
|
+
return "?";
|
|
125
|
+
};
|
|
126
|
+
return <div class={`relative inline-block ${props.class ?? ""}`}>
|
|
127
|
+
<div
|
|
128
|
+
class={`${styles().container} rounded-full overflow-hidden bg-bg-200 flex items-center justify-center ring-2 ring-accent/50`}
|
|
129
|
+
>
|
|
130
|
+
<Show3
|
|
131
|
+
when={props.src}
|
|
132
|
+
fallback={<span class={`${styles().text} font-medium text-primary-300`}>
|
|
133
|
+
{initials()}
|
|
134
|
+
</span>}
|
|
135
|
+
>
|
|
136
|
+
<img
|
|
137
|
+
src={props.src}
|
|
138
|
+
alt={props.alt ?? "Avatar"}
|
|
139
|
+
class="w-full h-full object-cover"
|
|
140
|
+
/>
|
|
141
|
+
</Show3>
|
|
142
|
+
</div>
|
|
143
|
+
<Show3 when={props.online !== void 0}>
|
|
144
|
+
<span
|
|
145
|
+
class={`absolute bottom-0 right-0 ${styles().indicator} rounded-full ring-2 ring-bg-400 ${props.online ? "bg-success-400" : "bg-bg-light"}`}
|
|
146
|
+
/>
|
|
147
|
+
</Show3>
|
|
148
|
+
</div>;
|
|
149
|
+
}
|
|
150
|
+
function AvatarGroup(props) {
|
|
151
|
+
return <div class="flex -space-x-2">
|
|
152
|
+
{props.children}
|
|
153
|
+
</div>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/switch/index.tsx
|
|
157
|
+
import { createSignal, createEffect } from "solid-js";
|
|
158
|
+
|
|
159
|
+
// src/switch/ToggleSwitch.tsx
|
|
160
|
+
import { splitProps as splitProps2, mergeProps as solidMergeProps2 } from "solid-js";
|
|
161
|
+
import { ToggleSwitch as HeadlessToggleSwitch } from "@proyecto-viviana/solidaria-components";
|
|
162
|
+
var sizeStyles3 = {
|
|
163
|
+
sm: {
|
|
164
|
+
track: "h-5 w-9",
|
|
165
|
+
thumb: "h-4 w-4",
|
|
166
|
+
translate: "translate-x-4"
|
|
167
|
+
},
|
|
168
|
+
md: {
|
|
169
|
+
track: "h-6 w-11",
|
|
170
|
+
thumb: "h-5 w-5",
|
|
171
|
+
translate: "translate-x-5"
|
|
172
|
+
},
|
|
173
|
+
lg: {
|
|
174
|
+
track: "h-7 w-14",
|
|
175
|
+
thumb: "h-6 w-6",
|
|
176
|
+
translate: "translate-x-7"
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
function ToggleSwitch(props) {
|
|
180
|
+
const defaultProps = {
|
|
181
|
+
size: "md"
|
|
182
|
+
};
|
|
183
|
+
const merged = solidMergeProps2(defaultProps, props);
|
|
184
|
+
const [local, headlessProps] = splitProps2(merged, [
|
|
185
|
+
"size",
|
|
186
|
+
"class",
|
|
187
|
+
"children"
|
|
188
|
+
]);
|
|
189
|
+
const size = () => sizeStyles3[local.size];
|
|
190
|
+
const getClassName = (renderProps) => {
|
|
191
|
+
const base = "inline-flex items-center gap-2 cursor-pointer";
|
|
192
|
+
const disabledClass = renderProps.isDisabled ? "cursor-not-allowed opacity-50" : "";
|
|
193
|
+
const custom = local.class || "";
|
|
194
|
+
return [base, disabledClass, custom].filter(Boolean).join(" ");
|
|
195
|
+
};
|
|
196
|
+
return <HeadlessToggleSwitch
|
|
197
|
+
{...headlessProps}
|
|
198
|
+
class={getClassName}
|
|
199
|
+
>
|
|
200
|
+
{(renderProps) => <>
|
|
201
|
+
<span
|
|
202
|
+
class={[
|
|
203
|
+
"relative rounded-full transition-colors duration-200",
|
|
204
|
+
"focus-within:ring-2 focus-within:ring-accent-300 focus-within:ring-offset-2 focus-within:ring-offset-bg-400",
|
|
205
|
+
size().track,
|
|
206
|
+
renderProps.isSelected ? "bg-accent" : "bg-bg-300",
|
|
207
|
+
renderProps.isDisabled ? "cursor-not-allowed" : "cursor-pointer"
|
|
208
|
+
].join(" ")}
|
|
209
|
+
>
|
|
210
|
+
<span
|
|
211
|
+
class={[
|
|
212
|
+
"absolute top-0.5 left-0.5 rounded-full bg-white shadow transition-transform duration-200",
|
|
213
|
+
size().thumb,
|
|
214
|
+
renderProps.isSelected ? size().translate : "translate-x-0"
|
|
215
|
+
].join(" ")}
|
|
216
|
+
/>
|
|
217
|
+
</span>
|
|
218
|
+
{local.children && <span class="text-primary-200">{local.children}</span>}
|
|
219
|
+
</>}
|
|
220
|
+
</HeadlessToggleSwitch>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/switch/index.tsx
|
|
224
|
+
function TabSwitch(props) {
|
|
225
|
+
const [leftSelected, setLeftSelected] = createSignal(
|
|
226
|
+
props.value ? props.value === props.options[0]?.value : true
|
|
227
|
+
);
|
|
228
|
+
createEffect(() => {
|
|
229
|
+
if (props.value !== void 0) {
|
|
230
|
+
setLeftSelected(props.value === props.options[0]?.value);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
const toggle = () => {
|
|
234
|
+
const newLeftSelected = !leftSelected();
|
|
235
|
+
setLeftSelected(newLeftSelected);
|
|
236
|
+
const newValue = newLeftSelected ? props.options[0]?.value : props.options[1]?.value;
|
|
237
|
+
if (newValue) {
|
|
238
|
+
props.onChange?.(newValue);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
const leftSelectedStyle = "left-0 w-[142px] border-l-2";
|
|
242
|
+
const rightSelectedStyle = "left-[142px] w-[108px] border-r-2";
|
|
243
|
+
const textSelected = "font-extrabold text-primary-300";
|
|
244
|
+
const textUnselected = "font-medium text-primary-600 tracking-wider";
|
|
245
|
+
return <div
|
|
246
|
+
onClick={toggle}
|
|
247
|
+
class={`relative bg-bg-400 rounded-full w-[250px] cursor-pointer ${props.class ?? ""}`}
|
|
248
|
+
>
|
|
249
|
+
<div
|
|
250
|
+
class={`${leftSelected() ? leftSelectedStyle : rightSelectedStyle} transition-all duration-500 ease-in-out z-0 absolute bg-primary-600 rounded-full h-8 border-accent-300`}
|
|
251
|
+
/>
|
|
252
|
+
<div class="flex z-10 h-8 justify-around">
|
|
253
|
+
<button
|
|
254
|
+
type="button"
|
|
255
|
+
class={`${leftSelected() ? textSelected : textUnselected} transition-all ease-in-out duration-500 z-10 text-lg flex justify-center items-center pointer-events-none`}
|
|
256
|
+
>
|
|
257
|
+
<span>{props.options[0]?.label ?? "TENDENCIAS"}</span>
|
|
258
|
+
</button>
|
|
259
|
+
<button
|
|
260
|
+
type="button"
|
|
261
|
+
class={`${leftSelected() ? textUnselected : textSelected} transition-all ease-in-out duration-500 z-10 text-lg flex justify-center items-center pointer-events-none`}
|
|
262
|
+
>
|
|
263
|
+
<span>{props.options[1]?.label ?? "\xDALTIMOS"}</span>
|
|
264
|
+
</button>
|
|
265
|
+
</div>
|
|
266
|
+
</div>;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/checkbox/index.tsx
|
|
270
|
+
import { splitProps as splitProps3, mergeProps as solidMergeProps3, Show as Show4 } from "solid-js";
|
|
271
|
+
import {
|
|
272
|
+
Checkbox as HeadlessCheckbox,
|
|
273
|
+
CheckboxGroup as HeadlessCheckboxGroup
|
|
274
|
+
} from "@proyecto-viviana/solidaria-components";
|
|
275
|
+
var sizeStyles4 = {
|
|
276
|
+
sm: {
|
|
277
|
+
box: "h-4 w-4",
|
|
278
|
+
icon: "h-3 w-3",
|
|
279
|
+
label: "text-sm"
|
|
280
|
+
},
|
|
281
|
+
md: {
|
|
282
|
+
box: "h-5 w-5",
|
|
283
|
+
icon: "h-3.5 w-3.5",
|
|
284
|
+
label: "text-base"
|
|
285
|
+
},
|
|
286
|
+
lg: {
|
|
287
|
+
box: "h-6 w-6",
|
|
288
|
+
icon: "h-4 w-4",
|
|
289
|
+
label: "text-lg"
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
function CheckIcon(props) {
|
|
293
|
+
return <svg
|
|
294
|
+
class={props.class}
|
|
295
|
+
viewBox="0 0 12 10"
|
|
296
|
+
fill="none"
|
|
297
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
298
|
+
>
|
|
299
|
+
<path
|
|
300
|
+
d="M1 5L4.5 8.5L11 1"
|
|
301
|
+
stroke="currentColor"
|
|
302
|
+
stroke-width="2"
|
|
303
|
+
stroke-linecap="round"
|
|
304
|
+
stroke-linejoin="round"
|
|
305
|
+
/>
|
|
306
|
+
</svg>;
|
|
307
|
+
}
|
|
308
|
+
function IndeterminateIcon(props) {
|
|
309
|
+
return <svg
|
|
310
|
+
class={props.class}
|
|
311
|
+
viewBox="0 0 12 2"
|
|
312
|
+
fill="none"
|
|
313
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
314
|
+
>
|
|
315
|
+
<path
|
|
316
|
+
d="M1 1H11"
|
|
317
|
+
stroke="currentColor"
|
|
318
|
+
stroke-width="2"
|
|
319
|
+
stroke-linecap="round"
|
|
320
|
+
/>
|
|
321
|
+
</svg>;
|
|
322
|
+
}
|
|
323
|
+
function Checkbox(props) {
|
|
324
|
+
const defaultProps = {
|
|
325
|
+
size: "md"
|
|
326
|
+
};
|
|
327
|
+
const merged = solidMergeProps3(defaultProps, props);
|
|
328
|
+
const [local, headlessProps] = splitProps3(merged, [
|
|
329
|
+
"size",
|
|
330
|
+
"class",
|
|
331
|
+
"children"
|
|
332
|
+
]);
|
|
333
|
+
const size = () => sizeStyles4[local.size];
|
|
334
|
+
const getClassName = (renderProps) => {
|
|
335
|
+
const base = "inline-flex items-center gap-2 cursor-pointer";
|
|
336
|
+
const disabledClass = renderProps.isDisabled ? "cursor-not-allowed opacity-50" : "";
|
|
337
|
+
const custom = local.class || "";
|
|
338
|
+
return [base, disabledClass, custom].filter(Boolean).join(" ");
|
|
339
|
+
};
|
|
340
|
+
return <HeadlessCheckbox
|
|
341
|
+
{...headlessProps}
|
|
342
|
+
class={getClassName}
|
|
343
|
+
>
|
|
344
|
+
{(renderProps) => {
|
|
345
|
+
const boxClasses = () => {
|
|
346
|
+
const base = "relative flex items-center justify-center rounded border-2 transition-all duration-200";
|
|
347
|
+
const sizeClass = size().box;
|
|
348
|
+
let colorClass;
|
|
349
|
+
if (renderProps.isDisabled) {
|
|
350
|
+
colorClass = "border-bg-300 bg-bg-200";
|
|
351
|
+
} else if (renderProps.isSelected || renderProps.isIndeterminate) {
|
|
352
|
+
colorClass = "border-accent bg-accent";
|
|
353
|
+
} else {
|
|
354
|
+
colorClass = "border-primary-600 bg-transparent hover:border-accent-300";
|
|
355
|
+
}
|
|
356
|
+
const focusClass = renderProps.isFocusVisible ? "ring-2 ring-accent-300 ring-offset-2 ring-offset-bg-400" : "";
|
|
357
|
+
const cursorClass = renderProps.isDisabled ? "cursor-not-allowed" : "cursor-pointer";
|
|
358
|
+
return [base, sizeClass, colorClass, focusClass, cursorClass].filter(Boolean).join(" ");
|
|
359
|
+
};
|
|
360
|
+
const iconClasses = () => {
|
|
361
|
+
const base = "text-white transition-opacity duration-200";
|
|
362
|
+
const sizeClass = size().icon;
|
|
363
|
+
const visibilityClass = renderProps.isSelected || renderProps.isIndeterminate ? "opacity-100" : "opacity-0";
|
|
364
|
+
return [base, sizeClass, visibilityClass].filter(Boolean).join(" ");
|
|
365
|
+
};
|
|
366
|
+
const labelClasses = () => {
|
|
367
|
+
const base = "text-primary-200";
|
|
368
|
+
const sizeClass = size().label;
|
|
369
|
+
const disabledClass = renderProps.isDisabled ? "opacity-50" : "";
|
|
370
|
+
return [base, sizeClass, disabledClass].filter(Boolean).join(" ");
|
|
371
|
+
};
|
|
372
|
+
return <>
|
|
373
|
+
<span class={boxClasses()}>
|
|
374
|
+
<Show4
|
|
375
|
+
when={!renderProps.isIndeterminate}
|
|
376
|
+
fallback={<IndeterminateIcon class={iconClasses()} />}
|
|
377
|
+
>
|
|
378
|
+
<CheckIcon class={iconClasses()} />
|
|
379
|
+
</Show4>
|
|
380
|
+
</span>
|
|
381
|
+
<Show4 when={local.children}>
|
|
382
|
+
<span class={labelClasses()}>{local.children}</span>
|
|
383
|
+
</Show4>
|
|
384
|
+
</>;
|
|
385
|
+
}}
|
|
386
|
+
</HeadlessCheckbox>;
|
|
387
|
+
}
|
|
388
|
+
function CheckboxGroup(props) {
|
|
389
|
+
const [local, headlessProps] = splitProps3(props, [
|
|
390
|
+
"class",
|
|
391
|
+
"children",
|
|
392
|
+
"label",
|
|
393
|
+
"description",
|
|
394
|
+
"errorMessage"
|
|
395
|
+
]);
|
|
396
|
+
const getClassName = (renderProps) => {
|
|
397
|
+
const base = "flex flex-col gap-2";
|
|
398
|
+
const disabledClass = renderProps.isDisabled ? "opacity-50" : "";
|
|
399
|
+
const custom = local.class || "";
|
|
400
|
+
return [base, disabledClass, custom].filter(Boolean).join(" ");
|
|
401
|
+
};
|
|
402
|
+
const renderChildren = (renderProps) => <>
|
|
403
|
+
<Show4 when={local.label}>
|
|
404
|
+
<span class="text-sm font-medium text-primary-200">{local.label}</span>
|
|
405
|
+
</Show4>
|
|
406
|
+
<div class="flex flex-col gap-2">
|
|
407
|
+
{local.children}
|
|
408
|
+
</div>
|
|
409
|
+
<Show4 when={local.description && !renderProps.isInvalid}>
|
|
410
|
+
<span class="text-sm text-primary-400">{local.description}</span>
|
|
411
|
+
</Show4>
|
|
412
|
+
<Show4 when={local.errorMessage && renderProps.isInvalid}>
|
|
413
|
+
<span class="text-sm text-danger-400">{local.errorMessage}</span>
|
|
414
|
+
</Show4>
|
|
415
|
+
</>;
|
|
416
|
+
return <HeadlessCheckboxGroup
|
|
417
|
+
{...headlessProps}
|
|
418
|
+
class={getClassName}
|
|
419
|
+
children={renderChildren}
|
|
420
|
+
/>;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// src/radio/index.tsx
|
|
424
|
+
import { Show as Show5, createContext, useContext, splitProps as splitProps4 } from "solid-js";
|
|
425
|
+
import {
|
|
426
|
+
RadioGroup as HeadlessRadioGroup,
|
|
427
|
+
Radio as HeadlessRadio
|
|
428
|
+
} from "@proyecto-viviana/solidaria-components";
|
|
429
|
+
var RadioSizeContext = createContext("md");
|
|
430
|
+
var sizeStyles5 = {
|
|
431
|
+
sm: {
|
|
432
|
+
circle: "h-4 w-4",
|
|
433
|
+
dot: "h-2 w-2",
|
|
434
|
+
label: "text-sm"
|
|
435
|
+
},
|
|
436
|
+
md: {
|
|
437
|
+
circle: "h-5 w-5",
|
|
438
|
+
dot: "h-2.5 w-2.5",
|
|
439
|
+
label: "text-base"
|
|
440
|
+
},
|
|
441
|
+
lg: {
|
|
442
|
+
circle: "h-6 w-6",
|
|
443
|
+
dot: "h-3 w-3",
|
|
444
|
+
label: "text-lg"
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
function RadioGroup(props) {
|
|
448
|
+
const [local, headlessProps] = splitProps4(props, [
|
|
449
|
+
"size",
|
|
450
|
+
"class",
|
|
451
|
+
"label",
|
|
452
|
+
"description",
|
|
453
|
+
"errorMessage",
|
|
454
|
+
"children"
|
|
455
|
+
]);
|
|
456
|
+
const size = local.size ?? "md";
|
|
457
|
+
const customClass = local.class ?? "";
|
|
458
|
+
const getClassName = (renderProps) => {
|
|
459
|
+
const base = "flex gap-2";
|
|
460
|
+
const orientationClass = renderProps.orientation === "horizontal" ? "flex-row flex-wrap" : "flex-col";
|
|
461
|
+
const disabledClass = renderProps.isDisabled ? "opacity-50" : "";
|
|
462
|
+
return [base, orientationClass, disabledClass, customClass].filter(Boolean).join(" ");
|
|
463
|
+
};
|
|
464
|
+
const renderChildren = (renderProps) => <>
|
|
465
|
+
<Show5 when={local.label}>
|
|
466
|
+
<span class="text-primary-200 font-medium mb-1">{local.label}</span>
|
|
467
|
+
</Show5>
|
|
468
|
+
{typeof local.children === "function" ? local.children(renderProps) : local.children}
|
|
469
|
+
<Show5 when={local.description && !renderProps.isInvalid}>
|
|
470
|
+
<span class="text-primary-400 text-sm">{local.description}</span>
|
|
471
|
+
</Show5>
|
|
472
|
+
<Show5 when={local.errorMessage && renderProps.isInvalid}>
|
|
473
|
+
<span class="text-danger-400 text-sm">{local.errorMessage}</span>
|
|
474
|
+
</Show5>
|
|
475
|
+
</>;
|
|
476
|
+
return <RadioSizeContext.Provider value={size}>
|
|
477
|
+
<HeadlessRadioGroup
|
|
478
|
+
{...headlessProps}
|
|
479
|
+
class={getClassName}
|
|
480
|
+
data-size={size}
|
|
481
|
+
children={renderChildren}
|
|
482
|
+
/>
|
|
483
|
+
</RadioSizeContext.Provider>;
|
|
484
|
+
}
|
|
485
|
+
function Radio(props) {
|
|
486
|
+
const sizeFromContext = useContext(RadioSizeContext);
|
|
487
|
+
const size = () => sizeStyles5[sizeFromContext];
|
|
488
|
+
const customClass = props.class ?? "";
|
|
489
|
+
const getClassName = (renderProps) => {
|
|
490
|
+
const base = "inline-flex items-center gap-2 cursor-pointer";
|
|
491
|
+
const disabledClass = renderProps.isDisabled ? "cursor-not-allowed opacity-50" : "";
|
|
492
|
+
return [base, disabledClass, customClass].filter(Boolean).join(" ");
|
|
493
|
+
};
|
|
494
|
+
const { class: _, children, ...headlessProps } = props;
|
|
495
|
+
return <HeadlessRadio
|
|
496
|
+
{...headlessProps}
|
|
497
|
+
class={getClassName}
|
|
498
|
+
>
|
|
499
|
+
{(renderProps) => {
|
|
500
|
+
const circleClasses = () => {
|
|
501
|
+
const base = "relative flex items-center justify-center rounded-full border-2 transition-all duration-200";
|
|
502
|
+
const sizeClass = size().circle;
|
|
503
|
+
let colorClass;
|
|
504
|
+
if (renderProps.isDisabled) {
|
|
505
|
+
colorClass = "border-bg-300 bg-bg-200";
|
|
506
|
+
} else if (renderProps.isSelected) {
|
|
507
|
+
colorClass = "border-accent bg-transparent";
|
|
508
|
+
} else {
|
|
509
|
+
colorClass = "border-primary-600 bg-transparent hover:border-accent-300";
|
|
510
|
+
}
|
|
511
|
+
const focusClass = renderProps.isFocusVisible ? "ring-2 ring-accent-300 ring-offset-2 ring-offset-bg-400" : "";
|
|
512
|
+
const cursorClass = renderProps.isDisabled ? "cursor-not-allowed" : "cursor-pointer";
|
|
513
|
+
return [base, sizeClass, colorClass, focusClass, cursorClass].filter(Boolean).join(" ");
|
|
514
|
+
};
|
|
515
|
+
const dotClasses = () => {
|
|
516
|
+
const base = "rounded-full bg-accent transition-all duration-200";
|
|
517
|
+
const sizeClass = size().dot;
|
|
518
|
+
const visibilityClass = renderProps.isSelected ? "scale-100 opacity-100" : "scale-0 opacity-0";
|
|
519
|
+
return [base, sizeClass, visibilityClass].filter(Boolean).join(" ");
|
|
520
|
+
};
|
|
521
|
+
const labelClasses = () => {
|
|
522
|
+
const base = "text-primary-200";
|
|
523
|
+
const sizeClass = size().label;
|
|
524
|
+
const disabledClass = renderProps.isDisabled ? "opacity-50" : "";
|
|
525
|
+
return [base, sizeClass, disabledClass].filter(Boolean).join(" ");
|
|
526
|
+
};
|
|
527
|
+
const resolvedChildren = typeof children === "function" ? children(renderProps) : children;
|
|
528
|
+
return <>
|
|
529
|
+
<span class={circleClasses()}>
|
|
530
|
+
<span class={dotClasses()} />
|
|
531
|
+
</span>
|
|
532
|
+
<Show5 when={resolvedChildren}>
|
|
533
|
+
<span class={labelClasses()}>{resolvedChildren}</span>
|
|
534
|
+
</Show5>
|
|
535
|
+
</>;
|
|
536
|
+
}}
|
|
537
|
+
</HeadlessRadio>;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/dialog/index.tsx
|
|
541
|
+
import { Show as Show6 } from "solid-js";
|
|
542
|
+
|
|
543
|
+
// src/custom/chip/index.tsx
|
|
544
|
+
var variantStyles3 = {
|
|
545
|
+
primary: "bg-primary-700 text-primary-200 shadow-primary-chip",
|
|
546
|
+
secondary: "bg-primary-600 text-primary-100 hover:bg-primary-500",
|
|
547
|
+
accent: "bg-accent text-white",
|
|
548
|
+
outline: "bg-transparent border border-primary-500 text-primary-300"
|
|
549
|
+
};
|
|
550
|
+
function Chip(props) {
|
|
551
|
+
const variant = () => props.variant ?? "primary";
|
|
552
|
+
return <button
|
|
553
|
+
class={`flex justify-center items-center h-6 w-auto rounded-full px-4 py-1 font-medium text-sm tracking-wide transition-colors ${variantStyles3[variant()]} ${props.class ?? ""}`}
|
|
554
|
+
onClick={props.onClick}
|
|
555
|
+
>
|
|
556
|
+
{props.icon && <span class="mr-1.5">{props.icon}</span>}
|
|
557
|
+
<span>{props.text}</span>
|
|
558
|
+
</button>;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// src/dialog/index.tsx
|
|
562
|
+
function Dialog(props) {
|
|
563
|
+
return <div class={`flex flex-col w-full max-w-[540px] ${props.class ?? ""}`}>
|
|
564
|
+
<span class="relative left-8 top-4 bg-gradient-to-b from-primary-100 to-primary-500 bg-clip-text text-4xl font-extrabold text-transparent">
|
|
565
|
+
{props.title}
|
|
566
|
+
</span>
|
|
567
|
+
<div class="flex h-[50px] flex-col justify-end rounded-t-[26px] bg-primary-800">
|
|
568
|
+
<div class="flex h-[40px] flex-col justify-end rounded-t-[30px] bg-primary-600">
|
|
569
|
+
<div class="flex h-[20px] items-center justify-end rounded-t-[100px] bg-primary-700 pr-4">
|
|
570
|
+
<Show6 when={props.subtitle}>
|
|
571
|
+
<span class="text-base font-normal text-primary-300">
|
|
572
|
+
{props.subtitle}
|
|
573
|
+
</span>
|
|
574
|
+
</Show6>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
</div>
|
|
578
|
+
<div class="mt-1 flex min-h-[200px] flex-col rounded-b-[26px] rounded-t-lg border-b border-accent-500 bg-bg-300">
|
|
579
|
+
<div class="flex flex-1 flex-col p-4">
|
|
580
|
+
<div class="text-lg text-gray-100">{props.children}</div>
|
|
581
|
+
<Show6 when={props.primaryAction || props.secondaryAction}>
|
|
582
|
+
<div class="flex flex-1 flex-row items-end justify-center gap-5 py-5">
|
|
583
|
+
<Show6 when={props.secondaryAction}>
|
|
584
|
+
<Button variant="primary" buttonStyle="outline" onPress={props.secondaryAction.onClick}>
|
|
585
|
+
{props.secondaryAction.label}
|
|
586
|
+
</Button>
|
|
587
|
+
</Show6>
|
|
588
|
+
<Show6 when={props.primaryAction}>
|
|
589
|
+
<Button variant="primary" onPress={props.primaryAction.onClick}>
|
|
590
|
+
{props.primaryAction.label}
|
|
591
|
+
</Button>
|
|
592
|
+
</Show6>
|
|
593
|
+
</div>
|
|
594
|
+
</Show6>
|
|
595
|
+
</div>
|
|
596
|
+
</div>
|
|
597
|
+
<Show6 when={props.tags && props.tags.length > 0}>
|
|
598
|
+
<div class="relative bottom-4 right-4 w-full">
|
|
599
|
+
<div class="flex flex-row justify-end gap-2 pr-4">
|
|
600
|
+
{props.tags.map((tag) => <Chip variant="primary" text={tag} />)}
|
|
601
|
+
</div>
|
|
602
|
+
</div>
|
|
603
|
+
</Show6>
|
|
604
|
+
</div>;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// src/icon/icons/GitHubIcon.tsx
|
|
608
|
+
function GitHubIcon(props) {
|
|
609
|
+
return <svg
|
|
610
|
+
viewBox="0 0 24 24"
|
|
611
|
+
width={props.size}
|
|
612
|
+
height={props.size}
|
|
613
|
+
fill={props.color}
|
|
614
|
+
aria-hidden="true"
|
|
615
|
+
>
|
|
616
|
+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
|
617
|
+
</svg>;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// src/icon/index.tsx
|
|
621
|
+
function Icon(props) {
|
|
622
|
+
const size = () => props.size ?? 24;
|
|
623
|
+
const color = () => props.color ?? "var(--color-primary-500)";
|
|
624
|
+
const IconComponent = props.icon;
|
|
625
|
+
return <div
|
|
626
|
+
class={`vui-icon ${props.withShadow ? "vui-icon--with-shadow" : ""} ${props.class ?? ""}`}
|
|
627
|
+
onClick={props.onClick}
|
|
628
|
+
>
|
|
629
|
+
{props.withShadow && <div class="vui-icon__shadow">
|
|
630
|
+
<IconComponent size={size()} color="var(--color-accent)" />
|
|
631
|
+
</div>}
|
|
632
|
+
<div class="vui-icon__main">
|
|
633
|
+
<IconComponent size={size()} color={color()} />
|
|
634
|
+
</div>
|
|
635
|
+
</div>;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// src/tooltip/index.tsx
|
|
639
|
+
function Tooltip(props) {
|
|
640
|
+
const position = () => props.position ?? "bottom";
|
|
641
|
+
return <div class={`vui-tooltip ${props.class ?? ""}`}>
|
|
642
|
+
<div class="vui-tooltip__trigger">
|
|
643
|
+
{props.children}
|
|
644
|
+
</div>
|
|
645
|
+
<div class={`vui-tooltip__content vui-tooltip__content--${position()}`}>
|
|
646
|
+
<span>{props.label}</span>
|
|
647
|
+
</div>
|
|
648
|
+
</div>;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/textfield/index.tsx
|
|
652
|
+
import { splitProps as splitProps5, mergeProps as solidMergeProps4, Show as Show7 } from "solid-js";
|
|
653
|
+
import {
|
|
654
|
+
createTextField,
|
|
655
|
+
createFocusRing
|
|
656
|
+
} from "@proyecto-viviana/solidaria";
|
|
657
|
+
|
|
658
|
+
// ../solid-stately/dist/index.js
|
|
659
|
+
import { createSignal as createSignal2, createUniqueId, untrack } from "solid-js";
|
|
660
|
+
import { isServer } from "solid-js/web";
|
|
661
|
+
function access(value) {
|
|
662
|
+
return typeof value === "function" ? value() : value;
|
|
663
|
+
}
|
|
664
|
+
function createTextFieldState(props = {}) {
|
|
665
|
+
const getProps = () => access(props);
|
|
666
|
+
const initialProps = getProps();
|
|
667
|
+
const initialValue = initialProps.value ?? initialProps.defaultValue ?? "";
|
|
668
|
+
const [internalValue, setInternalValue] = createSignal2(initialValue);
|
|
669
|
+
const isControlled = () => getProps().value !== void 0;
|
|
670
|
+
const value = () => {
|
|
671
|
+
const p = getProps();
|
|
672
|
+
return isControlled() ? p.value ?? "" : internalValue();
|
|
673
|
+
};
|
|
674
|
+
function setValue(newValue) {
|
|
675
|
+
const p = getProps();
|
|
676
|
+
if (!isControlled()) {
|
|
677
|
+
setInternalValue(newValue);
|
|
678
|
+
}
|
|
679
|
+
p.onChange?.(newValue);
|
|
680
|
+
}
|
|
681
|
+
return {
|
|
682
|
+
value,
|
|
683
|
+
setValue
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// src/textfield/index.tsx
|
|
688
|
+
var sizeStyles6 = {
|
|
689
|
+
sm: {
|
|
690
|
+
input: "h-8 px-2 text-sm",
|
|
691
|
+
label: "text-sm",
|
|
692
|
+
description: "text-xs"
|
|
693
|
+
},
|
|
694
|
+
md: {
|
|
695
|
+
input: "h-10 px-3 text-base",
|
|
696
|
+
label: "text-sm",
|
|
697
|
+
description: "text-sm"
|
|
698
|
+
},
|
|
699
|
+
lg: {
|
|
700
|
+
input: "h-12 px-4 text-lg",
|
|
701
|
+
label: "text-base",
|
|
702
|
+
description: "text-sm"
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
function TextField(props) {
|
|
706
|
+
const defaultProps = {
|
|
707
|
+
size: "md",
|
|
708
|
+
variant: "outline"
|
|
709
|
+
};
|
|
710
|
+
const merged = solidMergeProps4(defaultProps, props);
|
|
711
|
+
const [local, ariaProps] = splitProps5(merged, [
|
|
712
|
+
"size",
|
|
713
|
+
"variant",
|
|
714
|
+
"class",
|
|
715
|
+
"label",
|
|
716
|
+
"description",
|
|
717
|
+
"errorMessage"
|
|
718
|
+
]);
|
|
719
|
+
const size = () => sizeStyles6[local.size];
|
|
720
|
+
const state = createTextFieldState(() => ({
|
|
721
|
+
value: ariaProps.value,
|
|
722
|
+
defaultValue: ariaProps.defaultValue,
|
|
723
|
+
onChange: ariaProps.onChange
|
|
724
|
+
}));
|
|
725
|
+
const textFieldAria = createTextField(() => ({
|
|
726
|
+
...ariaProps,
|
|
727
|
+
value: state.value(),
|
|
728
|
+
onChange: state.setValue
|
|
729
|
+
}));
|
|
730
|
+
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
731
|
+
const containerClasses = () => {
|
|
732
|
+
const base = "flex flex-col";
|
|
733
|
+
const disabledClass = ariaProps.isDisabled ? "opacity-60" : "";
|
|
734
|
+
const custom = local.class || "";
|
|
735
|
+
return [base, disabledClass, custom].filter(Boolean).join(" ");
|
|
736
|
+
};
|
|
737
|
+
const inputClasses = () => {
|
|
738
|
+
const base = "w-full rounded-md transition-all duration-200 outline-none";
|
|
739
|
+
const sizeClass = size().input;
|
|
740
|
+
let variantClass;
|
|
741
|
+
if (local.variant === "filled") {
|
|
742
|
+
variantClass = "bg-bg-200 border border-transparent";
|
|
743
|
+
} else {
|
|
744
|
+
variantClass = "bg-transparent border border-bg-400";
|
|
745
|
+
}
|
|
746
|
+
let stateClass;
|
|
747
|
+
if (ariaProps.isDisabled) {
|
|
748
|
+
stateClass = "bg-bg-200 text-primary-500 cursor-not-allowed";
|
|
749
|
+
} else if (textFieldAria.isInvalid) {
|
|
750
|
+
stateClass = "border-danger-500 focus:border-danger-400 focus:ring-2 focus:ring-danger-400/20";
|
|
751
|
+
} else {
|
|
752
|
+
stateClass = "text-primary-100 placeholder:text-primary-500 focus:border-accent focus:ring-2 focus:ring-accent/20";
|
|
753
|
+
}
|
|
754
|
+
const hoverClass = ariaProps.isDisabled ? "" : "hover:border-accent-300";
|
|
755
|
+
return [base, sizeClass, variantClass, stateClass, hoverClass].filter(Boolean).join(" ");
|
|
756
|
+
};
|
|
757
|
+
const labelClasses = () => {
|
|
758
|
+
const base = "block font-medium text-primary-200 mb-1";
|
|
759
|
+
const sizeClass = size().label;
|
|
760
|
+
return [base, sizeClass].filter(Boolean).join(" ");
|
|
761
|
+
};
|
|
762
|
+
const descriptionClasses = () => {
|
|
763
|
+
const base = "mt-1 text-primary-400";
|
|
764
|
+
const sizeClass = size().description;
|
|
765
|
+
return [base, sizeClass].filter(Boolean).join(" ");
|
|
766
|
+
};
|
|
767
|
+
const errorClasses = () => {
|
|
768
|
+
const base = "mt-1 text-danger-400";
|
|
769
|
+
const sizeClass = size().description;
|
|
770
|
+
return [base, sizeClass].filter(Boolean).join(" ");
|
|
771
|
+
};
|
|
772
|
+
const cleanLabelProps = () => {
|
|
773
|
+
const { ref: _ref, ...rest } = textFieldAria.labelProps;
|
|
774
|
+
return rest;
|
|
775
|
+
};
|
|
776
|
+
const cleanInputProps = () => {
|
|
777
|
+
const { ref: _ref1, ...rest } = textFieldAria.inputProps;
|
|
778
|
+
const { ref: _ref2, ...focusRest } = focusProps;
|
|
779
|
+
return { ...rest, ...focusRest };
|
|
780
|
+
};
|
|
781
|
+
const cleanDescriptionProps = () => {
|
|
782
|
+
const { ref: _ref, ...rest } = textFieldAria.descriptionProps;
|
|
783
|
+
return rest;
|
|
784
|
+
};
|
|
785
|
+
const cleanErrorMessageProps = () => {
|
|
786
|
+
const { ref: _ref, ...rest } = textFieldAria.errorMessageProps;
|
|
787
|
+
return rest;
|
|
788
|
+
};
|
|
789
|
+
return <div
|
|
790
|
+
class={containerClasses()}
|
|
791
|
+
data-disabled={ariaProps.isDisabled || void 0}
|
|
792
|
+
data-invalid={textFieldAria.isInvalid || void 0}
|
|
793
|
+
data-readonly={ariaProps.isReadOnly || void 0}
|
|
794
|
+
data-required={ariaProps.isRequired || void 0}
|
|
795
|
+
data-focused={isFocused() || void 0}
|
|
796
|
+
data-focus-visible={isFocusVisible() || void 0}
|
|
797
|
+
>
|
|
798
|
+
<Show7 when={local.label}>
|
|
799
|
+
<label {...cleanLabelProps()} class={labelClasses()}>
|
|
800
|
+
{local.label}
|
|
801
|
+
<Show7 when={ariaProps.isRequired}>
|
|
802
|
+
<span class="text-danger-400 ml-0.5">*</span>
|
|
803
|
+
</Show7>
|
|
804
|
+
</label>
|
|
805
|
+
</Show7>
|
|
806
|
+
|
|
807
|
+
<input {...cleanInputProps()} class={inputClasses()} />
|
|
808
|
+
|
|
809
|
+
<Show7 when={local.description && !textFieldAria.isInvalid}>
|
|
810
|
+
<p {...cleanDescriptionProps()} class={descriptionClasses()}>
|
|
811
|
+
{local.description}
|
|
812
|
+
</p>
|
|
813
|
+
</Show7>
|
|
814
|
+
|
|
815
|
+
<Show7 when={local.errorMessage && textFieldAria.isInvalid}>
|
|
816
|
+
<p {...cleanErrorMessageProps()} class={errorClasses()}>
|
|
817
|
+
{local.errorMessage}
|
|
818
|
+
</p>
|
|
819
|
+
</Show7>
|
|
820
|
+
</div>;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// src/link/index.tsx
|
|
824
|
+
import { splitProps as splitProps6 } from "solid-js";
|
|
825
|
+
import {
|
|
826
|
+
Link as HeadlessLink
|
|
827
|
+
} from "@proyecto-viviana/solidaria-components";
|
|
828
|
+
var variantStyles4 = {
|
|
829
|
+
primary: "text-accent hover:text-accent-300",
|
|
830
|
+
secondary: "text-primary-300 hover:text-primary-200",
|
|
831
|
+
subtle: "text-primary-400 hover:text-primary-300"
|
|
832
|
+
};
|
|
833
|
+
function Link(props) {
|
|
834
|
+
const [local, headlessProps] = splitProps6(props, [
|
|
835
|
+
"variant",
|
|
836
|
+
"isStandalone",
|
|
837
|
+
"isQuiet",
|
|
838
|
+
"class",
|
|
839
|
+
"children"
|
|
840
|
+
]);
|
|
841
|
+
const variant = local.variant ?? "primary";
|
|
842
|
+
const customClass = local.class ?? "";
|
|
843
|
+
const getClassName = (renderProps) => {
|
|
844
|
+
const base = "transition-colors duration-200 cursor-pointer rounded-sm outline-none";
|
|
845
|
+
const variantClass = variantStyles4[variant];
|
|
846
|
+
let underlineClass;
|
|
847
|
+
if (local.isStandalone && local.isQuiet) {
|
|
848
|
+
underlineClass = renderProps.isHovered || renderProps.isFocusVisible ? "underline" : "no-underline";
|
|
849
|
+
} else {
|
|
850
|
+
underlineClass = "underline";
|
|
851
|
+
}
|
|
852
|
+
const weightClass = local.isStandalone ? "font-medium" : "";
|
|
853
|
+
const focusClass = renderProps.isFocusVisible ? "ring-2 ring-accent-300 ring-offset-2 ring-offset-bg-400" : "";
|
|
854
|
+
const disabledClass = renderProps.isDisabled ? "opacity-50 cursor-not-allowed" : "";
|
|
855
|
+
const pressedClass = renderProps.isPressed ? "opacity-80" : "";
|
|
856
|
+
return [
|
|
857
|
+
base,
|
|
858
|
+
variantClass,
|
|
859
|
+
underlineClass,
|
|
860
|
+
weightClass,
|
|
861
|
+
focusClass,
|
|
862
|
+
disabledClass,
|
|
863
|
+
pressedClass,
|
|
864
|
+
customClass
|
|
865
|
+
].filter(Boolean).join(" ");
|
|
866
|
+
};
|
|
867
|
+
return <HeadlessLink
|
|
868
|
+
{...headlessProps}
|
|
869
|
+
class={getClassName}
|
|
870
|
+
>
|
|
871
|
+
{local.children}
|
|
872
|
+
</HeadlessLink>;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// src/progress-bar/index.tsx
|
|
876
|
+
import { splitProps as splitProps7, Show as Show8, createMemo } from "solid-js";
|
|
877
|
+
import { createProgressBar } from "@proyecto-viviana/solidaria";
|
|
878
|
+
var sizeStyles7 = {
|
|
879
|
+
sm: {
|
|
880
|
+
track: "h-1",
|
|
881
|
+
text: "text-xs"
|
|
882
|
+
},
|
|
883
|
+
md: {
|
|
884
|
+
track: "h-2",
|
|
885
|
+
text: "text-sm"
|
|
886
|
+
},
|
|
887
|
+
lg: {
|
|
888
|
+
track: "h-3",
|
|
889
|
+
text: "text-base"
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
var variantStyles5 = {
|
|
893
|
+
primary: "bg-primary-500",
|
|
894
|
+
accent: "bg-accent",
|
|
895
|
+
success: "bg-green-500",
|
|
896
|
+
warning: "bg-yellow-500",
|
|
897
|
+
danger: "bg-red-500"
|
|
898
|
+
};
|
|
899
|
+
function clamp(value, min, max) {
|
|
900
|
+
return Math.min(Math.max(value, min), max);
|
|
901
|
+
}
|
|
902
|
+
function ProgressBar(props) {
|
|
903
|
+
const [local, ariaProps] = splitProps7(props, [
|
|
904
|
+
"size",
|
|
905
|
+
"variant",
|
|
906
|
+
"label",
|
|
907
|
+
"showValueLabel",
|
|
908
|
+
"class"
|
|
909
|
+
]);
|
|
910
|
+
const size = () => local.size ?? "md";
|
|
911
|
+
const variant = () => local.variant ?? "primary";
|
|
912
|
+
const isIndeterminate = () => ariaProps.isIndeterminate ?? false;
|
|
913
|
+
const showValueLabel = () => local.showValueLabel ?? !isIndeterminate();
|
|
914
|
+
const progressAria = createProgressBar({
|
|
915
|
+
get value() {
|
|
916
|
+
return ariaProps.value;
|
|
917
|
+
},
|
|
918
|
+
get minValue() {
|
|
919
|
+
return ariaProps.minValue;
|
|
920
|
+
},
|
|
921
|
+
get maxValue() {
|
|
922
|
+
return ariaProps.maxValue;
|
|
923
|
+
},
|
|
924
|
+
get valueLabel() {
|
|
925
|
+
return ariaProps.valueLabel;
|
|
926
|
+
},
|
|
927
|
+
get isIndeterminate() {
|
|
928
|
+
return ariaProps.isIndeterminate;
|
|
929
|
+
},
|
|
930
|
+
get label() {
|
|
931
|
+
return local.label;
|
|
932
|
+
},
|
|
933
|
+
get "aria-label"() {
|
|
934
|
+
return ariaProps["aria-label"];
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
const percentage = createMemo(() => {
|
|
938
|
+
if (isIndeterminate()) {
|
|
939
|
+
return void 0;
|
|
940
|
+
}
|
|
941
|
+
const value = ariaProps.value ?? 0;
|
|
942
|
+
const minValue = ariaProps.minValue ?? 0;
|
|
943
|
+
const maxValue = ariaProps.maxValue ?? 100;
|
|
944
|
+
const clampedValue = clamp(value, minValue, maxValue);
|
|
945
|
+
return (clampedValue - minValue) / (maxValue - minValue) * 100;
|
|
946
|
+
});
|
|
947
|
+
const valueText = () => progressAria.progressBarProps["aria-valuetext"];
|
|
948
|
+
const sizeConfig = () => sizeStyles7[size()];
|
|
949
|
+
return <div
|
|
950
|
+
{...progressAria.progressBarProps}
|
|
951
|
+
class={`w-full ${local.class ?? ""}`}
|
|
952
|
+
>
|
|
953
|
+
{
|
|
954
|
+
/* Label and value row */
|
|
955
|
+
}
|
|
956
|
+
<Show8 when={local.label || showValueLabel()}>
|
|
957
|
+
<div class={`flex justify-between items-center mb-1 ${sizeConfig().text}`}>
|
|
958
|
+
<Show8 when={local.label}>
|
|
959
|
+
<span class="text-primary-200 font-medium">{local.label}</span>
|
|
960
|
+
</Show8>
|
|
961
|
+
<Show8 when={showValueLabel() && !isIndeterminate()}>
|
|
962
|
+
<span class="text-primary-300">{valueText()}</span>
|
|
963
|
+
</Show8>
|
|
964
|
+
</div>
|
|
965
|
+
</Show8>
|
|
966
|
+
|
|
967
|
+
{
|
|
968
|
+
/* Track */
|
|
969
|
+
}
|
|
970
|
+
<div class={`w-full ${sizeConfig().track} bg-bg-300 rounded-full overflow-hidden`}>
|
|
971
|
+
{
|
|
972
|
+
/* Fill */
|
|
973
|
+
}
|
|
974
|
+
<div
|
|
975
|
+
class={`h-full rounded-full transition-all duration-300 ${variantStyles5[variant()]} ${isIndeterminate() ? "animate-progress-indeterminate" : ""}`}
|
|
976
|
+
style={{
|
|
977
|
+
width: isIndeterminate() ? "30%" : `${percentage()}%`
|
|
978
|
+
}}
|
|
979
|
+
/>
|
|
980
|
+
</div>
|
|
981
|
+
</div>;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/separator/index.tsx
|
|
985
|
+
import { splitProps as splitProps8, createMemo as createMemo2, Show as Show9 } from "solid-js";
|
|
986
|
+
import { createSeparator } from "@proyecto-viviana/solidaria";
|
|
987
|
+
var variantStyles6 = {
|
|
988
|
+
default: "bg-bg-100",
|
|
989
|
+
subtle: "bg-bg-200",
|
|
990
|
+
strong: "bg-primary-600"
|
|
991
|
+
};
|
|
992
|
+
var horizontalSizeStyles = {
|
|
993
|
+
sm: "h-px",
|
|
994
|
+
md: "h-0.5",
|
|
995
|
+
lg: "h-1"
|
|
996
|
+
};
|
|
997
|
+
var verticalSizeStyles = {
|
|
998
|
+
sm: "w-px",
|
|
999
|
+
md: "w-0.5",
|
|
1000
|
+
lg: "w-1"
|
|
1001
|
+
};
|
|
1002
|
+
function Separator(props) {
|
|
1003
|
+
const [local, ariaProps] = splitProps8(props, [
|
|
1004
|
+
"orientation",
|
|
1005
|
+
"variant",
|
|
1006
|
+
"size",
|
|
1007
|
+
"class"
|
|
1008
|
+
]);
|
|
1009
|
+
const orientation = () => local.orientation ?? "horizontal";
|
|
1010
|
+
const variant = () => local.variant ?? "default";
|
|
1011
|
+
const size = () => local.size ?? "md";
|
|
1012
|
+
const elementType = createMemo2(() => {
|
|
1013
|
+
if (orientation() === "vertical") {
|
|
1014
|
+
return "div";
|
|
1015
|
+
}
|
|
1016
|
+
return "hr";
|
|
1017
|
+
});
|
|
1018
|
+
const separatorAria = createSeparator({
|
|
1019
|
+
get orientation() {
|
|
1020
|
+
return orientation();
|
|
1021
|
+
},
|
|
1022
|
+
get elementType() {
|
|
1023
|
+
return elementType();
|
|
1024
|
+
},
|
|
1025
|
+
get "aria-label"() {
|
|
1026
|
+
return ariaProps["aria-label"];
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
const className = createMemo2(() => {
|
|
1030
|
+
const isVertical = orientation() === "vertical";
|
|
1031
|
+
const sizeStyles8 = isVertical ? verticalSizeStyles : horizontalSizeStyles;
|
|
1032
|
+
const base = [
|
|
1033
|
+
variantStyles6[variant()],
|
|
1034
|
+
sizeStyles8[size()],
|
|
1035
|
+
isVertical ? "h-full self-stretch" : "w-full",
|
|
1036
|
+
"border-0",
|
|
1037
|
+
// Reset hr default border
|
|
1038
|
+
local.class ?? ""
|
|
1039
|
+
];
|
|
1040
|
+
return base.filter(Boolean).join(" ");
|
|
1041
|
+
});
|
|
1042
|
+
const getAriaProps = () => {
|
|
1043
|
+
const { ref: _, ...props2 } = separatorAria.separatorProps;
|
|
1044
|
+
return props2;
|
|
1045
|
+
};
|
|
1046
|
+
return <Show9
|
|
1047
|
+
when={orientation() === "vertical"}
|
|
1048
|
+
fallback={<hr
|
|
1049
|
+
{...getAriaProps()}
|
|
1050
|
+
class={className()}
|
|
1051
|
+
/>}
|
|
1052
|
+
>
|
|
1053
|
+
<div
|
|
1054
|
+
{...getAriaProps()}
|
|
1055
|
+
class={className()}
|
|
1056
|
+
/>
|
|
1057
|
+
</Show9>;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// src/custom/nav-header/index.tsx
|
|
1061
|
+
import { Show as Show10 } from "solid-js";
|
|
1062
|
+
function NavHeader(props) {
|
|
1063
|
+
return <nav class={`flex items-center bg-bg-400 h-[70px] border-b-4 border-accent-500 ${props.class ?? ""}`}>
|
|
1064
|
+
<div class="pl-1 md:pl-8 flex items-center">
|
|
1065
|
+
<Show10 when={props.logo} fallback={<Show10 when={props.logoText}>
|
|
1066
|
+
<span class="text-[34px] font-light text-primary-700 flex items-center">
|
|
1067
|
+
{props.logoText}
|
|
1068
|
+
</span>
|
|
1069
|
+
</Show10>}>
|
|
1070
|
+
<img src={props.logo} alt={props.logoAlt ?? "Logo"} class="h-[42px] w-auto" />
|
|
1071
|
+
</Show10>
|
|
1072
|
+
</div>
|
|
1073
|
+
|
|
1074
|
+
<div class="flex-1 flex justify-end items-center pr-1 md:pr-8">
|
|
1075
|
+
{props.children}
|
|
1076
|
+
<Show10 when={props.menuIcon}>
|
|
1077
|
+
<button
|
|
1078
|
+
class="md:hidden flex items-center justify-center"
|
|
1079
|
+
onClick={props.onMenuClick}
|
|
1080
|
+
>
|
|
1081
|
+
{props.menuIcon}
|
|
1082
|
+
</button>
|
|
1083
|
+
</Show10>
|
|
1084
|
+
</div>
|
|
1085
|
+
</nav>;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// src/custom/lateral-nav/index.tsx
|
|
1089
|
+
import { Show as Show11, For } from "solid-js";
|
|
1090
|
+
function NavItem(props) {
|
|
1091
|
+
return <li class={`flex items-center ${props.class ?? ""}`}>
|
|
1092
|
+
<span class="text-lg font-bold text-primary-200">{props.title}</span>
|
|
1093
|
+
{props.children}
|
|
1094
|
+
</li>;
|
|
1095
|
+
}
|
|
1096
|
+
function NavLink(props) {
|
|
1097
|
+
const activeStyles = "font-medium text-primary-300 underline underline-offset-4";
|
|
1098
|
+
const inactiveStyles = "font-normal text-gray-200 underline-offset-4 hover:text-gray-100 hover:underline";
|
|
1099
|
+
return <a
|
|
1100
|
+
href={props.href}
|
|
1101
|
+
class={`${props.active ? activeStyles : inactiveStyles} ${props.class ?? ""}`}
|
|
1102
|
+
>
|
|
1103
|
+
{props.children}
|
|
1104
|
+
</a>;
|
|
1105
|
+
}
|
|
1106
|
+
function NavSection(props) {
|
|
1107
|
+
return <div class={props.class ?? ""}>
|
|
1108
|
+
<NavItem title={props.title} />
|
|
1109
|
+
<div class="flex h-full">
|
|
1110
|
+
<div class="h-5 w-1 bg-accent-300" />
|
|
1111
|
+
<ul class="flex h-full flex-1 flex-col gap-1 pl-4">
|
|
1112
|
+
<Show11 when={props.links}>
|
|
1113
|
+
<For each={props.links}>
|
|
1114
|
+
{(link) => <li>
|
|
1115
|
+
<NavLink href={link.href} active={link.active}>
|
|
1116
|
+
{link.label}
|
|
1117
|
+
</NavLink>
|
|
1118
|
+
</li>}
|
|
1119
|
+
</For>
|
|
1120
|
+
</Show11>
|
|
1121
|
+
{props.children}
|
|
1122
|
+
</ul>
|
|
1123
|
+
</div>
|
|
1124
|
+
</div>;
|
|
1125
|
+
}
|
|
1126
|
+
function LateralNav(props) {
|
|
1127
|
+
const bgColor = () => props.transparent ? "" : "bg-bg-200";
|
|
1128
|
+
return <div
|
|
1129
|
+
class={`hidden w-[300px] md:block ${bgColor()} m-0 border-r border-primary-600 p-3 ${props.class ?? ""}`}
|
|
1130
|
+
>
|
|
1131
|
+
{props.children}
|
|
1132
|
+
</div>;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// src/custom/timeline-item/index.tsx
|
|
1136
|
+
import { Show as Show12 } from "solid-js";
|
|
1137
|
+
var eventMessages = {
|
|
1138
|
+
follow: (left, right) => <>
|
|
1139
|
+
<span class="font-semibold text-accent-200">{left}</span>
|
|
1140
|
+
{" ha empezado a seguir a "}
|
|
1141
|
+
<span class="font-semibold text-accent-200">{right}</span>
|
|
1142
|
+
</>,
|
|
1143
|
+
like: (left, right) => <>
|
|
1144
|
+
<span class="font-semibold text-accent-200">{left}</span>
|
|
1145
|
+
{" le ha dado like a "}
|
|
1146
|
+
<span class="font-semibold text-accent-200">{right}</span>
|
|
1147
|
+
</>,
|
|
1148
|
+
comment: (left, right) => <>
|
|
1149
|
+
<span class="font-semibold text-accent-200">{left}</span>
|
|
1150
|
+
{" ha comentado en "}
|
|
1151
|
+
<span class="font-semibold text-accent-200">{right}</span>
|
|
1152
|
+
</>,
|
|
1153
|
+
event: (left, right) => <>
|
|
1154
|
+
<span class="font-semibold text-accent-200">{left}</span>
|
|
1155
|
+
{" asistir\xE1 al evento de "}
|
|
1156
|
+
<span class="font-semibold text-accent-200">{right}</span>
|
|
1157
|
+
</>,
|
|
1158
|
+
custom: () => null
|
|
1159
|
+
};
|
|
1160
|
+
function TimelineItem(props) {
|
|
1161
|
+
const type = () => props.type ?? "follow";
|
|
1162
|
+
const leftName = () => props.leftUser?.name ?? "";
|
|
1163
|
+
const rightName = () => props.rightUser?.name ?? "";
|
|
1164
|
+
return <div class={`inline-flex w-auto flex-col gap-5 rounded-2xl border border-primary-700 bg-bg-200 p-5 hover:bg-bg-300 transition-colors ${props.class ?? ""}`}>
|
|
1165
|
+
<div class="flex items-center justify-around gap-3">
|
|
1166
|
+
<Show12 when={props.leftUser}>
|
|
1167
|
+
<Avatar src={props.leftUser.avatar} alt={props.leftUser.name} />
|
|
1168
|
+
</Show12>
|
|
1169
|
+
<Show12 when={props.icon}>
|
|
1170
|
+
{props.icon}
|
|
1171
|
+
</Show12>
|
|
1172
|
+
<Show12 when={props.rightUser}>
|
|
1173
|
+
<Avatar src={props.rightUser.avatar} alt={props.rightUser.name} />
|
|
1174
|
+
</Show12>
|
|
1175
|
+
</div>
|
|
1176
|
+
<div class="flex items-center justify-center gap-3 text-center">
|
|
1177
|
+
<span class="font-light text-primary-300">
|
|
1178
|
+
<Show12 when={props.message} fallback={eventMessages[type()](leftName(), rightName())}>
|
|
1179
|
+
{props.message}
|
|
1180
|
+
</Show12>
|
|
1181
|
+
</span>
|
|
1182
|
+
</div>
|
|
1183
|
+
</div>;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// src/custom/conversation/index.tsx
|
|
1187
|
+
import { Show as Show13, For as For2 } from "solid-js";
|
|
1188
|
+
function ConversationPreview(props) {
|
|
1189
|
+
return <button
|
|
1190
|
+
class={`flex w-full items-center gap-3 rounded-xl p-3 hover:bg-bg-300 transition-colors text-left ${props.class ?? ""}`}
|
|
1191
|
+
onClick={props.onClick}
|
|
1192
|
+
>
|
|
1193
|
+
<Avatar
|
|
1194
|
+
src={props.user.avatar}
|
|
1195
|
+
alt={props.user.name}
|
|
1196
|
+
online={props.user.online}
|
|
1197
|
+
size="md"
|
|
1198
|
+
/>
|
|
1199
|
+
<div class="flex-1 min-w-0">
|
|
1200
|
+
<div class="flex items-center justify-between">
|
|
1201
|
+
<span class="font-semibold text-primary-100 truncate">{props.user.name}</span>
|
|
1202
|
+
<Show13 when={props.timestamp}>
|
|
1203
|
+
<span class="text-xs text-primary-500">{props.timestamp}</span>
|
|
1204
|
+
</Show13>
|
|
1205
|
+
</div>
|
|
1206
|
+
<Show13 when={props.lastMessage}>
|
|
1207
|
+
<p class="text-sm text-primary-400 truncate">{props.lastMessage}</p>
|
|
1208
|
+
</Show13>
|
|
1209
|
+
</div>
|
|
1210
|
+
<Show13 when={props.unreadCount && props.unreadCount > 0}>
|
|
1211
|
+
<span class="flex h-5 w-5 items-center justify-center rounded-full bg-accent text-xs font-bold text-white">
|
|
1212
|
+
{props.unreadCount}
|
|
1213
|
+
</span>
|
|
1214
|
+
</Show13>
|
|
1215
|
+
</button>;
|
|
1216
|
+
}
|
|
1217
|
+
function ConversationBubble(props) {
|
|
1218
|
+
const isUser = () => props.sender === "user";
|
|
1219
|
+
return <div class={`flex ${isUser() ? "justify-end" : "justify-start"} ${props.class ?? ""}`}>
|
|
1220
|
+
<div
|
|
1221
|
+
class={`max-w-[70%] rounded-2xl px-4 py-2 ${isUser() ? "bg-accent text-white rounded-br-sm" : "bg-bg-300 text-primary-100 rounded-bl-sm"}`}
|
|
1222
|
+
>
|
|
1223
|
+
<p>{props.content}</p>
|
|
1224
|
+
<Show13 when={props.timestamp}>
|
|
1225
|
+
<span class={`text-xs ${isUser() ? "text-white/70" : "text-primary-500"}`}>
|
|
1226
|
+
{props.timestamp}
|
|
1227
|
+
</span>
|
|
1228
|
+
</Show13>
|
|
1229
|
+
</div>
|
|
1230
|
+
</div>;
|
|
1231
|
+
}
|
|
1232
|
+
function Conversation(props) {
|
|
1233
|
+
return <div class={`flex flex-col gap-2 p-4 ${props.class ?? ""}`}>
|
|
1234
|
+
<For2 each={props.messages}>
|
|
1235
|
+
{(message) => <ConversationBubble
|
|
1236
|
+
content={message.content}
|
|
1237
|
+
sender={message.sender}
|
|
1238
|
+
timestamp={message.timestamp}
|
|
1239
|
+
/>}
|
|
1240
|
+
</For2>
|
|
1241
|
+
</div>;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// src/custom/profile-card/index.tsx
|
|
1245
|
+
import { Show as Show14 } from "solid-js";
|
|
1246
|
+
function ProfileCard(props) {
|
|
1247
|
+
const formatNumber = (num) => {
|
|
1248
|
+
if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
|
|
1249
|
+
if (num >= 1e3) return `${(num / 1e3).toFixed(1)}K`;
|
|
1250
|
+
return num.toString();
|
|
1251
|
+
};
|
|
1252
|
+
return <div class={`bg-bg-200 rounded-xl p-4 ${props.class ?? ""}`}>
|
|
1253
|
+
<div class="flex items-start gap-4">
|
|
1254
|
+
<Avatar src={props.avatar} alt={props.username} size="lg" />
|
|
1255
|
+
<div class="flex-1 min-w-0">
|
|
1256
|
+
<h3 class="font-semibold text-primary-100 text-lg truncate">
|
|
1257
|
+
{props.username}
|
|
1258
|
+
</h3>
|
|
1259
|
+
<Show14 when={props.bio}>
|
|
1260
|
+
<p class="text-primary-300 text-sm mt-1 line-clamp-2">{props.bio}</p>
|
|
1261
|
+
</Show14>
|
|
1262
|
+
<div class="flex gap-4 mt-2 text-sm">
|
|
1263
|
+
<Show14 when={props.followers !== void 0}>
|
|
1264
|
+
<span class="text-primary-300">
|
|
1265
|
+
<span class="font-semibold text-primary-100">
|
|
1266
|
+
{formatNumber(props.followers)}
|
|
1267
|
+
</span>{" "}
|
|
1268
|
+
seguidores
|
|
1269
|
+
</span>
|
|
1270
|
+
</Show14>
|
|
1271
|
+
<Show14 when={props.following !== void 0}>
|
|
1272
|
+
<span class="text-primary-300">
|
|
1273
|
+
<span class="font-semibold text-primary-100">
|
|
1274
|
+
{formatNumber(props.following)}
|
|
1275
|
+
</span>{" "}
|
|
1276
|
+
siguiendo
|
|
1277
|
+
</span>
|
|
1278
|
+
</Show14>
|
|
1279
|
+
</div>
|
|
1280
|
+
</div>
|
|
1281
|
+
</div>
|
|
1282
|
+
<Show14 when={props.actions}>
|
|
1283
|
+
<div class="mt-4 flex gap-2">{props.actions}</div>
|
|
1284
|
+
</Show14>
|
|
1285
|
+
</div>;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
// src/custom/event-card/index.tsx
|
|
1289
|
+
import { Show as Show15, For as For3 } from "solid-js";
|
|
1290
|
+
function EventCard(props) {
|
|
1291
|
+
const displayedAttendees = () => props.attendees?.slice(0, 3) ?? [];
|
|
1292
|
+
const remainingCount = () => {
|
|
1293
|
+
const total = props.attendeeCount ?? props.attendees?.length ?? 0;
|
|
1294
|
+
const displayed = displayedAttendees().length;
|
|
1295
|
+
return total - displayed;
|
|
1296
|
+
};
|
|
1297
|
+
return <div class={`relative bg-bg-200 rounded-3xl overflow-hidden ${props.class ?? ""}`}>
|
|
1298
|
+
{
|
|
1299
|
+
/* Decoration image (fire gif, etc) */
|
|
1300
|
+
}
|
|
1301
|
+
<Show15 when={props.decorationImage}>
|
|
1302
|
+
<div class="absolute -top-2 -right-2 z-10 flex flex-col gap-1">
|
|
1303
|
+
<img src={props.decorationImage} alt="" class="w-8 h-8 object-contain" />
|
|
1304
|
+
<img src={props.decorationImage} alt="" class="w-6 h-6 object-contain ml-2" />
|
|
1305
|
+
<img src={props.decorationImage} alt="" class="w-5 h-5 object-contain" />
|
|
1306
|
+
</div>
|
|
1307
|
+
</Show15>
|
|
1308
|
+
|
|
1309
|
+
<Show15 when={props.image}>
|
|
1310
|
+
<div class="relative h-32 w-full">
|
|
1311
|
+
<img
|
|
1312
|
+
src={props.image}
|
|
1313
|
+
alt={props.title}
|
|
1314
|
+
class="w-full h-full object-cover"
|
|
1315
|
+
/>
|
|
1316
|
+
<div class="absolute inset-0 bg-gradient-to-t from-bg-200 via-transparent to-transparent" />
|
|
1317
|
+
</div>
|
|
1318
|
+
</Show15>
|
|
1319
|
+
|
|
1320
|
+
<div class="p-4 pt-2">
|
|
1321
|
+
<h3 class="font-bold text-xl leading-tight bg-gradient-to-r from-accent to-accent-300 bg-clip-text text-transparent">
|
|
1322
|
+
{props.title}
|
|
1323
|
+
</h3>
|
|
1324
|
+
|
|
1325
|
+
<Show15 when={props.date || props.author}>
|
|
1326
|
+
<div class="flex items-center gap-4 mt-3 text-sm text-primary-300">
|
|
1327
|
+
<Show15 when={props.author}>
|
|
1328
|
+
<div class="flex items-center gap-1.5">
|
|
1329
|
+
<span class="text-accent">@</span>
|
|
1330
|
+
<span>{props.author}</span>
|
|
1331
|
+
</div>
|
|
1332
|
+
</Show15>
|
|
1333
|
+
<Show15 when={props.date}>
|
|
1334
|
+
<div class="flex items-center gap-1.5">
|
|
1335
|
+
<span class="text-accent">⏱</span>
|
|
1336
|
+
<span>{props.date}</span>
|
|
1337
|
+
</div>
|
|
1338
|
+
</Show15>
|
|
1339
|
+
</div>
|
|
1340
|
+
</Show15>
|
|
1341
|
+
|
|
1342
|
+
<Show15 when={displayedAttendees().length > 0}>
|
|
1343
|
+
<div class="flex items-center mt-3">
|
|
1344
|
+
<div class="flex -space-x-2">
|
|
1345
|
+
<For3 each={displayedAttendees()}>
|
|
1346
|
+
{(attendee) => <Avatar src={attendee.avatar} alt={attendee.name} size="sm" />}
|
|
1347
|
+
</For3>
|
|
1348
|
+
</div>
|
|
1349
|
+
<Show15 when={remainingCount() > 0}>
|
|
1350
|
+
<span class="ml-2 text-sm text-primary-300">
|
|
1351
|
+
+{remainingCount()} más
|
|
1352
|
+
</span>
|
|
1353
|
+
</Show15>
|
|
1354
|
+
</div>
|
|
1355
|
+
</Show15>
|
|
1356
|
+
|
|
1357
|
+
<Show15 when={props.actions}>
|
|
1358
|
+
<div class="mt-4 flex gap-2">{props.actions}</div>
|
|
1359
|
+
</Show15>
|
|
1360
|
+
</div>
|
|
1361
|
+
</div>;
|
|
1362
|
+
}
|
|
1363
|
+
function EventListItem(props) {
|
|
1364
|
+
return <button
|
|
1365
|
+
class={`flex items-center gap-3 w-full p-2 rounded-lg hover:bg-bg-300 transition-colors text-left ${props.class ?? ""}`}
|
|
1366
|
+
onClick={props.onClick}
|
|
1367
|
+
>
|
|
1368
|
+
<Show15 when={props.image}>
|
|
1369
|
+
<div class="w-12 h-12 rounded-lg overflow-hidden flex-shrink-0">
|
|
1370
|
+
<img
|
|
1371
|
+
src={props.image}
|
|
1372
|
+
alt={props.title}
|
|
1373
|
+
class="w-full h-full object-cover"
|
|
1374
|
+
/>
|
|
1375
|
+
</div>
|
|
1376
|
+
</Show15>
|
|
1377
|
+
<div class="flex-1 min-w-0">
|
|
1378
|
+
<h4 class="font-medium text-primary-100 truncate">{props.title}</h4>
|
|
1379
|
+
<Show15 when={props.subtitle}>
|
|
1380
|
+
<p class="text-sm text-primary-300 truncate">{props.subtitle}</p>
|
|
1381
|
+
</Show15>
|
|
1382
|
+
</div>
|
|
1383
|
+
</button>;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
// src/custom/calendar-card/index.tsx
|
|
1387
|
+
import { Show as Show16, For as For4 } from "solid-js";
|
|
1388
|
+
function CalendarCard(props) {
|
|
1389
|
+
const displayedFollowers = () => props.followers?.slice(0, 2) ?? [];
|
|
1390
|
+
const remainingCount = () => {
|
|
1391
|
+
const total = props.followerCount ?? props.followers?.length ?? 0;
|
|
1392
|
+
const displayed = displayedFollowers().length;
|
|
1393
|
+
return total - displayed;
|
|
1394
|
+
};
|
|
1395
|
+
return <div class={`flex h-[100px] w-full max-w-[500px] items-center rounded-xl border border-primary-600 border-b-accent-500 bg-bg-300 p-2 ${props.class ?? ""}`}>
|
|
1396
|
+
<Show16 when={props.image}>
|
|
1397
|
+
<div class="relative h-[80px] w-[80px] flex-shrink-0 overflow-hidden rounded-xl border-2 border-accent-200">
|
|
1398
|
+
<img src={props.image} alt={props.title} class="h-full w-full object-cover" />
|
|
1399
|
+
</div>
|
|
1400
|
+
</Show16>
|
|
1401
|
+
<div class="relative h-full flex-1 flex-col pl-3">
|
|
1402
|
+
<Show16 when={props.tags && props.tags.length > 0}>
|
|
1403
|
+
<div class="absolute bottom-[-20px] h-[30px] w-full">
|
|
1404
|
+
<div class="flex h-full w-full flex-1 justify-end gap-1">
|
|
1405
|
+
<For4 each={props.tags}>
|
|
1406
|
+
{(tag) => <Chip text={tag} variant="primary" />}
|
|
1407
|
+
</For4>
|
|
1408
|
+
</div>
|
|
1409
|
+
</div>
|
|
1410
|
+
</Show16>
|
|
1411
|
+
<div class="flex h-full flex-col items-end justify-center pb-3 pr-5 pt-2">
|
|
1412
|
+
<div class="flex flex-1">
|
|
1413
|
+
<span class="text-lg font-semibold text-white drop-shadow-sm">
|
|
1414
|
+
{props.title}
|
|
1415
|
+
</span>
|
|
1416
|
+
</div>
|
|
1417
|
+
<Show16 when={displayedFollowers().length > 0}>
|
|
1418
|
+
<div class="flex flex-1">
|
|
1419
|
+
<span class="text-base font-normal text-primary-500">
|
|
1420
|
+
seguida por{" "}
|
|
1421
|
+
<For4 each={displayedFollowers()}>
|
|
1422
|
+
{(follower, index) => <>
|
|
1423
|
+
<span class="font-semibold text-accent-200">{follower.name}</span>
|
|
1424
|
+
{index() < displayedFollowers().length - 1 && ", "}
|
|
1425
|
+
</>}
|
|
1426
|
+
</For4>
|
|
1427
|
+
<Show16 when={remainingCount() > 0}>
|
|
1428
|
+
{" "}y <span class="font-semibold text-accent-200">{remainingCount()} más</span>
|
|
1429
|
+
</Show16>
|
|
1430
|
+
</span>
|
|
1431
|
+
</div>
|
|
1432
|
+
</Show16>
|
|
1433
|
+
</div>
|
|
1434
|
+
</div>
|
|
1435
|
+
</div>;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
// src/custom/logo/index.tsx
|
|
1439
|
+
function Logo(props) {
|
|
1440
|
+
const sizeClass = () => {
|
|
1441
|
+
switch (props.size) {
|
|
1442
|
+
case "sm":
|
|
1443
|
+
return "vui-logo--sm";
|
|
1444
|
+
case "lg":
|
|
1445
|
+
return "vui-logo--lg";
|
|
1446
|
+
case "xl":
|
|
1447
|
+
return "vui-logo--xl";
|
|
1448
|
+
case "md":
|
|
1449
|
+
default:
|
|
1450
|
+
return "vui-logo--md";
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
const firstWord = () => props.firstWord ?? "Proyecto";
|
|
1454
|
+
const secondWord = () => props.secondWord ?? "Viviana";
|
|
1455
|
+
return <span class={`vui-logo ${sizeClass()} ${props.class ?? ""}`}>
|
|
1456
|
+
<span class="vui-logo__first">{firstWord()}</span>
|
|
1457
|
+
<span class="vui-logo__second" data-text={secondWord()}>
|
|
1458
|
+
{secondWord()}
|
|
1459
|
+
</span>
|
|
1460
|
+
</span>;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
// src/custom/project-card/index.tsx
|
|
1464
|
+
function ProjectCard(props) {
|
|
1465
|
+
const size = () => props.size ?? "sm";
|
|
1466
|
+
const inactive = () => props.inactive ?? false;
|
|
1467
|
+
const cardContent = () => <>
|
|
1468
|
+
<div class="vui-project-card__tooltip">
|
|
1469
|
+
<span>{props.name}</span>
|
|
1470
|
+
</div>
|
|
1471
|
+
<img
|
|
1472
|
+
class="vui-project-card__image"
|
|
1473
|
+
src={props.imageSrc}
|
|
1474
|
+
alt={props.imageAlt ?? props.name}
|
|
1475
|
+
/>
|
|
1476
|
+
</>;
|
|
1477
|
+
const cardClasses = () => `vui-project-card vui-project-card--${size()} ${inactive() ? "vui-project-card--inactive" : ""} ${props.class ?? ""}`;
|
|
1478
|
+
if (props.href) {
|
|
1479
|
+
return <a href={props.href} target="_blank" rel="noopener noreferrer" class={cardClasses()}>
|
|
1480
|
+
{cardContent()}
|
|
1481
|
+
</a>;
|
|
1482
|
+
}
|
|
1483
|
+
return <div class={cardClasses()}>
|
|
1484
|
+
{cardContent()}
|
|
1485
|
+
</div>;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
// src/custom/page-layout/index.tsx
|
|
1489
|
+
import { splitProps as splitProps9 } from "solid-js";
|
|
1490
|
+
function PageLayout(props) {
|
|
1491
|
+
const [local, rest] = splitProps9(props, ["children", "class"]);
|
|
1492
|
+
return <div class={`vui-page ${local.class ?? ""}`} {...rest}>
|
|
1493
|
+
{local.children}
|
|
1494
|
+
</div>;
|
|
1495
|
+
}
|
|
1496
|
+
export {
|
|
1497
|
+
Alert,
|
|
1498
|
+
Avatar,
|
|
1499
|
+
AvatarGroup,
|
|
1500
|
+
Badge,
|
|
1501
|
+
Button,
|
|
1502
|
+
CalendarCard,
|
|
1503
|
+
Checkbox,
|
|
1504
|
+
CheckboxGroup,
|
|
1505
|
+
Chip,
|
|
1506
|
+
Conversation,
|
|
1507
|
+
ConversationBubble,
|
|
1508
|
+
ConversationPreview,
|
|
1509
|
+
Dialog,
|
|
1510
|
+
EventCard,
|
|
1511
|
+
EventListItem,
|
|
1512
|
+
GitHubIcon,
|
|
1513
|
+
Icon,
|
|
1514
|
+
LateralNav,
|
|
1515
|
+
Link,
|
|
1516
|
+
Logo,
|
|
1517
|
+
NavHeader,
|
|
1518
|
+
NavItem,
|
|
1519
|
+
NavLink,
|
|
1520
|
+
NavSection,
|
|
1521
|
+
PageLayout,
|
|
1522
|
+
ProfileCard,
|
|
1523
|
+
ProgressBar,
|
|
1524
|
+
ProjectCard,
|
|
1525
|
+
Radio,
|
|
1526
|
+
RadioGroup,
|
|
1527
|
+
Separator,
|
|
1528
|
+
TabSwitch,
|
|
1529
|
+
TextField,
|
|
1530
|
+
TimelineItem,
|
|
1531
|
+
ToggleSwitch,
|
|
1532
|
+
Tooltip
|
|
1533
|
+
};
|