@dev-dga/react 0.5.0 → 0.6.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.
package/dist/index.js CHANGED
@@ -514,6 +514,47 @@ function ChevronRight(props) {
514
514
  }
515
515
  );
516
516
  }
517
+ function ChevronLeft(props) {
518
+ return /* @__PURE__ */ jsx6(
519
+ "svg",
520
+ {
521
+ xmlns: "http://www.w3.org/2000/svg",
522
+ width: "1em",
523
+ height: "1em",
524
+ viewBox: "0 0 24 24",
525
+ fill: "none",
526
+ stroke: "currentColor",
527
+ strokeWidth: "2",
528
+ strokeLinecap: "round",
529
+ strokeLinejoin: "round",
530
+ ...props,
531
+ children: /* @__PURE__ */ jsx6("path", { d: "m15 18-6-6 6-6" })
532
+ }
533
+ );
534
+ }
535
+ function CalendarIcon(props) {
536
+ return /* @__PURE__ */ jsxs4(
537
+ "svg",
538
+ {
539
+ xmlns: "http://www.w3.org/2000/svg",
540
+ width: "1em",
541
+ height: "1em",
542
+ viewBox: "0 0 24 24",
543
+ fill: "none",
544
+ stroke: "currentColor",
545
+ strokeWidth: "2",
546
+ strokeLinecap: "round",
547
+ strokeLinejoin: "round",
548
+ ...props,
549
+ children: [
550
+ /* @__PURE__ */ jsx6("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
551
+ /* @__PURE__ */ jsx6("line", { x1: "16", x2: "16", y1: "2", y2: "6" }),
552
+ /* @__PURE__ */ jsx6("line", { x1: "8", x2: "8", y1: "2", y2: "6" }),
553
+ /* @__PURE__ */ jsx6("line", { x1: "3", x2: "21", y1: "10", y2: "10" })
554
+ ]
555
+ }
556
+ );
557
+ }
517
558
  function MoreHorizontal(props) {
518
559
  return /* @__PURE__ */ jsxs4(
519
560
  "svg",
@@ -533,6 +574,64 @@ function MoreHorizontal(props) {
533
574
  }
534
575
  );
535
576
  }
577
+ function Plus(props) {
578
+ return /* @__PURE__ */ jsxs4(
579
+ "svg",
580
+ {
581
+ xmlns: "http://www.w3.org/2000/svg",
582
+ width: "1em",
583
+ height: "1em",
584
+ viewBox: "0 0 24 24",
585
+ fill: "none",
586
+ stroke: "currentColor",
587
+ strokeWidth: "3",
588
+ strokeLinecap: "round",
589
+ strokeLinejoin: "round",
590
+ ...props,
591
+ children: [
592
+ /* @__PURE__ */ jsx6("path", { d: "M12 5v14" }),
593
+ /* @__PURE__ */ jsx6("path", { d: "M5 12h14" })
594
+ ]
595
+ }
596
+ );
597
+ }
598
+ function Star(props) {
599
+ return /* @__PURE__ */ jsx6(
600
+ "svg",
601
+ {
602
+ xmlns: "http://www.w3.org/2000/svg",
603
+ width: "1em",
604
+ height: "1em",
605
+ viewBox: "0 0 24 24",
606
+ fill: "currentColor",
607
+ stroke: "none",
608
+ ...props,
609
+ children: /* @__PURE__ */ jsx6("path", { d: "m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" })
610
+ }
611
+ );
612
+ }
613
+ function Upload(props) {
614
+ return /* @__PURE__ */ jsxs4(
615
+ "svg",
616
+ {
617
+ xmlns: "http://www.w3.org/2000/svg",
618
+ width: "1em",
619
+ height: "1em",
620
+ viewBox: "0 0 24 24",
621
+ fill: "none",
622
+ stroke: "currentColor",
623
+ strokeWidth: "2",
624
+ strokeLinecap: "round",
625
+ strokeLinejoin: "round",
626
+ ...props,
627
+ children: [
628
+ /* @__PURE__ */ jsx6("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
629
+ /* @__PURE__ */ jsx6("path", { d: "M17 8l-5-5-5 5" }),
630
+ /* @__PURE__ */ jsx6("path", { d: "M12 3v12" })
631
+ ]
632
+ }
633
+ );
634
+ }
536
635
 
537
636
  // src/components/Checkbox/Checkbox.tsx
538
637
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -819,7 +918,7 @@ function Select({
819
918
  "aria-labelledby": rootProps["aria-labelledby"]
820
919
  });
821
920
  const ctx = useContext2(DgaContext);
822
- const portalContainer = ctx?.rootEl ?? void 0;
921
+ const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? void 0;
823
922
  return /* @__PURE__ */ jsxs8("div", { "data-slot": "select-field", className: "ddga-field", children: [
824
923
  label && /* @__PURE__ */ jsxs8("label", { htmlFor: fieldId, className: "ddga-select__label", children: [
825
924
  label,
@@ -1238,7 +1337,7 @@ function TooltipContent({
1238
1337
  ...props
1239
1338
  }) {
1240
1339
  const ctx = useContext3(DgaContext);
1241
- const portalContainer = ctx?.rootEl ?? void 0;
1340
+ const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? void 0;
1242
1341
  return /* @__PURE__ */ jsx15(TooltipPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs11(
1243
1342
  TooltipPrimitive.Content,
1244
1343
  {
@@ -1381,7 +1480,7 @@ function ModalContent({
1381
1480
  ...props
1382
1481
  }) {
1383
1482
  const ctx = useContext4(DgaContext);
1384
- const portalContainer = ctx?.rootEl ?? void 0;
1483
+ const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? void 0;
1385
1484
  return /* @__PURE__ */ jsxs13(DialogPrimitive.Portal, { container: portalContainer, children: [
1386
1485
  /* @__PURE__ */ jsx17(DialogPrimitive.Overlay, { className: "ddga-modal__overlay", "data-slot": "modal-overlay" }),
1387
1486
  /* @__PURE__ */ jsxs13(
@@ -2279,7 +2378,7 @@ function DropdownMenuContent({
2279
2378
  ...props
2280
2379
  }) {
2281
2380
  const ctx = useContext5(DgaContext);
2282
- const portalContainer = ctx?.rootEl ?? void 0;
2381
+ const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? void 0;
2283
2382
  return /* @__PURE__ */ jsx26(DropdownMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx26(
2284
2383
  DropdownMenuPrimitive.Content,
2285
2384
  {
@@ -2410,7 +2509,7 @@ function DropdownMenuSubTrigger({
2410
2509
  }
2411
2510
  function DropdownMenuSubContent({ size, className, ...props }) {
2412
2511
  const ctx = useContext5(DgaContext);
2413
- const portalContainer = ctx?.rootEl ?? void 0;
2512
+ const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? void 0;
2414
2513
  return /* @__PURE__ */ jsx26(DropdownMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx26(
2415
2514
  DropdownMenuPrimitive.SubContent,
2416
2515
  {
@@ -2462,7 +2561,7 @@ function DrawerContent({
2462
2561
  ...props
2463
2562
  }) {
2464
2563
  const ctx = useContext6(DgaContext);
2465
- const portalContainer = ctx?.rootEl ?? void 0;
2564
+ const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? void 0;
2466
2565
  return /* @__PURE__ */ jsxs20(DialogPrimitive2.Portal, { container: portalContainer, children: [
2467
2566
  /* @__PURE__ */ jsx27(DialogPrimitive2.Overlay, { className: "ddga-drawer__overlay", "data-slot": "drawer-overlay" }),
2468
2567
  /* @__PURE__ */ jsxs20(
@@ -2636,7 +2735,7 @@ function Combobox({
2636
2735
  "aria-labelledby": ariaLabelledBy
2637
2736
  });
2638
2737
  const providerCtx = useContext7(DgaContext);
2639
- const portalContainer = providerCtx?.rootEl ?? void 0;
2738
+ const portalContainer = providerCtx?.portalEl ?? providerCtx?.rootEl ?? void 0;
2640
2739
  const triggerLabel = useMemo(() => {
2641
2740
  if (value === void 0) return null;
2642
2741
  if (getLabel) return getLabel(value);
@@ -2761,11 +2860,1173 @@ function ComboboxSeparator({ className, ...props }) {
2761
2860
  );
2762
2861
  }
2763
2862
 
2863
+ // src/components/DatePicker/DatePicker.tsx
2864
+ import { useCallback as useCallback2, useContext as useContext8, useMemo as useMemo2, useState as useState4 } from "react";
2865
+ import {
2866
+ Button as AriaButton,
2867
+ Calendar as AriaCalendar,
2868
+ CalendarCell as AriaCalendarCell,
2869
+ CalendarGrid as AriaCalendarGrid,
2870
+ CalendarGridBody as AriaCalendarGridBody,
2871
+ CalendarGridHeader as AriaCalendarGridHeader,
2872
+ CalendarHeaderCell as AriaCalendarHeaderCell,
2873
+ CalendarStateContext as AriaCalendarStateContext,
2874
+ DateInput as AriaDateInput,
2875
+ DatePicker as AriaDatePicker,
2876
+ DateSegment as AriaDateSegment,
2877
+ Dialog as AriaDialog,
2878
+ FieldError as AriaFieldError,
2879
+ Group as AriaGroup,
2880
+ I18nProvider,
2881
+ Label as AriaLabel,
2882
+ Popover as AriaPopover,
2883
+ Text as AriaText
2884
+ } from "react-aria-components";
2885
+ import {
2886
+ CalendarDate,
2887
+ GregorianCalendar,
2888
+ IslamicUmalquraCalendar,
2889
+ toCalendar
2890
+ } from "@internationalized/date";
2891
+ import { cva as cva27 } from "class-variance-authority";
2892
+ import { Fragment as Fragment2, jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
2893
+ var datePickerTriggerVariants = cva27("ddga-date-picker-trigger", {
2894
+ variants: {
2895
+ size: {
2896
+ sm: "ddga-date-picker-trigger--sm",
2897
+ md: "ddga-date-picker-trigger--md"
2898
+ },
2899
+ error: {
2900
+ true: "ddga-date-picker-trigger--error"
2901
+ }
2902
+ },
2903
+ defaultVariants: {
2904
+ size: "md"
2905
+ }
2906
+ });
2907
+ var datePickerVariants = datePickerTriggerVariants;
2908
+ function dateToCalendarDate(date) {
2909
+ if (!date) return null;
2910
+ return new CalendarDate(date.getFullYear(), date.getMonth() + 1, date.getDate());
2911
+ }
2912
+ function calendarDateToDate(value) {
2913
+ if (!value) return null;
2914
+ const greg = value.calendar.identifier === "gregory" ? value : toCalendar(value, new GregorianCalendar());
2915
+ return new Date(greg.year, greg.month - 1, greg.day);
2916
+ }
2917
+ function composeLocale(dgaLocale, calendar) {
2918
+ const base = dgaLocale === "ar" ? "ar-SA" : dgaLocale === "en" ? "en-US" : dgaLocale;
2919
+ const isArabic = base.startsWith("ar");
2920
+ if (calendar === "hijri") {
2921
+ return isArabic ? `${base}-u-ca-islamic-umalqura-nu-latn` : `${base}-u-ca-islamic-umalqura`;
2922
+ }
2923
+ return isArabic ? `${base}-u-nu-latn` : base;
2924
+ }
2925
+ var GREGORIAN = new GregorianCalendar();
2926
+ var ISLAMIC_UMALQURA = new IslamicUmalquraCalendar();
2927
+ function secondaryDayNumber(date, mainCalendar) {
2928
+ const other = mainCalendar === "hijri" ? GREGORIAN : ISLAMIC_UMALQURA;
2929
+ return toCalendar(date, other).day;
2930
+ }
2931
+ function CalendarNavHeader({ locale, monthLabel, yearLabel }) {
2932
+ const state = useContext8(AriaCalendarStateContext);
2933
+ const focusedDate = state?.focusedDate ?? null;
2934
+ const focusedYear = focusedDate?.year ?? 0;
2935
+ const focusedCalendar = focusedDate?.calendar ?? GREGORIAN;
2936
+ const minValue = state?.minValue ?? null;
2937
+ const maxValue = state?.maxValue ?? null;
2938
+ const monthNames = useMemo2(() => {
2939
+ if (!focusedDate) return [];
2940
+ const fmt = new Intl.DateTimeFormat(locale, { month: "long" });
2941
+ return Array.from({ length: 12 }, (_, i) => {
2942
+ const cd = new CalendarDate(focusedCalendar, focusedYear, i + 1, 1);
2943
+ const greg = toCalendar(cd, GREGORIAN);
2944
+ const js = new Date(greg.year, greg.month - 1, greg.day);
2945
+ return fmt.format(js);
2946
+ });
2947
+ }, [locale, focusedDate, focusedCalendar, focusedYear]);
2948
+ const yearOptions = useMemo2(() => {
2949
+ if (!focusedDate) return [];
2950
+ const minY = minValue ? toCalendar(minValue, focusedCalendar).year : focusedYear - 100;
2951
+ const maxY = maxValue ? toCalendar(maxValue, focusedCalendar).year : focusedYear + 30;
2952
+ const start = Math.min(minY, focusedYear);
2953
+ const end = Math.max(maxY, focusedYear);
2954
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
2955
+ }, [focusedDate, focusedCalendar, focusedYear, minValue, maxValue]);
2956
+ if (!state || !focusedDate) return null;
2957
+ return /* @__PURE__ */ jsxs22("div", { className: "ddga-date-picker-calendar__nav-selects", "data-slot": "date-picker-calendar-nav", children: [
2958
+ /* @__PURE__ */ jsx29(
2959
+ "select",
2960
+ {
2961
+ "aria-label": monthLabel,
2962
+ className: "ddga-date-picker-calendar__select ddga-date-picker-calendar__month-select",
2963
+ "data-slot": "date-picker-month-select",
2964
+ value: focusedDate.month,
2965
+ onChange: (e) => state.setFocusedDate(focusedDate.set({ month: Number(e.target.value) })),
2966
+ children: monthNames.map((name, i) => /* @__PURE__ */ jsx29("option", { value: i + 1, children: name }, i + 1))
2967
+ }
2968
+ ),
2969
+ /* @__PURE__ */ jsx29(
2970
+ "select",
2971
+ {
2972
+ "aria-label": yearLabel,
2973
+ className: "ddga-date-picker-calendar__select ddga-date-picker-calendar__year-select",
2974
+ "data-slot": "date-picker-year-select",
2975
+ value: focusedDate.year,
2976
+ onChange: (e) => state.setFocusedDate(focusedDate.set({ year: Number(e.target.value) })),
2977
+ children: yearOptions.map((y) => /* @__PURE__ */ jsx29("option", { value: y, children: y }, y))
2978
+ }
2979
+ )
2980
+ ] });
2981
+ }
2982
+ function CalendarDayCell({ date, showSecondary, calendarSystem }) {
2983
+ const state = useContext8(AriaCalendarStateContext);
2984
+ const start = state?.visibleRange.start;
2985
+ const isOutside = !!start && (date.year !== start.year || date.month !== start.month);
2986
+ const isOutOfBounds = state ? state.isInvalid(date) : false;
2987
+ if (state && isOutside && !isOutOfBounds) {
2988
+ const selected = state.value;
2989
+ const isSelected = !!selected && selected.year === date.year && selected.month === date.month && selected.day === date.day;
2990
+ const handleSelect = () => {
2991
+ state.setFocusedDate(date);
2992
+ state.selectDate(date);
2993
+ };
2994
+ return /* @__PURE__ */ jsx29("td", { role: "gridcell", children: /* @__PURE__ */ jsx29(
2995
+ "button",
2996
+ {
2997
+ type: "button",
2998
+ tabIndex: -1,
2999
+ className: "ddga-date-picker-calendar__cell",
3000
+ "data-outside-month": "",
3001
+ "data-selected": isSelected ? "" : void 0,
3002
+ "data-slot": "date-picker-day-cell",
3003
+ onClick: handleSelect,
3004
+ children: showSecondary ? /* @__PURE__ */ jsxs22(Fragment2, { children: [
3005
+ /* @__PURE__ */ jsx29("span", { className: "ddga-date-picker-calendar__cell-primary", children: date.day }),
3006
+ /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "ddga-date-picker-calendar__cell-secondary", children: secondaryDayNumber(date, calendarSystem) })
3007
+ ] }) : String(date.day)
3008
+ }
3009
+ ) });
3010
+ }
3011
+ return /* @__PURE__ */ jsx29(AriaCalendarCell, { date, className: "ddga-date-picker-calendar__cell", children: ({ formattedDate }) => showSecondary ? /* @__PURE__ */ jsxs22(Fragment2, { children: [
3012
+ /* @__PURE__ */ jsx29("span", { className: "ddga-date-picker-calendar__cell-primary", children: formattedDate }),
3013
+ /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "ddga-date-picker-calendar__cell-secondary", children: secondaryDayNumber(date, calendarSystem) })
3014
+ ] }) : formattedDate });
3015
+ }
3016
+ function DatePicker({
3017
+ value: controlledValue,
3018
+ defaultValue,
3019
+ onChange,
3020
+ minValue,
3021
+ maxValue,
3022
+ label,
3023
+ helperText,
3024
+ errorMessage,
3025
+ error,
3026
+ required,
3027
+ disabled,
3028
+ size,
3029
+ id,
3030
+ className,
3031
+ "aria-label": ariaLabel,
3032
+ "aria-labelledby": ariaLabelledBy,
3033
+ calendar: controlledCalendar,
3034
+ defaultCalendar = "gregorian",
3035
+ onCalendarChange,
3036
+ showCalendarToggle = true,
3037
+ calendarLabels,
3038
+ showSecondaryCalendar = false
3039
+ }) {
3040
+ const isValueControlled = controlledValue !== void 0;
3041
+ const [internalValue, setInternalValue] = useState4(
3042
+ () => dateToCalendarDate(defaultValue)
3043
+ );
3044
+ const value = isValueControlled ? dateToCalendarDate(controlledValue) : internalValue;
3045
+ const handleAriaChange = useCallback2(
3046
+ (next) => {
3047
+ const nextCD = next ? new CalendarDate(next.year, next.month, next.day) : null;
3048
+ if (!isValueControlled) setInternalValue(nextCD);
3049
+ onChange?.(calendarDateToDate(nextCD));
3050
+ },
3051
+ [isValueControlled, onChange]
3052
+ );
3053
+ const isCalendarControlled = controlledCalendar !== void 0;
3054
+ const [internalCalendar, setInternalCalendar] = useState4(defaultCalendar);
3055
+ const calendarSystem = isCalendarControlled ? controlledCalendar : internalCalendar;
3056
+ const setCalendar = useCallback2(
3057
+ (next) => {
3058
+ if (!isCalendarControlled) setInternalCalendar(next);
3059
+ onCalendarChange?.(next);
3060
+ },
3061
+ [isCalendarControlled, onCalendarChange]
3062
+ );
3063
+ const dgaCtx = useContext8(DgaContext);
3064
+ const dgaLocale = dgaCtx?.locale ?? "en";
3065
+ const ariaLocale = useMemo2(
3066
+ () => composeLocale(dgaLocale, calendarSystem),
3067
+ [dgaLocale, calendarSystem]
3068
+ );
3069
+ const portalContainer = dgaCtx?.portalEl ?? dgaCtx?.rootEl ?? void 0;
3070
+ const dgaDir = dgaCtx?.dir ?? "ltr";
3071
+ const PrevChevron = dgaDir === "rtl" ? ChevronRight : ChevronLeft;
3072
+ const NextChevron = dgaDir === "rtl" ? ChevronLeft : ChevronRight;
3073
+ const resolvedLabels = useMemo2(() => {
3074
+ if (calendarLabels) return calendarLabels;
3075
+ const isArabic = dgaLocale.startsWith("ar");
3076
+ return isArabic ? { gregorian: "\u0645\u064A\u0644\u0627\u062F\u064A", hijri: "\u0647\u062C\u0631\u064A" } : { gregorian: "Gregorian", hijri: "Hijri" };
3077
+ }, [calendarLabels, dgaLocale]);
3078
+ const navLabels = useMemo2(
3079
+ () => dgaLocale.startsWith("ar") ? { month: "\u0627\u0644\u0634\u0647\u0631", year: "\u0627\u0644\u0633\u0646\u0629" } : { month: "Month", year: "Year" },
3080
+ [dgaLocale]
3081
+ );
3082
+ const ariaMinValue = useMemo2(() => dateToCalendarDate(minValue) ?? void 0, [minValue]);
3083
+ const ariaMaxValue = useMemo2(() => dateToCalendarDate(maxValue) ?? void 0, [maxValue]);
3084
+ const dialogAriaLabel = ariaLabel ?? (typeof label === "string" ? label : ariaLabelledBy ? void 0 : "Date");
3085
+ const showToggle = showCalendarToggle && !isCalendarControlled;
3086
+ const hasError = !!error;
3087
+ const hasErrorMessage = hasError && errorMessage != null && errorMessage !== "";
3088
+ const hasHelper = !hasErrorMessage && helperText != null && helperText !== "";
3089
+ return /* @__PURE__ */ jsx29(I18nProvider, { locale: ariaLocale, children: /* @__PURE__ */ jsxs22(
3090
+ AriaDatePicker,
3091
+ {
3092
+ value,
3093
+ onChange: handleAriaChange,
3094
+ minValue: ariaMinValue,
3095
+ maxValue: ariaMaxValue,
3096
+ isRequired: required,
3097
+ isDisabled: disabled,
3098
+ isInvalid: hasError,
3099
+ shouldCloseOnSelect: true,
3100
+ id,
3101
+ "aria-label": ariaLabel,
3102
+ "aria-labelledby": ariaLabelledBy,
3103
+ className: "ddga-field",
3104
+ "data-slot": "date-picker-field",
3105
+ children: [
3106
+ label && /* @__PURE__ */ jsxs22(AriaLabel, { className: "ddga-date-picker__label", children: [
3107
+ label,
3108
+ required && /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", className: "ddga-date-picker__required", children: "*" })
3109
+ ] }),
3110
+ /* @__PURE__ */ jsxs22(
3111
+ AriaGroup,
3112
+ {
3113
+ "data-slot": "date-picker-trigger",
3114
+ className: cn(datePickerTriggerVariants({ size, error: hasError }), className),
3115
+ children: [
3116
+ /* @__PURE__ */ jsx29(AriaDateInput, { className: "ddga-date-picker__input", "data-slot": "date-picker-input", children: (segment) => /* @__PURE__ */ jsx29(
3117
+ AriaDateSegment,
3118
+ {
3119
+ segment,
3120
+ className: "ddga-date-picker__segment",
3121
+ "data-slot": "date-picker-segment"
3122
+ }
3123
+ ) }),
3124
+ /* @__PURE__ */ jsx29(
3125
+ AriaButton,
3126
+ {
3127
+ className: "ddga-date-picker__icon-button",
3128
+ "aria-label": "Open calendar",
3129
+ "data-slot": "date-picker-trigger-button",
3130
+ children: /* @__PURE__ */ jsx29(CalendarIcon, { "aria-hidden": "true", className: "ddga-date-picker__icon" })
3131
+ }
3132
+ )
3133
+ ]
3134
+ }
3135
+ ),
3136
+ hasHelper && /* @__PURE__ */ jsx29(
3137
+ AriaText,
3138
+ {
3139
+ slot: "description",
3140
+ className: "ddga-field__message ddga-field__message--helper",
3141
+ "data-slot": "field-helper",
3142
+ children: helperText
3143
+ }
3144
+ ),
3145
+ hasErrorMessage && /* @__PURE__ */ jsx29(
3146
+ AriaFieldError,
3147
+ {
3148
+ className: "ddga-field__message ddga-field__message--error",
3149
+ "data-slot": "field-error",
3150
+ children: errorMessage
3151
+ }
3152
+ ),
3153
+ /* @__PURE__ */ jsx29(
3154
+ AriaPopover,
3155
+ {
3156
+ UNSTABLE_portalContainer: portalContainer,
3157
+ className: "ddga-date-picker-popover",
3158
+ "data-slot": "date-picker-popover",
3159
+ offset: 6,
3160
+ containerPadding: 12,
3161
+ children: /* @__PURE__ */ jsxs22(
3162
+ AriaDialog,
3163
+ {
3164
+ className: "ddga-date-picker-dialog",
3165
+ "data-slot": "date-picker-dialog",
3166
+ "aria-label": dialogAriaLabel,
3167
+ "aria-labelledby": ariaLabelledBy,
3168
+ children: [
3169
+ showToggle && /* @__PURE__ */ jsxs22(
3170
+ "div",
3171
+ {
3172
+ role: "tablist",
3173
+ "aria-label": "Calendar system",
3174
+ className: "ddga-date-picker-toggle",
3175
+ "data-slot": "date-picker-toggle",
3176
+ children: [
3177
+ /* @__PURE__ */ jsx29(
3178
+ "button",
3179
+ {
3180
+ type: "button",
3181
+ role: "tab",
3182
+ "aria-selected": calendarSystem === "gregorian",
3183
+ className: "ddga-date-picker-toggle__button",
3184
+ "data-active": calendarSystem === "gregorian" ? "" : void 0,
3185
+ onClick: () => setCalendar("gregorian"),
3186
+ children: resolvedLabels.gregorian
3187
+ }
3188
+ ),
3189
+ /* @__PURE__ */ jsx29(
3190
+ "button",
3191
+ {
3192
+ type: "button",
3193
+ role: "tab",
3194
+ "aria-selected": calendarSystem === "hijri",
3195
+ className: "ddga-date-picker-toggle__button",
3196
+ "data-active": calendarSystem === "hijri" ? "" : void 0,
3197
+ onClick: () => setCalendar("hijri"),
3198
+ children: resolvedLabels.hijri
3199
+ }
3200
+ )
3201
+ ]
3202
+ }
3203
+ ),
3204
+ /* @__PURE__ */ jsxs22(AriaCalendar, { className: "ddga-date-picker-calendar", "data-slot": "date-picker-calendar", children: [
3205
+ /* @__PURE__ */ jsxs22("header", { className: "ddga-date-picker-calendar__header", children: [
3206
+ /* @__PURE__ */ jsx29(
3207
+ AriaButton,
3208
+ {
3209
+ slot: "previous",
3210
+ className: "ddga-date-picker-calendar__nav",
3211
+ "data-slot": "date-picker-calendar-prev",
3212
+ children: /* @__PURE__ */ jsx29(PrevChevron, { "aria-hidden": "true" })
3213
+ }
3214
+ ),
3215
+ /* @__PURE__ */ jsx29(
3216
+ CalendarNavHeader,
3217
+ {
3218
+ locale: ariaLocale,
3219
+ monthLabel: navLabels.month,
3220
+ yearLabel: navLabels.year
3221
+ }
3222
+ ),
3223
+ /* @__PURE__ */ jsx29(
3224
+ AriaButton,
3225
+ {
3226
+ slot: "next",
3227
+ className: "ddga-date-picker-calendar__nav",
3228
+ "data-slot": "date-picker-calendar-next",
3229
+ children: /* @__PURE__ */ jsx29(NextChevron, { "aria-hidden": "true" })
3230
+ }
3231
+ )
3232
+ ] }),
3233
+ /* @__PURE__ */ jsxs22(AriaCalendarGrid, { className: "ddga-date-picker-calendar__grid", children: [
3234
+ /* @__PURE__ */ jsx29(AriaCalendarGridHeader, { children: (day) => /* @__PURE__ */ jsx29(AriaCalendarHeaderCell, { className: "ddga-date-picker-calendar__weekday", children: day }) }),
3235
+ /* @__PURE__ */ jsx29(AriaCalendarGridBody, { children: (date) => /* @__PURE__ */ jsx29(
3236
+ CalendarDayCell,
3237
+ {
3238
+ date,
3239
+ showSecondary: showSecondaryCalendar,
3240
+ calendarSystem
3241
+ }
3242
+ ) })
3243
+ ] })
3244
+ ] })
3245
+ ]
3246
+ }
3247
+ )
3248
+ }
3249
+ )
3250
+ ]
3251
+ }
3252
+ ) });
3253
+ }
3254
+
3255
+ // src/components/FileUpload/FileUpload.tsx
3256
+ import { useRef, useState as useState5 } from "react";
3257
+ import { jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
3258
+ function matchesAccept(file, accept) {
3259
+ if (!accept) return true;
3260
+ const tokens = accept.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
3261
+ if (tokens.length === 0) return true;
3262
+ const name = file.name.toLowerCase();
3263
+ const type = file.type.toLowerCase();
3264
+ return tokens.some((token) => {
3265
+ if (token.startsWith(".")) return name.endsWith(token);
3266
+ if (token.endsWith("/*")) return type.startsWith(token.slice(0, token.indexOf("/") + 1));
3267
+ return type === token;
3268
+ });
3269
+ }
3270
+ function splitFiles(incoming, config) {
3271
+ const { accept, maxSize, maxFiles, currentCount } = config;
3272
+ const accepted = [];
3273
+ const rejections = [];
3274
+ for (const file of incoming) {
3275
+ const errors = [];
3276
+ if (!matchesAccept(file, accept)) errors.push("file-invalid-type");
3277
+ if (maxSize != null && file.size > maxSize) errors.push("file-too-large");
3278
+ if (errors.length > 0) {
3279
+ rejections.push({ file, errors });
3280
+ continue;
3281
+ }
3282
+ if (maxFiles != null && currentCount + accepted.length >= maxFiles) {
3283
+ rejections.push({ file, errors: ["too-many-files"] });
3284
+ continue;
3285
+ }
3286
+ accepted.push(file);
3287
+ }
3288
+ return { accepted, rejections };
3289
+ }
3290
+ var UNITS = ["B", "KB", "MB", "GB", "TB"];
3291
+ function formatBytes(bytes) {
3292
+ if (bytes === 0) return "0 B";
3293
+ const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), UNITS.length - 1);
3294
+ const value = bytes / 1024 ** exponent;
3295
+ return `${exponent === 0 ? value : value.toFixed(1)} ${UNITS[exponent]}`;
3296
+ }
3297
+ function FileUpload({
3298
+ files,
3299
+ onFilesAdded,
3300
+ onFilesRejected,
3301
+ onRemove,
3302
+ accept,
3303
+ maxSize,
3304
+ maxFiles,
3305
+ multiple = true,
3306
+ disabled = false,
3307
+ required,
3308
+ label,
3309
+ helperText,
3310
+ errorMessage,
3311
+ error,
3312
+ hint = "Drag files here, or click to browse",
3313
+ removeLabel = "Remove",
3314
+ id: externalId,
3315
+ className,
3316
+ ...props
3317
+ }) {
3318
+ const inputRef = useRef(null);
3319
+ const [isDragging, setIsDragging] = useState5(false);
3320
+ const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
3321
+ name: "FileUpload",
3322
+ id: externalId,
3323
+ label,
3324
+ error,
3325
+ errorMessage,
3326
+ helperText,
3327
+ "aria-label": props["aria-label"],
3328
+ "aria-labelledby": props["aria-labelledby"]
3329
+ });
3330
+ const effectiveMaxFiles = multiple ? maxFiles : 1;
3331
+ function process2(incoming) {
3332
+ if (disabled || incoming.length === 0) return;
3333
+ const { accepted, rejections } = splitFiles(incoming, {
3334
+ accept,
3335
+ maxSize,
3336
+ maxFiles: effectiveMaxFiles,
3337
+ currentCount: files.length
3338
+ });
3339
+ if (accepted.length > 0) onFilesAdded(accepted);
3340
+ if (rejections.length > 0) onFilesRejected?.(rejections);
3341
+ }
3342
+ function handleInputChange(event) {
3343
+ process2(Array.from(event.target.files ?? []));
3344
+ event.target.value = "";
3345
+ }
3346
+ function handleDrop(event) {
3347
+ event.preventDefault();
3348
+ setIsDragging(false);
3349
+ if (disabled) return;
3350
+ process2(Array.from(event.dataTransfer.files));
3351
+ }
3352
+ function handleDragOver(event) {
3353
+ event.preventDefault();
3354
+ if (!disabled) setIsDragging(true);
3355
+ }
3356
+ function handleDragLeave(event) {
3357
+ if (!event.currentTarget.contains(event.relatedTarget)) {
3358
+ setIsDragging(false);
3359
+ }
3360
+ }
3361
+ return /* @__PURE__ */ jsxs23("div", { "data-slot": "file-upload-field", className: cn("ddga-field", "ddga-file-upload", className), children: [
3362
+ label && /* @__PURE__ */ jsxs23("label", { htmlFor: fieldId, className: "ddga-file-upload__label", children: [
3363
+ label,
3364
+ required && /* @__PURE__ */ jsx30("span", { "aria-hidden": "true", className: "ddga-file-upload__required", children: "*" })
3365
+ ] }),
3366
+ /* @__PURE__ */ jsxs23(
3367
+ "div",
3368
+ {
3369
+ "data-slot": "file-upload-dropzone",
3370
+ className: cn(
3371
+ "ddga-file-upload__dropzone",
3372
+ hasError && "ddga-file-upload__dropzone--error"
3373
+ ),
3374
+ "data-dragging": isDragging || void 0,
3375
+ "data-disabled": disabled || void 0,
3376
+ "aria-disabled": disabled || void 0,
3377
+ onClick: () => {
3378
+ if (!disabled) inputRef.current?.click();
3379
+ },
3380
+ onDragOver: handleDragOver,
3381
+ onDragLeave: handleDragLeave,
3382
+ onDrop: handleDrop,
3383
+ children: [
3384
+ /* @__PURE__ */ jsx30(Upload, { className: "ddga-file-upload__icon", "aria-hidden": "true" }),
3385
+ /* @__PURE__ */ jsx30("span", { className: "ddga-file-upload__hint", children: hint }),
3386
+ /* @__PURE__ */ jsx30(
3387
+ "input",
3388
+ {
3389
+ ...controlProps,
3390
+ ref: inputRef,
3391
+ type: "file",
3392
+ className: "ddga-file-upload__input",
3393
+ accept,
3394
+ multiple,
3395
+ disabled,
3396
+ required,
3397
+ onChange: handleInputChange,
3398
+ onClick: (event) => event.stopPropagation(),
3399
+ "data-slot": "file-upload-input"
3400
+ }
3401
+ )
3402
+ ]
3403
+ }
3404
+ ),
3405
+ hasErrorMessage && /* @__PURE__ */ jsx30(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
3406
+ hasHelper && /* @__PURE__ */ jsx30(FieldMessage, { id: helperId, variant: "helper", children: helperText }),
3407
+ files.length > 0 && /* @__PURE__ */ jsx30("ul", { "data-slot": "file-upload-list", className: "ddga-file-upload__list", children: files.map((item) => {
3408
+ const status = item.status ?? "pending";
3409
+ return /* @__PURE__ */ jsxs23(
3410
+ "li",
3411
+ {
3412
+ "data-slot": "file-upload-item",
3413
+ "data-status": status,
3414
+ className: "ddga-file-upload__item",
3415
+ children: [
3416
+ /* @__PURE__ */ jsx30("span", { className: "ddga-file-upload__item-icon", "aria-hidden": "true", children: status === "success" ? /* @__PURE__ */ jsx30(Check, {}) : status === "error" ? /* @__PURE__ */ jsx30(AlertCircle, {}) : /* @__PURE__ */ jsx30(Upload, {}) }),
3417
+ /* @__PURE__ */ jsxs23("div", { className: "ddga-file-upload__item-main", children: [
3418
+ /* @__PURE__ */ jsxs23("div", { className: "ddga-file-upload__item-head", children: [
3419
+ /* @__PURE__ */ jsx30("span", { className: "ddga-file-upload__item-name", title: item.file.name, children: item.file.name }),
3420
+ /* @__PURE__ */ jsx30("span", { className: "ddga-file-upload__item-meta", children: formatBytes(item.file.size) })
3421
+ ] }),
3422
+ status === "uploading" && /* @__PURE__ */ jsx30(
3423
+ Progress,
3424
+ {
3425
+ size: "sm",
3426
+ value: item.progress ?? 0,
3427
+ "aria-label": `Uploading ${item.file.name}`,
3428
+ className: "ddga-file-upload__item-progress"
3429
+ }
3430
+ ),
3431
+ status === "error" && item.error && /* @__PURE__ */ jsx30("span", { role: "alert", className: "ddga-file-upload__item-error", children: item.error })
3432
+ ] }),
3433
+ onRemove && /* @__PURE__ */ jsx30(
3434
+ Button,
3435
+ {
3436
+ type: "button",
3437
+ variant: "ghost",
3438
+ size: "icon-sm",
3439
+ "aria-label": `${removeLabel}: ${item.file.name}`,
3440
+ onClick: () => onRemove(item.id),
3441
+ className: "ddga-file-upload__item-remove",
3442
+ children: /* @__PURE__ */ jsx30(Close, { "aria-hidden": "true" })
3443
+ }
3444
+ )
3445
+ ]
3446
+ },
3447
+ item.id
3448
+ );
3449
+ }) })
3450
+ ] });
3451
+ }
3452
+
3453
+ // src/components/Slider/Slider.tsx
3454
+ import { useId as useId4 } from "react";
3455
+ import { Slider as SliderPrimitive } from "radix-ui";
3456
+ import { cva as cva28 } from "class-variance-authority";
3457
+ import { jsx as jsx31, jsxs as jsxs24 } from "react/jsx-runtime";
3458
+ var sliderVariants = cva28("ddga-slider", {
3459
+ variants: {
3460
+ size: {
3461
+ sm: "ddga-slider--sm",
3462
+ md: "ddga-slider--md"
3463
+ },
3464
+ error: {
3465
+ true: "ddga-slider--error"
3466
+ }
3467
+ },
3468
+ defaultVariants: {
3469
+ size: "md"
3470
+ }
3471
+ });
3472
+ var DEFAULT_THUMB_LABELS = ["Minimum", "Maximum"];
3473
+ function toArray(value) {
3474
+ if (value === void 0) return void 0;
3475
+ return Array.isArray(value) ? value : [value];
3476
+ }
3477
+ function Slider({
3478
+ id: externalId,
3479
+ value,
3480
+ defaultValue,
3481
+ onValueChange,
3482
+ onValueCommit,
3483
+ min = 0,
3484
+ max = 100,
3485
+ size,
3486
+ label,
3487
+ helperText,
3488
+ errorMessage,
3489
+ error,
3490
+ showValue = false,
3491
+ formatValue,
3492
+ thumbLabels = DEFAULT_THUMB_LABELS,
3493
+ className,
3494
+ ...props
3495
+ }) {
3496
+ const labelId = useId4();
3497
+ const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
3498
+ name: "Slider",
3499
+ id: externalId,
3500
+ label,
3501
+ error,
3502
+ errorMessage,
3503
+ helperText,
3504
+ "aria-label": props["aria-label"],
3505
+ "aria-labelledby": props["aria-labelledby"] ?? (label ? labelId : void 0)
3506
+ });
3507
+ const isRange = Array.isArray(value ?? defaultValue);
3508
+ const valueArray = toArray(value);
3509
+ const defaultArray = toArray(defaultValue) ?? [min];
3510
+ const wrap = (next) => isRange ? next : next[0];
3511
+ const currentForRender = valueArray ?? defaultArray;
3512
+ const fmt = (n) => formatValue ? formatValue(n) : String(n);
3513
+ return /* @__PURE__ */ jsxs24("div", { "data-slot": "slider-field", className: "ddga-field", children: [
3514
+ (label || showValue) && /* @__PURE__ */ jsxs24("div", { className: "ddga-slider__header", children: [
3515
+ label && /* @__PURE__ */ jsx31("span", { id: labelId, className: "ddga-slider__label", children: label }),
3516
+ showValue && /* @__PURE__ */ jsx31("span", { className: "ddga-slider__value", "aria-hidden": "true", children: currentForRender.map(fmt).join(" \u2013 ") })
3517
+ ] }),
3518
+ /* @__PURE__ */ jsxs24(
3519
+ SliderPrimitive.Root,
3520
+ {
3521
+ ...props,
3522
+ id: fieldId,
3523
+ min,
3524
+ max,
3525
+ value: valueArray,
3526
+ defaultValue: value === void 0 ? defaultArray : void 0,
3527
+ onValueChange: onValueChange ? (next) => onValueChange(wrap(next)) : void 0,
3528
+ onValueCommit: onValueCommit ? (next) => onValueCommit(wrap(next)) : void 0,
3529
+ "aria-invalid": controlProps["aria-invalid"],
3530
+ "data-slot": "slider",
3531
+ className: cn(sliderVariants({ size, error: hasError }), className),
3532
+ children: [
3533
+ /* @__PURE__ */ jsx31(SliderPrimitive.Track, { "data-slot": "slider-track", className: "ddga-slider__track", children: /* @__PURE__ */ jsx31(SliderPrimitive.Range, { "data-slot": "slider-range", className: "ddga-slider__range" }) }),
3534
+ currentForRender.map((thumbValue, index) => /* @__PURE__ */ jsx31(
3535
+ SliderPrimitive.Thumb,
3536
+ {
3537
+ "data-slot": "slider-thumb",
3538
+ className: "ddga-slider__thumb",
3539
+ "aria-label": isRange ? thumbLabels[index] : void 0,
3540
+ "aria-labelledby": !isRange && label ? labelId : void 0,
3541
+ "aria-valuetext": formatValue ? fmt(thumbValue) : void 0,
3542
+ "aria-describedby": controlProps["aria-describedby"]
3543
+ },
3544
+ index
3545
+ ))
3546
+ ]
3547
+ }
3548
+ ),
3549
+ hasErrorMessage && /* @__PURE__ */ jsx31(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
3550
+ hasHelper && /* @__PURE__ */ jsx31(FieldMessage, { id: helperId, variant: "helper", children: helperText })
3551
+ ] });
3552
+ }
3553
+
3554
+ // src/components/NumberInput/NumberInput.tsx
3555
+ import { useState as useState6 } from "react";
3556
+ import { cva as cva29 } from "class-variance-authority";
3557
+ import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
3558
+ var numberInputVariants = cva29("ddga-number-input", {
3559
+ variants: {
3560
+ size: {
3561
+ sm: "ddga-number-input--sm",
3562
+ md: "ddga-number-input--md",
3563
+ lg: "ddga-number-input--lg"
3564
+ },
3565
+ error: {
3566
+ true: "ddga-number-input--error"
3567
+ }
3568
+ },
3569
+ defaultVariants: {
3570
+ size: "md"
3571
+ }
3572
+ });
3573
+ function clamp(value, min, max) {
3574
+ let next = value;
3575
+ if (min != null) next = Math.max(min, next);
3576
+ if (max != null) next = Math.min(max, next);
3577
+ return next;
3578
+ }
3579
+ function formatNumber(value) {
3580
+ if (!Number.isFinite(value)) return "";
3581
+ return value.toLocaleString("en-US", { useGrouping: false, maximumFractionDigits: 20 });
3582
+ }
3583
+ function NumberInput({
3584
+ id: externalId,
3585
+ value,
3586
+ defaultValue,
3587
+ onValueChange,
3588
+ min,
3589
+ max,
3590
+ step = 1,
3591
+ size,
3592
+ hideControls = false,
3593
+ decrementLabel = "Decrease",
3594
+ incrementLabel = "Increase",
3595
+ label,
3596
+ helperText,
3597
+ errorMessage,
3598
+ error,
3599
+ required,
3600
+ disabled,
3601
+ className,
3602
+ onBlur,
3603
+ onKeyDown,
3604
+ ...props
3605
+ }) {
3606
+ const isControlled = value !== void 0;
3607
+ const [internal, setInternal] = useState6(defaultValue ?? null);
3608
+ const numericValue = isControlled ? value : internal;
3609
+ const [draft, setDraft] = useState6(null);
3610
+ const allowDecimal = !Number.isInteger(step);
3611
+ const allowNegative = min == null || min < 0;
3612
+ const displayValue = draft ?? (numericValue == null ? "" : formatNumber(numericValue));
3613
+ const allowedPattern = new RegExp(
3614
+ `^${allowNegative ? "-?" : ""}\\d*${allowDecimal ? "(\\.\\d*)?" : ""}$`
3615
+ );
3616
+ function commit(next) {
3617
+ if (!isControlled) setInternal(next);
3618
+ onValueChange?.(next);
3619
+ }
3620
+ const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
3621
+ name: "NumberInput",
3622
+ id: externalId,
3623
+ label,
3624
+ error,
3625
+ errorMessage,
3626
+ helperText,
3627
+ "aria-label": props["aria-label"],
3628
+ "aria-labelledby": props["aria-labelledby"]
3629
+ });
3630
+ function handleChange(event) {
3631
+ const raw = event.target.value;
3632
+ if (!allowedPattern.test(raw)) return;
3633
+ setDraft(raw);
3634
+ if (raw.trim() === "") {
3635
+ commit(null);
3636
+ return;
3637
+ }
3638
+ const parsed = Number(raw);
3639
+ if (Number.isFinite(parsed)) commit(parsed);
3640
+ }
3641
+ function handleBlur(event) {
3642
+ if (numericValue != null) commit(clamp(numericValue, min, max));
3643
+ setDraft(null);
3644
+ onBlur?.(event);
3645
+ }
3646
+ function stepBy(direction) {
3647
+ const base = numericValue ?? (direction > 0 ? min ?? 0 : max ?? 0);
3648
+ const next = clamp(base + direction * step, min, max);
3649
+ const rounded = allowDecimal ? Number(next.toFixed(10)) : next;
3650
+ commit(rounded);
3651
+ setDraft(null);
3652
+ }
3653
+ function handleKeyDown(event) {
3654
+ if (!disabled) {
3655
+ if (event.key === "ArrowUp") {
3656
+ event.preventDefault();
3657
+ stepBy(1);
3658
+ } else if (event.key === "ArrowDown") {
3659
+ event.preventDefault();
3660
+ stepBy(-1);
3661
+ }
3662
+ }
3663
+ onKeyDown?.(event);
3664
+ }
3665
+ const atMin = min != null && numericValue != null && numericValue <= min;
3666
+ const atMax = max != null && numericValue != null && numericValue >= max;
3667
+ return /* @__PURE__ */ jsxs25("div", { "data-slot": "number-input-field", className: "ddga-field", children: [
3668
+ label && /* @__PURE__ */ jsxs25("label", { htmlFor: fieldId, className: "ddga-number-input__label", children: [
3669
+ label,
3670
+ required && /* @__PURE__ */ jsx32("span", { "aria-hidden": "true", className: "ddga-number-input__required", children: "*" })
3671
+ ] }),
3672
+ /* @__PURE__ */ jsxs25(
3673
+ "div",
3674
+ {
3675
+ "data-slot": "number-input-control",
3676
+ className: cn(numberInputVariants({ size, error: hasError }), className),
3677
+ children: [
3678
+ !hideControls && /* @__PURE__ */ jsx32(
3679
+ "button",
3680
+ {
3681
+ type: "button",
3682
+ "data-slot": "number-input-decrement",
3683
+ className: "ddga-number-input__step ddga-number-input__step--decrement",
3684
+ "aria-label": decrementLabel,
3685
+ onClick: () => stepBy(-1),
3686
+ disabled: disabled || atMin,
3687
+ tabIndex: -1,
3688
+ children: /* @__PURE__ */ jsx32(Minus, { "aria-hidden": "true" })
3689
+ }
3690
+ ),
3691
+ /* @__PURE__ */ jsx32(
3692
+ "input",
3693
+ {
3694
+ ...props,
3695
+ ...controlProps,
3696
+ type: "text",
3697
+ inputMode: allowDecimal ? "decimal" : "numeric",
3698
+ value: displayValue,
3699
+ required,
3700
+ disabled,
3701
+ onChange: handleChange,
3702
+ onBlur: handleBlur,
3703
+ onKeyDown: handleKeyDown,
3704
+ "data-slot": "number-input",
3705
+ className: "ddga-number-input__field"
3706
+ }
3707
+ ),
3708
+ !hideControls && /* @__PURE__ */ jsx32(
3709
+ "button",
3710
+ {
3711
+ type: "button",
3712
+ "data-slot": "number-input-increment",
3713
+ className: "ddga-number-input__step ddga-number-input__step--increment",
3714
+ "aria-label": incrementLabel,
3715
+ onClick: () => stepBy(1),
3716
+ disabled: disabled || atMax,
3717
+ tabIndex: -1,
3718
+ children: /* @__PURE__ */ jsx32(Plus, { "aria-hidden": "true" })
3719
+ }
3720
+ )
3721
+ ]
3722
+ }
3723
+ ),
3724
+ hasErrorMessage && /* @__PURE__ */ jsx32(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
3725
+ hasHelper && /* @__PURE__ */ jsx32(FieldMessage, { id: helperId, variant: "helper", children: helperText })
3726
+ ] });
3727
+ }
3728
+
3729
+ // src/components/Rating/Rating.tsx
3730
+ import { useRef as useRef2, useState as useState7 } from "react";
3731
+ import { cva as cva30 } from "class-variance-authority";
3732
+ import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
3733
+ var ratingVariants = cva30("ddga-rating", {
3734
+ variants: {
3735
+ size: {
3736
+ sm: "ddga-rating--sm",
3737
+ md: "ddga-rating--md",
3738
+ lg: "ddga-rating--lg"
3739
+ }
3740
+ },
3741
+ defaultVariants: {
3742
+ size: "md"
3743
+ }
3744
+ });
3745
+ function clamp2(value, min, max) {
3746
+ return Math.min(max, Math.max(min, value));
3747
+ }
3748
+ function defaultValueText(value, max) {
3749
+ return `${value} out of ${max} stars`;
3750
+ }
3751
+ function fillFor(index, value, allowHalf) {
3752
+ if (value >= index + 1) return "full";
3753
+ if (allowHalf && value >= index + 0.5) return "half";
3754
+ return "empty";
3755
+ }
3756
+ function Rating({
3757
+ id: externalId,
3758
+ value,
3759
+ defaultValue,
3760
+ onValueChange,
3761
+ max = 5,
3762
+ allowHalf = false,
3763
+ readOnly = false,
3764
+ disabled = false,
3765
+ size,
3766
+ label,
3767
+ helperText,
3768
+ errorMessage,
3769
+ error,
3770
+ formatValueText = defaultValueText,
3771
+ className,
3772
+ ...props
3773
+ }) {
3774
+ const rootRef = useRef2(null);
3775
+ const isControlled = value !== void 0;
3776
+ const [internal, setInternal] = useState7(defaultValue ?? 0);
3777
+ const currentValue = isControlled ? value : internal;
3778
+ const [hover, setHover] = useState7(null);
3779
+ const interactive = !readOnly && !disabled;
3780
+ const stepSize = allowHalf ? 0.5 : 1;
3781
+ const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } = useFieldA11y({
3782
+ name: "Rating",
3783
+ id: externalId,
3784
+ label,
3785
+ error,
3786
+ errorMessage,
3787
+ helperText,
3788
+ // role=slider / role=img always have an accessible name (label or the
3789
+ // value text), so suppress the no-label dev warning.
3790
+ "aria-label": props["aria-label"] ?? formatValueText(currentValue, max),
3791
+ "aria-labelledby": props["aria-labelledby"]
3792
+ });
3793
+ const displayValue = hover ?? currentValue;
3794
+ function commit(next) {
3795
+ if (!isControlled) setInternal(next);
3796
+ onValueChange?.(next);
3797
+ }
3798
+ function readDir() {
3799
+ const el = rootRef.current;
3800
+ if (!el || typeof getComputedStyle !== "function") return "ltr";
3801
+ return getComputedStyle(el).direction === "rtl" ? "rtl" : "ltr";
3802
+ }
3803
+ function pointerValue(event, index) {
3804
+ const rect = event.currentTarget.getBoundingClientRect();
3805
+ let fraction = rect.width ? (event.clientX - rect.left) / rect.width : 1;
3806
+ if (readDir() === "rtl") fraction = 1 - fraction;
3807
+ if (allowHalf) return index + (fraction <= 0.5 ? 0.5 : 1);
3808
+ return index + 1;
3809
+ }
3810
+ function handleKeyDown(event) {
3811
+ if (!interactive) return;
3812
+ const rtl = readDir() === "rtl";
3813
+ let next = null;
3814
+ switch (event.key) {
3815
+ case "ArrowUp":
3816
+ next = currentValue + stepSize;
3817
+ break;
3818
+ case "ArrowDown":
3819
+ next = currentValue - stepSize;
3820
+ break;
3821
+ case "ArrowRight":
3822
+ next = currentValue + (rtl ? -stepSize : stepSize);
3823
+ break;
3824
+ case "ArrowLeft":
3825
+ next = currentValue + (rtl ? stepSize : -stepSize);
3826
+ break;
3827
+ case "Home":
3828
+ next = 0;
3829
+ break;
3830
+ case "End":
3831
+ next = max;
3832
+ break;
3833
+ default:
3834
+ return;
3835
+ }
3836
+ event.preventDefault();
3837
+ commit(clamp2(next, 0, max));
3838
+ }
3839
+ const stars = Array.from({ length: max }, (_, index) => {
3840
+ const level = fillFor(index, displayValue, allowHalf);
3841
+ return /* @__PURE__ */ jsxs26(
3842
+ "span",
3843
+ {
3844
+ "data-slot": "rating-star",
3845
+ "data-fill": level,
3846
+ className: "ddga-rating__star",
3847
+ onPointerMove: interactive ? (event) => setHover(pointerValue(event, index)) : void 0,
3848
+ onClick: interactive ? (event) => commit(pointerValue(event, index)) : void 0,
3849
+ children: [
3850
+ /* @__PURE__ */ jsx33(Star, { className: "ddga-rating__star-bg", "aria-hidden": "true" }),
3851
+ /* @__PURE__ */ jsx33("span", { className: "ddga-rating__star-fill", "aria-hidden": "true", children: /* @__PURE__ */ jsx33(Star, { className: "ddga-rating__star-fg", "aria-hidden": "true" }) })
3852
+ ]
3853
+ },
3854
+ index
3855
+ );
3856
+ });
3857
+ const sharedProps = {
3858
+ ref: rootRef,
3859
+ "data-slot": "rating",
3860
+ "data-disabled": disabled || void 0,
3861
+ className: cn(ratingVariants({ size }), hasError && "ddga-rating--error", className),
3862
+ onPointerLeave: interactive ? () => setHover(null) : void 0
3863
+ };
3864
+ const labelledBy = label ? `${fieldId}-label` : props["aria-labelledby"];
3865
+ const ariaLabel = labelledBy ? void 0 : props["aria-label"] ?? "Rating";
3866
+ return /* @__PURE__ */ jsxs26("div", { "data-slot": "rating-field", className: "ddga-field", children: [
3867
+ label && /* @__PURE__ */ jsx33("span", { id: `${fieldId}-label`, className: "ddga-rating__label", children: label }),
3868
+ readOnly ? /* @__PURE__ */ jsx33("div", { ...sharedProps, role: "img", "aria-label": formatValueText(currentValue, max), children: stars }) : /* @__PURE__ */ jsx33(
3869
+ "div",
3870
+ {
3871
+ ...sharedProps,
3872
+ role: "slider",
3873
+ id: fieldId,
3874
+ tabIndex: disabled ? -1 : 0,
3875
+ "aria-valuemin": 0,
3876
+ "aria-valuemax": max,
3877
+ "aria-valuenow": currentValue,
3878
+ "aria-valuetext": formatValueText(currentValue, max),
3879
+ "aria-labelledby": labelledBy,
3880
+ "aria-label": ariaLabel,
3881
+ "aria-invalid": controlProps["aria-invalid"],
3882
+ "aria-describedby": controlProps["aria-describedby"],
3883
+ "aria-disabled": disabled || void 0,
3884
+ onKeyDown: handleKeyDown,
3885
+ children: stars
3886
+ }
3887
+ ),
3888
+ hasErrorMessage && /* @__PURE__ */ jsx33(FieldMessage, { id: errorId, variant: "error", children: errorMessage }),
3889
+ hasHelper && /* @__PURE__ */ jsx33(FieldMessage, { id: helperId, variant: "helper", children: helperText })
3890
+ ] });
3891
+ }
3892
+
3893
+ // src/components/Toggle/Toggle.tsx
3894
+ import { Toggle as TogglePrimitive, ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
3895
+ import { cva as cva31 } from "class-variance-authority";
3896
+ import { jsx as jsx34 } from "react/jsx-runtime";
3897
+ var toggleVariants = cva31("ddga-toggle", {
3898
+ variants: {
3899
+ variant: {
3900
+ default: "ddga-toggle--default",
3901
+ outline: "ddga-toggle--outline"
3902
+ },
3903
+ size: {
3904
+ sm: "ddga-toggle--sm",
3905
+ md: "ddga-toggle--md",
3906
+ lg: "ddga-toggle--lg"
3907
+ }
3908
+ },
3909
+ defaultVariants: {
3910
+ variant: "default",
3911
+ size: "md"
3912
+ }
3913
+ });
3914
+ var toggleGroupVariants = cva31("ddga-toggle-group", {
3915
+ variants: {
3916
+ variant: {
3917
+ default: "ddga-toggle-group--default",
3918
+ outline: "ddga-toggle-group--outline"
3919
+ },
3920
+ size: {
3921
+ sm: "ddga-toggle-group--sm",
3922
+ md: "ddga-toggle-group--md",
3923
+ lg: "ddga-toggle-group--lg"
3924
+ }
3925
+ },
3926
+ defaultVariants: {
3927
+ variant: "default",
3928
+ size: "md"
3929
+ }
3930
+ });
3931
+ function Toggle({ variant, size, className, ...props }) {
3932
+ return /* @__PURE__ */ jsx34(
3933
+ TogglePrimitive.Root,
3934
+ {
3935
+ "data-slot": "toggle",
3936
+ className: cn(toggleVariants({ variant, size }), className),
3937
+ ...props
3938
+ }
3939
+ );
3940
+ }
3941
+ function ToggleGroup({ variant, size, className, ...props }) {
3942
+ if (process.env.NODE_ENV === "development" && !props["aria-label"] && !props["aria-labelledby"]) {
3943
+ console.warn(
3944
+ "[@dev-dga/react] ToggleGroup should have an `aria-label` or `aria-labelledby` so the button group has an accessible name."
3945
+ );
3946
+ }
3947
+ return /* @__PURE__ */ jsx34(
3948
+ ToggleGroupPrimitive.Root,
3949
+ {
3950
+ "data-slot": "toggle-group",
3951
+ className: cn(toggleGroupVariants({ variant, size }), className),
3952
+ ...props
3953
+ }
3954
+ );
3955
+ }
3956
+ function ToggleGroupItem({ className, ...props }) {
3957
+ return /* @__PURE__ */ jsx34(
3958
+ ToggleGroupPrimitive.Item,
3959
+ {
3960
+ "data-slot": "toggle-group-item",
3961
+ className: cn("ddga-toggle-group__item", className),
3962
+ ...props
3963
+ }
3964
+ );
3965
+ }
3966
+
3967
+ // src/components/DescriptionList/DescriptionList.tsx
3968
+ import { cva as cva32 } from "class-variance-authority";
3969
+ import { jsx as jsx35 } from "react/jsx-runtime";
3970
+ var descriptionListVariants = cva32("ddga-description-list", {
3971
+ variants: {
3972
+ orientation: {
3973
+ horizontal: "ddga-description-list--horizontal",
3974
+ vertical: "ddga-description-list--vertical"
3975
+ },
3976
+ divided: {
3977
+ true: "ddga-description-list--divided"
3978
+ }
3979
+ },
3980
+ defaultVariants: {
3981
+ orientation: "horizontal"
3982
+ }
3983
+ });
3984
+ function DescriptionList({ orientation, divided, className, ...props }) {
3985
+ return /* @__PURE__ */ jsx35(
3986
+ "dl",
3987
+ {
3988
+ "data-slot": "description-list",
3989
+ className: cn(descriptionListVariants({ orientation, divided }), className),
3990
+ ...props
3991
+ }
3992
+ );
3993
+ }
3994
+ function DescriptionItem({ className, ...props }) {
3995
+ return /* @__PURE__ */ jsx35(
3996
+ "div",
3997
+ {
3998
+ "data-slot": "description-item",
3999
+ className: cn("ddga-description-list__item", className),
4000
+ ...props
4001
+ }
4002
+ );
4003
+ }
4004
+ function DescriptionTerm({ className, ...props }) {
4005
+ return /* @__PURE__ */ jsx35(
4006
+ "dt",
4007
+ {
4008
+ "data-slot": "description-term",
4009
+ className: cn("ddga-description-list__term", className),
4010
+ ...props
4011
+ }
4012
+ );
4013
+ }
4014
+ function DescriptionDetails({ className, ...props }) {
4015
+ return /* @__PURE__ */ jsx35(
4016
+ "dd",
4017
+ {
4018
+ "data-slot": "description-details",
4019
+ className: cn("ddga-description-list__details", className),
4020
+ ...props
4021
+ }
4022
+ );
4023
+ }
4024
+
2764
4025
  // src/providers/DgaProvider.tsx
2765
- import { useState as useState4, useMemo as useMemo2, useContext as useContext8 } from "react";
4026
+ import { useState as useState8, useMemo as useMemo3, useContext as useContext9, useEffect, useRef as useRef3 } from "react";
2766
4027
  import { Direction as DirectionPrimitive, Tooltip as TooltipPrimitive2 } from "radix-ui";
2767
4028
  import { buildTheme } from "@dev-dga/tokens";
2768
- import { jsx as jsx29 } from "react/jsx-runtime";
4029
+ import { jsx as jsx36 } from "react/jsx-runtime";
2769
4030
  function DgaProvider({
2770
4031
  dir = "ltr",
2771
4032
  locale,
@@ -2776,17 +4037,46 @@ function DgaProvider({
2776
4037
  style: consumerStyle,
2777
4038
  children
2778
4039
  }) {
2779
- const parentCtx = useContext8(DgaContext);
4040
+ const parentCtx = useContext9(DgaContext);
2780
4041
  const isNested = parentCtx !== null;
2781
- const [rootEl, setRootEl] = useState4(null);
4042
+ const [rootEl, setRootEl] = useState8(null);
4043
+ const portalRef = useRef3(null);
4044
+ const [portalEl, setPortalEl] = useState8(null);
2782
4045
  const resolvedLocale = locale ?? (dir === "rtl" ? "ar" : "en");
2783
- const ctxValue = useMemo2(
2784
- () => ({ dir, locale: resolvedLocale, mode, rootEl }),
2785
- [dir, resolvedLocale, mode, rootEl]
4046
+ const themeVars = useMemo3(() => theme ? buildTheme(theme) : null, [theme]);
4047
+ useEffect(() => {
4048
+ if (typeof document === "undefined") return;
4049
+ const el = document.createElement("div");
4050
+ el.setAttribute("data-slot", "dga-portal");
4051
+ el.style.position = "relative";
4052
+ el.style.zIndex = "50";
4053
+ document.body.appendChild(el);
4054
+ portalRef.current = el;
4055
+ setPortalEl(el);
4056
+ return () => {
4057
+ el.remove();
4058
+ portalRef.current = null;
4059
+ setPortalEl(null);
4060
+ };
4061
+ }, []);
4062
+ useEffect(() => {
4063
+ const el = portalRef.current;
4064
+ if (!el) return;
4065
+ el.setAttribute("data-theme", mode);
4066
+ el.setAttribute("dir", dir);
4067
+ el.style.colorScheme = mode;
4068
+ if (themeVars) {
4069
+ for (const [k, v] of Object.entries(themeVars)) {
4070
+ el.style.setProperty(k, String(v));
4071
+ }
4072
+ }
4073
+ }, [mode, dir, themeVars, portalEl]);
4074
+ const ctxValue = useMemo3(
4075
+ () => ({ dir, locale: resolvedLocale, mode, rootEl, portalEl }),
4076
+ [dir, resolvedLocale, mode, rootEl, portalEl]
2786
4077
  );
2787
- const themeVars = useMemo2(() => theme ? buildTheme(theme) : null, [theme]);
2788
- const inner = /* @__PURE__ */ jsx29(DirectionPrimitive.Provider, { dir, children });
2789
- return /* @__PURE__ */ jsx29(DgaContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx29(
4078
+ const inner = /* @__PURE__ */ jsx36(DirectionPrimitive.Provider, { dir, children });
4079
+ return /* @__PURE__ */ jsx36(DgaContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx36(
2790
4080
  Component,
2791
4081
  {
2792
4082
  ref: setRootEl,
@@ -2796,7 +4086,7 @@ function DgaProvider({
2796
4086
  "data-theme": mode,
2797
4087
  className,
2798
4088
  style: { colorScheme: mode, ...themeVars ?? {}, ...consumerStyle },
2799
- children: isNested ? inner : /* @__PURE__ */ jsx29(TooltipPrimitive2.Provider, { delayDuration: 300, skipDelayDuration: 100, children: inner })
4089
+ children: isNested ? inner : /* @__PURE__ */ jsx36(TooltipPrimitive2.Provider, { delayDuration: 300, skipDelayDuration: 100, children: inner })
2800
4090
  }
2801
4091
  ) });
2802
4092
  }
@@ -2839,6 +4129,11 @@ export {
2839
4129
  ComboboxGroup,
2840
4130
  ComboboxItem,
2841
4131
  ComboboxSeparator,
4132
+ DatePicker,
4133
+ DescriptionDetails,
4134
+ DescriptionItem,
4135
+ DescriptionList,
4136
+ DescriptionTerm,
2842
4137
  DgaProvider,
2843
4138
  Divider,
2844
4139
  Drawer,
@@ -2864,6 +4159,7 @@ export {
2864
4159
  DropdownMenuSubTrigger,
2865
4160
  DropdownMenuTrigger,
2866
4161
  FieldMessage,
4162
+ FileUpload,
2867
4163
  Input,
2868
4164
  Modal,
2869
4165
  ModalClose,
@@ -2873,6 +4169,7 @@ export {
2873
4169
  ModalHeader,
2874
4170
  ModalTitle,
2875
4171
  ModalTrigger,
4172
+ NumberInput,
2876
4173
  Pagination,
2877
4174
  PaginationContent,
2878
4175
  PaginationEllipsis,
@@ -2883,9 +4180,11 @@ export {
2883
4180
  Progress,
2884
4181
  Radio,
2885
4182
  RadioGroup,
4183
+ Rating,
2886
4184
  Select,
2887
4185
  SelectItem,
2888
4186
  Skeleton,
4187
+ Slider,
2889
4188
  Spinner,
2890
4189
  Step,
2891
4190
  StepDescription,
@@ -2899,6 +4198,9 @@ export {
2899
4198
  TabsTrigger,
2900
4199
  Textarea,
2901
4200
  Toaster,
4201
+ Toggle,
4202
+ ToggleGroup,
4203
+ ToggleGroupItem,
2902
4204
  Tooltip,
2903
4205
  TooltipContent,
2904
4206
  TooltipTrigger,
@@ -2916,18 +4218,23 @@ export {
2916
4218
  comboboxVariants,
2917
4219
  createToast,
2918
4220
  createToastStore,
4221
+ datePickerVariants,
4222
+ descriptionListVariants,
2919
4223
  dividerVariants,
2920
4224
  drawerVariants,
2921
4225
  dropdownMenuVariants,
2922
4226
  inputVariants,
2923
4227
  modalContentVariants,
4228
+ numberInputVariants,
2924
4229
  paginationLinkVariants,
2925
4230
  paginationVariants,
2926
4231
  progressVariants,
2927
4232
  radioGroupVariants,
2928
4233
  radioVariants,
4234
+ ratingVariants,
2929
4235
  selectTriggerVariants,
2930
4236
  skeletonVariants,
4237
+ sliderVariants,
2931
4238
  spinnerVariants,
2932
4239
  stepVariants,
2933
4240
  stepsVariants,
@@ -2939,6 +4246,8 @@ export {
2939
4246
  toastStore,
2940
4247
  toastVariants,
2941
4248
  toastViewportVariants,
4249
+ toggleGroupVariants,
4250
+ toggleVariants,
2942
4251
  tooltipContentVariants,
2943
4252
  useDga,
2944
4253
  useDir,