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