asterui 0.12.78 → 0.12.80
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/codeeditor.d.ts +1 -0
- package/dist/codeeditor.js +5 -0
- package/dist/codeeditor.js.map +1 -0
- package/dist/components/CodeEditor.d.ts +47 -0
- package/dist/components/CodeEditor.js +244 -0
- package/dist/components/CodeEditor.js.map +1 -0
- package/dist/components/DateOfBirth.js +122 -133
- package/dist/components/DateOfBirth.js.map +1 -1
- package/dist/components/Terminal.d.ts +40 -0
- package/dist/components/Terminal.js +146 -0
- package/dist/components/Terminal.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +101 -99
- package/dist/index.js.map +1 -1
- package/dist/terminal.d.ts +1 -0
- package/dist/terminal.js +5 -0
- package/dist/terminal.js.map +1 -0
- package/package.json +95 -2
|
@@ -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":";;;;;;;;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;AAEA,SAASC,GAAYT,GAAyBU,GAAiBC,GAAiB;AAC9E,MAAI,CAACX,EAAM,QAAQ,CAACA,EAAM,SAAS,CAACA,EAAM,IAAK,QAAO;AACtD,QAAMO,IAAO,OAAOP,EAAM,IAAI,GACxBQ,IAAQ,OAAOR,EAAM,KAAK,IAAI,GAC9BY,IAAM,OAAOZ,EAAM,GAAG,GACtBa,IAAY,IAAI,KAAKN,GAAMC,GAAOI,CAAG;AAC3C,MAAI,OAAO,MAAMC,EAAU,QAAA,CAAS,EAAG,QAAO;AAC9C,QAAMC,wBAAY,KAAA;AAClB,MAAIC,IAAMD,EAAM,YAAA,IAAgBD,EAAU,YAAA;AAM1C,SAJEC,EAAM,SAAA,IAAaD,EAAU,cAC5BC,EAAM,SAAA,MAAeD,EAAU,cAAcC,EAAM,QAAA,KAAaD,EAAU,QAAA,MACxDE,KAAO,IACxB,EAAAL,MAAW,UAAaK,IAAML,KAC9BC,MAAW,UAAaI,IAAMJ;AAEpC;AAEO,MAAMK,IAAoC,CAAC;AAAA,EAChD,OAAAhB;AAAA,EACA,cAAAiB;AAAA,EACA,UAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,QAAAT,IAAS;AAAA,EACT,QAAAC;AAAA,EACA,OAAAS,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,QAAA7B,GAAQ,eAAA8B,EAAA,IAAkBC,EAAA,GAC5BC,IAAgBR,KAAQM,KAAiB,MACzCG,IAAepC,MAAU,QACzB,CAACqC,GAAeC,CAAgB,IAAIC;AAAA,IACxCvC,KAASiB,KAAgB,CAAA;AAAA,EAAC;AAG5B,EAAAuB,EAAU,MAAM;AACd,IAAIJ,KACFE,EAAiBtC,KAAS,EAAE;AAAA,EAEhC,GAAG,CAACoC,GAAcpC,CAAK,CAAC;AAExB,QAAMyC,IAAeL,IAAgBpC,KAAS,CAAA,IAAMqC,GAC9CK,IAAavC,GAAQ,UAAU,SAC/BwC,IAAcC;AAAA,IAClB,MAAM1C,GAAewC,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,QAAQ3B,EAAA,GAAY,CAACzB,GAAGqD,MAAM,OAAOD,IAAcC,CAAC,CAAC;AAAA,EAC3E,GAAG,CAAC5B,CAAQ,CAAC,GAEP6B,IAAaJ,EAAQ,MAAM;AAC/B,QAAI,CAACH,EAAa,MAAO,QAAO,MAAM,KAAK,EAAE,QAAQ,GAAA,GAAM,CAAC/C,GAAGqD,MAAM,OAAOA,IAAI,CAAC,CAAC;AAClF,UAAMvC,IAAQ,OAAOiC,EAAa,KAAK,GACjClC,IAAOkC,EAAa,OAAO,OAAOA,EAAa,IAAI,IAAI,KACvDQ,IAAc3C,GAAeC,GAAMC,CAAK;AAC9C,WAAO,MAAM,KAAK,EAAE,QAAQyC,EAAA,GAAe,CAACvD,GAAGqD,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,GAE5BjC,IAAWiC,CAAS;AAAA,EACtB,GAEMC,IAAc,MACd/B,MAAe,2BAEd,OAAA,EAAI,WAAU,0BACZ,UAAAsB,EAAY,IAAI,CAACnC,MAAU;AAC1B,UAAM6C,IAAWZ,EAAa,UAAUjC,EAAM;AAC9C,WACE,gBAAA8C;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,OAAOjC,EAAM,OAAO;AAAA,QACnE,eAAaqB,IAAS,GAAGA,CAAM,UAAUrB,EAAM,KAAK,KAAK;AAAA,QAExD,UAAAA,EAAM;AAAA,MAAA;AAAA,MATFA,EAAM;AAAA,IAAA;AAAA,EAYjB,CAAC,EAAA,CACH,IAKF,gBAAAgD;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,CAACnC,MAChB,gBAAA8C,EAAC,UAAA,EAAyB,OAAO9C,EAAM,OACpC,UAAAA,EAAM,MAAA,GADIA,EAAM,KAEnB,CACD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAKDkD,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,CAACpC,MACf,gBAAA0C,EAAC,YAAiB,OAAO1C,GAAM,UAAAA,EAAA,GAAlBA,CAAsB,CACpC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAIC+C,IAAa,MACbrC,MAAc,UAEd,gBAAAgC;AAAA,IAACM;AAAA,IAAA;AAAA,MACC,OAAOnB,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,CAACtC,MACd,gBAAA+C,EAAC,YAAkB,OAAO/C,GAAO,UAAAA,EAAA,GAApBA,CAAyB,CACvC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAKDsD,IAAW;AAAA,IACf,GAAGT,EAAA;AAAA,IACH,GAAGM,EAAA;AAAA,IACH,GAAGC,EAAA;AAAA,EAAW,GAGVG,IAAgB1C,EAAM,MAAM,EAAE,EAAE,IAAI,CAAC2C,MAAQA,CAA4B,GACzEC,IAAa5C,EAChB,MAAM,EAAE,EACR,OAAO,CAAC2C,MAAQA,MAAQ,GAAG,EAC3B,IAAI,CAACA,MAAQA,CAA4B,GACtCE,IAA+C;AAAA,IACnD,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EAAA,GAGCC,IAAiBzB,EAAa,QAAQA,EAAa,SAASA,EAAa,OAAO,CAAChC,GAAYgC,GAAc/B,GAAQC,CAAM;AAa/H,SACE,gBAAA6C;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAA5B;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,UAAA;AAAA,QAAAX,MAAe,SACd,gBAAAmC,EAACe,IAAA,EAAM,WAAU,YAAW,MAAK,MAC9B,UAAA;AAAA,UAAAnB,EAAA;AAAA,4BACAoB,GAAA,EAAK,KAAI,MACP,UAAAR,EAAW,IAAI,CAACS,MACf,gBAAAnB,EAAC,SAAmB,WAAWW,EAAYQ,CAAQ,GAChD,UAAAZ,EAASY,CAAQ,EAAA,GADVA,CAEV,CACD,EAAA,CACH;AAAA,QAAA,EAAA,CACF,sBAECD,GAAA,EAAK,MAAK,QAAO,KAAI,MACnB,UAAAV,EAAc,IAAI,CAACW,wBACjB,OAAA,EAAmB,WAAWR,EAAYQ,CAAQ,GAChD,YAASA,CAAQ,EAAA,GADVA,CAEV,CACD,EAAA,CACH;AAAA,QAGDP,uBACE,OAAA,EAAI,WAAU,2BACZ,UAAAxD,IAAS,wBAAwBA,CAAM,gBAAgB,8BAAA,CAC1D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;AAEAM,EAAY,WAAWpB;AAEvBoB,EAAY,cAAc;"}
|
|
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;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { Terminal as XTermType, ITerminalOptions, ITerminalInitOnlyOptions } from '@xterm/xterm';
|
|
3
|
+
export interface TerminalRef {
|
|
4
|
+
/** The underlying xterm.js Terminal instance */
|
|
5
|
+
terminal: XTermType | null;
|
|
6
|
+
/** Write data to the terminal */
|
|
7
|
+
write: (data: string) => void;
|
|
8
|
+
/** Write a line to the terminal (with newline) */
|
|
9
|
+
writeln: (data: string) => void;
|
|
10
|
+
/** Clear the terminal */
|
|
11
|
+
clear: () => void;
|
|
12
|
+
/** Focus the terminal */
|
|
13
|
+
focus: () => void;
|
|
14
|
+
/** Fit the terminal to its container */
|
|
15
|
+
fit: () => void;
|
|
16
|
+
/** Command history (only available with readline mode) */
|
|
17
|
+
history: string[];
|
|
18
|
+
/** Clear command history (only available with readline mode) */
|
|
19
|
+
clearHistory: () => void;
|
|
20
|
+
}
|
|
21
|
+
export interface TerminalProps {
|
|
22
|
+
/** Callback when user types in the terminal (raw input) */
|
|
23
|
+
onData?: (data: string) => void;
|
|
24
|
+
/** Callback when terminal is ready */
|
|
25
|
+
onReady?: (terminal: XTermType) => void;
|
|
26
|
+
/** Enable readline mode with line editing and history */
|
|
27
|
+
readline?: boolean;
|
|
28
|
+
/** Prompt string for readline mode (supports ANSI colors) */
|
|
29
|
+
prompt?: string;
|
|
30
|
+
/** Callback when user submits a line in readline mode */
|
|
31
|
+
onLine?: (line: string) => void;
|
|
32
|
+
/** xterm.js options (theme is auto-applied unless you override it) */
|
|
33
|
+
options?: ITerminalOptions & ITerminalInitOnlyOptions;
|
|
34
|
+
/** Additional CSS classes for the container */
|
|
35
|
+
className?: string;
|
|
36
|
+
/** Container style */
|
|
37
|
+
style?: React.CSSProperties;
|
|
38
|
+
'data-testid'?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare const Terminal: React.ForwardRefExoticComponent<TerminalProps & React.RefAttributes<TerminalRef>>;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { jsx as C } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as R, useRef as d, useImperativeHandle as T, useEffect as b } from "react";
|
|
3
|
+
import p from "@xterm/xterm";
|
|
4
|
+
import g from "@xterm/addon-fit";
|
|
5
|
+
import { useTheme as D } from "../hooks/useTheme.js";
|
|
6
|
+
const S = p.Terminal ?? p.Terminal, M = g.FitAddon ?? g.FitAddon;
|
|
7
|
+
let y = !1;
|
|
8
|
+
function H() {
|
|
9
|
+
if (y || typeof document > "u") return;
|
|
10
|
+
y = !0;
|
|
11
|
+
const i = document.createElement("style");
|
|
12
|
+
i.setAttribute("data-xterm", ""), i.textContent = ".xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}", document.head.appendChild(i);
|
|
13
|
+
}
|
|
14
|
+
const O = R(({
|
|
15
|
+
onData: i,
|
|
16
|
+
onReady: v,
|
|
17
|
+
readline: a = !1,
|
|
18
|
+
prompt: c = "$ ",
|
|
19
|
+
onLine: w,
|
|
20
|
+
options: B = {},
|
|
21
|
+
className: k = "",
|
|
22
|
+
style: I,
|
|
23
|
+
"data-testid": z
|
|
24
|
+
}, A) => {
|
|
25
|
+
const u = d(null), o = d(null), x = d(null), { isDark: l, colors: t } = D(), f = d({
|
|
26
|
+
buffer: "",
|
|
27
|
+
cursor: 0,
|
|
28
|
+
history: [],
|
|
29
|
+
historyIndex: -1,
|
|
30
|
+
savedBuffer: ""
|
|
31
|
+
}), h = () => ({
|
|
32
|
+
background: t.background,
|
|
33
|
+
foreground: t.foreground,
|
|
34
|
+
cursor: t.primary,
|
|
35
|
+
cursorAccent: t.background,
|
|
36
|
+
selectionBackground: t.primary + "40",
|
|
37
|
+
selectionForeground: t.foreground,
|
|
38
|
+
black: l ? "#000000" : "#2e3436",
|
|
39
|
+
red: t.error,
|
|
40
|
+
green: t.success,
|
|
41
|
+
yellow: t.warning,
|
|
42
|
+
blue: t.info,
|
|
43
|
+
magenta: t.secondary,
|
|
44
|
+
cyan: t.accent,
|
|
45
|
+
white: l ? "#d3d7cf" : "#eeeeec",
|
|
46
|
+
brightBlack: "#555753",
|
|
47
|
+
brightRed: t.error,
|
|
48
|
+
brightGreen: t.success,
|
|
49
|
+
brightYellow: t.warning,
|
|
50
|
+
brightBlue: t.info,
|
|
51
|
+
brightMagenta: t.secondary,
|
|
52
|
+
brightCyan: t.accent,
|
|
53
|
+
brightWhite: l ? "#eeeeec" : "#ffffff"
|
|
54
|
+
});
|
|
55
|
+
T(A, () => ({
|
|
56
|
+
terminal: o.current,
|
|
57
|
+
write: (r) => o.current?.write(r),
|
|
58
|
+
writeln: (r) => o.current?.writeln(r),
|
|
59
|
+
clear: () => o.current?.clear(),
|
|
60
|
+
focus: () => o.current?.focus(),
|
|
61
|
+
fit: () => x.current?.fit(),
|
|
62
|
+
history: f.current.history,
|
|
63
|
+
clearHistory: () => {
|
|
64
|
+
f.current.history = [];
|
|
65
|
+
}
|
|
66
|
+
}), []);
|
|
67
|
+
const s = () => {
|
|
68
|
+
const r = o.current;
|
|
69
|
+
if (!r) return;
|
|
70
|
+
const n = f.current;
|
|
71
|
+
r.write("\r\x1B[K" + c + n.buffer);
|
|
72
|
+
const e = n.buffer.length - n.cursor;
|
|
73
|
+
e > 0 && r.write(`\x1B[${e}D`);
|
|
74
|
+
}, F = (r) => {
|
|
75
|
+
const n = o.current;
|
|
76
|
+
if (!n) return;
|
|
77
|
+
const e = f.current;
|
|
78
|
+
if (r === "\x1B[A") {
|
|
79
|
+
e.history.length > 0 && e.historyIndex < e.history.length - 1 && (e.historyIndex === -1 && (e.savedBuffer = e.buffer), e.historyIndex++, e.buffer = e.history[e.history.length - 1 - e.historyIndex], e.cursor = e.buffer.length, s());
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (r === "\x1B[B") {
|
|
83
|
+
e.historyIndex > -1 && (e.historyIndex--, e.buffer = e.historyIndex === -1 ? e.savedBuffer : e.history[e.history.length - 1 - e.historyIndex], e.cursor = e.buffer.length, s());
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (r === "\x1B[C") {
|
|
87
|
+
e.cursor < e.buffer.length && (e.cursor++, n.write("\x1B[C"));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (r === "\x1B[D") {
|
|
91
|
+
e.cursor > 0 && (e.cursor--, n.write("\x1B[D"));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (r === "\x1B[H" || r === "\x1BOH" || r === "\x1B[1~") {
|
|
95
|
+
e.cursor > 0 && (n.write(`\x1B[${e.cursor}D`), e.cursor = 0);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (r === "\x1B[F" || r === "\x1BOF" || r === "\x1B[4~") {
|
|
99
|
+
e.cursor < e.buffer.length && (n.write(`\x1B[${e.buffer.length - e.cursor}C`), e.cursor = e.buffer.length);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (r === "\x1B[3~") {
|
|
103
|
+
e.cursor < e.buffer.length && (e.buffer = e.buffer.slice(0, e.cursor) + e.buffer.slice(e.cursor + 1), s());
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (!r.startsWith("\x1B"))
|
|
107
|
+
if (r === "\r") {
|
|
108
|
+
n.writeln("");
|
|
109
|
+
const m = e.buffer;
|
|
110
|
+
m.trim() && e.history.push(m), e.buffer = "", e.cursor = 0, e.historyIndex = -1, e.savedBuffer = "", w?.(m), n.write(c);
|
|
111
|
+
} else r === "" || r === "\b" ? e.cursor > 0 && (e.buffer = e.buffer.slice(0, e.cursor - 1) + e.buffer.slice(e.cursor), e.cursor--, s()) : r === "" ? (n.writeln("^C"), e.buffer = "", e.cursor = 0, e.historyIndex = -1, n.write(c)) : (r >= " " || r === " ") && (e.buffer = e.buffer.slice(0, e.cursor) + r + e.buffer.slice(e.cursor), e.cursor += r.length, s());
|
|
112
|
+
};
|
|
113
|
+
return b(() => {
|
|
114
|
+
if (!u.current) return;
|
|
115
|
+
H();
|
|
116
|
+
const r = new S({
|
|
117
|
+
theme: h(),
|
|
118
|
+
cursorBlink: !0,
|
|
119
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',
|
|
120
|
+
fontSize: 14,
|
|
121
|
+
...B
|
|
122
|
+
}), n = new M();
|
|
123
|
+
r.loadAddon(n), r.open(u.current), n.fit(), o.current = r, x.current = n, a ? r.onData(F) : i && r.onData(i), v?.(r), a && r.write(c);
|
|
124
|
+
const e = new ResizeObserver(() => {
|
|
125
|
+
n.fit();
|
|
126
|
+
});
|
|
127
|
+
return e.observe(u.current), () => {
|
|
128
|
+
e.disconnect(), r.dispose(), o.current = null, x.current = null;
|
|
129
|
+
};
|
|
130
|
+
}, []), b(() => {
|
|
131
|
+
o.current && (o.current.options.theme = h());
|
|
132
|
+
}, [l, t]), /* @__PURE__ */ C(
|
|
133
|
+
"div",
|
|
134
|
+
{
|
|
135
|
+
ref: u,
|
|
136
|
+
className: k,
|
|
137
|
+
style: { width: "100%", height: "100%", ...I },
|
|
138
|
+
"data-testid": z
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
O.displayName = "Terminal";
|
|
143
|
+
export {
|
|
144
|
+
O as Terminal
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=Terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Terminal.js","sources":["../../src/components/Terminal.tsx"],"sourcesContent":["import React, { useEffect, useRef, useImperativeHandle, forwardRef } from 'react'\nimport XTermPkg from '@xterm/xterm'\nimport FitAddonPkg from '@xterm/addon-fit'\nimport type { Terminal as XTermType, ITerminalOptions, ITerminalInitOnlyOptions } from '@xterm/xterm'\nimport type { FitAddon as FitAddonType } from '@xterm/addon-fit'\nimport { useTheme } from '../hooks/useTheme'\n\nconst XTerm = XTermPkg.Terminal ?? (XTermPkg as unknown as { Terminal: typeof XTermPkg.Terminal }).Terminal\nconst FitAddon = FitAddonPkg.FitAddon ?? (FitAddonPkg as unknown as { FitAddon: typeof FitAddonPkg.FitAddon }).FitAddon\n\n// Inject xterm.css once (inlined for reliability across bundlers)\nlet cssInjected = false\nfunction injectXtermCSS() {\n if (cssInjected || typeof document === 'undefined') return\n cssInjected = true\n\n const style = document.createElement('style')\n style.setAttribute('data-xterm', '')\n style.textContent = `.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}`\n document.head.appendChild(style)\n}\n\nexport interface TerminalRef {\n /** The underlying xterm.js Terminal instance */\n terminal: XTermType | null\n /** Write data to the terminal */\n write: (data: string) => void\n /** Write a line to the terminal (with newline) */\n writeln: (data: string) => void\n /** Clear the terminal */\n clear: () => void\n /** Focus the terminal */\n focus: () => void\n /** Fit the terminal to its container */\n fit: () => void\n /** Command history (only available with readline mode) */\n history: string[]\n /** Clear command history (only available with readline mode) */\n clearHistory: () => void\n}\n\nexport interface TerminalProps {\n /** Callback when user types in the terminal (raw input) */\n onData?: (data: string) => void\n /** Callback when terminal is ready */\n onReady?: (terminal: XTermType) => void\n /** Enable readline mode with line editing and history */\n readline?: boolean\n /** Prompt string for readline mode (supports ANSI colors) */\n prompt?: string\n /** Callback when user submits a line in readline mode */\n onLine?: (line: string) => void\n /** xterm.js options (theme is auto-applied unless you override it) */\n options?: ITerminalOptions & ITerminalInitOnlyOptions\n /** Additional CSS classes for the container */\n className?: string\n /** Container style */\n style?: React.CSSProperties\n 'data-testid'?: string\n}\n\nexport const Terminal = forwardRef<TerminalRef, TerminalProps>(({\n onData,\n onReady,\n readline = false,\n prompt = '$ ',\n onLine,\n options = {},\n className = '',\n style,\n 'data-testid': testId,\n}, ref) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const terminalRef = useRef<XTermType | null>(null)\n const fitAddonRef = useRef<FitAddonType | null>(null)\n const { isDark, colors } = useTheme()\n\n // Readline state\n const readlineState = useRef({\n buffer: '',\n cursor: 0,\n history: [] as string[],\n historyIndex: -1,\n savedBuffer: '',\n })\n\n // Build theme from DaisyUI colors\n const getTheme = () => ({\n background: colors.background,\n foreground: colors.foreground,\n cursor: colors.primary,\n cursorAccent: colors.background,\n selectionBackground: colors.primary + '40',\n selectionForeground: colors.foreground,\n black: isDark ? '#000000' : '#2e3436',\n red: colors.error,\n green: colors.success,\n yellow: colors.warning,\n blue: colors.info,\n magenta: colors.secondary,\n cyan: colors.accent,\n white: isDark ? '#d3d7cf' : '#eeeeec',\n brightBlack: '#555753',\n brightRed: colors.error,\n brightGreen: colors.success,\n brightYellow: colors.warning,\n brightBlue: colors.info,\n brightMagenta: colors.secondary,\n brightCyan: colors.accent,\n brightWhite: isDark ? '#eeeeec' : '#ffffff',\n })\n\n useImperativeHandle(ref, () => ({\n terminal: terminalRef.current,\n write: (data: string) => terminalRef.current?.write(data),\n writeln: (data: string) => terminalRef.current?.writeln(data),\n clear: () => terminalRef.current?.clear(),\n focus: () => terminalRef.current?.focus(),\n fit: () => fitAddonRef.current?.fit(),\n history: readlineState.current.history,\n clearHistory: () => { readlineState.current.history = [] },\n }), [])\n\n // Redraw the current line in readline mode\n const redrawLine = () => {\n const term = terminalRef.current\n if (!term) return\n const s = readlineState.current\n // Move to start of line, clear line, write prompt + buffer, position cursor\n term.write('\\r\\x1b[K' + prompt + s.buffer)\n // Move cursor to correct position\n const moveBack = s.buffer.length - s.cursor\n if (moveBack > 0) {\n term.write(`\\x1b[${moveBack}D`)\n }\n }\n\n // Handle readline input\n const handleReadlineData = (data: string) => {\n const term = terminalRef.current\n if (!term) return\n const s = readlineState.current\n\n // Handle escape sequences (arrow keys)\n if (data === '\\x1b[A') {\n // Up arrow - history previous\n if (s.history.length > 0 && s.historyIndex < s.history.length - 1) {\n if (s.historyIndex === -1) s.savedBuffer = s.buffer\n s.historyIndex++\n s.buffer = s.history[s.history.length - 1 - s.historyIndex]\n s.cursor = s.buffer.length\n redrawLine()\n }\n return\n }\n if (data === '\\x1b[B') {\n // Down arrow - history next\n if (s.historyIndex > -1) {\n s.historyIndex--\n s.buffer = s.historyIndex === -1 ? s.savedBuffer : s.history[s.history.length - 1 - s.historyIndex]\n s.cursor = s.buffer.length\n redrawLine()\n }\n return\n }\n if (data === '\\x1b[C') {\n // Right arrow\n if (s.cursor < s.buffer.length) {\n s.cursor++\n term.write('\\x1b[C')\n }\n return\n }\n if (data === '\\x1b[D') {\n // Left arrow\n if (s.cursor > 0) {\n s.cursor--\n term.write('\\x1b[D')\n }\n return\n }\n if (data === '\\x1b[H' || data === '\\x1bOH' || data === '\\x1b[1~') {\n // Home - move to start of line\n if (s.cursor > 0) {\n term.write(`\\x1b[${s.cursor}D`)\n s.cursor = 0\n }\n return\n }\n if (data === '\\x1b[F' || data === '\\x1bOF' || data === '\\x1b[4~') {\n // End - move to end of line\n if (s.cursor < s.buffer.length) {\n term.write(`\\x1b[${s.buffer.length - s.cursor}C`)\n s.cursor = s.buffer.length\n }\n return\n }\n if (data === '\\x1b[3~') {\n // Delete key - delete character at cursor\n if (s.cursor < s.buffer.length) {\n s.buffer = s.buffer.slice(0, s.cursor) + s.buffer.slice(s.cursor + 1)\n redrawLine()\n }\n return\n }\n\n // Ignore other escape sequences\n if (data.startsWith('\\x1b')) return\n\n if (data === '\\r') {\n // Enter\n term.writeln('')\n const line = s.buffer\n if (line.trim()) {\n s.history.push(line)\n }\n s.buffer = ''\n s.cursor = 0\n s.historyIndex = -1\n s.savedBuffer = ''\n onLine?.(line)\n term.write(prompt)\n } else if (data === '\\x7f' || data === '\\b') {\n // Backspace\n if (s.cursor > 0) {\n s.buffer = s.buffer.slice(0, s.cursor - 1) + s.buffer.slice(s.cursor)\n s.cursor--\n redrawLine()\n }\n } else if (data === '\\x03') {\n // Ctrl+C\n term.writeln('^C')\n s.buffer = ''\n s.cursor = 0\n s.historyIndex = -1\n term.write(prompt)\n } else if (data >= ' ' || data === '\\t') {\n // Printable characters\n s.buffer = s.buffer.slice(0, s.cursor) + data + s.buffer.slice(s.cursor)\n s.cursor += data.length\n redrawLine()\n }\n }\n\n // Initialize terminal\n useEffect(() => {\n if (!containerRef.current) return\n\n injectXtermCSS()\n\n const terminal = new XTerm({\n theme: getTheme(),\n cursorBlink: true,\n fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace',\n fontSize: 14,\n ...options,\n })\n const fitAddon = new FitAddon()\n\n terminal.loadAddon(fitAddon)\n terminal.open(containerRef.current)\n fitAddon.fit()\n\n terminalRef.current = terminal\n fitAddonRef.current = fitAddon\n\n if (readline) {\n terminal.onData(handleReadlineData)\n } else if (onData) {\n terminal.onData(onData)\n }\n\n onReady?.(terminal)\n\n // Write initial prompt after onReady so welcome messages appear first\n if (readline) {\n terminal.write(prompt)\n }\n\n const resizeObserver = new ResizeObserver(() => {\n fitAddon.fit()\n })\n resizeObserver.observe(containerRef.current)\n\n return () => {\n resizeObserver.disconnect()\n terminal.dispose()\n terminalRef.current = null\n fitAddonRef.current = null\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Update theme when colors change\n useEffect(() => {\n if (!terminalRef.current) return\n terminalRef.current.options.theme = getTheme()\n }, [isDark, colors]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ width: '100%', height: '100%', ...style }}\n data-testid={testId}\n />\n )\n})\n\nTerminal.displayName = 'Terminal'\n"],"names":["XTerm","XTermPkg","FitAddon","FitAddonPkg","cssInjected","injectXtermCSS","style","Terminal","forwardRef","onData","onReady","readline","prompt","onLine","options","className","testId","ref","containerRef","useRef","terminalRef","fitAddonRef","isDark","colors","useTheme","readlineState","getTheme","useImperativeHandle","data","redrawLine","term","s","moveBack","handleReadlineData","line","useEffect","terminal","fitAddon","resizeObserver","jsx"],"mappings":"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"}
|