asterui 0.12.77 → 0.12.79
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,189 +1,178 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { useConfig as
|
|
4
|
-
import { Button as
|
|
5
|
-
import { Flex as
|
|
6
|
-
import { InputNumber as
|
|
1
|
+
import { jsxs as w, jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { useState as X, useEffect as x, useMemo as N } from "react";
|
|
3
|
+
import { useConfig as Z } from "../providers/ConfigProvider.js";
|
|
4
|
+
import { Button as K } from "./Button.js";
|
|
5
|
+
import { Flex as O } from "./Flex.js";
|
|
6
|
+
import { InputNumber as I } from "./InputNumber.js";
|
|
7
7
|
import { Select as C } from "./Select.js";
|
|
8
|
-
import { Space as
|
|
9
|
-
const re = Array.from({ length: 12 }, (
|
|
10
|
-
function
|
|
11
|
-
const
|
|
8
|
+
import { Space as ee } from "./Space.js";
|
|
9
|
+
const re = Array.from({ length: 12 }, (n, o) => String(o + 1));
|
|
10
|
+
function te(n = {}) {
|
|
11
|
+
const o = n.message ?? "Please select a complete date of birth.";
|
|
12
12
|
return {
|
|
13
13
|
validateTrigger: ["onBlur", "onSubmit"],
|
|
14
|
-
rules: [({ isSubmitAttempted:
|
|
15
|
-
validate: (
|
|
16
|
-
const
|
|
17
|
-
return !!!(
|
|
14
|
+
rules: [({ isSubmitAttempted: s }) => ({
|
|
15
|
+
validate: (h) => {
|
|
16
|
+
const l = h ?? {};
|
|
17
|
+
return !!!(l.month || l.day || l.year) && !s() || l.month && l.day && l.year ? !0 : o;
|
|
18
18
|
}
|
|
19
19
|
})]
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
const
|
|
24
|
-
return re.map((
|
|
25
|
-
value:
|
|
26
|
-
label:
|
|
22
|
+
function ne(n, o) {
|
|
23
|
+
const d = new Intl.DateTimeFormat(n, { month: o });
|
|
24
|
+
return re.map((s, h) => ({
|
|
25
|
+
value: s,
|
|
26
|
+
label: d.format(new Date(2020, h, 1))
|
|
27
27
|
}));
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
return new Date(
|
|
29
|
+
function ae(n, o) {
|
|
30
|
+
return new Date(n, o, 0).getDate();
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
onChange: u,
|
|
44
|
-
yearSpan: d = 120,
|
|
45
|
-
minAge: s = 13,
|
|
46
|
-
maxAge: i,
|
|
47
|
-
order: l = "mdy",
|
|
48
|
-
monthStyle: c = "select",
|
|
49
|
-
yearStyle: f = "select",
|
|
50
|
-
monthPlaceholder: F = "Month",
|
|
32
|
+
const _ = ({
|
|
33
|
+
value: n,
|
|
34
|
+
defaultValue: o,
|
|
35
|
+
onChange: d,
|
|
36
|
+
yearSpan: s = 120,
|
|
37
|
+
minAge: h,
|
|
38
|
+
maxAge: l,
|
|
39
|
+
order: b = "mdy",
|
|
40
|
+
monthStyle: g = "select",
|
|
41
|
+
yearStyle: Y = "select",
|
|
42
|
+
monthPlaceholder: q = "Month",
|
|
51
43
|
dayPlaceholder: E = "Day",
|
|
52
44
|
yearPlaceholder: S = "Year",
|
|
53
|
-
disabled:
|
|
54
|
-
size:
|
|
55
|
-
className:
|
|
56
|
-
"data-testid":
|
|
57
|
-
onBlur:
|
|
58
|
-
onFocus:
|
|
59
|
-
...
|
|
45
|
+
disabled: u = !1,
|
|
46
|
+
size: L,
|
|
47
|
+
className: j = "",
|
|
48
|
+
"data-testid": a,
|
|
49
|
+
onBlur: R,
|
|
50
|
+
onFocus: U,
|
|
51
|
+
...k
|
|
60
52
|
}) => {
|
|
61
|
-
const { locale:
|
|
62
|
-
|
|
53
|
+
const { locale: H, componentSize: V } = Z(), p = L ?? V ?? "md", f = n !== void 0, [W, z] = X(
|
|
54
|
+
n ?? o ?? {}
|
|
63
55
|
);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}, [
|
|
67
|
-
const
|
|
68
|
-
() =>
|
|
69
|
-
[
|
|
70
|
-
),
|
|
56
|
+
x(() => {
|
|
57
|
+
f && z(n ?? {});
|
|
58
|
+
}, [f, n]);
|
|
59
|
+
const r = f ? n ?? {} : W, B = H?.locale ?? "en-US", M = N(
|
|
60
|
+
() => ne(B, g === "grid" ? "short" : "long"),
|
|
61
|
+
[B, g]
|
|
62
|
+
), v = N(() => {
|
|
71
63
|
const e = (/* @__PURE__ */ new Date()).getFullYear();
|
|
72
|
-
return Array.from({ length:
|
|
73
|
-
}, [
|
|
74
|
-
if (!
|
|
75
|
-
const e = Number(
|
|
76
|
-
return Array.from({ length:
|
|
77
|
-
}, [
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}, [
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
const
|
|
85
|
-
return /* @__PURE__ */
|
|
86
|
-
|
|
64
|
+
return Array.from({ length: s }, (i, m) => String(e - m));
|
|
65
|
+
}, [s]), A = N(() => {
|
|
66
|
+
if (!r.month) return Array.from({ length: 31 }, (y, D) => String(D + 1));
|
|
67
|
+
const e = Number(r.month), i = r.year ? Number(r.year) : 2e3, m = ae(i, e);
|
|
68
|
+
return Array.from({ length: m }, (y, D) => String(D + 1));
|
|
69
|
+
}, [r.month, r.year]);
|
|
70
|
+
x(() => {
|
|
71
|
+
r.day && !A.includes(r.day) && c({ ...r, day: void 0 });
|
|
72
|
+
}, [r.day, A]);
|
|
73
|
+
const c = (e) => {
|
|
74
|
+
f || z(e), d?.(e);
|
|
75
|
+
}, T = () => g === "grid" ? /* @__PURE__ */ t("div", { className: "grid grid-cols-3 gap-2", children: M.map((e) => {
|
|
76
|
+
const i = r.month === e.value;
|
|
77
|
+
return /* @__PURE__ */ t(
|
|
78
|
+
K,
|
|
87
79
|
{
|
|
88
80
|
htmlType: "button",
|
|
89
81
|
size: "sm",
|
|
90
|
-
color:
|
|
91
|
-
variant:
|
|
92
|
-
disabled:
|
|
93
|
-
onClick: () =>
|
|
94
|
-
"data-testid":
|
|
82
|
+
color: i ? "primary" : void 0,
|
|
83
|
+
variant: i ? "solid" : "ghost",
|
|
84
|
+
disabled: u,
|
|
85
|
+
onClick: () => c({ ...r, month: e.value }),
|
|
86
|
+
"data-testid": a ? `${a}-month-${e.value}` : void 0,
|
|
95
87
|
children: e.label
|
|
96
88
|
},
|
|
97
89
|
e.value
|
|
98
90
|
);
|
|
99
|
-
}) }) : /* @__PURE__ */
|
|
91
|
+
}) }) : /* @__PURE__ */ w(
|
|
100
92
|
C,
|
|
101
93
|
{
|
|
102
|
-
value:
|
|
103
|
-
onChange: (e) =>
|
|
104
|
-
disabled:
|
|
105
|
-
size:
|
|
106
|
-
"data-testid":
|
|
94
|
+
value: r.month ?? "",
|
|
95
|
+
onChange: (e) => c({ ...r, month: e.target.value }),
|
|
96
|
+
disabled: u,
|
|
97
|
+
size: p,
|
|
98
|
+
"data-testid": a ? `${a}-month` : void 0,
|
|
107
99
|
children: [
|
|
108
|
-
/* @__PURE__ */
|
|
109
|
-
|
|
100
|
+
/* @__PURE__ */ t("option", { value: "", children: q }),
|
|
101
|
+
M.map((e) => /* @__PURE__ */ t("option", { value: e.value, children: e.label }, e.value))
|
|
110
102
|
]
|
|
111
103
|
}
|
|
112
|
-
), G = () => /* @__PURE__ */
|
|
104
|
+
), G = () => /* @__PURE__ */ w(
|
|
113
105
|
C,
|
|
114
106
|
{
|
|
115
|
-
value:
|
|
116
|
-
onChange: (e) =>
|
|
117
|
-
disabled:
|
|
118
|
-
size:
|
|
119
|
-
"data-testid":
|
|
107
|
+
value: r.day ?? "",
|
|
108
|
+
onChange: (e) => c({ ...r, day: e.target.value }),
|
|
109
|
+
disabled: u,
|
|
110
|
+
size: p,
|
|
111
|
+
"data-testid": a ? `${a}-day` : void 0,
|
|
120
112
|
children: [
|
|
121
|
-
/* @__PURE__ */
|
|
122
|
-
|
|
113
|
+
/* @__PURE__ */ t("option", { value: "", children: E }),
|
|
114
|
+
A.map((e) => /* @__PURE__ */ t("option", { value: e, children: e }, e))
|
|
123
115
|
]
|
|
124
116
|
}
|
|
125
|
-
), J = () =>
|
|
126
|
-
|
|
117
|
+
), J = () => Y === "input" ? /* @__PURE__ */ t(
|
|
118
|
+
I,
|
|
127
119
|
{
|
|
128
|
-
value:
|
|
129
|
-
min: Number(
|
|
130
|
-
max: Number(
|
|
120
|
+
value: r.year ? Number(r.year) : void 0,
|
|
121
|
+
min: Number(v[v.length - 1]),
|
|
122
|
+
max: Number(v[0]),
|
|
131
123
|
placeholder: S,
|
|
132
|
-
disabled:
|
|
133
|
-
size:
|
|
134
|
-
onChange: (e) =>
|
|
135
|
-
"data-testid":
|
|
124
|
+
disabled: u,
|
|
125
|
+
size: p,
|
|
126
|
+
onChange: (e) => c({ ...r, year: e ? String(e) : void 0 }),
|
|
127
|
+
"data-testid": a ? `${a}-year` : void 0
|
|
136
128
|
}
|
|
137
|
-
) : /* @__PURE__ */
|
|
129
|
+
) : /* @__PURE__ */ w(
|
|
138
130
|
C,
|
|
139
131
|
{
|
|
140
|
-
value:
|
|
141
|
-
onChange: (e) =>
|
|
142
|
-
disabled:
|
|
143
|
-
size:
|
|
144
|
-
"data-testid":
|
|
132
|
+
value: r.year ?? "",
|
|
133
|
+
onChange: (e) => c({ ...r, year: e.target.value }),
|
|
134
|
+
disabled: u,
|
|
135
|
+
size: p,
|
|
136
|
+
"data-testid": a ? `${a}-year` : void 0,
|
|
145
137
|
children: [
|
|
146
|
-
/* @__PURE__ */
|
|
147
|
-
|
|
138
|
+
/* @__PURE__ */ t("option", { value: "", children: S }),
|
|
139
|
+
v.map((e) => /* @__PURE__ */ t("option", { value: e, children: e }, e))
|
|
148
140
|
]
|
|
149
141
|
}
|
|
150
|
-
),
|
|
151
|
-
m:
|
|
142
|
+
), F = {
|
|
143
|
+
m: T(),
|
|
152
144
|
d: G(),
|
|
153
145
|
y: J()
|
|
154
|
-
}, P =
|
|
146
|
+
}, P = b.split("").map((e) => e), Q = b.split("").filter((e) => e !== "m").map((e) => e), $ = {
|
|
155
147
|
m: "w-full sm:w-[7rem]",
|
|
156
148
|
d: "w-full sm:w-[5rem]",
|
|
157
149
|
y: "w-full sm:w-[5rem]"
|
|
158
|
-
}
|
|
159
|
-
return /* @__PURE__ */
|
|
150
|
+
};
|
|
151
|
+
return /* @__PURE__ */ t(
|
|
160
152
|
"div",
|
|
161
153
|
{
|
|
162
|
-
className:
|
|
163
|
-
"data-testid":
|
|
154
|
+
className: j,
|
|
155
|
+
"data-testid": a,
|
|
164
156
|
onBlur: (e) => {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
-
|
|
157
|
+
const i = e.currentTarget, m = e.relatedTarget;
|
|
158
|
+
m && i.contains(m) || requestAnimationFrame(() => {
|
|
159
|
+
const y = document.activeElement;
|
|
160
|
+
y && i.contains(y) || R?.(e);
|
|
169
161
|
});
|
|
170
162
|
},
|
|
171
|
-
onFocus:
|
|
172
|
-
...
|
|
173
|
-
children: [
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
] }) : /* @__PURE__ */ n(_, { wrap: "wrap", gap: "sm", children: P.map((e) => /* @__PURE__ */ n("div", { className: x[e], children: $[e] }, e)) }),
|
|
178
|
-
X && /* @__PURE__ */ n("div", { className: "text-xs text-error mt-2", children: s ? `You must be at least ${s} years old.` : "Date of birth is not valid." })
|
|
179
|
-
]
|
|
163
|
+
onFocus: U,
|
|
164
|
+
...k,
|
|
165
|
+
children: g === "grid" ? /* @__PURE__ */ w(ee, { direction: "vertical", size: "sm", children: [
|
|
166
|
+
T(),
|
|
167
|
+
/* @__PURE__ */ t(O, { gap: "sm", children: Q.map((e) => /* @__PURE__ */ t("div", { className: $[e], children: F[e] }, e)) })
|
|
168
|
+
] }) : /* @__PURE__ */ t(O, { wrap: "wrap", gap: "sm", children: P.map((e) => /* @__PURE__ */ t("div", { className: $[e], children: F[e] }, e)) })
|
|
180
169
|
}
|
|
181
170
|
);
|
|
182
171
|
};
|
|
183
|
-
|
|
184
|
-
|
|
172
|
+
_.required = te;
|
|
173
|
+
_.displayName = "DateOfBirth";
|
|
185
174
|
export {
|
|
186
|
-
|
|
187
|
-
|
|
175
|
+
_ as DateOfBirth,
|
|
176
|
+
te as dateOfBirthRequired
|
|
188
177
|
};
|
|
189
178
|
//# sourceMappingURL=DateOfBirth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateOfBirth.js","sources":["../../src/components/DateOfBirth.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\nimport { Button } from './Button'\nimport { Flex } from './Flex'\nimport { InputNumber } from './InputNumber'\nimport { Select } from './Select'\nimport { Space } from './Space'\nimport type { FormItemProps, FormRuleInput } from './Form'\n\nexport type DateOfBirthOrder = 'mdy' | 'dmy' | 'ymd'\nexport type DateOfBirthMonthStyle = 'select' | 'grid'\nexport type DateOfBirthYearStyle = 'select' | 'input'\n\nexport interface DateOfBirthValue {\n month?: string\n day?: string\n year?: string\n}\n\nexport interface DateOfBirthProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> {\n value?: DateOfBirthValue\n defaultValue?: DateOfBirthValue\n onChange?: (value: DateOfBirthValue) => void\n yearSpan?: number\n minAge?: number\n maxAge?: number\n order?: DateOfBirthOrder\n monthStyle?: DateOfBirthMonthStyle\n yearStyle?: DateOfBirthYearStyle\n monthPlaceholder?: string\n dayPlaceholder?: string\n yearPlaceholder?: string\n disabled?: boolean\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n className?: string\n /** Test ID prefix for child elements */\n 'data-testid'?: string\n}\n\nconst DEFAULT_MONTHS = Array.from({ length: 12 }, (_, index) => String(index + 1))\n\nexport interface DateOfBirthRequiredOptions {\n message?: string\n}\n\nexport type DateOfBirthRequiredProps = Pick<FormItemProps, 'rules' | 'validateTrigger'>\n\nexport function dateOfBirthRequired(options: DateOfBirthRequiredOptions = {}): DateOfBirthRequiredProps {\n const message = options.message ?? 'Please select a complete date of birth.'\n\n const rules: FormRuleInput[] = [({ isSubmitAttempted }) => ({\n validate: (value: DateOfBirthValue | undefined) => {\n const dob = value ?? {}\n const hasAny = !!(dob.month || dob.day || dob.year)\n if (!hasAny && !isSubmitAttempted()) {\n return true\n }\n return dob.month && dob.day && dob.year ? true : message\n },\n })]\n\n return {\n validateTrigger: ['onBlur', 'onSubmit'],\n rules,\n }\n}\n\ntype DateOfBirthComponent = React.FC<DateOfBirthProps> & {\n required: (options?: DateOfBirthRequiredOptions) => DateOfBirthRequiredProps\n}\n\nfunction getMonthLabels(locale: string, format: 'long' | 'short') {\n const formatter = new Intl.DateTimeFormat(locale, { month: format })\n return DEFAULT_MONTHS.map((value, index) => ({\n value,\n label: formatter.format(new Date(2020, index, 1)),\n }))\n}\n\nfunction getDaysInMonth(year: number, month: number) {\n return new Date(year, month, 0).getDate()\n}\n\nfunction validateAge(value: DateOfBirthValue, minAge?: number, maxAge?: number) {\n if (!value.year || !value.month || !value.day) return true\n const year = Number(value.year)\n const month = Number(value.month) - 1\n const day = Number(value.day)\n const birthDate = new Date(year, month, day)\n if (Number.isNaN(birthDate.getTime())) return false\n const today = new Date()\n let age = today.getFullYear() - birthDate.getFullYear()\n const hasHadBirthday =\n today.getMonth() > birthDate.getMonth() ||\n (today.getMonth() === birthDate.getMonth() && today.getDate() >= birthDate.getDate())\n if (!hasHadBirthday) age -= 1\n if (minAge !== undefined && age < minAge) return false\n if (maxAge !== undefined && age > maxAge) return false\n return true\n}\n\nexport const DateOfBirth: DateOfBirthComponent = ({\n value,\n defaultValue,\n onChange,\n yearSpan = 120,\n minAge = 13,\n maxAge,\n order = 'mdy',\n monthStyle = 'select',\n yearStyle = 'select',\n monthPlaceholder = 'Month',\n dayPlaceholder = 'Day',\n yearPlaceholder = 'Year',\n disabled = false,\n size,\n className = '',\n 'data-testid': testId,\n onBlur,\n onFocus,\n ...rest\n}) => {\n const { locale, componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n const isControlled = value !== undefined\n const [internalValue, setInternalValue] = useState<DateOfBirthValue>(\n value ?? defaultValue ?? {}\n )\n\n useEffect(() => {\n if (isControlled) {\n setInternalValue(value ?? {})\n }\n }, [isControlled, value])\n\n const currentValue = isControlled ? (value ?? {}) : internalValue\n const localeCode = locale?.locale ?? 'en-US'\n const monthLabels = useMemo(\n () => getMonthLabels(localeCode, monthStyle === 'grid' ? 'short' : 'long'),\n [localeCode, monthStyle]\n )\n\n const yearRange = useMemo(() => {\n const currentYear = new Date().getFullYear()\n return Array.from({ length: yearSpan }, (_, i) => String(currentYear - i))\n }, [yearSpan])\n\n const dayOptions = useMemo(() => {\n if (!currentValue.month) return Array.from({ length: 31 }, (_, i) => String(i + 1))\n const month = Number(currentValue.month)\n const year = currentValue.year ? Number(currentValue.year) : 2000\n const daysInMonth = getDaysInMonth(year, month)\n return Array.from({ length: daysInMonth }, (_, i) => String(i + 1))\n }, [currentValue.month, currentValue.year])\n\n useEffect(() => {\n if (currentValue.day && !dayOptions.includes(currentValue.day)) {\n handleChange({ ...currentValue, day: undefined })\n }\n }, [currentValue.day, dayOptions])\n\n const handleChange = (nextValue: DateOfBirthValue) => {\n if (!isControlled) {\n setInternalValue(nextValue)\n }\n onChange?.(nextValue)\n }\n\n const renderMonth = () => {\n if (monthStyle === 'grid') {\n return (\n <div className=\"grid grid-cols-3 gap-2\">\n {monthLabels.map((month) => {\n const isActive = currentValue.month === month.value\n return (\n <Button\n key={month.value}\n htmlType=\"button\"\n size=\"sm\"\n color={isActive ? 'primary' : undefined}\n variant={isActive ? 'solid' : 'ghost'}\n disabled={disabled}\n onClick={() => handleChange({ ...currentValue, month: month.value })}\n data-testid={testId ? `${testId}-month-${month.value}` : undefined}\n >\n {month.label}\n </Button>\n )\n })}\n </div>\n )\n }\n\n return (\n <Select\n value={currentValue.month ?? ''}\n onChange={(e) => handleChange({ ...currentValue, month: e.target.value })}\n disabled={disabled}\n size={effectiveSize}\n data-testid={testId ? `${testId}-month` : undefined}\n >\n <option value=\"\">{monthPlaceholder}</option>\n {monthLabels.map((month) => (\n <option key={month.value} value={month.value}>\n {month.label}\n </option>\n ))}\n </Select>\n )\n }\n\n const renderDay = () => (\n <Select\n value={currentValue.day ?? ''}\n onChange={(e) => handleChange({ ...currentValue, day: e.target.value })}\n disabled={disabled}\n size={effectiveSize}\n data-testid={testId ? `${testId}-day` : undefined}\n >\n <option value=\"\">{dayPlaceholder}</option>\n {dayOptions.map((day) => (\n <option key={day} value={day}>{day}</option>\n ))}\n </Select>\n )\n\n const renderYear = () => {\n if (yearStyle === 'input') {\n return (\n <InputNumber\n value={currentValue.year ? Number(currentValue.year) : undefined}\n min={Number(yearRange[yearRange.length - 1])}\n max={Number(yearRange[0])}\n placeholder={yearPlaceholder}\n disabled={disabled}\n size={effectiveSize}\n onChange={(nextValue) => handleChange({ ...currentValue, year: nextValue ? String(nextValue) : undefined })}\n data-testid={testId ? `${testId}-year` : undefined}\n />\n )\n }\n\n return (\n <Select\n value={currentValue.year ?? ''}\n onChange={(e) => handleChange({ ...currentValue, year: e.target.value })}\n disabled={disabled}\n size={effectiveSize}\n data-testid={testId ? `${testId}-year` : undefined}\n >\n <option value=\"\">{yearPlaceholder}</option>\n {yearRange.map((year) => (\n <option key={year} value={year}>{year}</option>\n ))}\n </Select>\n )\n }\n\n const fieldMap = {\n m: renderMonth(),\n d: renderDay(),\n y: renderYear(),\n }\n\n const orderedFields = order.split('').map((key) => key as keyof typeof fieldMap)\n const gridFields = order\n .split('')\n .filter((key) => key !== 'm')\n .map((key) => key as keyof typeof fieldMap)\n const fieldWidths: Record<'m' | 'd' | 'y', string> = {\n m: 'w-full sm:w-[7rem]',\n d: 'w-full sm:w-[5rem]',\n y: 'w-full sm:w-[5rem]',\n }\n\n const showAgeWarning = currentValue.year && currentValue.month && currentValue.day && !validateAge(currentValue, minAge, maxAge)\n\n const handleBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n const currentTarget = event.currentTarget\n const next = event.relatedTarget as Node | null\n if (next && currentTarget.contains(next)) return\n requestAnimationFrame(() => {\n const active = document.activeElement\n if (active && currentTarget.contains(active)) return\n onBlur?.(event)\n })\n }\n\n return (\n <div\n className={className}\n data-testid={testId}\n onBlur={handleBlur}\n onFocus={onFocus}\n {...rest}\n >\n {monthStyle === 'grid' ? (\n <Space direction=\"vertical\" size=\"sm\">\n {renderMonth()}\n <Flex gap=\"sm\">\n {gridFields.map((fieldKey) => (\n <div key={fieldKey} className={fieldWidths[fieldKey]}>\n {fieldMap[fieldKey]}\n </div>\n ))}\n </Flex>\n </Space>\n ) : (\n <Flex wrap=\"wrap\" gap=\"sm\">\n {orderedFields.map((fieldKey) => (\n <div key={fieldKey} className={fieldWidths[fieldKey]}>\n {fieldMap[fieldKey]}\n </div>\n ))}\n </Flex>\n )}\n\n {showAgeWarning && (\n <div className=\"text-xs text-error mt-2\">\n {minAge ? `You must be at least ${minAge} years old.` : 'Date of birth is not valid.'}\n </div>\n )}\n </div>\n )\n}\n\nDateOfBirth.required = dateOfBirthRequired\n\nDateOfBirth.displayName = 'DateOfBirth'\n"],"names":["DEFAULT_MONTHS","_","index","dateOfBirthRequired","options","message","isSubmitAttempted","value","dob","getMonthLabels","locale","format","formatter","getDaysInMonth","year","month","validateAge","minAge","maxAge","day","birthDate","today","age","DateOfBirth","defaultValue","onChange","yearSpan","order","monthStyle","yearStyle","monthPlaceholder","dayPlaceholder","yearPlaceholder","disabled","size","className","testId","onBlur","onFocus","rest","componentSize","useConfig","effectiveSize","isControlled","internalValue","setInternalValue","useState","useEffect","currentValue","localeCode","monthLabels","useMemo","yearRange","currentYear","i","dayOptions","daysInMonth","handleChange","nextValue","renderMonth","isActive","jsx","Button","jsxs","Select","renderDay","renderYear","InputNumber","fieldMap","orderedFields","key","gridFields","fieldWidths","showAgeWarning","event","currentTarget","next","active","Space","Flex","fieldKey"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateOfBirth.js","sources":["../../src/components/DateOfBirth.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\nimport { Button } from './Button'\nimport { Flex } from './Flex'\nimport { InputNumber } from './InputNumber'\nimport { Select } from './Select'\nimport { Space } from './Space'\nimport type { FormItemProps, FormRuleInput } from './Form'\n\nexport type DateOfBirthOrder = 'mdy' | 'dmy' | 'ymd'\nexport type DateOfBirthMonthStyle = 'select' | 'grid'\nexport type DateOfBirthYearStyle = 'select' | 'input'\n\nexport interface DateOfBirthValue {\n month?: string\n day?: string\n year?: string\n}\n\nexport interface DateOfBirthProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> {\n value?: DateOfBirthValue\n defaultValue?: DateOfBirthValue\n onChange?: (value: DateOfBirthValue) => void\n yearSpan?: number\n minAge?: number\n maxAge?: number\n order?: DateOfBirthOrder\n monthStyle?: DateOfBirthMonthStyle\n yearStyle?: DateOfBirthYearStyle\n monthPlaceholder?: string\n dayPlaceholder?: string\n yearPlaceholder?: string\n disabled?: boolean\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n className?: string\n /** Test ID prefix for child elements */\n 'data-testid'?: string\n}\n\nconst DEFAULT_MONTHS = Array.from({ length: 12 }, (_, index) => String(index + 1))\n\nexport interface DateOfBirthRequiredOptions {\n message?: string\n}\n\nexport type DateOfBirthRequiredProps = Pick<FormItemProps, 'rules' | 'validateTrigger'>\n\nexport function dateOfBirthRequired(options: DateOfBirthRequiredOptions = {}): DateOfBirthRequiredProps {\n const message = options.message ?? 'Please select a complete date of birth.'\n\n const rules: FormRuleInput[] = [({ isSubmitAttempted }) => ({\n validate: (value: DateOfBirthValue | undefined) => {\n const dob = value ?? {}\n const hasAny = !!(dob.month || dob.day || dob.year)\n if (!hasAny && !isSubmitAttempted()) {\n return true\n }\n return dob.month && dob.day && dob.year ? true : message\n },\n })]\n\n return {\n validateTrigger: ['onBlur', 'onSubmit'],\n rules,\n }\n}\n\ntype DateOfBirthComponent = React.FC<DateOfBirthProps> & {\n required: (options?: DateOfBirthRequiredOptions) => DateOfBirthRequiredProps\n}\n\nfunction getMonthLabels(locale: string, format: 'long' | 'short') {\n const formatter = new Intl.DateTimeFormat(locale, { month: format })\n return DEFAULT_MONTHS.map((value, index) => ({\n value,\n label: formatter.format(new Date(2020, index, 1)),\n }))\n}\n\nfunction getDaysInMonth(year: number, month: number) {\n return new Date(year, month, 0).getDate()\n}\n\nexport const DateOfBirth: DateOfBirthComponent = ({\n value,\n defaultValue,\n onChange,\n yearSpan = 120,\n minAge,\n maxAge,\n order = 'mdy',\n monthStyle = 'select',\n yearStyle = 'select',\n monthPlaceholder = 'Month',\n dayPlaceholder = 'Day',\n yearPlaceholder = 'Year',\n disabled = false,\n size,\n className = '',\n 'data-testid': testId,\n onBlur,\n onFocus,\n ...rest\n}) => {\n const { locale, componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n const isControlled = value !== undefined\n const [internalValue, setInternalValue] = useState<DateOfBirthValue>(\n value ?? defaultValue ?? {}\n )\n\n useEffect(() => {\n if (isControlled) {\n setInternalValue(value ?? {})\n }\n }, [isControlled, value])\n\n const currentValue = isControlled ? (value ?? {}) : internalValue\n const localeCode = locale?.locale ?? 'en-US'\n const monthLabels = useMemo(\n () => getMonthLabels(localeCode, monthStyle === 'grid' ? 'short' : 'long'),\n [localeCode, monthStyle]\n )\n\n const yearRange = useMemo(() => {\n const currentYear = new Date().getFullYear()\n return Array.from({ length: yearSpan }, (_, i) => String(currentYear - i))\n }, [yearSpan])\n\n const dayOptions = useMemo(() => {\n if (!currentValue.month) return Array.from({ length: 31 }, (_, i) => String(i + 1))\n const month = Number(currentValue.month)\n const year = currentValue.year ? Number(currentValue.year) : 2000\n const daysInMonth = getDaysInMonth(year, month)\n return Array.from({ length: daysInMonth }, (_, i) => String(i + 1))\n }, [currentValue.month, currentValue.year])\n\n useEffect(() => {\n if (currentValue.day && !dayOptions.includes(currentValue.day)) {\n handleChange({ ...currentValue, day: undefined })\n }\n }, [currentValue.day, dayOptions])\n\n const handleChange = (nextValue: DateOfBirthValue) => {\n if (!isControlled) {\n setInternalValue(nextValue)\n }\n onChange?.(nextValue)\n }\n\n const renderMonth = () => {\n if (monthStyle === 'grid') {\n return (\n <div className=\"grid grid-cols-3 gap-2\">\n {monthLabels.map((month) => {\n const isActive = currentValue.month === month.value\n return (\n <Button\n key={month.value}\n htmlType=\"button\"\n size=\"sm\"\n color={isActive ? 'primary' : undefined}\n variant={isActive ? 'solid' : 'ghost'}\n disabled={disabled}\n onClick={() => handleChange({ ...currentValue, month: month.value })}\n data-testid={testId ? `${testId}-month-${month.value}` : undefined}\n >\n {month.label}\n </Button>\n )\n })}\n </div>\n )\n }\n\n return (\n <Select\n value={currentValue.month ?? ''}\n onChange={(e) => handleChange({ ...currentValue, month: e.target.value })}\n disabled={disabled}\n size={effectiveSize}\n data-testid={testId ? `${testId}-month` : undefined}\n >\n <option value=\"\">{monthPlaceholder}</option>\n {monthLabels.map((month) => (\n <option key={month.value} value={month.value}>\n {month.label}\n </option>\n ))}\n </Select>\n )\n }\n\n const renderDay = () => (\n <Select\n value={currentValue.day ?? ''}\n onChange={(e) => handleChange({ ...currentValue, day: e.target.value })}\n disabled={disabled}\n size={effectiveSize}\n data-testid={testId ? `${testId}-day` : undefined}\n >\n <option value=\"\">{dayPlaceholder}</option>\n {dayOptions.map((day) => (\n <option key={day} value={day}>{day}</option>\n ))}\n </Select>\n )\n\n const renderYear = () => {\n if (yearStyle === 'input') {\n return (\n <InputNumber\n value={currentValue.year ? Number(currentValue.year) : undefined}\n min={Number(yearRange[yearRange.length - 1])}\n max={Number(yearRange[0])}\n placeholder={yearPlaceholder}\n disabled={disabled}\n size={effectiveSize}\n onChange={(nextValue) => handleChange({ ...currentValue, year: nextValue ? String(nextValue) : undefined })}\n data-testid={testId ? `${testId}-year` : undefined}\n />\n )\n }\n\n return (\n <Select\n value={currentValue.year ?? ''}\n onChange={(e) => handleChange({ ...currentValue, year: e.target.value })}\n disabled={disabled}\n size={effectiveSize}\n data-testid={testId ? `${testId}-year` : undefined}\n >\n <option value=\"\">{yearPlaceholder}</option>\n {yearRange.map((year) => (\n <option key={year} value={year}>{year}</option>\n ))}\n </Select>\n )\n }\n\n const fieldMap = {\n m: renderMonth(),\n d: renderDay(),\n y: renderYear(),\n }\n\n const orderedFields = order.split('').map((key) => key as keyof typeof fieldMap)\n const gridFields = order\n .split('')\n .filter((key) => key !== 'm')\n .map((key) => key as keyof typeof fieldMap)\n const fieldWidths: Record<'m' | 'd' | 'y', string> = {\n m: 'w-full sm:w-[7rem]',\n d: 'w-full sm:w-[5rem]',\n y: 'w-full sm:w-[5rem]',\n }\n\n const handleBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n const currentTarget = event.currentTarget\n const next = event.relatedTarget as Node | null\n if (next && currentTarget.contains(next)) return\n requestAnimationFrame(() => {\n const active = document.activeElement\n if (active && currentTarget.contains(active)) return\n onBlur?.(event)\n })\n }\n\n return (\n <div\n className={className}\n data-testid={testId}\n onBlur={handleBlur}\n onFocus={onFocus}\n {...rest}\n >\n {monthStyle === 'grid' ? (\n <Space direction=\"vertical\" size=\"sm\">\n {renderMonth()}\n <Flex gap=\"sm\">\n {gridFields.map((fieldKey) => (\n <div key={fieldKey} className={fieldWidths[fieldKey]}>\n {fieldMap[fieldKey]}\n </div>\n ))}\n </Flex>\n </Space>\n ) : (\n <Flex wrap=\"wrap\" gap=\"sm\">\n {orderedFields.map((fieldKey) => (\n <div key={fieldKey} className={fieldWidths[fieldKey]}>\n {fieldMap[fieldKey]}\n </div>\n ))}\n </Flex>\n )}\n </div>\n )\n}\n\nDateOfBirth.required = dateOfBirthRequired\n\nDateOfBirth.displayName = 'DateOfBirth'\n"],"names":["DEFAULT_MONTHS","_","index","dateOfBirthRequired","options","message","isSubmitAttempted","value","dob","getMonthLabels","locale","format","formatter","getDaysInMonth","year","month","DateOfBirth","defaultValue","onChange","yearSpan","minAge","maxAge","order","monthStyle","yearStyle","monthPlaceholder","dayPlaceholder","yearPlaceholder","disabled","size","className","testId","onBlur","onFocus","rest","componentSize","useConfig","effectiveSize","isControlled","internalValue","setInternalValue","useState","useEffect","currentValue","localeCode","monthLabels","useMemo","yearRange","currentYear","i","dayOptions","daysInMonth","handleChange","nextValue","renderMonth","isActive","jsx","Button","jsxs","Select","renderDay","day","renderYear","InputNumber","fieldMap","orderedFields","key","gridFields","fieldWidths","event","currentTarget","next","active","Space","Flex","fieldKey"],"mappings":";;;;;;;;AAuCA,MAAMA,KAAiB,MAAM,KAAK,EAAE,QAAQ,GAAA,GAAM,CAACC,GAAGC,MAAU,OAAOA,IAAQ,CAAC,CAAC;AAQ1E,SAASC,GAAoBC,IAAsC,IAA8B;AACtG,QAAMC,IAAUD,EAAQ,WAAW;AAanC,SAAO;AAAA,IACL,iBAAiB,CAAC,UAAU,UAAU;AAAA,IACtC,OAb6B,CAAC,CAAC,EAAE,mBAAAE,SAAyB;AAAA,MAC1D,UAAU,CAACC,MAAwC;AACjD,cAAMC,IAAMD,KAAS,CAAA;AAErB,eAAI,CADW,CAAC,EAAEC,EAAI,SAASA,EAAI,OAAOA,EAAI,SAC/B,CAACF,OAGTE,EAAI,SAASA,EAAI,OAAOA,EAAI,OAF1B,KAEwCH;AAAA,MACnD;AAAA,IAAA,EACA;AAAA,EAIA;AAEJ;AAMA,SAASI,GAAeC,GAAgBC,GAA0B;AAChE,QAAMC,IAAY,IAAI,KAAK,eAAeF,GAAQ,EAAE,OAAOC,GAAQ;AACnE,SAAOX,GAAe,IAAI,CAACO,GAAOL,OAAW;AAAA,IAC3C,OAAAK;AAAA,IACA,OAAOK,EAAU,OAAO,IAAI,KAAK,MAAMV,GAAO,CAAC,CAAC;AAAA,EAAA,EAChD;AACJ;AAEA,SAASW,GAAeC,GAAcC,GAAe;AACnD,SAAO,IAAI,KAAKD,GAAMC,GAAO,CAAC,EAAE,QAAA;AAClC;AAEO,MAAMC,IAAoC,CAAC;AAAA,EAChD,OAAAT;AAAA,EACA,cAAAU;AAAA,EACA,UAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,YAAAC,IAAa;AAAA,EACb,WAAAC,IAAY;AAAA,EACZ,kBAAAC,IAAmB;AAAA,EACnB,gBAAAC,IAAiB;AAAA,EACjB,iBAAAC,IAAkB;AAAA,EAClB,UAAAC,IAAW;AAAA,EACX,MAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,eAAeC;AAAA,EACf,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,GAAGC;AACL,MAAM;AACJ,QAAM,EAAE,QAAAxB,GAAQ,eAAAyB,EAAA,IAAkBC,EAAA,GAC5BC,IAAgBR,KAAQM,KAAiB,MACzCG,IAAe/B,MAAU,QACzB,CAACgC,GAAeC,CAAgB,IAAIC;AAAA,IACxClC,KAASU,KAAgB,CAAA;AAAA,EAAC;AAG5B,EAAAyB,EAAU,MAAM;AACd,IAAIJ,KACFE,EAAiBjC,KAAS,EAAE;AAAA,EAEhC,GAAG,CAAC+B,GAAc/B,CAAK,CAAC;AAExB,QAAMoC,IAAeL,IAAgB/B,KAAS,CAAA,IAAMgC,GAC9CK,IAAalC,GAAQ,UAAU,SAC/BmC,IAAcC;AAAA,IAClB,MAAMrC,GAAemC,GAAYrB,MAAe,SAAS,UAAU,MAAM;AAAA,IACzE,CAACqB,GAAYrB,CAAU;AAAA,EAAA,GAGnBwB,IAAYD,EAAQ,MAAM;AAC9B,UAAME,KAAc,oBAAI,KAAA,GAAO,YAAA;AAC/B,WAAO,MAAM,KAAK,EAAE,QAAQ7B,EAAA,GAAY,CAAClB,GAAGgD,MAAM,OAAOD,IAAcC,CAAC,CAAC;AAAA,EAC3E,GAAG,CAAC9B,CAAQ,CAAC,GAEP+B,IAAaJ,EAAQ,MAAM;AAC/B,QAAI,CAACH,EAAa,MAAO,QAAO,MAAM,KAAK,EAAE,QAAQ,GAAA,GAAM,CAAC1C,GAAGgD,MAAM,OAAOA,IAAI,CAAC,CAAC;AAClF,UAAMlC,IAAQ,OAAO4B,EAAa,KAAK,GACjC7B,IAAO6B,EAAa,OAAO,OAAOA,EAAa,IAAI,IAAI,KACvDQ,IAActC,GAAeC,GAAMC,CAAK;AAC9C,WAAO,MAAM,KAAK,EAAE,QAAQoC,EAAA,GAAe,CAAClD,GAAGgD,MAAM,OAAOA,IAAI,CAAC,CAAC;AAAA,EACpE,GAAG,CAACN,EAAa,OAAOA,EAAa,IAAI,CAAC;AAE1C,EAAAD,EAAU,MAAM;AACd,IAAIC,EAAa,OAAO,CAACO,EAAW,SAASP,EAAa,GAAG,KAC3DS,EAAa,EAAE,GAAGT,GAAc,KAAK,QAAW;AAAA,EAEpD,GAAG,CAACA,EAAa,KAAKO,CAAU,CAAC;AAEjC,QAAME,IAAe,CAACC,MAAgC;AACpD,IAAKf,KACHE,EAAiBa,CAAS,GAE5BnC,IAAWmC,CAAS;AAAA,EACtB,GAEMC,IAAc,MACd/B,MAAe,2BAEd,OAAA,EAAI,WAAU,0BACZ,UAAAsB,EAAY,IAAI,CAAC9B,MAAU;AAC1B,UAAMwC,IAAWZ,EAAa,UAAU5B,EAAM;AAC9C,WACE,gBAAAyC;AAAA,MAACC;AAAA,MAAA;AAAA,QAEC,UAAS;AAAA,QACT,MAAK;AAAA,QACL,OAAOF,IAAW,YAAY;AAAA,QAC9B,SAASA,IAAW,UAAU;AAAA,QAC9B,UAAA3B;AAAA,QACA,SAAS,MAAMwB,EAAa,EAAE,GAAGT,GAAc,OAAO5B,EAAM,OAAO;AAAA,QACnE,eAAagB,IAAS,GAAGA,CAAM,UAAUhB,EAAM,KAAK,KAAK;AAAA,QAExD,UAAAA,EAAM;AAAA,MAAA;AAAA,MATFA,EAAM;AAAA,IAAA;AAAA,EAYjB,CAAC,EAAA,CACH,IAKF,gBAAA2C;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAOhB,EAAa,SAAS;AAAA,MAC7B,UAAU,CAAC,MAAMS,EAAa,EAAE,GAAGT,GAAc,OAAO,EAAE,OAAO,OAAO;AAAA,MACxE,UAAAf;AAAA,MACA,MAAMS;AAAA,MACN,eAAaN,IAAS,GAAGA,CAAM,WAAW;AAAA,MAE1C,UAAA;AAAA,QAAA,gBAAAyB,EAAC,UAAA,EAAO,OAAM,IAAI,UAAA/B,GAAiB;AAAA,QAClCoB,EAAY,IAAI,CAAC9B,MAChB,gBAAAyC,EAAC,UAAA,EAAyB,OAAOzC,EAAM,OACpC,UAAAA,EAAM,MAAA,GADIA,EAAM,KAEnB,CACD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAKD6C,IAAY,MAChB,gBAAAF;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAOhB,EAAa,OAAO;AAAA,MAC3B,UAAU,CAAC,MAAMS,EAAa,EAAE,GAAGT,GAAc,KAAK,EAAE,OAAO,OAAO;AAAA,MACtE,UAAAf;AAAA,MACA,MAAMS;AAAA,MACN,eAAaN,IAAS,GAAGA,CAAM,SAAS;AAAA,MAExC,UAAA;AAAA,QAAA,gBAAAyB,EAAC,UAAA,EAAO,OAAM,IAAI,UAAA9B,GAAe;AAAA,QAChCwB,EAAW,IAAI,CAACW,MACf,gBAAAL,EAAC,YAAiB,OAAOK,GAAM,UAAAA,EAAA,GAAlBA,CAAsB,CACpC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAICC,IAAa,MACbtC,MAAc,UAEd,gBAAAgC;AAAA,IAACO;AAAA,IAAA;AAAA,MACC,OAAOpB,EAAa,OAAO,OAAOA,EAAa,IAAI,IAAI;AAAA,MACvD,KAAK,OAAOI,EAAUA,EAAU,SAAS,CAAC,CAAC;AAAA,MAC3C,KAAK,OAAOA,EAAU,CAAC,CAAC;AAAA,MACxB,aAAapB;AAAA,MACb,UAAAC;AAAA,MACA,MAAMS;AAAA,MACN,UAAU,CAACgB,MAAcD,EAAa,EAAE,GAAGT,GAAc,MAAMU,IAAY,OAAOA,CAAS,IAAI,QAAW;AAAA,MAC1G,eAAatB,IAAS,GAAGA,CAAM,UAAU;AAAA,IAAA;AAAA,EAAA,IAM7C,gBAAA2B;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAOhB,EAAa,QAAQ;AAAA,MAC5B,UAAU,CAAC,MAAMS,EAAa,EAAE,GAAGT,GAAc,MAAM,EAAE,OAAO,OAAO;AAAA,MACvE,UAAAf;AAAA,MACA,MAAMS;AAAA,MACN,eAAaN,IAAS,GAAGA,CAAM,UAAU;AAAA,MAEzC,UAAA;AAAA,QAAA,gBAAAyB,EAAC,UAAA,EAAO,OAAM,IAAI,UAAA7B,GAAgB;AAAA,QACjCoB,EAAU,IAAI,CAACjC,MACd,gBAAA0C,EAAC,YAAkB,OAAO1C,GAAO,UAAAA,EAAA,GAApBA,CAAyB,CACvC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAKDkD,IAAW;AAAA,IACf,GAAGV,EAAA;AAAA,IACH,GAAGM,EAAA;AAAA,IACH,GAAGE,EAAA;AAAA,EAAW,GAGVG,IAAgB3C,EAAM,MAAM,EAAE,EAAE,IAAI,CAAC4C,MAAQA,CAA4B,GACzEC,IAAa7C,EAChB,MAAM,EAAE,EACR,OAAO,CAAC4C,MAAQA,MAAQ,GAAG,EAC3B,IAAI,CAACA,MAAQA,CAA4B,GACtCE,IAA+C;AAAA,IACnD,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EAAA;AAcL,SACE,gBAAAZ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAA1B;AAAA,MACA,eAAaC;AAAA,MACb,QAfe,CAACsC,MAA4C;AAC9D,cAAMC,IAAgBD,EAAM,eACtBE,IAAOF,EAAM;AACnB,QAAIE,KAAQD,EAAc,SAASC,CAAI,KACvC,sBAAsB,MAAM;AAC1B,gBAAMC,IAAS,SAAS;AACxB,UAAIA,KAAUF,EAAc,SAASE,CAAM,KAC3CxC,IAASqC,CAAK;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,MAOI,SAAApC;AAAA,MACC,GAAGC;AAAA,MAEH,gBAAe,SACd,gBAAAwB,EAACe,MAAM,WAAU,YAAW,MAAK,MAC9B,UAAA;AAAA,QAAAnB,EAAA;AAAA,0BACAoB,GAAA,EAAK,KAAI,MACP,UAAAP,EAAW,IAAI,CAACQ,MACf,gBAAAnB,EAAC,SAAmB,WAAWY,EAAYO,CAAQ,GAChD,UAAAX,EAASW,CAAQ,EAAA,GADVA,CAEV,CACD,EAAA,CACH;AAAA,MAAA,EAAA,CACF,sBAECD,GAAA,EAAK,MAAK,QAAO,KAAI,MACnB,UAAAT,EAAc,IAAI,CAACU,wBACjB,OAAA,EAAmB,WAAWP,EAAYO,CAAQ,GAChD,YAASA,CAAQ,KADVA,CAEV,CACD,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAIR;AAEA3D,EAAY,WAAWb;AAEvBa,EAAY,cAAc;"}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
+
export interface SelectOption {
|
|
3
|
+
label: React.ReactNode;
|
|
4
|
+
value: string | number;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
}
|
|
2
7
|
export interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
|
|
3
8
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
9
|
color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error';
|
|
@@ -12,6 +17,8 @@ export interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectE
|
|
|
12
17
|
addonBefore?: React.ReactNode;
|
|
13
18
|
/** Text/element after select (outside, using DaisyUI label) */
|
|
14
19
|
addonAfter?: React.ReactNode;
|
|
20
|
+
/** Select options array (recommended for better performance) */
|
|
21
|
+
options?: SelectOption[];
|
|
15
22
|
className?: string;
|
|
16
23
|
children?: React.ReactNode;
|
|
17
24
|
'data-testid'?: string;
|
|
@@ -1,88 +1,89 @@
|
|
|
1
1
|
import { jsx as c, jsxs as w } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import { useConfig as
|
|
4
|
-
const i = "select", f = "select-bordered",
|
|
2
|
+
import { forwardRef as F, useRef as G } from "react";
|
|
3
|
+
import { useConfig as M } from "../providers/ConfigProvider.js";
|
|
4
|
+
const i = "select", f = "select-bordered", O = "select-ghost", P = "select-xs", k = "select-sm", q = "select-md", A = "select-lg", D = "select-xl", H = "select-neutral", J = "select-primary", K = "select-secondary", L = "select-accent", Q = "select-info", U = "select-success", y = "select-warning", N = "select-error", V = "floating-label", Y = F(
|
|
5
5
|
({
|
|
6
6
|
size: j,
|
|
7
7
|
color: m,
|
|
8
|
-
status:
|
|
9
|
-
ghost:
|
|
10
|
-
bordered:
|
|
8
|
+
status: u,
|
|
9
|
+
ghost: R = !1,
|
|
10
|
+
bordered: $ = !0,
|
|
11
11
|
floatingLabel: l,
|
|
12
12
|
addonBefore: n,
|
|
13
13
|
addonAfter: o,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
options: S,
|
|
15
|
+
className: g = "",
|
|
16
|
+
children: z,
|
|
17
|
+
"data-testid": s,
|
|
18
|
+
...h
|
|
19
|
+
}, B) => {
|
|
20
|
+
const { componentSize: E } = M(), t = j ?? E ?? "md", p = () => S ? S.map((e) => /* @__PURE__ */ c("option", { value: e.value, disabled: e.disabled, children: e.label }, e.value)) : z, T = G(null), b = B || T, a = {
|
|
21
|
+
xs: P,
|
|
22
|
+
sm: k,
|
|
23
|
+
md: q,
|
|
24
|
+
lg: A,
|
|
25
|
+
xl: D
|
|
26
|
+
}, x = u ? {
|
|
26
27
|
error: N,
|
|
27
28
|
warning: y
|
|
28
|
-
}[
|
|
29
|
-
neutral:
|
|
30
|
-
primary:
|
|
31
|
-
secondary:
|
|
32
|
-
accent:
|
|
33
|
-
info:
|
|
34
|
-
success:
|
|
29
|
+
}[u] : m ? {
|
|
30
|
+
neutral: H,
|
|
31
|
+
primary: J,
|
|
32
|
+
secondary: K,
|
|
33
|
+
accent: L,
|
|
34
|
+
info: Q,
|
|
35
|
+
success: U,
|
|
35
36
|
warning: y,
|
|
36
37
|
error: N
|
|
37
|
-
}[m] : "", r = n || o,
|
|
38
|
+
}[m] : "", r = n || o, W = r || !!l, d = (e) => s ? `${s}-${e}` : void 0, C = s ? W ? d("select") : s : void 0, X = r ? ["grow", "bg-transparent", "border-0", "outline-none", "focus:outline-none", g].filter(Boolean).join(" ") : [
|
|
38
39
|
i,
|
|
39
40
|
"w-full",
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
].filter(Boolean).join(" "),
|
|
41
|
+
$ && f,
|
|
42
|
+
R && O,
|
|
43
|
+
t && a[t],
|
|
44
|
+
x,
|
|
45
|
+
g
|
|
46
|
+
].filter(Boolean).join(" "), v = /* @__PURE__ */ c("select", { ref: b, className: X, "data-testid": C, ...h, children: p() });
|
|
46
47
|
if (l) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const e = [
|
|
49
|
+
V,
|
|
50
|
+
t && a[t]
|
|
50
51
|
].filter(Boolean).join(" ");
|
|
51
|
-
return /* @__PURE__ */ w("label", { className:
|
|
52
|
+
return /* @__PURE__ */ w("label", { className: e, "data-testid": s, children: [
|
|
52
53
|
/* @__PURE__ */ c(
|
|
53
54
|
"select",
|
|
54
55
|
{
|
|
55
|
-
ref:
|
|
56
|
+
ref: b,
|
|
56
57
|
className: `${i} ${f} w-full`,
|
|
57
|
-
"data-testid":
|
|
58
|
-
...
|
|
59
|
-
children:
|
|
58
|
+
"data-testid": C,
|
|
59
|
+
...h,
|
|
60
|
+
children: p()
|
|
60
61
|
}
|
|
61
62
|
),
|
|
62
63
|
/* @__PURE__ */ c("span", { children: l })
|
|
63
64
|
] });
|
|
64
65
|
}
|
|
65
66
|
if (r) {
|
|
66
|
-
const
|
|
67
|
+
const e = [
|
|
67
68
|
i,
|
|
68
69
|
f,
|
|
69
70
|
"flex",
|
|
70
71
|
"items-center",
|
|
71
72
|
"gap-2",
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
t && a[t],
|
|
74
|
+
x
|
|
74
75
|
].filter(Boolean).join(" ");
|
|
75
|
-
return /* @__PURE__ */ w("label", { className:
|
|
76
|
+
return /* @__PURE__ */ w("label", { className: e, "data-testid": s, children: [
|
|
76
77
|
n && /* @__PURE__ */ c("span", { className: "text-base-content/70", "data-testid": d("addon-before"), children: n }),
|
|
77
|
-
|
|
78
|
+
v,
|
|
78
79
|
o && /* @__PURE__ */ c("span", { className: "text-base-content/70", "data-testid": d("addon-after"), children: o })
|
|
79
80
|
] });
|
|
80
81
|
}
|
|
81
|
-
return
|
|
82
|
+
return v;
|
|
82
83
|
}
|
|
83
84
|
);
|
|
84
|
-
|
|
85
|
+
Y.displayName = "Select";
|
|
85
86
|
export {
|
|
86
|
-
|
|
87
|
+
Y as Select
|
|
87
88
|
};
|
|
88
89
|
//# sourceMappingURL=Select.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.js","sources":["../../src/components/Select.tsx"],"sourcesContent":["import React, { forwardRef, useRef } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dSelect = 'select'\nconst dSelectBordered = 'select-bordered'\nconst dSelectGhost = 'select-ghost'\nconst dSelectXs = 'select-xs'\nconst dSelectSm = 'select-sm'\nconst dSelectMd = 'select-md'\nconst dSelectLg = 'select-lg'\nconst dSelectXl = 'select-xl'\nconst dSelectNeutral = 'select-neutral'\nconst dSelectPrimary = 'select-primary'\nconst dSelectSecondary = 'select-secondary'\nconst dSelectAccent = 'select-accent'\nconst dSelectInfo = 'select-info'\nconst dSelectSuccess = 'select-success'\nconst dSelectWarning = 'select-warning'\nconst dSelectError = 'select-error'\nconst dFloatingLabel = 'floating-label'\n\nexport interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'size'> {\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'\n /** Validation status */\n status?: 'error' | 'warning'\n ghost?: boolean\n bordered?: boolean\n /** Floating label text (uses DaisyUI floating-label) */\n floatingLabel?: string\n /** Text/element before select (outside, using DaisyUI label) */\n addonBefore?: React.ReactNode\n /** Text/element after select (outside, using DaisyUI label) */\n addonAfter?: React.ReactNode\n className?: string\n children?: React.ReactNode\n 'data-testid'?: string\n}\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n (\n {\n size,\n color,\n status,\n ghost = false,\n bordered = true,\n floatingLabel,\n addonBefore,\n addonAfter,\n className = '',\n children,\n 'data-testid': testId,\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const innerRef = useRef<HTMLSelectElement>(null)\n const selectRef = (ref as React.RefObject<HTMLSelectElement>) || innerRef\n\n const sizeClasses = {\n xs: dSelectXs,\n sm: dSelectSm,\n md: dSelectMd,\n lg: dSelectLg,\n xl: dSelectXl,\n }\n\n const colorClasses = {\n neutral: dSelectNeutral,\n primary: dSelectPrimary,\n secondary: dSelectSecondary,\n accent: dSelectAccent,\n info: dSelectInfo,\n success: dSelectSuccess,\n warning: dSelectWarning,\n error: dSelectError,\n }\n\n const statusClasses = {\n error: dSelectError,\n warning: dSelectWarning,\n }\n\n // Status takes precedence over color for validation feedback\n const effectiveColorClass = status ? statusClasses[status] : (color ? colorClasses[color] : '')\n\n // When wrapped with external addons, the wrapper has the styling\n const hasExternalAddons = addonBefore || addonAfter\n const hasWrapper = hasExternalAddons || !!floatingLabel\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n const selectTestId = testId ? (hasWrapper ? getTestId('select') : testId) : undefined\n\n const selectClasses = hasExternalAddons\n ? ['grow', 'bg-transparent', 'border-0', 'outline-none', 'focus:outline-none', className].filter(Boolean).join(' ')\n : [\n dSelect,\n 'w-full',\n bordered && dSelectBordered,\n ghost && dSelectGhost,\n effectiveSize && sizeClasses[effectiveSize],\n effectiveColorClass,\n className,\n ].filter(Boolean).join(' ')\n\n // Build the core select element\n const selectElement = (\n <select ref={selectRef} className={selectClasses} data-testid={selectTestId} {...props}>\n {
|
|
1
|
+
{"version":3,"file":"Select.js","sources":["../../src/components/Select.tsx"],"sourcesContent":["import React, { forwardRef, useRef } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dSelect = 'select'\nconst dSelectBordered = 'select-bordered'\nconst dSelectGhost = 'select-ghost'\nconst dSelectXs = 'select-xs'\nconst dSelectSm = 'select-sm'\nconst dSelectMd = 'select-md'\nconst dSelectLg = 'select-lg'\nconst dSelectXl = 'select-xl'\nconst dSelectNeutral = 'select-neutral'\nconst dSelectPrimary = 'select-primary'\nconst dSelectSecondary = 'select-secondary'\nconst dSelectAccent = 'select-accent'\nconst dSelectInfo = 'select-info'\nconst dSelectSuccess = 'select-success'\nconst dSelectWarning = 'select-warning'\nconst dSelectError = 'select-error'\nconst dFloatingLabel = 'floating-label'\n\nexport interface SelectOption {\n label: React.ReactNode\n value: string | number\n disabled?: boolean\n}\n\nexport interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'size'> {\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'\n /** Validation status */\n status?: 'error' | 'warning'\n ghost?: boolean\n bordered?: boolean\n /** Floating label text (uses DaisyUI floating-label) */\n floatingLabel?: string\n /** Text/element before select (outside, using DaisyUI label) */\n addonBefore?: React.ReactNode\n /** Text/element after select (outside, using DaisyUI label) */\n addonAfter?: React.ReactNode\n /** Select options array (recommended for better performance) */\n options?: SelectOption[]\n className?: string\n children?: React.ReactNode\n 'data-testid'?: string\n}\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n (\n {\n size,\n color,\n status,\n ghost = false,\n bordered = true,\n floatingLabel,\n addonBefore,\n addonAfter,\n options,\n className = '',\n children,\n 'data-testid': testId,\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n // Render options from array or use children\n const renderOptions = () => {\n if (options) {\n return options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))\n }\n return children\n }\n\n const innerRef = useRef<HTMLSelectElement>(null)\n const selectRef = (ref as React.RefObject<HTMLSelectElement>) || innerRef\n\n const sizeClasses = {\n xs: dSelectXs,\n sm: dSelectSm,\n md: dSelectMd,\n lg: dSelectLg,\n xl: dSelectXl,\n }\n\n const colorClasses = {\n neutral: dSelectNeutral,\n primary: dSelectPrimary,\n secondary: dSelectSecondary,\n accent: dSelectAccent,\n info: dSelectInfo,\n success: dSelectSuccess,\n warning: dSelectWarning,\n error: dSelectError,\n }\n\n const statusClasses = {\n error: dSelectError,\n warning: dSelectWarning,\n }\n\n // Status takes precedence over color for validation feedback\n const effectiveColorClass = status ? statusClasses[status] : (color ? colorClasses[color] : '')\n\n // When wrapped with external addons, the wrapper has the styling\n const hasExternalAddons = addonBefore || addonAfter\n const hasWrapper = hasExternalAddons || !!floatingLabel\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n const selectTestId = testId ? (hasWrapper ? getTestId('select') : testId) : undefined\n\n const selectClasses = hasExternalAddons\n ? ['grow', 'bg-transparent', 'border-0', 'outline-none', 'focus:outline-none', className].filter(Boolean).join(' ')\n : [\n dSelect,\n 'w-full',\n bordered && dSelectBordered,\n ghost && dSelectGhost,\n effectiveSize && sizeClasses[effectiveSize],\n effectiveColorClass,\n className,\n ].filter(Boolean).join(' ')\n\n // Build the core select element\n const selectElement = (\n <select ref={selectRef} className={selectClasses} data-testid={selectTestId} {...props}>\n {renderOptions()}\n </select>\n )\n\n // Wrap with floating label if specified\n if (floatingLabel) {\n const floatingClasses = [\n dFloatingLabel,\n effectiveSize && sizeClasses[effectiveSize],\n ].filter(Boolean).join(' ')\n\n return (\n <label className={floatingClasses} data-testid={testId}>\n <select\n ref={selectRef}\n className={`${dSelect} ${dSelectBordered} w-full`}\n data-testid={selectTestId}\n {...props}\n >\n {renderOptions()}\n </select>\n <span>{floatingLabel}</span>\n </label>\n )\n }\n\n // Wrap with external addons if specified\n if (hasExternalAddons) {\n const addonClasses = [\n dSelect,\n dSelectBordered,\n 'flex',\n 'items-center',\n 'gap-2',\n effectiveSize && sizeClasses[effectiveSize],\n effectiveColorClass,\n ].filter(Boolean).join(' ')\n\n return (\n <label className={addonClasses} data-testid={testId}>\n {addonBefore && (\n <span className=\"text-base-content/70\" data-testid={getTestId('addon-before')}>\n {addonBefore}\n </span>\n )}\n {selectElement}\n {addonAfter && (\n <span className=\"text-base-content/70\" data-testid={getTestId('addon-after')}>\n {addonAfter}\n </span>\n )}\n </label>\n )\n }\n\n return selectElement\n }\n)\n\nSelect.displayName = 'Select'\n"],"names":["dSelect","dSelectBordered","dSelectGhost","dSelectXs","dSelectSm","dSelectMd","dSelectLg","dSelectXl","dSelectNeutral","dSelectPrimary","dSelectSecondary","dSelectAccent","dSelectInfo","dSelectSuccess","dSelectWarning","dSelectError","dFloatingLabel","Select","forwardRef","size","color","status","ghost","bordered","floatingLabel","addonBefore","addonAfter","options","className","children","testId","props","ref","componentSize","useConfig","effectiveSize","renderOptions","option","jsx","innerRef","useRef","selectRef","sizeClasses","effectiveColorClass","hasExternalAddons","hasWrapper","getTestId","suffix","selectTestId","selectClasses","selectElement","floatingClasses","jsxs","addonClasses"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -151,7 +151,7 @@ export type { RatingProps, RatingItemProps } from './components/Rating';
|
|
|
151
151
|
export { Result } from './components/Result';
|
|
152
152
|
export type { ResultProps, ResultStatus } from './components/Result';
|
|
153
153
|
export { Select } from './components/Select';
|
|
154
|
-
export type { SelectProps } from './components/Select';
|
|
154
|
+
export type { SelectProps, SelectOption } from './components/Select';
|
|
155
155
|
export { Segmented } from './components/Segmented';
|
|
156
156
|
export type { SegmentedProps, SegmentedItemProps, SegmentedValue } from './components/Segmented';
|
|
157
157
|
export { Skeleton } from './components/Skeleton';
|