@aspprev/versi-ds 0.1.1 → 0.3.0

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.
@@ -2,7 +2,7 @@ import {
2
2
  Tooltip_default,
3
3
  getFloatingLayerClass,
4
4
  mergeAriaDescribedBy
5
- } from "./chunk-CSQXTG32.js";
5
+ } from "./chunk-FTRF27XF.js";
6
6
  import {
7
7
  COUNTRY_OPTIONS,
8
8
  PHONE_COUNTRY_OPTIONS,
@@ -2159,7 +2159,14 @@ import {
2159
2159
  } from "date-fns";
2160
2160
  import { ptBR } from "date-fns/locale/pt-BR";
2161
2161
  import { FormikContext, getIn } from "formik";
2162
- import { useContext, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef5, useState as useState4 } from "react";
2162
+ import {
2163
+ useContext,
2164
+ useEffect as useEffect3,
2165
+ useId as useId3,
2166
+ useMemo as useMemo2,
2167
+ useRef as useRef5,
2168
+ useState as useState4
2169
+ } from "react";
2163
2170
  import { createPortal as createPortal3 } from "react-dom";
2164
2171
  import { MdCalendarMonth, MdChevronLeft, MdChevronRight } from "react-icons/md";
2165
2172
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -2181,12 +2188,13 @@ var MONTHS = [
2181
2188
  "Novembro",
2182
2189
  "Dezembro"
2183
2190
  ];
2184
- var formatDateForInput = (date) => {
2191
+ var formatDateForInput = (date, selectionMode = "day") => {
2185
2192
  if (!date || !isValid(date)) return "";
2186
- return format(date, "dd/MM/yyyy");
2193
+ return format(date, selectionMode === "year" ? "yyyy" : "dd/MM/yyyy");
2187
2194
  };
2188
- var formatInputValue = (value) => {
2189
- const digits = value.replace(/\D/g, "").slice(0, 8);
2195
+ var formatInputValue = (value, selectionMode = "day") => {
2196
+ const digits = value.replace(/\D/g, "").slice(0, selectionMode === "year" ? 4 : 8);
2197
+ if (selectionMode === "year") return digits;
2190
2198
  if (digits.length <= 2) return digits;
2191
2199
  if (digits.length <= 4) return `${digits.slice(0, 2)}/${digits.slice(2)}`;
2192
2200
  return `${digits.slice(0, 2)}/${digits.slice(2, 4)}/${digits.slice(4)}`;
@@ -2222,9 +2230,12 @@ var UnifiedDatePicker = ({
2222
2230
  name = "data",
2223
2231
  error,
2224
2232
  errorText,
2233
+ helperText,
2225
2234
  defaultView = "days",
2226
2235
  navigationVariant = "drilldown",
2236
+ selectionMode = "day",
2227
2237
  showAdjacentDays = true,
2238
+ ariaLabel,
2228
2239
  className
2229
2240
  }) => {
2230
2241
  const formik = useContext(
@@ -2239,10 +2250,11 @@ var UnifiedDatePicker = ({
2239
2250
  const formikTouched = hasFormikField && formik ? Boolean(getIn(formik.touched, name)) : false;
2240
2251
  const formikError = hasFormikField && formik ? getIn(formik.errors, name) : void 0;
2241
2252
  const isFieldDisabled = disabled || isDisabled;
2253
+ const resolvedPlaceholder = selectionMode === "year" ? "aaaa" : placeholder;
2242
2254
  const [isOpen, setIsOpen] = useState4(false);
2243
2255
  const [isEditing, setIsEditing] = useState4(false);
2244
2256
  const [draftValue, setDraftValue] = useState4(
2245
- formatDateForInput(selectedDate)
2257
+ formatDateForInput(selectedDate, selectionMode)
2246
2258
  );
2247
2259
  const [viewDate, setViewDate] = useState4(getSafeViewDate(selectedDate));
2248
2260
  const [mode, setMode] = useState4(defaultView);
@@ -2250,22 +2262,33 @@ var UnifiedDatePicker = ({
2250
2262
  const containerRef = useRef5(null);
2251
2263
  const inputRef = useRef5(null);
2252
2264
  const dropdownRef = useRef5(null);
2265
+ const calendarId = `date-picker-${useId3()}`;
2266
+ const wasOpenRef = useRef5(false);
2253
2267
  const rafRef = useRef5(null);
2254
2268
  const [isMounted, setIsMounted] = useState4(false);
2255
2269
  const [panelNeedsScroll, setPanelNeedsScroll] = useState4(false);
2256
2270
  const [dropdownStyle, setDropdownStyle] = useState4({});
2271
+ useEffect3(() => {
2272
+ var _a, _b;
2273
+ if (wasOpenRef.current && !isOpen && ((_a = dropdownRef.current) == null ? void 0 : _a.contains(document.activeElement))) {
2274
+ (_b = inputRef.current) == null ? void 0 : _b.focus();
2275
+ }
2276
+ wasOpenRef.current = isOpen;
2277
+ }, [isOpen]);
2257
2278
  useEffect3(() => {
2258
2279
  setIsMounted(true);
2259
2280
  }, []);
2260
2281
  useEffect3(() => {
2261
2282
  if (!isEditing) {
2262
- setDraftValue(formatDateForInput(selectedDate));
2283
+ setDraftValue(formatDateForInput(selectedDate, selectionMode));
2263
2284
  }
2264
2285
  setViewDate(getSafeViewDate(selectedDate));
2265
- }, [isEditing, selectedDate]);
2286
+ }, [isEditing, selectedDate, selectionMode]);
2266
2287
  useEffect3(() => {
2267
2288
  if (!isOpen) return;
2268
- setMode(navigationVariant === "dropdown" ? "days" : defaultView);
2289
+ setMode(
2290
+ selectionMode === "year" ? "years" : selectionMode === "month" ? "months" : navigationVariant === "dropdown" ? "days" : defaultView
2291
+ );
2269
2292
  const onMouseDown = (event) => {
2270
2293
  var _a, _b;
2271
2294
  if (!((_a = containerRef.current) == null ? void 0 : _a.contains(event.target)) && !((_b = dropdownRef.current) == null ? void 0 : _b.contains(event.target))) {
@@ -2273,7 +2296,7 @@ var UnifiedDatePicker = ({
2273
2296
  }
2274
2297
  };
2275
2298
  const onKeyDown = (event) => {
2276
- if (event.key === "Escape") setIsOpen(false);
2299
+ if (event.key === "Escape") closeCalendar();
2277
2300
  };
2278
2301
  document.addEventListener("mousedown", onMouseDown);
2279
2302
  document.addEventListener("keydown", onKeyDown);
@@ -2281,7 +2304,7 @@ var UnifiedDatePicker = ({
2281
2304
  document.removeEventListener("mousedown", onMouseDown);
2282
2305
  document.removeEventListener("keydown", onKeyDown);
2283
2306
  };
2284
- }, [defaultView, isOpen, navigationVariant]);
2307
+ }, [defaultView, isOpen, navigationVariant, selectionMode]);
2285
2308
  useEffect3(() => {
2286
2309
  if (!isOpen) return;
2287
2310
  const updateDropdownPosition = () => {
@@ -2354,12 +2377,18 @@ var UnifiedDatePicker = ({
2354
2377
  setIsOpen(true);
2355
2378
  (_a = inputRef.current) == null ? void 0 : _a.focus();
2356
2379
  };
2380
+ const closeCalendar = () => {
2381
+ var _a;
2382
+ setIsOpen(false);
2383
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
2384
+ };
2357
2385
  const getDaysInView = () => {
2358
2386
  const start = startOfWeek(startOfMonth(viewDate), { weekStartsOn: 0 });
2359
2387
  const end = endOfWeek(endOfMonth(viewDate), { weekStartsOn: 0 });
2360
2388
  return eachDayOfInterval({ start, end });
2361
2389
  };
2362
2390
  const handleDayClick = (day) => {
2391
+ if (selectionMode !== "day") return;
2363
2392
  if (isBefore(day, startOfDay(minDate)) || isAfter(day, startOfDay(maxDate)))
2364
2393
  return;
2365
2394
  syncValue(day);
@@ -2367,9 +2396,21 @@ var UnifiedDatePicker = ({
2367
2396
  setInputError(null);
2368
2397
  setViewDate(day);
2369
2398
  touchField();
2370
- setIsOpen(false);
2399
+ closeCalendar();
2371
2400
  };
2372
2401
  const handleMonthClick = (monthIndex) => {
2402
+ const candidate = new Date(viewDate.getFullYear(), monthIndex, 1);
2403
+ const monthDisabled = isBefore(endOfMonth(candidate), startOfDay(minDate)) || isAfter(startOfMonth(candidate), startOfDay(maxDate));
2404
+ if (monthDisabled) return;
2405
+ if (selectionMode === "month") {
2406
+ const nextDate = isBefore(candidate, minDate) ? minDate : isAfter(candidate, maxDate) ? maxDate : candidate;
2407
+ syncValue(nextDate);
2408
+ setDraftValue(formatDateForInput(nextDate, selectionMode));
2409
+ setInputError(null);
2410
+ touchField();
2411
+ closeCalendar();
2412
+ return;
2413
+ }
2373
2414
  setViewDate((currentDate) => {
2374
2415
  const nextDate = new Date(currentDate);
2375
2416
  nextDate.setMonth(monthIndex);
@@ -2386,12 +2427,23 @@ var UnifiedDatePicker = ({
2386
2427
  });
2387
2428
  };
2388
2429
  const handleYearClick = (year) => {
2430
+ if (year < minDate.getFullYear() || year > maxDate.getFullYear()) return;
2431
+ if (selectionMode === "year") {
2432
+ const firstDay = new Date(year, 0, 1);
2433
+ const nextDate = year === minDate.getFullYear() && firstDay < minDate ? minDate : year === maxDate.getFullYear() && firstDay > maxDate ? maxDate : firstDay;
2434
+ syncValue(nextDate);
2435
+ setDraftValue(formatDateForInput(nextDate, selectionMode));
2436
+ setInputError(null);
2437
+ touchField();
2438
+ closeCalendar();
2439
+ return;
2440
+ }
2389
2441
  setViewDate((currentDate) => {
2390
2442
  const nextDate = new Date(currentDate);
2391
2443
  nextDate.setFullYear(year);
2392
2444
  return nextDate;
2393
2445
  });
2394
- setMode("days");
2446
+ setMode(selectionMode === "month" ? "months" : "days");
2395
2447
  };
2396
2448
  const handleYearChange = (year) => {
2397
2449
  setViewDate((currentDate) => {
@@ -2407,8 +2459,38 @@ var UnifiedDatePicker = ({
2407
2459
  return nextDate;
2408
2460
  });
2409
2461
  };
2462
+ const moveCalendarFocus = (event, columns) => {
2463
+ var _a, _b;
2464
+ const movement = {
2465
+ ArrowLeft: -1,
2466
+ ArrowRight: 1,
2467
+ ArrowUp: -columns,
2468
+ ArrowDown: columns
2469
+ };
2470
+ const buttons = Array.from(
2471
+ (_b = (_a = dropdownRef.current) == null ? void 0 : _a.querySelectorAll(
2472
+ '[data-calendar-option="true"]:not(:disabled)'
2473
+ )) != null ? _b : []
2474
+ );
2475
+ const currentIndex = buttons.indexOf(event.currentTarget);
2476
+ if (currentIndex < 0) return;
2477
+ let nextIndex = currentIndex;
2478
+ if (event.key in movement) {
2479
+ nextIndex = currentIndex + movement[event.key];
2480
+ } else if (event.key === "Home") {
2481
+ nextIndex = currentIndex - currentIndex % columns;
2482
+ } else if (event.key === "End") {
2483
+ nextIndex = currentIndex - currentIndex % columns + columns - 1;
2484
+ } else {
2485
+ return;
2486
+ }
2487
+ const nextButton = buttons[nextIndex];
2488
+ if (!nextButton) return;
2489
+ event.preventDefault();
2490
+ nextButton.focus();
2491
+ };
2410
2492
  const commitDraftValue = (rawValue) => {
2411
- const normalizedValue = formatInputValue(rawValue);
2493
+ const normalizedValue = formatInputValue(rawValue, selectionMode);
2412
2494
  setDraftValue(normalizedValue);
2413
2495
  touchField();
2414
2496
  if (!normalizedValue) {
@@ -2416,6 +2498,22 @@ var UnifiedDatePicker = ({
2416
2498
  setInputError(null);
2417
2499
  return;
2418
2500
  }
2501
+ if (selectionMode === "year") {
2502
+ if (normalizedValue.length < 4) {
2503
+ syncValue(null);
2504
+ setInputError("Ano incompleto");
2505
+ return;
2506
+ }
2507
+ const year = Number(normalizedValue);
2508
+ if (year < minDate.getFullYear() || year > maxDate.getFullYear()) {
2509
+ syncValue(null);
2510
+ setInputError("Ano fora do intervalo permitido");
2511
+ return;
2512
+ }
2513
+ handleYearClick(year);
2514
+ setInputError(null);
2515
+ return;
2516
+ }
2419
2517
  if (normalizedValue.length < 10) {
2420
2518
  syncValue(null);
2421
2519
  setInputError("Data incompleta");
@@ -2470,6 +2568,8 @@ var UnifiedDatePicker = ({
2470
2568
  ref: containerRef,
2471
2569
  label,
2472
2570
  labelFor: name,
2571
+ description: helperText,
2572
+ descriptionId: `${name}-description`,
2473
2573
  invalid: hasError,
2474
2574
  message: resolvedErrorText,
2475
2575
  messageId: errorId,
@@ -2493,14 +2593,22 @@ var UnifiedDatePicker = ({
2493
2593
  ref: inputRef,
2494
2594
  id: name,
2495
2595
  name,
2596
+ "aria-label": ariaLabel != null ? ariaLabel : !label ? "Data" : void 0,
2597
+ role: "combobox",
2496
2598
  "aria-invalid": hasError || void 0,
2497
- "aria-describedby": hasError && resolvedErrorText ? errorId : void 0,
2599
+ "aria-describedby": mergeAriaDescribedBy(
2600
+ !hasError && helperText !== void 0 ? `${name}-description` : void 0,
2601
+ hasError && resolvedErrorText ? errorId : void 0
2602
+ ),
2603
+ "aria-haspopup": "dialog",
2604
+ "aria-expanded": isOpen,
2605
+ "aria-controls": isOpen ? calendarId : void 0,
2498
2606
  type: "text",
2499
2607
  inputMode: "numeric",
2500
2608
  autoComplete: "off",
2501
- maxLength: 10,
2609
+ maxLength: selectionMode === "year" ? 4 : 10,
2502
2610
  disabled: isFieldDisabled,
2503
- placeholder,
2611
+ placeholder: resolvedPlaceholder,
2504
2612
  value: draftValue,
2505
2613
  onClick: openCalendar,
2506
2614
  onFocus: () => {
@@ -2508,10 +2616,10 @@ var UnifiedDatePicker = ({
2508
2616
  openCalendar();
2509
2617
  },
2510
2618
  onChange: (event) => {
2511
- const nextValue = formatInputValue(event.target.value);
2619
+ const nextValue = formatInputValue(event.target.value, selectionMode);
2512
2620
  setDraftValue(nextValue);
2513
2621
  setInputError(null);
2514
- if (nextValue.length === 10) {
2622
+ if (selectionMode === "day" && nextValue.length === 10) {
2515
2623
  const parsedDate = parseDateValue(nextValue);
2516
2624
  if (parsedDate) {
2517
2625
  setViewDate(parsedDate);
@@ -2526,7 +2634,7 @@ var UnifiedDatePicker = ({
2526
2634
  onKeyDown: (event) => {
2527
2635
  if (event.key === "Enter") {
2528
2636
  commitDraftValue(draftValue);
2529
- setIsOpen(false);
2637
+ closeCalendar();
2530
2638
  }
2531
2639
  },
2532
2640
  className: FIELD_INPUT_CLASS
@@ -2558,10 +2666,13 @@ var UnifiedDatePicker = ({
2558
2666
  "div",
2559
2667
  {
2560
2668
  ref: dropdownRef,
2669
+ id: calendarId,
2670
+ role: "dialog",
2671
+ "aria-label": selectionMode === "year" ? "Selecionar ano" : selectionMode === "month" ? "Selecionar m\xC3\xAAs" : "Selecionar data",
2561
2672
  style: dropdownStyle,
2562
2673
  className: classNames6(
2563
2674
  getFloatingLayerClass(containerRef.current, "popover"),
2564
- "rounded-sm border border-border-default bg-white shadow-md transition-all duration-150",
2675
+ "rounded-sm border border-border-default bg-white shadow-md transition-all duration-150 motion-reduce:transition-none",
2565
2676
  panelNeedsScroll ? "overflow-y-auto overscroll-contain" : "overflow-visible",
2566
2677
  "py-3"
2567
2678
  ),
@@ -2647,100 +2758,141 @@ var UnifiedDatePicker = ({
2647
2758
  )
2648
2759
  ] }),
2649
2760
  mode === "days" && /* @__PURE__ */ jsxs6("div", { className: "px-3", children: [
2650
- /* @__PURE__ */ jsx6("div", { className: "grid grid-cols-7 gap-x-1", children: WEEKDAYS.map((weekday) => /* @__PURE__ */ jsx6(
2761
+ /* @__PURE__ */ jsx6("div", { className: "grid grid-cols-7 gap-x-1", role: "row", children: WEEKDAYS.map((weekday) => /* @__PURE__ */ jsx6(
2651
2762
  "div",
2652
2763
  {
2764
+ role: "columnheader",
2653
2765
  className: "select-none py-0.5 text-center text-2xs font-semibold text-content-muted",
2654
2766
  children: weekday
2655
2767
  },
2656
2768
  weekday
2657
2769
  )) }),
2658
- /* @__PURE__ */ jsx6("div", { className: "grid grid-cols-7 gap-x-1", children: getDaysInView().map((day, index) => {
2659
- const selected = selectedDate ? isSameDay(day, selectedDate) : false;
2660
- const currentDay = isToday(day);
2661
- const inMonth = isSameMonth(day, viewDate);
2662
- const dayDisabled = isBefore(day, startOfDay(minDate)) || isAfter(day, startOfDay(maxDate));
2663
- if (!showAdjacentDays && !inMonth) {
2664
- return /* @__PURE__ */ jsx6(
2665
- "span",
2666
- {
2667
- "aria-hidden": "true",
2668
- className: "h-7"
2669
- },
2670
- `${day.toISOString()}-${index}`
2671
- );
2672
- }
2673
- return /* @__PURE__ */ jsx6(
2674
- "button",
2675
- {
2676
- type: "button",
2677
- onClick: () => handleDayClick(day),
2678
- disabled: dayDisabled,
2679
- className: classNames6(
2680
- "group flex h-7 w-full items-center justify-center text-xs transition-colors",
2681
- {
2682
- "opacity-30 cursor-not-allowed": dayDisabled,
2683
- "cursor-pointer": !dayDisabled
2684
- }
2685
- ),
2686
- children: /* @__PURE__ */ jsx6(
2687
- "span",
2770
+ /* @__PURE__ */ jsx6(
2771
+ "div",
2772
+ {
2773
+ className: "grid grid-cols-7 gap-x-1",
2774
+ role: "grid",
2775
+ "aria-label": `Dias de ${headerLabel}`,
2776
+ children: getDaysInView().map((day, index) => {
2777
+ const selected = selectedDate ? isSameDay(day, selectedDate) : false;
2778
+ const currentDay = isToday(day);
2779
+ const inMonth = isSameMonth(day, viewDate);
2780
+ const dayDisabled = isBefore(day, startOfDay(minDate)) || isAfter(day, startOfDay(maxDate));
2781
+ if (!showAdjacentDays && !inMonth) {
2782
+ return /* @__PURE__ */ jsx6(
2783
+ "span",
2784
+ {
2785
+ "aria-hidden": "true",
2786
+ className: "h-7"
2787
+ },
2788
+ `${day.toISOString()}-${index}`
2789
+ );
2790
+ }
2791
+ return /* @__PURE__ */ jsx6(
2792
+ "button",
2688
2793
  {
2794
+ type: "button",
2795
+ "data-calendar-option": "true",
2796
+ "aria-label": format(day, "dd/MM/yyyy"),
2797
+ "aria-current": currentDay ? "date" : void 0,
2798
+ "aria-pressed": selected,
2799
+ onKeyDown: (event) => moveCalendarFocus(event, 7),
2800
+ onClick: () => handleDayClick(day),
2801
+ disabled: dayDisabled,
2689
2802
  className: classNames6(
2690
- "flex h-6 w-6 items-center justify-center rounded-sm transition-colors",
2803
+ "group flex h-7 w-full items-center justify-center text-xs transition-colors",
2691
2804
  {
2692
- "border border-selection-border bg-selection-background font-semibold text-selection-content": selected,
2693
- "border border-primary-1 text-primary-1 font-semibold group-hover:bg-primary-1/10": currentDay && inMonth && !selected,
2694
- "text-content-primary group-hover:bg-primary-1/10": inMonth && !selected && !currentDay,
2695
- "text-content-muted": !inMonth
2805
+ "opacity-30 cursor-not-allowed": dayDisabled,
2806
+ "cursor-pointer": !dayDisabled
2696
2807
  }
2697
2808
  ),
2698
- children: format(day, "d")
2699
- }
2700
- )
2701
- },
2702
- `${day.toISOString()}-${index}`
2703
- );
2704
- }) })
2809
+ children: /* @__PURE__ */ jsx6(
2810
+ "span",
2811
+ {
2812
+ className: classNames6(
2813
+ "flex h-6 w-6 items-center justify-center rounded-sm transition-colors",
2814
+ {
2815
+ "border border-selection-border bg-selection-background font-semibold text-selection-content": selected,
2816
+ "border border-primary-1 text-primary-1 font-semibold group-hover:bg-primary-1/10": currentDay && inMonth && !selected,
2817
+ "text-content-primary group-hover:bg-primary-1/10": inMonth && !selected && !currentDay,
2818
+ "text-content-muted": !inMonth
2819
+ }
2820
+ ),
2821
+ children: format(day, "d")
2822
+ }
2823
+ )
2824
+ },
2825
+ `${day.toISOString()}-${index}`
2826
+ );
2827
+ })
2828
+ }
2829
+ )
2705
2830
  ] }),
2706
- mode === "months" && /* @__PURE__ */ jsx6("div", { className: "grid grid-cols-3 gap-1 px-3", children: MONTHS.map((month, index) => {
2707
- const selected = index === viewDate.getMonth();
2708
- return /* @__PURE__ */ jsx6(
2709
- "button",
2710
- {
2711
- type: "button",
2712
- onClick: () => handleMonthClick(index),
2713
- className: classNames6(
2714
- "rounded-sm py-1 text-xs capitalize transition-colors",
2831
+ mode === "months" && /* @__PURE__ */ jsx6(
2832
+ "div",
2833
+ {
2834
+ className: "grid grid-cols-3 gap-1 px-3",
2835
+ role: "group",
2836
+ "aria-label": "Meses do calend\xC3\xA1rio",
2837
+ children: MONTHS.map((month, index) => {
2838
+ const selected = index === viewDate.getMonth();
2839
+ const monthDate = new Date(viewDate.getFullYear(), index, 1);
2840
+ const monthDisabled = isBefore(endOfMonth(monthDate), startOfDay(minDate)) || isAfter(startOfMonth(monthDate), startOfDay(maxDate));
2841
+ return /* @__PURE__ */ jsx6(
2842
+ "button",
2715
2843
  {
2716
- "border border-selection-border bg-selection-background font-semibold text-selection-content": selected,
2717
- "text-content-primary hover:bg-primary-1/10": !selected
2718
- }
2719
- ),
2720
- children: month.slice(0, 3)
2721
- },
2722
- month
2723
- );
2724
- }) }),
2725
- mode === "years" && /* @__PURE__ */ jsx6("div", { className: "grid grid-cols-3 gap-1 px-3", children: years.map((year) => {
2726
- const selected = year === viewDate.getFullYear();
2727
- return /* @__PURE__ */ jsx6(
2728
- "button",
2729
- {
2730
- type: "button",
2731
- onClick: () => handleYearClick(year),
2732
- className: classNames6(
2733
- "rounded-sm py-1 text-xs transition-colors",
2844
+ type: "button",
2845
+ "data-calendar-option": "true",
2846
+ "aria-pressed": selected,
2847
+ disabled: monthDisabled,
2848
+ onKeyDown: (event) => moveCalendarFocus(event, 3),
2849
+ onClick: () => handleMonthClick(index),
2850
+ className: classNames6(
2851
+ "rounded-sm py-1 text-xs capitalize transition-colors",
2852
+ {
2853
+ "border border-selection-border bg-selection-background font-semibold text-selection-content": selected,
2854
+ "text-content-primary hover:bg-primary-1/10": !selected
2855
+ }
2856
+ ),
2857
+ children: month.slice(0, 3)
2858
+ },
2859
+ month
2860
+ );
2861
+ })
2862
+ }
2863
+ ),
2864
+ mode === "years" && /* @__PURE__ */ jsx6(
2865
+ "div",
2866
+ {
2867
+ className: "grid grid-cols-3 gap-1 px-3",
2868
+ role: "group",
2869
+ "aria-label": "Anos do calend\xC3\xA1rio",
2870
+ children: years.map((year) => {
2871
+ const selected = year === viewDate.getFullYear();
2872
+ const yearDisabled = year < minYear || year > maxYear;
2873
+ return /* @__PURE__ */ jsx6(
2874
+ "button",
2734
2875
  {
2735
- "border border-selection-border bg-selection-background font-semibold text-selection-content": selected,
2736
- "text-content-primary hover:bg-primary-1/10": !selected
2737
- }
2738
- ),
2739
- children: year
2740
- },
2741
- year
2742
- );
2743
- }) })
2876
+ type: "button",
2877
+ "data-calendar-option": "true",
2878
+ "aria-pressed": selected,
2879
+ disabled: yearDisabled,
2880
+ onKeyDown: (event) => moveCalendarFocus(event, 3),
2881
+ onClick: () => handleYearClick(year),
2882
+ className: classNames6(
2883
+ "rounded-sm py-1 text-xs transition-colors",
2884
+ {
2885
+ "border border-selection-border bg-selection-background font-semibold text-selection-content": selected,
2886
+ "text-content-primary hover:bg-primary-1/10": !selected
2887
+ }
2888
+ ),
2889
+ children: year
2890
+ },
2891
+ year
2892
+ );
2893
+ })
2894
+ }
2895
+ )
2744
2896
  ]
2745
2897
  }
2746
2898
  ),
@@ -2761,7 +2913,7 @@ var datePicker_default = DatePicker;
2761
2913
  import cs from "classnames";
2762
2914
  import {
2763
2915
  useEffect as useEffect4,
2764
- useId as useId3,
2916
+ useId as useId4,
2765
2917
  useRef as useRef6,
2766
2918
  useState as useState5
2767
2919
  } from "react";
@@ -2773,7 +2925,7 @@ function SelectMultiView(props) {
2773
2925
  const containerRef = useRef6(null);
2774
2926
  const triggerRef = useRef6(null);
2775
2927
  const groupRef = useRef6(null);
2776
- const baseId = useId3();
2928
+ const baseId = useId4();
2777
2929
  const triggerId = `${baseId}-trigger`;
2778
2930
  const labelId = `${baseId}-label`;
2779
2931
  const groupId = `${baseId}-options`;
@@ -3102,7 +3254,7 @@ var SelectCountry_default = SelectCountry;
3102
3254
 
3103
3255
  // src/components/radio-group/radio-group.tsx
3104
3256
  import { useField as useField5 } from "formik";
3105
- import { useId as useId4 } from "react";
3257
+ import { useId as useId5 } from "react";
3106
3258
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3107
3259
  function RadioGroup(_a) {
3108
3260
  var _b = _a, {
@@ -3118,7 +3270,7 @@ function RadioGroup(_a) {
3118
3270
  ]);
3119
3271
  const [field, meta] = useField5(name);
3120
3272
  const hasError = Boolean(meta.touched && meta.error);
3121
- const errorId = `${useId4()}-error`;
3273
+ const errorId = `${useId5()}-error`;
3122
3274
  return /* @__PURE__ */ jsxs9(
3123
3275
  "fieldset",
3124
3276
  {
@@ -3169,7 +3321,7 @@ import classNames7 from "classnames";
3169
3321
  import { FormikContext as FormikContext2, getIn as getIn2 } from "formik";
3170
3322
  import {
3171
3323
  useContext as useContext2,
3172
- useId as useId5,
3324
+ useId as useId6,
3173
3325
  useMemo as useMemo3,
3174
3326
  useState as useState6
3175
3327
  } from "react";
@@ -3192,7 +3344,7 @@ function RadioCardGroup({
3192
3344
  const formikContext = useContext2(
3193
3345
  FormikContext2
3194
3346
  );
3195
- const generatedName = useId5();
3347
+ const generatedName = useId6();
3196
3348
  const errorId = `${generatedName}-error`;
3197
3349
  const [internalValue, setInternalValue] = useState6(defaultValue);
3198
3350
  const hasFormikBinding = Boolean(name) && isFormikContext(formikContext);
@@ -3287,6 +3439,237 @@ function RadioCardGroup({
3287
3439
  );
3288
3440
  }
3289
3441
 
3442
+ // src/components/otp-code-input/OtpCodeInput.tsx
3443
+ import classNames8 from "classnames";
3444
+ import {
3445
+ forwardRef as forwardRef2,
3446
+ useEffect as useEffect5,
3447
+ useId as useId7,
3448
+ useImperativeHandle,
3449
+ useRef as useRef7,
3450
+ useState as useState7
3451
+ } from "react";
3452
+ import { jsx as jsx12 } from "react/jsx-runtime";
3453
+ import { createElement } from "react";
3454
+ var normalizeMask = (value, mask) => {
3455
+ if (typeof mask === "function") return mask(value).slice(0, 1);
3456
+ if (mask instanceof RegExp) {
3457
+ const stableMask = new RegExp(mask.source, mask.flags.replace(/[gy]/g, ""));
3458
+ return stableMask.test(value) ? value.slice(0, 1) : "";
3459
+ }
3460
+ if (mask === "alphanumeric") return value.replace(/[^a-z\d]/gi, "").slice(0, 1);
3461
+ return value.replace(/\D/g, "").slice(0, 1);
3462
+ };
3463
+ var normalizeValues = (source, length, mask) => {
3464
+ const values = Array.isArray(source) ? source : Array.from(source != null ? source : "");
3465
+ return Array.from({ length }, (_, index) => {
3466
+ var _a;
3467
+ return normalizeMask((_a = values[index]) != null ? _a : "", mask);
3468
+ });
3469
+ };
3470
+ var OtpCodeInput = forwardRef2(
3471
+ function OtpCodeInput2(_a, ref) {
3472
+ var _b = _a, {
3473
+ length = 6,
3474
+ value,
3475
+ values,
3476
+ onChange,
3477
+ onComplete,
3478
+ onPaste,
3479
+ autoFocus = false,
3480
+ disabled = false,
3481
+ error = false,
3482
+ errorText,
3483
+ helperText,
3484
+ label = "C\xF3digo de uso \xFAnico",
3485
+ inputMode = "numeric",
3486
+ mask = "numeric",
3487
+ name,
3488
+ onFocus: onInputFocus,
3489
+ onKeyDown: onInputKeyDown,
3490
+ className
3491
+ } = _b, inputProps = __objRest(_b, [
3492
+ "length",
3493
+ "value",
3494
+ "values",
3495
+ "onChange",
3496
+ "onComplete",
3497
+ "onPaste",
3498
+ "autoFocus",
3499
+ "disabled",
3500
+ "error",
3501
+ "errorText",
3502
+ "helperText",
3503
+ "label",
3504
+ "inputMode",
3505
+ "mask",
3506
+ "name",
3507
+ "onFocus",
3508
+ "onKeyDown",
3509
+ "className"
3510
+ ]);
3511
+ const safeLength = Math.max(1, Number.isFinite(length) ? Math.floor(length) : 6);
3512
+ const groupId = useId7();
3513
+ const errorId = `${groupId}-error`;
3514
+ const helperId = `${groupId}-helper`;
3515
+ const inputRefs = useRef7([]);
3516
+ const isControlled = value !== void 0 || values !== void 0;
3517
+ const [internalValues, setInternalValues] = useState7(
3518
+ () => normalizeValues(values != null ? values : value, safeLength, mask)
3519
+ );
3520
+ const currentValues = isControlled ? normalizeValues(values != null ? values : value, safeLength, mask) : internalValues;
3521
+ useEffect5(() => {
3522
+ if (!isControlled) {
3523
+ setInternalValues((previous) => {
3524
+ const normalized = normalizeValues(previous, safeLength, mask);
3525
+ return previous.length === normalized.length && previous.every(
3526
+ (item, index) => item === normalized[index]
3527
+ ) ? previous : normalized;
3528
+ });
3529
+ }
3530
+ }, [isControlled, mask, safeLength]);
3531
+ useImperativeHandle(ref, () => ({
3532
+ focus: (index = 0) => {
3533
+ var _a2;
3534
+ return (_a2 = inputRefs.current[Math.min(Math.max(index, 0), safeLength - 1)]) == null ? void 0 : _a2.focus();
3535
+ },
3536
+ clear: () => {
3537
+ var _a2;
3538
+ const next = Array.from({ length: safeLength }, () => "");
3539
+ if (!isControlled) setInternalValues(next);
3540
+ onChange == null ? void 0 : onChange("", next);
3541
+ (_a2 = inputRefs.current[0]) == null ? void 0 : _a2.focus();
3542
+ }
3543
+ }), [isControlled, onChange, safeLength]);
3544
+ useEffect5(() => {
3545
+ var _a2;
3546
+ if (autoFocus) (_a2 = inputRefs.current[0]) == null ? void 0 : _a2.focus();
3547
+ }, [autoFocus]);
3548
+ const emit = (next, focusIndex) => {
3549
+ var _a2;
3550
+ const normalized = normalizeValues(next, safeLength, mask);
3551
+ if (!isControlled) setInternalValues(normalized);
3552
+ const nextValue = normalized.join("");
3553
+ const wasComplete = currentValues.every(Boolean) && currentValues.length === safeLength;
3554
+ onChange == null ? void 0 : onChange(nextValue, normalized);
3555
+ if (!wasComplete && normalized.every(Boolean) && nextValue.length === safeLength) {
3556
+ onComplete == null ? void 0 : onComplete(nextValue);
3557
+ }
3558
+ if (focusIndex !== void 0) (_a2 = inputRefs.current[focusIndex]) == null ? void 0 : _a2.focus();
3559
+ };
3560
+ const handlePaste = (event, index) => {
3561
+ onPaste == null ? void 0 : onPaste(event);
3562
+ if (event.defaultPrevented) return;
3563
+ event.preventDefault();
3564
+ const pasted = Array.from(event.clipboardData.getData("text")).map((item) => normalizeMask(item, mask)).filter(Boolean).slice(0, safeLength - index);
3565
+ if (!pasted.length) return;
3566
+ const next = [...currentValues];
3567
+ pasted.forEach((item, offset) => {
3568
+ next[index + offset] = item;
3569
+ });
3570
+ emit(next, Math.min(index + pasted.length, safeLength - 1));
3571
+ };
3572
+ const handleKeyDown = (event, index) => {
3573
+ var _a2, _b2, _c, _d;
3574
+ if (event.key === "ArrowLeft" && index > 0) {
3575
+ event.preventDefault();
3576
+ (_a2 = inputRefs.current[index - 1]) == null ? void 0 : _a2.focus();
3577
+ } else if (event.key === "ArrowRight" && index < safeLength - 1) {
3578
+ event.preventDefault();
3579
+ (_b2 = inputRefs.current[index + 1]) == null ? void 0 : _b2.focus();
3580
+ } else if (event.key === "Backspace") {
3581
+ if (currentValues[index]) {
3582
+ const next = [...currentValues];
3583
+ next[index] = "";
3584
+ emit(next);
3585
+ } else if (index > 0) {
3586
+ event.preventDefault();
3587
+ const next = [...currentValues];
3588
+ next[index - 1] = "";
3589
+ emit(next, index - 1);
3590
+ }
3591
+ } else if (event.key === "Delete" && currentValues[index]) {
3592
+ const next = [...currentValues];
3593
+ next[index] = "";
3594
+ emit(next);
3595
+ } else if (event.key === "Home") {
3596
+ event.preventDefault();
3597
+ (_c = inputRefs.current[0]) == null ? void 0 : _c.focus();
3598
+ } else if (event.key === "End") {
3599
+ event.preventDefault();
3600
+ (_d = inputRefs.current[safeLength - 1]) == null ? void 0 : _d.focus();
3601
+ }
3602
+ };
3603
+ const hasError = Boolean(error || errorText);
3604
+ const describedBy = [helperText ? helperId : "", hasError && errorText ? errorId : ""].filter(Boolean).join(" ") || void 0;
3605
+ return /* @__PURE__ */ jsx12(
3606
+ FieldFrame_default,
3607
+ {
3608
+ label,
3609
+ labelId: `${groupId}-label`,
3610
+ labelFor: `${groupId}-0`,
3611
+ message: errorText,
3612
+ messageId: errorId,
3613
+ description: helperText,
3614
+ descriptionId: helperId,
3615
+ invalid: hasError,
3616
+ className,
3617
+ children: /* @__PURE__ */ jsx12(
3618
+ "div",
3619
+ {
3620
+ role: "group",
3621
+ "aria-labelledby": label ? `${groupId}-label` : void 0,
3622
+ "aria-describedby": describedBy,
3623
+ "aria-invalid": hasError || void 0,
3624
+ className: "mt-1 flex flex-wrap gap-2",
3625
+ children: Array.from({ length: safeLength }, (_, index) => /* @__PURE__ */ createElement(
3626
+ "input",
3627
+ __spreadProps(__spreadValues({}, inputProps), {
3628
+ key: index,
3629
+ ref: (element) => {
3630
+ inputRefs.current[index] = element;
3631
+ },
3632
+ id: `${groupId}-${index}`,
3633
+ name: index === 0 ? name : void 0,
3634
+ type: "text",
3635
+ inputMode,
3636
+ autoComplete: index === 0 ? "one-time-code" : "off",
3637
+ maxLength: 1,
3638
+ value: currentValues[index],
3639
+ disabled,
3640
+ "aria-label": `${label}, d\xEDgito ${index + 1} de ${safeLength}`,
3641
+ "aria-invalid": hasError || void 0,
3642
+ "aria-describedby": describedBy,
3643
+ onChange: (event) => {
3644
+ const next = [...currentValues];
3645
+ const nextValue = normalizeMask(event.target.value, mask);
3646
+ next[index] = nextValue;
3647
+ emit(next, nextValue && index < safeLength - 1 ? index + 1 : void 0);
3648
+ },
3649
+ onPaste: (event) => handlePaste(event, index),
3650
+ onKeyDown: (event) => {
3651
+ onInputKeyDown == null ? void 0 : onInputKeyDown(event);
3652
+ if (!event.defaultPrevented) handleKeyDown(event, index);
3653
+ },
3654
+ onFocus: (event) => {
3655
+ onInputFocus == null ? void 0 : onInputFocus(event);
3656
+ if (!event.defaultPrevented) event.currentTarget.select();
3657
+ },
3658
+ className: classNames8(
3659
+ "h-11 w-11 rounded-sm border bg-field-surface text-center text-lg font-bold text-field-content outline-none transition-colors focus-visible:border-field-border-active focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring disabled:cursor-not-allowed disabled:bg-field-surface-disabled",
3660
+ hasError ? "border-field-border-error" : "border-field-border-default"
3661
+ )
3662
+ })
3663
+ ))
3664
+ }
3665
+ )
3666
+ }
3667
+ );
3668
+ }
3669
+ );
3670
+ OtpCodeInput.displayName = "OtpCodeInput";
3671
+ var OtpCodeInput_default = OtpCodeInput;
3672
+
3290
3673
  export {
3291
3674
  Input_default,
3292
3675
  InputStandalone,
@@ -3303,6 +3686,7 @@ export {
3303
3686
  CountrySelect,
3304
3687
  SelectCountry_default,
3305
3688
  RadioGroup,
3306
- RadioCardGroup
3689
+ RadioCardGroup,
3690
+ OtpCodeInput_default
3307
3691
  };
3308
- //# sourceMappingURL=chunk-5VJ6H62W.js.map
3692
+ //# sourceMappingURL=chunk-OQECJKGA.js.map