domify-ui 1.0.2 → 1.0.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.js ADDED
@@ -0,0 +1,828 @@
1
+ // src/button.tsx
2
+ import * as React from "react";
3
+
4
+ // src/utils.ts
5
+ import { clsx } from "clsx";
6
+ import { twMerge } from "tailwind-merge";
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ // src/button.tsx
12
+ import { jsx } from "react/jsx-runtime";
13
+ var Button = React.forwardRef(
14
+ ({ className, variant = "default", size = "default", ...props }, ref) => {
15
+ return /* @__PURE__ */ jsx(
16
+ "button",
17
+ {
18
+ className: cn(
19
+ "inline-flex items-center justify-center text-sm transition-all",
20
+ "font-medium rounded-[10px]",
21
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[#0052CC]",
22
+ "disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed",
23
+ {
24
+ "bg-[#0052CC] text-white hover:bg-[#003d99] active:bg-[#002d73] shadow-sm hover:shadow-md": variant === "default",
25
+ "bg-[#FF7A00] text-white hover:bg-[#e66d00] active:bg-[#cc6000] shadow-sm hover:shadow-md": variant === "secondary",
26
+ "bg-red-600 text-white hover:bg-red-700 active:bg-red-800 shadow-sm hover:shadow-md": variant === "destructive",
27
+ "border-2 border-[#0052CC] bg-white text-[#0052CC] hover:bg-[#f0f5ff] hover:border-[#003d99]": variant === "outline",
28
+ "text-[#4A4A4A] hover:bg-gray-100 active:bg-gray-200": variant === "ghost"
29
+ },
30
+ {
31
+ "h-11 px-5 py-2.5": size === "default",
32
+ "h-9 px-3 py-2 text-xs": size === "sm",
33
+ "h-12 px-8 py-3": size === "lg"
34
+ },
35
+ className
36
+ ),
37
+ ref,
38
+ ...props
39
+ }
40
+ );
41
+ }
42
+ );
43
+ Button.displayName = "Button";
44
+
45
+ // src/input.tsx
46
+ import * as React2 from "react";
47
+ import { jsx as jsx2 } from "react/jsx-runtime";
48
+ var Input = React2.forwardRef(
49
+ ({ className, type, ...props }, ref) => {
50
+ return /* @__PURE__ */ jsx2(
51
+ "input",
52
+ {
53
+ type,
54
+ className: cn(
55
+ "flex h-11 w-full rounded-lg border-2 border-gray-300 bg-white px-4 py-2.5 text-sm text-[#0B2346] placeholder:text-[#888888] transition-all",
56
+ "hover:border-gray-400",
57
+ "focus:outline-none focus:ring-2 focus:ring-[#0052CC] focus:border-[#0052CC]",
58
+ "disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-gray-50",
59
+ className
60
+ ),
61
+ style: { fontFamily: "Inter, sans-serif" },
62
+ ref,
63
+ ...props
64
+ }
65
+ );
66
+ }
67
+ );
68
+ Input.displayName = "Input";
69
+
70
+ // src/select.tsx
71
+ import * as React3 from "react";
72
+ import { jsx as jsx3 } from "react/jsx-runtime";
73
+ var Select = React3.forwardRef(
74
+ ({ className, ...props }, ref) => {
75
+ return /* @__PURE__ */ jsx3(
76
+ "select",
77
+ {
78
+ className: cn(
79
+ "flex h-11 w-full rounded-lg border-2 border-gray-300 bg-white px-4 py-2.5 text-sm text-gray-900 transition-all",
80
+ "hover:border-gray-400",
81
+ "focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
82
+ "disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-gray-50",
83
+ className
84
+ ),
85
+ ref,
86
+ ...props
87
+ }
88
+ );
89
+ }
90
+ );
91
+ Select.displayName = "Select";
92
+
93
+ // src/textarea.tsx
94
+ import * as React4 from "react";
95
+ import { jsx as jsx4 } from "react/jsx-runtime";
96
+ var Textarea = React4.forwardRef(
97
+ ({ className, ...props }, ref) => {
98
+ return /* @__PURE__ */ jsx4(
99
+ "textarea",
100
+ {
101
+ className: cn(
102
+ "flex min-h-[100px] w-full rounded-lg border-2 border-gray-300 bg-white px-4 py-3 text-sm text-gray-900 placeholder:text-gray-500 transition-all",
103
+ "hover:border-gray-400",
104
+ "focus:outline-none focus:ring-2 focus:ring-[#0052CC] focus:border-[#0052CC]",
105
+ "disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-gray-50",
106
+ "resize-y",
107
+ className
108
+ ),
109
+ ref,
110
+ ...props
111
+ }
112
+ );
113
+ }
114
+ );
115
+ Textarea.displayName = "Textarea";
116
+
117
+ // src/checkbox.tsx
118
+ import * as React5 from "react";
119
+ import { jsx as jsx5, jsxs } from "react/jsx-runtime";
120
+ var Checkbox = React5.forwardRef(
121
+ ({ className, label, ...props }, ref) => {
122
+ return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
123
+ /* @__PURE__ */ jsx5(
124
+ "input",
125
+ {
126
+ type: "checkbox",
127
+ className: cn(
128
+ "w-5 h-5 rounded border-2 border-gray-300 text-blue-600 transition-all",
129
+ "hover:border-gray-400",
130
+ "focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
131
+ "disabled:cursor-not-allowed disabled:opacity-50",
132
+ "cursor-pointer",
133
+ className
134
+ ),
135
+ ref,
136
+ ...props
137
+ }
138
+ ),
139
+ label ? /* @__PURE__ */ jsx5("span", { className: "text-sm font-medium text-gray-700 select-none", children: label }) : null
140
+ ] });
141
+ }
142
+ );
143
+ Checkbox.displayName = "Checkbox";
144
+
145
+ // src/switch.tsx
146
+ import * as React6 from "react";
147
+ import { jsx as jsx6 } from "react/jsx-runtime";
148
+ var Switch = React6.forwardRef(
149
+ ({ id, checked = false, onCheckedChange, disabled = false, className }, ref) => {
150
+ const handleClick = () => {
151
+ if (!disabled && onCheckedChange) {
152
+ onCheckedChange(!checked);
153
+ }
154
+ };
155
+ return /* @__PURE__ */ jsx6(
156
+ "button",
157
+ {
158
+ type: "button",
159
+ id,
160
+ role: "switch",
161
+ "aria-checked": checked,
162
+ disabled,
163
+ onClick: handleClick,
164
+ ref,
165
+ className: cn(
166
+ "relative inline-flex h-6 w-11 items-center rounded-full transition-colors",
167
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2",
168
+ "disabled:cursor-not-allowed disabled:opacity-50",
169
+ checked ? "bg-[#0052CC]" : "bg-gray-300",
170
+ className
171
+ ),
172
+ children: /* @__PURE__ */ jsx6(
173
+ "span",
174
+ {
175
+ className: cn(
176
+ "inline-block h-5 w-5 transform rounded-full bg-white shadow-sm transition-transform",
177
+ checked ? "translate-x-6" : "translate-x-0.5"
178
+ )
179
+ }
180
+ )
181
+ }
182
+ );
183
+ }
184
+ );
185
+ Switch.displayName = "Switch";
186
+
187
+ // src/tabs.tsx
188
+ import * as React7 from "react";
189
+ import { jsx as jsx7 } from "react/jsx-runtime";
190
+ var TabsContext = React7.createContext(void 0);
191
+ function useTabsContext() {
192
+ const context = React7.useContext(TabsContext);
193
+ if (!context) {
194
+ throw new Error("Tabs components must be used within a Tabs component");
195
+ }
196
+ return context;
197
+ }
198
+ function Tabs({
199
+ defaultValue,
200
+ onValueChange,
201
+ children,
202
+ className,
203
+ ...props
204
+ }) {
205
+ const [value, setValue] = React7.useState(defaultValue);
206
+ const handleValueChange = React7.useCallback(
207
+ (newValue) => {
208
+ setValue(newValue);
209
+ onValueChange?.(newValue);
210
+ },
211
+ [onValueChange]
212
+ );
213
+ return /* @__PURE__ */ jsx7(TabsContext.Provider, { value: { value, onValueChange: handleValueChange }, children: /* @__PURE__ */ jsx7("div", { className: cn("w-full", className), ...props, children }) });
214
+ }
215
+ function TabsList({ children, className, ...props }) {
216
+ return /* @__PURE__ */ jsx7(
217
+ "div",
218
+ {
219
+ className: cn(
220
+ "inline-flex h-10 items-center justify-center rounded-lg bg-gray-100 p-1 text-gray-500",
221
+ className
222
+ ),
223
+ ...props,
224
+ children
225
+ }
226
+ );
227
+ }
228
+ function TabsTrigger({
229
+ value,
230
+ children,
231
+ className,
232
+ ...props
233
+ }) {
234
+ const { value: selectedValue, onValueChange } = useTabsContext();
235
+ const isSelected = value === selectedValue;
236
+ return /* @__PURE__ */ jsx7(
237
+ "button",
238
+ {
239
+ type: "button",
240
+ role: "tab",
241
+ "aria-selected": isSelected,
242
+ onClick: () => onValueChange(value),
243
+ className: cn(
244
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium transition-all",
245
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2",
246
+ "disabled:pointer-events-none disabled:opacity-50",
247
+ isSelected ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:bg-gray-50 hover:text-gray-900",
248
+ className
249
+ ),
250
+ ...props,
251
+ children
252
+ }
253
+ );
254
+ }
255
+ function TabsContent({
256
+ value,
257
+ children,
258
+ className,
259
+ ...props
260
+ }) {
261
+ const { value: selectedValue } = useTabsContext();
262
+ if (value !== selectedValue) return null;
263
+ return /* @__PURE__ */ jsx7("div", { role: "tabpanel", className: cn("mt-2", className), ...props, children });
264
+ }
265
+
266
+ // src/pagination.tsx
267
+ import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react";
268
+ import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
269
+ function Pagination({
270
+ currentPage,
271
+ totalPages,
272
+ totalItems,
273
+ perPage,
274
+ onPageChange,
275
+ className = ""
276
+ }) {
277
+ const startItem = (currentPage - 1) * perPage + 1;
278
+ const endItem = Math.min(currentPage * perPage, totalItems);
279
+ const getPageNumbers = () => {
280
+ const pages = [];
281
+ const maxVisiblePages = 5;
282
+ if (totalPages <= maxVisiblePages) {
283
+ for (let i = 1; i <= totalPages; i++) pages.push(i);
284
+ return pages;
285
+ }
286
+ pages.push(1);
287
+ if (currentPage > 3) pages.push("...");
288
+ const start = Math.max(2, currentPage - 1);
289
+ const end = Math.min(totalPages - 1, currentPage + 1);
290
+ for (let i = start; i <= end; i++) {
291
+ if (!pages.includes(i)) pages.push(i);
292
+ }
293
+ if (currentPage < totalPages - 2) pages.push("...");
294
+ if (!pages.includes(totalPages)) pages.push(totalPages);
295
+ return pages;
296
+ };
297
+ if (totalPages <= 1) {
298
+ return /* @__PURE__ */ jsxs2("div", { className: `flex items-center justify-center text-sm text-[#888888] ${className}`, children: [
299
+ "Mostrando ",
300
+ totalItems,
301
+ " de ",
302
+ totalItems,
303
+ " ",
304
+ totalItems === 1 ? "item" : "itens"
305
+ ] });
306
+ }
307
+ return /* @__PURE__ */ jsxs2("div", { className: `flex flex-col sm:flex-row items-center justify-between gap-4 ${className}`, children: [
308
+ /* @__PURE__ */ jsxs2("div", { className: "text-sm text-[#888888]", style: { fontFamily: "Inter" }, children: [
309
+ "Mostrando ",
310
+ startItem,
311
+ " a ",
312
+ endItem,
313
+ " de ",
314
+ totalItems,
315
+ " ",
316
+ totalItems === 1 ? "item" : "itens"
317
+ ] }),
318
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1", children: [
319
+ /* @__PURE__ */ jsx8(
320
+ Button,
321
+ {
322
+ variant: "outline",
323
+ size: "sm",
324
+ onClick: () => onPageChange(1),
325
+ disabled: currentPage === 1,
326
+ className: "hidden sm:flex",
327
+ children: /* @__PURE__ */ jsx8(ChevronsLeft, { size: 16 })
328
+ }
329
+ ),
330
+ /* @__PURE__ */ jsx8(
331
+ Button,
332
+ {
333
+ variant: "outline",
334
+ size: "sm",
335
+ onClick: () => onPageChange(currentPage - 1),
336
+ disabled: currentPage === 1,
337
+ children: /* @__PURE__ */ jsx8(ChevronLeft, { size: 16 })
338
+ }
339
+ ),
340
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-1", children: getPageNumbers().map(
341
+ (page, index) => page === "..." ? /* @__PURE__ */ jsx8("span", { className: "px-2 text-[#888888]", children: "..." }, `ellipsis-${index}`) : /* @__PURE__ */ jsx8(
342
+ Button,
343
+ {
344
+ variant: currentPage === page ? "default" : "outline",
345
+ size: "sm",
346
+ onClick: () => onPageChange(page),
347
+ className: "min-w-[36px]",
348
+ children: page
349
+ },
350
+ page
351
+ )
352
+ ) }),
353
+ /* @__PURE__ */ jsx8(
354
+ Button,
355
+ {
356
+ variant: "outline",
357
+ size: "sm",
358
+ onClick: () => onPageChange(currentPage + 1),
359
+ disabled: currentPage === totalPages,
360
+ children: /* @__PURE__ */ jsx8(ChevronRight, { size: 16 })
361
+ }
362
+ ),
363
+ /* @__PURE__ */ jsx8(
364
+ Button,
365
+ {
366
+ variant: "outline",
367
+ size: "sm",
368
+ onClick: () => onPageChange(totalPages),
369
+ disabled: currentPage === totalPages,
370
+ className: "hidden sm:flex",
371
+ children: /* @__PURE__ */ jsx8(ChevronsRight, { size: 16 })
372
+ }
373
+ )
374
+ ] })
375
+ ] });
376
+ }
377
+ function PaginationCompact({
378
+ currentPage,
379
+ totalPages,
380
+ onPageChange
381
+ }) {
382
+ if (totalPages <= 1) return null;
383
+ return /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-center gap-4", children: [
384
+ /* @__PURE__ */ jsxs2(
385
+ Button,
386
+ {
387
+ variant: "outline",
388
+ size: "sm",
389
+ onClick: () => onPageChange(currentPage - 1),
390
+ disabled: currentPage === 1,
391
+ children: [
392
+ /* @__PURE__ */ jsx8(ChevronLeft, { size: 16 }),
393
+ "Anterior"
394
+ ]
395
+ }
396
+ ),
397
+ /* @__PURE__ */ jsxs2("span", { className: "text-sm text-[#888888]", style: { fontFamily: "Inter" }, children: [
398
+ "Pagina ",
399
+ currentPage,
400
+ " de ",
401
+ totalPages
402
+ ] }),
403
+ /* @__PURE__ */ jsxs2(
404
+ Button,
405
+ {
406
+ variant: "outline",
407
+ size: "sm",
408
+ onClick: () => onPageChange(currentPage + 1),
409
+ disabled: currentPage === totalPages,
410
+ children: [
411
+ "Proxima",
412
+ /* @__PURE__ */ jsx8(ChevronRight, { size: 16 })
413
+ ]
414
+ }
415
+ )
416
+ ] });
417
+ }
418
+
419
+ // src/skeleton.tsx
420
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
421
+ function Skeleton({ className }) {
422
+ return /* @__PURE__ */ jsx9("div", { className: cn("animate-pulse rounded-md bg-gray-200", className) });
423
+ }
424
+ function PropertyCardSkeleton() {
425
+ return /* @__PURE__ */ jsxs3("div", { className: "bg-white rounded-lg shadow overflow-hidden", children: [
426
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-48 w-full rounded-none" }),
427
+ /* @__PURE__ */ jsxs3("div", { className: "p-4 space-y-3", children: [
428
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-1/4" }),
429
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-6 w-3/4" }),
430
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-1/2" }),
431
+ /* @__PURE__ */ jsxs3("div", { className: "flex gap-4 pt-2", children: [
432
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-16" }),
433
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-16" }),
434
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-16" })
435
+ ] }),
436
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-between pt-4", children: [
437
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-6 w-24" }),
438
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-8 w-20" })
439
+ ] })
440
+ ] })
441
+ ] });
442
+ }
443
+ function TableRowSkeleton({ columns = 5 }) {
444
+ return /* @__PURE__ */ jsx9("tr", { className: "border-b border-gray-100", children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx9("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-full" }) }, i)) });
445
+ }
446
+ function TableSkeleton({
447
+ rows = 5,
448
+ columns = 5
449
+ }) {
450
+ return /* @__PURE__ */ jsx9("div", { className: "bg-white rounded-lg shadow overflow-hidden", children: /* @__PURE__ */ jsx9("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs3("table", { className: "w-full", children: [
451
+ /* @__PURE__ */ jsx9("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsx9("tr", { children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx9("th", { className: "px-4 py-3 text-left", children: /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-20" }) }, i)) }) }),
452
+ /* @__PURE__ */ jsx9("tbody", { children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsx9(TableRowSkeleton, { columns }, i)) })
453
+ ] }) }) });
454
+ }
455
+ function ListItemSkeleton() {
456
+ return /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-4 p-4 bg-white rounded-lg shadow", children: [
457
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-12 w-12 rounded-full" }),
458
+ /* @__PURE__ */ jsxs3("div", { className: "flex-1 space-y-2", children: [
459
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-1/3" }),
460
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-3 w-1/2" })
461
+ ] }),
462
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-8 w-20" })
463
+ ] });
464
+ }
465
+ function StatsCardSkeleton() {
466
+ return /* @__PURE__ */ jsx9("div", { className: "bg-white rounded-lg shadow p-6", children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between", children: [
467
+ /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
468
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-24" }),
469
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-8 w-16" })
470
+ ] }),
471
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-12 w-12 rounded-full" })
472
+ ] }) });
473
+ }
474
+ function FormSkeleton({ fields = 4 }) {
475
+ return /* @__PURE__ */ jsxs3("div", { className: "bg-white rounded-lg shadow p-6 space-y-6", children: [
476
+ Array.from({ length: fields }).map((_, i) => /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
477
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-24" }),
478
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-10 w-full" })
479
+ ] }, i)),
480
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-end gap-4 pt-4", children: [
481
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-10 w-24" }),
482
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-10 w-32" })
483
+ ] })
484
+ ] });
485
+ }
486
+ function DetailPageSkeleton() {
487
+ return /* @__PURE__ */ jsxs3("div", { className: "space-y-6", children: [
488
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between", children: [
489
+ /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
490
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-8 w-48" }),
491
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-32" })
492
+ ] }),
493
+ /* @__PURE__ */ jsxs3("div", { className: "flex gap-2", children: [
494
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-10 w-24" }),
495
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-10 w-24" })
496
+ ] })
497
+ ] }),
498
+ /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-6", children: [
499
+ /* @__PURE__ */ jsxs3("div", { className: "lg:col-span-2 space-y-6", children: [
500
+ /* @__PURE__ */ jsxs3("div", { className: "bg-white rounded-lg shadow p-6 space-y-4", children: [
501
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-6 w-32" }),
502
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-full" }),
503
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-full" }),
504
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-3/4" })
505
+ ] }),
506
+ /* @__PURE__ */ jsxs3("div", { className: "bg-white rounded-lg shadow p-6 space-y-4", children: [
507
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-6 w-32" }),
508
+ /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-2 gap-4", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs3("div", { className: "space-y-1", children: [
509
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-20" }),
510
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-28" })
511
+ ] }, i)) })
512
+ ] })
513
+ ] }),
514
+ /* @__PURE__ */ jsx9("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs3("div", { className: "bg-white rounded-lg shadow p-6 space-y-4", children: [
515
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-6 w-24" }),
516
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-8 w-full" }),
517
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-4 w-full" })
518
+ ] }) })
519
+ ] })
520
+ ] });
521
+ }
522
+ function DashboardSkeleton() {
523
+ return /* @__PURE__ */ jsxs3("div", { className: "space-y-6", children: [
524
+ /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx9(StatsCardSkeleton, {}, i)) }),
525
+ /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [
526
+ /* @__PURE__ */ jsxs3("div", { className: "bg-white rounded-lg shadow p-6", children: [
527
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-6 w-32 mb-4" }),
528
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-64 w-full" })
529
+ ] }),
530
+ /* @__PURE__ */ jsxs3("div", { className: "bg-white rounded-lg shadow p-6", children: [
531
+ /* @__PURE__ */ jsx9(Skeleton, { className: "h-6 w-32 mb-4" }),
532
+ /* @__PURE__ */ jsx9("div", { className: "space-y-4", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx9(ListItemSkeleton, {}, i)) })
533
+ ] })
534
+ ] })
535
+ ] });
536
+ }
537
+
538
+ // src/searchable-select.tsx
539
+ import * as React8 from "react";
540
+ import { Search, ChevronDown } from "lucide-react";
541
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
542
+ var SearchableSelect = React8.forwardRef(
543
+ ({
544
+ options,
545
+ value,
546
+ onChange,
547
+ onBlur,
548
+ placeholder = "Selecione uma opcao...",
549
+ disabled = false,
550
+ className,
551
+ getOptionLabel = (option) => option.label,
552
+ filterFunction,
553
+ emptyMessage = "Nenhuma opcao encontrada",
554
+ name
555
+ }, ref) => {
556
+ const [isOpen, setIsOpen] = React8.useState(false);
557
+ const [searchTerm, setSearchTerm] = React8.useState("");
558
+ const containerRef = React8.useRef(null);
559
+ const inputRef = React8.useRef(null);
560
+ const listRef = React8.useRef(null);
561
+ const selectedOption = React8.useMemo(
562
+ () => options.find((opt) => opt.id === value) || null,
563
+ [options, value]
564
+ );
565
+ const filteredOptions = React8.useMemo(() => {
566
+ if (!searchTerm.trim()) return options;
567
+ const term = searchTerm.toLowerCase().trim();
568
+ if (filterFunction) return options.filter((option) => filterFunction(option, term));
569
+ return options.filter((option) => getOptionLabel(option).toLowerCase().includes(term));
570
+ }, [options, searchTerm, getOptionLabel, filterFunction]);
571
+ React8.useEffect(() => {
572
+ const handleClickOutside = (event) => {
573
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
574
+ setIsOpen(false);
575
+ setSearchTerm("");
576
+ }
577
+ };
578
+ if (!isOpen) return;
579
+ document.addEventListener("mousedown", handleClickOutside);
580
+ return () => document.removeEventListener("mousedown", handleClickOutside);
581
+ }, [isOpen]);
582
+ React8.useEffect(() => {
583
+ if (!isOpen || !listRef.current || !selectedOption) return;
584
+ const selectedIndex = filteredOptions.findIndex((opt) => opt.id === selectedOption.id);
585
+ if (selectedIndex < 0) return;
586
+ const selectedElement = listRef.current.children[selectedIndex];
587
+ selectedElement?.scrollIntoView({ block: "nearest" });
588
+ }, [isOpen, selectedOption, filteredOptions]);
589
+ const handleSelect = (option) => {
590
+ onChange?.(option.id);
591
+ setIsOpen(false);
592
+ setSearchTerm("");
593
+ onBlur?.();
594
+ };
595
+ const handleToggle = () => {
596
+ if (disabled) return;
597
+ setIsOpen((prev) => !prev);
598
+ setTimeout(() => inputRef.current?.focus(), 0);
599
+ };
600
+ const displayValue = selectedOption ? getOptionLabel(selectedOption) : "";
601
+ return /* @__PURE__ */ jsxs4("div", { ref: containerRef, className: cn("relative w-full", className), children: [
602
+ /* @__PURE__ */ jsxs4(
603
+ "div",
604
+ {
605
+ className: cn(
606
+ "flex h-11 w-full rounded-lg border-2 bg-white px-4 py-2.5 text-sm text-gray-900 transition-all cursor-pointer",
607
+ "hover:border-gray-400",
608
+ "focus-within:outline-none focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-blue-500",
609
+ disabled && "cursor-not-allowed opacity-50 bg-gray-50 hover:border-gray-300",
610
+ !isOpen && "border-gray-300"
611
+ ),
612
+ onClick: handleToggle,
613
+ children: [
614
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center flex-1 min-w-0", children: [
615
+ !isOpen && !displayValue ? /* @__PURE__ */ jsx10("span", { className: "text-gray-500", children: placeholder }) : null,
616
+ !isOpen && displayValue ? /* @__PURE__ */ jsx10("span", { className: "truncate", children: displayValue }) : null,
617
+ isOpen ? /* @__PURE__ */ jsx10(
618
+ "input",
619
+ {
620
+ ref: inputRef,
621
+ type: "text",
622
+ value: searchTerm,
623
+ onChange: (e) => {
624
+ if (disabled) return;
625
+ setSearchTerm(e.target.value);
626
+ setIsOpen(true);
627
+ },
628
+ placeholder,
629
+ className: "flex-1 outline-none bg-transparent text-gray-900 placeholder:text-gray-500",
630
+ onClick: (e) => e.stopPropagation(),
631
+ disabled
632
+ }
633
+ ) : null
634
+ ] }),
635
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 ml-2", children: [
636
+ /* @__PURE__ */ jsx10(Search, { size: 18, className: cn("text-gray-500 transition-transform", isOpen && "rotate-90") }),
637
+ /* @__PURE__ */ jsx10(
638
+ ChevronDown,
639
+ {
640
+ size: 18,
641
+ className: cn("text-gray-500 transition-transform", isOpen && "rotate-180")
642
+ }
643
+ )
644
+ ] })
645
+ ]
646
+ }
647
+ ),
648
+ isOpen ? /* @__PURE__ */ jsx10("div", { className: "absolute z-50 w-full mt-1 bg-white border-2 border-gray-300 rounded-lg shadow-lg max-h-60 overflow-hidden", children: /* @__PURE__ */ jsx10("ul", { ref: listRef, className: "overflow-y-auto max-h-60 py-1", role: "listbox", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx10("li", { className: "px-4 py-3 text-sm text-gray-500 text-center", children: emptyMessage }) : filteredOptions.map((option) => {
649
+ const isSelected = option.id === value;
650
+ const label = getOptionLabel(option);
651
+ return /* @__PURE__ */ jsx10(
652
+ "li",
653
+ {
654
+ role: "option",
655
+ "aria-selected": isSelected,
656
+ className: cn(
657
+ "px-4 py-2 cursor-pointer text-sm transition-colors",
658
+ "hover:bg-blue-50 hover:text-blue-900",
659
+ isSelected && "bg-blue-100 text-blue-900 font-medium"
660
+ ),
661
+ onClick: () => handleSelect(option),
662
+ children: label
663
+ },
664
+ option.id
665
+ );
666
+ }) }) }) : null,
667
+ name ? /* @__PURE__ */ jsx10("input", { ref, type: "hidden", name, value: value || "", readOnly: true }) : null
668
+ ] });
669
+ }
670
+ );
671
+ SearchableSelect.displayName = "SearchableSelect";
672
+
673
+ // src/currency-input.tsx
674
+ import * as React9 from "react";
675
+
676
+ // src/masks.ts
677
+ function maskCurrency(value) {
678
+ const numValue = typeof value === "string" ? parseFloat(value.replace(/\D/g, "")) / 100 : typeof value === "number" ? value : 0;
679
+ if (isNaN(numValue) || numValue === 0) return "";
680
+ return new Intl.NumberFormat("pt-BR", {
681
+ minimumFractionDigits: 2,
682
+ maximumFractionDigits: 2
683
+ }).format(numValue);
684
+ }
685
+ function unmaskCurrency(value) {
686
+ if (!value || value.trim() === "") return 0;
687
+ const cleaned = value.replace(/[^\d,.-]/g, "");
688
+ if (cleaned === "") return 0;
689
+ if (cleaned.includes(",")) {
690
+ const normalized = cleaned.replace(/\./g, "").replace(",", ".");
691
+ const numValue = parseFloat(normalized);
692
+ return isNaN(numValue) ? 0 : numValue;
693
+ }
694
+ const parts = cleaned.split(".");
695
+ if (parts.length === 2 && parts[1].length <= 2) {
696
+ return parseFloat(cleaned) || 0;
697
+ }
698
+ if (parts.length > 1) {
699
+ return parseFloat(cleaned.replace(/\./g, "")) || 0;
700
+ }
701
+ return parseFloat(cleaned) || 0;
702
+ }
703
+
704
+ // src/currency-input.tsx
705
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
706
+ var CurrencyInput = React9.forwardRef(
707
+ ({ className, value, onChange, error, ...props }, ref) => {
708
+ const [displayValue, setDisplayValue] = React9.useState("");
709
+ React9.useEffect(() => {
710
+ if (value === void 0 || value === null || value === "" || value === 0) {
711
+ setDisplayValue("");
712
+ return;
713
+ }
714
+ const numValue = typeof value === "string" ? parseFloat(value) : value;
715
+ setDisplayValue(!isNaN(numValue) && numValue > 0 ? maskCurrency(numValue) : "");
716
+ }, [value]);
717
+ const handleChange = (e) => {
718
+ const inputValue = e.target.value;
719
+ const cleaned = inputValue.replace(/[^\d,.-]/g, "");
720
+ if (cleaned === "" || cleaned.replace(/\D/g, "") === "") {
721
+ setDisplayValue("");
722
+ onChange?.(0);
723
+ return;
724
+ }
725
+ setDisplayValue(cleaned);
726
+ onChange?.(unmaskCurrency(cleaned));
727
+ };
728
+ const handleBlur = (e) => {
729
+ const cleaned = e.target.value.replace(/[^\d,.-]/g, "");
730
+ if (cleaned === "" || cleaned.replace(/\D/g, "") === "") {
731
+ setDisplayValue("");
732
+ onChange?.(0);
733
+ } else {
734
+ const numericValue = unmaskCurrency(cleaned);
735
+ setDisplayValue(maskCurrency(numericValue));
736
+ onChange?.(numericValue);
737
+ }
738
+ props.onBlur?.(e);
739
+ };
740
+ return /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
741
+ /* @__PURE__ */ jsx11("span", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-gray-500 text-sm", children: "R$" }),
742
+ /* @__PURE__ */ jsx11(
743
+ Input,
744
+ {
745
+ ...props,
746
+ ref,
747
+ type: "text",
748
+ value: displayValue,
749
+ onChange: handleChange,
750
+ onBlur: handleBlur,
751
+ className: cn("pl-10", error && "border-red-500 focus:ring-red-500 focus:border-red-500", className),
752
+ placeholder: "0,00"
753
+ }
754
+ )
755
+ ] });
756
+ }
757
+ );
758
+ CurrencyInput.displayName = "CurrencyInput";
759
+
760
+ // src/logo.tsx
761
+ import * as React10 from "react";
762
+ import Image from "next/image";
763
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
764
+ var sizeClasses = {
765
+ sm: { width: 100, height: 30 },
766
+ md: { width: 140, height: 42 },
767
+ lg: { width: 180, height: 54 },
768
+ xl: { width: 220, height: 66 }
769
+ };
770
+ var DomifyLogo = React10.forwardRef(
771
+ ({ className, size = "md", showTagline = false, variant = "orange", ...props }, ref) => {
772
+ const taglineColor = variant === "orange" ? "text-[#FF7A00]" : "text-gray-300";
773
+ const logoSrc = `/logo_${variant}.png`;
774
+ const dimensions = sizeClasses[size];
775
+ return /* @__PURE__ */ jsxs6("div", { ref, className: cn("inline-block", className), ...props, children: [
776
+ /* @__PURE__ */ jsx12(
777
+ Image,
778
+ {
779
+ src: logoSrc,
780
+ alt: "Domify",
781
+ width: dimensions.width,
782
+ height: dimensions.height,
783
+ priority: true,
784
+ className: "object-contain",
785
+ style: { width: "auto", height: "auto" }
786
+ }
787
+ ),
788
+ showTagline ? /* @__PURE__ */ jsx12(
789
+ "p",
790
+ {
791
+ className: cn("text-xs mt-1", taglineColor, {
792
+ "mt-0.5": size === "sm"
793
+ }),
794
+ style: { fontFamily: "Inter", fontWeight: 300 },
795
+ children: "Gestao Inteligente de Imoveis"
796
+ }
797
+ ) : null
798
+ ] });
799
+ }
800
+ );
801
+ DomifyLogo.displayName = "DomifyLogo";
802
+ export {
803
+ Button,
804
+ Checkbox,
805
+ CurrencyInput,
806
+ DashboardSkeleton,
807
+ DetailPageSkeleton,
808
+ DomifyLogo,
809
+ FormSkeleton,
810
+ Input,
811
+ ListItemSkeleton,
812
+ Pagination,
813
+ PaginationCompact,
814
+ PropertyCardSkeleton,
815
+ SearchableSelect,
816
+ Select,
817
+ Skeleton,
818
+ StatsCardSkeleton,
819
+ Switch,
820
+ TableRowSkeleton,
821
+ TableSkeleton,
822
+ Tabs,
823
+ TabsContent,
824
+ TabsList,
825
+ TabsTrigger,
826
+ Textarea
827
+ };
828
+ //# sourceMappingURL=index.js.map