@iclips/ui 2.0.0 → 2.0.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"month-range-picker.js","sources":["../../../../src/components/ui/forms/month-range-picker.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { CalendarIcon, ChevronLeft, ChevronRight, X } from \"lucide-react\";\n\nimport { cn } from \"../utils\";\nimport { Input } from \"./input\";\nimport { Button } from \"../primitives/button\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../overlays/popover\";\n\nconst MESES = [\"Jan\", \"Fev\", \"Mar\", \"Abr\", \"Mai\", \"Jun\", \"Jul\", \"Ago\", \"Set\", \"Out\", \"Nov\", \"Dez\"];\n\nexport interface MonthYearRange {\n from: Date;\n to: Date;\n}\n\nexport interface MonthRangePickerProps {\n /**\n * Intervalo de meses selecionado. `from`/`to` representam o 1º dia do mês.\n */\n value?: MonthYearRange;\n /**\n * Callback quando o intervalo muda\n */\n onChange?: (range: MonthYearRange | undefined) => void;\n /**\n * Placeholder do campo\n * @default \"Selecione um período\"\n */\n placeholder?: string;\n /**\n * Desabilita o componente\n */\n disabled?: boolean;\n /**\n * Ano mínimo navegável\n * @default 2020\n */\n minYear?: number;\n /**\n * Ano máximo navegável\n * @default anoAtual + 5\n */\n maxYear?: number;\n /**\n * Classes CSS adicionais para o trigger\n */\n className?: string;\n /**\n * Estado de erro\n */\n error?: boolean;\n /**\n * ID do campo para acessibilidade\n */\n id?: string;\n /**\n * Nome do campo para formulários\n */\n name?: string;\n}\n\nfunction monthKey(year: number, month: number) {\n return year * 12 + month;\n}\n\nfunction formatMesAno(date: Date) {\n return `${MESES[date.getMonth()]}/${date.getFullYear()}`;\n}\n\nfunction parseMesAno(input: string): Date | null {\n const match = input.trim().match(/^([A-Za-zÀ-ÿ]{3,}|\\d{1,2})\\/(\\d{4})$/);\n if (!match) return null;\n\n const [, monthRaw, yearRaw] = match;\n const year = Number(yearRaw);\n if (Number.isNaN(year)) return null;\n\n let month: number;\n if (/^\\d+$/.test(monthRaw)) {\n month = Number(monthRaw);\n } else {\n const idx = MESES.findIndex((m) => m.toLowerCase() === monthRaw.toLowerCase().slice(0, 3));\n if (idx === -1) return null;\n month = idx + 1;\n }\n if (month < 1 || month > 12) return null;\n\n return new Date(year, month - 1, 1);\n}\n\nfunction parseInputRange(input: string): MonthYearRange | null {\n const trimmed = input.trim();\n if (!trimmed) return null;\n\n const separators = [\"→\", \"-\", \"até\", \"a\"];\n for (const sep of separators) {\n if (!trimmed.includes(sep)) continue;\n const parts = trimmed.split(sep).map((p) => p.trim());\n if (parts.length !== 2) continue;\n\n const from = parseMesAno(parts[0]);\n const to = parseMesAno(parts[1]);\n if (from && to) {\n // Mês final anterior ao inicial é inválido (não é corrigido silenciosamente) — dispara estado de erro no input\n if (monthKey(from.getFullYear(), from.getMonth() + 1) > monthKey(to.getFullYear(), to.getMonth() + 1)) {\n return null;\n }\n return { from, to };\n }\n }\n\n return null;\n}\n\ninterface MonthPanelProps {\n titulo: string;\n year: number;\n onYearChange: (year: number) => void;\n minYear: number;\n maxYear: number;\n selectedMonth: number;\n selectedYear: number;\n onSelect: (year: number, month: number) => void;\n isMonthDisabled?: (year: number, month: number) => boolean;\n}\n\nfunction PainelMes({\n titulo,\n year,\n onYearChange,\n minYear,\n maxYear,\n selectedMonth,\n selectedYear,\n onSelect,\n isMonthDisabled,\n}: MonthPanelProps) {\n return (\n <div className=\"p-3 w-56\">\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">{titulo}</p>\n <div className=\"flex items-center justify-center mb-2 gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0\"\n onClick={() => onYearChange(Math.max(minYear, year - 1))}\n disabled={year <= minYear}\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <Input\n type=\"number\"\n className=\"w-20 text-center h-8\"\n value={year}\n min={minYear}\n max={maxYear}\n onChange={(e) => {\n const parsed = Number(e.target.value);\n if (!Number.isNaN(parsed)) onYearChange(parsed);\n }}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0\"\n onClick={() => onYearChange(Math.min(maxYear, year + 1))}\n disabled={year >= maxYear}\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n <div className=\"grid grid-cols-3 gap-1\">\n {MESES.map((label, idx) => {\n const month = idx + 1;\n const disabled = isMonthDisabled?.(year, month) ?? false;\n const selected = year === selectedYear && month === selectedMonth;\n return (\n <Button\n key={label}\n type=\"button\"\n variant={selected ? \"default\" : \"ghost\"}\n size=\"sm\"\n className=\"px-0\"\n disabled={disabled}\n onClick={() => onSelect(year, month)}\n >\n {label}\n </Button>\n );\n })}\n </div>\n </div>\n );\n}\n\n/**\n * MonthRangePicker - Seleção de intervalo de meses (Mês/Ano Início + Mês/Ano Fim)\n *\n * @example\n * <MonthRangePicker\n * value={periodo}\n * onChange={setPeriodo}\n * placeholder=\"Selecione o período\"\n * />\n *\n * @example\n * // Digitação direta\n * // Set/2025 → Mar/2026\n * // 09/2025 - 03/2026\n */\nconst MonthRangePicker = React.forwardRef<\n React.ElementRef<typeof Input>,\n MonthRangePickerProps\n>(({\n value,\n onChange,\n placeholder = \"Selecione um período\",\n disabled = false,\n minYear = 2020,\n maxYear = new Date().getFullYear() + 5,\n className,\n error = false,\n id,\n name,\n}, ref) => {\n const [open, setOpen] = React.useState(false);\n const [pending, setPending] = React.useState<MonthYearRange | undefined>(value);\n const [inputValue, setInputValue] = React.useState(\"\");\n const [isInvalid, setIsInvalid] = React.useState(false);\n const [yearInicio, setYearInicio] = React.useState(() => (value?.from ?? new Date()).getFullYear());\n const [yearFim, setYearFim] = React.useState(() => (value?.to ?? new Date()).getFullYear());\n\n React.useEffect(() => {\n setPending(value);\n if (value?.from) setYearInicio(value.from.getFullYear());\n if (value?.to) setYearFim(value.to.getFullYear());\n\n if (value?.from && value?.to) {\n setInputValue(`${formatMesAno(value.from)} → ${formatMesAno(value.to)}`);\n } else {\n setInputValue(\"\");\n }\n setIsInvalid(false);\n }, [value]);\n\n const handleSelectInicio = (year: number, month: number) => {\n const from = new Date(year, month - 1, 1);\n const to = pending?.to && monthKey(pending.to.getFullYear(), pending.to.getMonth() + 1) >= monthKey(year, month)\n ? pending.to\n : from;\n setPending({ from, to });\n };\n\n const handleSelectFim = (year: number, month: number) => {\n if (!pending?.from) return;\n const to = new Date(year, month - 1, 1);\n setPending({ from: pending.from, to });\n };\n\n const isFimDisabled = (year: number, month: number) => {\n if (!pending?.from) return false;\n return monthKey(year, month) < monthKey(pending.from.getFullYear(), pending.from.getMonth() + 1);\n };\n\n const handleConfirm = () => {\n onChange?.(pending);\n setOpen(false);\n };\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n setPending(undefined);\n setInputValue(\"\");\n setIsInvalid(false);\n onChange?.(undefined);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n setInputValue(e.target.value);\n setIsInvalid(false);\n };\n\n const handleInputBlur = () => {\n if (disabled) return;\n if (!inputValue.trim()) {\n setPending(undefined);\n onChange?.(undefined);\n setIsInvalid(false);\n return;\n }\n\n const parsed = parseInputRange(inputValue);\n if (parsed) {\n setPending(parsed);\n setYearInicio(parsed.from.getFullYear());\n setYearFim(parsed.to.getFullYear());\n onChange?.(parsed);\n setIsInvalid(false);\n } else {\n setIsInvalid(true);\n }\n };\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n handleInputBlur();\n if (!isInvalid) setOpen(true);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n if (value?.from && value?.to) {\n setInputValue(`${formatMesAno(value.from)} → ${formatMesAno(value.to)}`);\n } else {\n setInputValue(\"\");\n }\n setIsInvalid(false);\n }\n };\n\n return (\n <Popover open={!disabled && open} onOpenChange={(o) => { if (!disabled) setOpen(o); }}>\n <div className=\"relative w-full\">\n <Input\n ref={ref}\n id={id}\n name={name}\n value={inputValue}\n onChange={handleInputChange}\n onBlur={handleInputBlur}\n onKeyDown={handleInputKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n aria-invalid={error || isInvalid}\n className={cn(\n \"pr-20\",\n (error || isInvalid) && \"border-destructive focus-visible:ring-destructive/20\",\n className,\n )}\n />\n <div className=\"absolute inset-y-0 right-0 flex items-center gap-1 pr-1\">\n {inputValue && !disabled && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0 hover:bg-transparent\"\n onClick={handleClear}\n tabIndex={-1}\n >\n <X className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n <span className=\"sr-only\">Limpar</span>\n </Button>\n )}\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0 hover:bg-transparent\"\n disabled={disabled}\n aria-label=\"Abrir calendário\"\n >\n <CalendarIcon className=\"h-4 w-4 text-muted-foreground\" />\n </Button>\n </PopoverTrigger>\n </div>\n </div>\n <PopoverContent align=\"start\" className=\"w-auto p-0 max-w-[calc(100vw-2rem)]\">\n <div className=\"flex flex-col sm:flex-row divide-y sm:divide-y-0 sm:divide-x\">\n <PainelMes\n titulo=\"Mês inicial\"\n year={yearInicio}\n onYearChange={setYearInicio}\n minYear={minYear}\n maxYear={maxYear}\n selectedYear={pending?.from?.getFullYear() ?? -1}\n selectedMonth={(pending?.from?.getMonth() ?? -2) + 1}\n onSelect={handleSelectInicio}\n />\n <PainelMes\n titulo=\"Mês final\"\n year={yearFim}\n onYearChange={setYearFim}\n minYear={minYear}\n maxYear={maxYear}\n selectedYear={pending?.to?.getFullYear() ?? -1}\n selectedMonth={(pending?.to?.getMonth() ?? -2) + 1}\n onSelect={handleSelectFim}\n isMonthDisabled={isFimDisabled}\n />\n </div>\n <div className=\"border-t p-3 flex justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={handleClear}>\n Limpar\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={!pending?.from || !pending?.to}\n onClick={handleConfirm}\n >\n Confirmar\n </Button>\n </div>\n </PopoverContent>\n </Popover>\n );\n});\n\nMonthRangePicker.displayName = \"MonthRangePicker\";\n\nexport { MonthRangePicker };\n"],"names":["MESES","monthKey","year","month","formatMesAno","date","parseMesAno","input","match","monthRaw","yearRaw","idx","m","parseInputRange","trimmed","separators","sep","parts","p","from","to","PainelMes","titulo","onYearChange","minYear","maxYear","selectedMonth","selectedYear","onSelect","isMonthDisabled","jsxs","jsx","Button","ChevronLeft","Input","e","parsed","ChevronRight","label","disabled","MonthRangePicker","React","value","onChange","placeholder","className","error","id","name","ref","open","setOpen","pending","setPending","inputValue","setInputValue","isInvalid","setIsInvalid","yearInicio","setYearInicio","yearFim","setYearFim","handleSelectInicio","handleSelectFim","isFimDisabled","handleConfirm","handleClear","handleInputChange","handleInputBlur","Popover","cn","X","PopoverTrigger","CalendarIcon","PopoverContent","_a","_b","_c","_d"],"mappings":"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"}
1
+ {"version":3,"file":"month-range-picker.js","sources":["../../../../src/components/ui/forms/month-range-picker.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { CalendarIcon, ChevronLeft, ChevronRight, X } from \"lucide-react\";\n\nimport { cn } from \"../utils\";\nimport { useControllableValue } from \"../use-controllable-value\";\nimport { Input } from \"./input\";\nimport { Button } from \"../primitives/button\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../overlays/popover\";\n\nconst MESES = [\"Jan\", \"Fev\", \"Mar\", \"Abr\", \"Mai\", \"Jun\", \"Jul\", \"Ago\", \"Set\", \"Out\", \"Nov\", \"Dez\"];\n\nexport interface MonthYearRange {\n from: Date;\n to: Date;\n}\n\nexport interface MonthRangePickerProps {\n /**\n * Intervalo de meses selecionado (modo controlado). `from`/`to` representam o\n * 1º dia do mês. Omita para o modo não-controlado.\n */\n value?: MonthYearRange;\n /**\n * Valor inicial no modo não-controlado (quando `value` não é passado).\n */\n defaultValue?: MonthYearRange;\n /**\n * Callback quando o intervalo muda. Chamado nos dois modos.\n */\n onChange?: (range: MonthYearRange | undefined) => void;\n /**\n * Placeholder do campo\n * @default \"Selecione um período\"\n */\n placeholder?: string;\n /**\n * Desabilita o componente\n */\n disabled?: boolean;\n /**\n * Ano mínimo navegável\n * @default 2020\n */\n minYear?: number;\n /**\n * Ano máximo navegável\n * @default anoAtual + 5\n */\n maxYear?: number;\n /**\n * Classes CSS adicionais para o trigger\n */\n className?: string;\n /**\n * Estado de erro\n */\n error?: boolean;\n /**\n * ID do campo para acessibilidade\n */\n id?: string;\n /**\n * Nome do campo para formulários\n */\n name?: string;\n}\n\nfunction monthKey(year: number, month: number) {\n return year * 12 + month;\n}\n\nfunction formatMesAno(date: Date) {\n return `${MESES[date.getMonth()]}/${date.getFullYear()}`;\n}\n\nfunction parseMesAno(input: string): Date | null {\n const match = input.trim().match(/^([A-Za-zÀ-ÿ]{3,}|\\d{1,2})\\/(\\d{4})$/);\n if (!match) return null;\n\n const [, monthRaw, yearRaw] = match;\n const year = Number(yearRaw);\n if (Number.isNaN(year)) return null;\n\n let month: number;\n if (/^\\d+$/.test(monthRaw)) {\n month = Number(monthRaw);\n } else {\n const idx = MESES.findIndex((m) => m.toLowerCase() === monthRaw.toLowerCase().slice(0, 3));\n if (idx === -1) return null;\n month = idx + 1;\n }\n if (month < 1 || month > 12) return null;\n\n return new Date(year, month - 1, 1);\n}\n\nfunction parseInputRange(input: string): MonthYearRange | null {\n const trimmed = input.trim();\n if (!trimmed) return null;\n\n const separators = [\"→\", \"-\", \"até\", \"a\"];\n for (const sep of separators) {\n if (!trimmed.includes(sep)) continue;\n const parts = trimmed.split(sep).map((p) => p.trim());\n if (parts.length !== 2) continue;\n\n const from = parseMesAno(parts[0]);\n const to = parseMesAno(parts[1]);\n if (from && to) {\n // Mês final anterior ao inicial é inválido (não é corrigido silenciosamente) — dispara estado de erro no input\n if (monthKey(from.getFullYear(), from.getMonth() + 1) > monthKey(to.getFullYear(), to.getMonth() + 1)) {\n return null;\n }\n return { from, to };\n }\n }\n\n return null;\n}\n\ninterface MonthPanelProps {\n titulo: string;\n year: number;\n onYearChange: (year: number) => void;\n minYear: number;\n maxYear: number;\n selectedMonth: number;\n selectedYear: number;\n onSelect: (year: number, month: number) => void;\n isMonthDisabled?: (year: number, month: number) => boolean;\n}\n\nfunction PainelMes({\n titulo,\n year,\n onYearChange,\n minYear,\n maxYear,\n selectedMonth,\n selectedYear,\n onSelect,\n isMonthDisabled,\n}: MonthPanelProps) {\n return (\n <div className=\"p-3 w-56\">\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">{titulo}</p>\n <div className=\"flex items-center justify-center mb-2 gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0\"\n onClick={() => onYearChange(Math.max(minYear, year - 1))}\n disabled={year <= minYear}\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <Input\n type=\"number\"\n className=\"w-20 text-center h-8\"\n value={year}\n min={minYear}\n max={maxYear}\n onChange={(e) => {\n const parsed = Number(e.target.value);\n if (!Number.isNaN(parsed)) onYearChange(parsed);\n }}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0\"\n onClick={() => onYearChange(Math.min(maxYear, year + 1))}\n disabled={year >= maxYear}\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n <div className=\"grid grid-cols-3 gap-1\">\n {MESES.map((label, idx) => {\n const month = idx + 1;\n const disabled = isMonthDisabled?.(year, month) ?? false;\n const selected = year === selectedYear && month === selectedMonth;\n return (\n <Button\n key={label}\n type=\"button\"\n variant={selected ? \"default\" : \"ghost\"}\n size=\"sm\"\n className=\"px-0\"\n disabled={disabled}\n onClick={() => onSelect(year, month)}\n >\n {label}\n </Button>\n );\n })}\n </div>\n </div>\n );\n}\n\n/**\n * MonthRangePicker - Seleção de intervalo de meses (Mês/Ano Início + Mês/Ano Fim)\n *\n * @example\n * <MonthRangePicker\n * value={periodo}\n * onChange={setPeriodo}\n * placeholder=\"Selecione o período\"\n * />\n *\n * @example\n * // Digitação direta\n * // Set/2025 → Mar/2026\n * // 09/2025 - 03/2026\n */\nconst MonthRangePicker = React.forwardRef<\n React.ElementRef<typeof Input>,\n MonthRangePickerProps\n>(({\n value: valueProp,\n defaultValue,\n onChange,\n placeholder = \"Selecione um período\",\n disabled = false,\n minYear = 2020,\n maxYear = new Date().getFullYear() + 5,\n className,\n error = false,\n id,\n name,\n}, ref) => {\n const [value, setValue] = useControllableValue<MonthYearRange>(valueProp, defaultValue, onChange);\n const [open, setOpen] = React.useState(false);\n const [pending, setPending] = React.useState<MonthYearRange | undefined>(value);\n const [inputValue, setInputValue] = React.useState(\"\");\n const [isInvalid, setIsInvalid] = React.useState(false);\n const [yearInicio, setYearInicio] = React.useState(() => (value?.from ?? new Date()).getFullYear());\n const [yearFim, setYearFim] = React.useState(() => (value?.to ?? new Date()).getFullYear());\n\n React.useEffect(() => {\n setPending(value);\n if (value?.from) setYearInicio(value.from.getFullYear());\n if (value?.to) setYearFim(value.to.getFullYear());\n\n if (value?.from && value?.to) {\n setInputValue(`${formatMesAno(value.from)} → ${formatMesAno(value.to)}`);\n } else {\n setInputValue(\"\");\n }\n setIsInvalid(false);\n }, [value]);\n\n const handleSelectInicio = (year: number, month: number) => {\n const from = new Date(year, month - 1, 1);\n const to = pending?.to && monthKey(pending.to.getFullYear(), pending.to.getMonth() + 1) >= monthKey(year, month)\n ? pending.to\n : from;\n setPending({ from, to });\n };\n\n const handleSelectFim = (year: number, month: number) => {\n if (!pending?.from) return;\n const to = new Date(year, month - 1, 1);\n setPending({ from: pending.from, to });\n };\n\n const isFimDisabled = (year: number, month: number) => {\n if (!pending?.from) return false;\n return monthKey(year, month) < monthKey(pending.from.getFullYear(), pending.from.getMonth() + 1);\n };\n\n const handleConfirm = () => {\n setValue(pending);\n setOpen(false);\n };\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n setPending(undefined);\n setInputValue(\"\");\n setIsInvalid(false);\n setValue(undefined);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n // Aceita \"09/2026\" e \"Set/2026\" (nome do mês) — filtra pontuação/símbolos fora disso.\n setInputValue(e.target.value.replace(/[^A-Za-zÀ-ÿ\\d/\\s→-]/g, \"\"));\n setIsInvalid(false);\n };\n\n const handleInputBlur = () => {\n if (disabled) return;\n if (!inputValue.trim()) {\n setPending(undefined);\n setValue(undefined);\n setIsInvalid(false);\n return;\n }\n\n const parsed = parseInputRange(inputValue);\n if (parsed) {\n setPending(parsed);\n setYearInicio(parsed.from.getFullYear());\n setYearFim(parsed.to.getFullYear());\n setValue(parsed);\n setIsInvalid(false);\n } else {\n setIsInvalid(true);\n }\n };\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n handleInputBlur();\n if (!isInvalid) setOpen(true);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n if (value?.from && value?.to) {\n setInputValue(`${formatMesAno(value.from)} → ${formatMesAno(value.to)}`);\n } else {\n setInputValue(\"\");\n }\n setIsInvalid(false);\n }\n };\n\n return (\n <Popover open={!disabled && open} onOpenChange={(o) => { if (!disabled) setOpen(o); }}>\n <div className=\"relative w-full\">\n <Input\n ref={ref}\n id={id}\n name={name}\n value={inputValue}\n onChange={handleInputChange}\n onBlur={handleInputBlur}\n onKeyDown={handleInputKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n aria-invalid={error || isInvalid}\n className={cn(\n \"pr-20\",\n (error || isInvalid) && \"border-destructive focus-visible:ring-destructive/20\",\n className,\n )}\n />\n <div className=\"absolute inset-y-0 right-0 flex items-center gap-1 pr-1\">\n {inputValue && !disabled && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0 hover:bg-transparent\"\n onClick={handleClear}\n tabIndex={-1}\n >\n <X className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n <span className=\"sr-only\">Limpar</span>\n </Button>\n )}\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-7 p-0 hover:bg-transparent\"\n disabled={disabled}\n aria-label=\"Abrir calendário\"\n >\n <CalendarIcon className=\"h-4 w-4 text-muted-foreground\" />\n </Button>\n </PopoverTrigger>\n </div>\n </div>\n <PopoverContent align=\"start\" className=\"w-auto p-0 max-w-[calc(100vw-2rem)]\">\n <div className=\"flex flex-col sm:flex-row divide-y sm:divide-y-0 sm:divide-x\">\n <PainelMes\n titulo=\"Mês inicial\"\n year={yearInicio}\n onYearChange={setYearInicio}\n minYear={minYear}\n maxYear={maxYear}\n selectedYear={pending?.from?.getFullYear() ?? -1}\n selectedMonth={(pending?.from?.getMonth() ?? -2) + 1}\n onSelect={handleSelectInicio}\n />\n <PainelMes\n titulo=\"Mês final\"\n year={yearFim}\n onYearChange={setYearFim}\n minYear={minYear}\n maxYear={maxYear}\n selectedYear={pending?.to?.getFullYear() ?? -1}\n selectedMonth={(pending?.to?.getMonth() ?? -2) + 1}\n onSelect={handleSelectFim}\n isMonthDisabled={isFimDisabled}\n />\n </div>\n <div className=\"border-t p-3 flex justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={handleClear}>\n Limpar\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={!pending?.from || !pending?.to}\n onClick={handleConfirm}\n >\n Confirmar\n </Button>\n </div>\n </PopoverContent>\n </Popover>\n );\n});\n\nMonthRangePicker.displayName = \"MonthRangePicker\";\n\nexport { MonthRangePicker };\n"],"names":["MESES","monthKey","year","month","formatMesAno","date","parseMesAno","input","match","monthRaw","yearRaw","idx","m","parseInputRange","trimmed","separators","sep","parts","p","from","to","PainelMes","titulo","onYearChange","minYear","maxYear","selectedMonth","selectedYear","onSelect","isMonthDisabled","jsxs","jsx","Button","ChevronLeft","Input","e","parsed","ChevronRight","label","disabled","MonthRangePicker","React","valueProp","defaultValue","onChange","placeholder","className","error","id","name","ref","value","setValue","useControllableValue","open","setOpen","pending","setPending","inputValue","setInputValue","isInvalid","setIsInvalid","yearInicio","setYearInicio","yearFim","setYearFim","handleSelectInicio","handleSelectFim","isFimDisabled","handleConfirm","handleClear","handleInputChange","handleInputBlur","Popover","o","cn","X","PopoverTrigger","CalendarIcon","PopoverContent","_a","_b","_c","_d"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react");function i(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const e in t)if(e!=="default"){const o=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(r,e,o.get?o:{enumerable:!0,get:()=>t[e]})}}return r.default=t,Object.freeze(r)}const c=i(a);function b(t,r,e){const[o,n]=c.useState(t??r),s=t!==void 0?t:o,u=c.useCallback(l=>{n(l),e==null||e(l)},[e]);return[s,u]}exports.useControllableValue=b;
2
+ //# sourceMappingURL=use-controllable-value.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-controllable-value.cjs","sources":["../../../src/components/ui/use-controllable-value.ts"],"sourcesContent":["import * as React from \"react\";\n\n/**\n * Estado que funciona nos dois modos, sem o consumidor precisar escolher:\n *\n * - **controlado** — `value` é passado: o componente reflete `value` e só\n * comunica mudanças via `onChange` (quem decide o próximo valor é o pai).\n * - **não-controlado** — `value` é `undefined`: o componente guarda o próprio\n * estado (iniciado em `defaultValue`) e continua chamando `onChange` quando\n * muda, para quem quiser só observar.\n *\n * Mesmo padrão de `number-input.tsx`. `setInternal` é sempre chamado (mantém o\n * estado interno como sombra do valor mesmo no modo controlado), então limpar\n * um valor no modo controlado volta a `undefined` de verdade em vez de reexibir\n * o último valor interno. Alternar entre os dois modos durante a vida do\n * componente não é suportado — é a mesma regra do React para `<input>`.\n */\nexport function useControllableValue<T>(\n value: T | undefined,\n defaultValue: T | undefined,\n onChange?: (next: T | undefined) => void,\n): [T | undefined, (next: T | undefined) => void] {\n const [internal, setInternal] = React.useState<T | undefined>(value ?? defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const set = React.useCallback(\n (next: T | undefined) => {\n setInternal(next);\n onChange?.(next);\n },\n [onChange],\n );\n\n return [current, set];\n}\n"],"names":["useControllableValue","value","defaultValue","onChange","internal","setInternal","React","current","set","next"],"mappings":"mYAiBO,SAASA,EACdC,EACAC,EACAC,EACgD,CAChD,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAM,SAAwBL,GAASC,CAAY,EAE7EK,EADeN,IAAU,OACAA,EAAQG,EAEjCI,EAAMF,EAAM,YACfG,GAAwB,CACvBJ,EAAYI,CAAI,EAChBN,GAAA,MAAAA,EAAWM,EACb,EACA,CAACN,CAAQ,CAAA,EAGX,MAAO,CAACI,EAASC,CAAG,CACtB"}
@@ -0,0 +1,14 @@
1
+ import * as l from "react";
2
+ function d(r, o, t) {
3
+ const [c, e] = l.useState(r ?? o), i = r !== void 0 ? r : c, u = l.useCallback(
4
+ (s) => {
5
+ e(s), t == null || t(s);
6
+ },
7
+ [t]
8
+ );
9
+ return [i, u];
10
+ }
11
+ export {
12
+ d as useControllableValue
13
+ };
14
+ //# sourceMappingURL=use-controllable-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-controllable-value.js","sources":["../../../src/components/ui/use-controllable-value.ts"],"sourcesContent":["import * as React from \"react\";\n\n/**\n * Estado que funciona nos dois modos, sem o consumidor precisar escolher:\n *\n * - **controlado** — `value` é passado: o componente reflete `value` e só\n * comunica mudanças via `onChange` (quem decide o próximo valor é o pai).\n * - **não-controlado** — `value` é `undefined`: o componente guarda o próprio\n * estado (iniciado em `defaultValue`) e continua chamando `onChange` quando\n * muda, para quem quiser só observar.\n *\n * Mesmo padrão de `number-input.tsx`. `setInternal` é sempre chamado (mantém o\n * estado interno como sombra do valor mesmo no modo controlado), então limpar\n * um valor no modo controlado volta a `undefined` de verdade em vez de reexibir\n * o último valor interno. Alternar entre os dois modos durante a vida do\n * componente não é suportado — é a mesma regra do React para `<input>`.\n */\nexport function useControllableValue<T>(\n value: T | undefined,\n defaultValue: T | undefined,\n onChange?: (next: T | undefined) => void,\n): [T | undefined, (next: T | undefined) => void] {\n const [internal, setInternal] = React.useState<T | undefined>(value ?? defaultValue);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const set = React.useCallback(\n (next: T | undefined) => {\n setInternal(next);\n onChange?.(next);\n },\n [onChange],\n );\n\n return [current, set];\n}\n"],"names":["useControllableValue","value","defaultValue","onChange","internal","setInternal","React","current","set","next"],"mappings":";AAiBO,SAASA,EACdC,GACAC,GACAC,GACgD;AAChD,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAAM,SAAwBL,KAASC,CAAY,GAE7EK,IADeN,MAAU,SACAA,IAAQG,GAEjCI,IAAMF,EAAM;AAAA,IAChB,CAACG,MAAwB;AACvB,MAAAJ,EAAYI,CAAI,GAChBN,KAAA,QAAAA,EAAWM;AAAA,IACb;AAAA,IACA,CAACN,CAAQ;AAAA,EAAA;AAGX,SAAO,CAACI,GAASC,CAAG;AACtB;"}