@code-plate/iran-cities 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/LICENSE +21 -0
- package/MIGRATION.fa.md +277 -0
- package/MIGRATION.md +272 -0
- package/NOTICE.md +38 -0
- package/README.fa.md +528 -201
- package/README.md +524 -201
- package/dist/boundaries.cjs +9218 -0
- package/dist/boundaries.cjs.map +1 -0
- package/dist/boundaries.d.cts +30 -0
- package/dist/boundaries.d.mts +30 -0
- package/dist/boundaries.mjs +9215 -0
- package/dist/boundaries.mjs.map +1 -0
- package/dist/changes-B-wz9-Gy.cjs +841 -0
- package/dist/changes-B-wz9-Gy.cjs.map +1 -0
- package/dist/changes-CMVZbfZO.d.mts +8 -0
- package/dist/changes-DLZkHBwZ.mjs +800 -0
- package/dist/changes-DLZkHBwZ.mjs.map +1 -0
- package/dist/changes-DnnwRAKl.d.cts +8 -0
- package/dist/components-B7060em0.mjs +240 -0
- package/dist/components-B7060em0.mjs.map +1 -0
- package/dist/components-BuMUB7XT.d.cts +47 -0
- package/dist/components-DZz72pd1.d.mts +47 -0
- package/dist/components-grWmOsaV.cjs +247 -0
- package/dist/components-grWmOsaV.cjs.map +1 -0
- package/dist/components.css +251 -0
- package/dist/data/cities.csv +1253 -0
- package/dist/data/cities.json +23305 -0
- package/dist/data/iran-cities.sql +1487 -0
- package/dist/data/iran-provinces.geojson +1 -0
- package/dist/data/provinces.csv +32 -0
- package/dist/data/provinces.json +460 -0
- package/dist/hooks-C6kjWLIE.mjs +134 -0
- package/dist/hooks-C6kjWLIE.mjs.map +1 -0
- package/dist/hooks-K7pTMF2R.cjs +139 -0
- package/dist/hooks-K7pTMF2R.cjs.map +1 -0
- package/dist/index.cjs +30 -7550
- package/dist/index.d.cts +25 -0
- package/dist/index.d.mts +25 -25
- package/dist/index.mjs +3 -7507
- package/dist/lite-CtNPRhU-.mjs +1926 -0
- package/dist/lite-CtNPRhU-.mjs.map +1 -0
- package/dist/lite-CutarzAc.cjs +2051 -0
- package/dist/lite-CutarzAc.cjs.map +1 -0
- package/dist/lite-react-1HVWJOWt.cjs +55 -0
- package/dist/lite-react-1HVWJOWt.cjs.map +1 -0
- package/dist/lite-react-Ds-DNmEi.mjs +20 -0
- package/dist/lite-react-Ds-DNmEi.mjs.map +1 -0
- package/dist/lite-react-components.cjs +12 -0
- package/dist/lite-react-components.cjs.map +1 -0
- package/dist/lite-react-components.d.cts +5 -0
- package/dist/lite-react-components.d.mts +5 -0
- package/dist/lite-react-components.mjs +11 -0
- package/dist/lite-react-components.mjs.map +1 -0
- package/dist/lite-react.cjs +8 -0
- package/dist/lite-react.d.cts +7 -0
- package/dist/lite-react.d.mts +7 -0
- package/dist/lite-react.mjs +2 -0
- package/dist/lite.cjs +28 -0
- package/dist/lite.d.cts +23 -0
- package/dist/lite.d.mts +23 -0
- package/dist/lite.mjs +3 -0
- package/dist/react-BKmJ476x.mjs +20 -0
- package/dist/react-BKmJ476x.mjs.map +1 -0
- package/dist/react-BZV3TkXB.cjs +55 -0
- package/dist/react-BZV3TkXB.cjs.map +1 -0
- package/dist/react-components.cjs +12 -0
- package/dist/react-components.cjs.map +1 -0
- package/dist/react-components.d.cts +5 -0
- package/dist/react-components.d.mts +5 -0
- package/dist/react-components.mjs +11 -0
- package/dist/react-components.mjs.map +1 -0
- package/dist/react.cjs +8 -7553
- package/dist/react.d.cts +7 -0
- package/dist/react.d.mts +7 -30
- package/dist/react.mjs +2 -7524
- package/dist/rolldown-runtime-78lK1XfQ.cjs +42 -0
- package/dist/rolldown-runtime-D3KUYPsf.mjs +12 -0
- package/dist/src-DRaUVbc4.mjs +4302 -0
- package/dist/src-DRaUVbc4.mjs.map +1 -0
- package/dist/src-mqZTwJfQ.cjs +4439 -0
- package/dist/src-mqZTwJfQ.cjs.map +1 -0
- package/dist/types/boundaries.d.ts +30 -0
- package/dist/types/changes.d.ts +4 -0
- package/dist/types/components.d.ts +47 -0
- package/dist/types/core.d.ts +25 -0
- package/dist/types/geo.d.ts +2 -0
- package/dist/types/hooks.d.ts +2 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/keyboard.d.ts +3 -0
- package/dist/types/lite-react-components.d.ts +5 -0
- package/dist/types/lite-react.d.ts +7 -0
- package/dist/types/lite.d.ts +26 -0
- package/dist/types/normalize.d.ts +1 -0
- package/dist/types/packed.d.ts +16 -0
- package/dist/types/react-components.d.ts +5 -0
- package/dist/types/react.d.ts +7 -0
- package/dist/types/types.d.ts +149 -0
- package/dist/types/valibot.d.ts +23 -0
- package/dist/types/validation-shared.d.ts +11 -0
- package/dist/types/zod.d.ts +23 -0
- package/dist/types-Ds_b0yHP.d.cts +150 -0
- package/dist/types-Ds_b0yHP.d.mts +150 -0
- package/dist/valibot.cjs +47 -0
- package/dist/valibot.cjs.map +1 -0
- package/dist/valibot.d.cts +21 -0
- package/dist/valibot.d.mts +21 -0
- package/dist/valibot.mjs +38 -0
- package/dist/valibot.mjs.map +1 -0
- package/dist/validation-shared-BFilTuY1.cjs +58 -0
- package/dist/validation-shared-BFilTuY1.cjs.map +1 -0
- package/dist/validation-shared-C7l2cv4e.d.cts +8 -0
- package/dist/validation-shared-CJjGRx8p.d.mts +7 -0
- package/dist/validation-shared-mh_saZne.mjs +29 -0
- package/dist/validation-shared-mh_saZne.mjs.map +1 -0
- package/dist/zod.cjs +49 -0
- package/dist/zod.cjs.map +1 -0
- package/dist/zod.d.cts +21 -0
- package/dist/zod.d.mts +21 -0
- package/dist/zod.mjs +42 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +177 -29
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -25
- package/dist/index.mjs.map +0 -1
- package/dist/react.cjs.map +0 -1
- package/dist/react.d.ts +0 -30
- package/dist/react.mjs.map +0 -1
- package/dist/types-DzSw8Uw2.d.mts +0 -52
- package/dist/types-DzSw8Uw2.d.ts +0 -52
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-78lK1XfQ.cjs");
|
|
2
|
+
let react = require("react");
|
|
3
|
+
react = require_rolldown_runtime.__toESM(react);
|
|
4
|
+
// src/components.tsx
|
|
5
|
+
let idCounter = 0;
|
|
6
|
+
function useStableId(explicit) {
|
|
7
|
+
const reactUseId = react.useId;
|
|
8
|
+
const generated = reactUseId ? reactUseId() : void 0;
|
|
9
|
+
const [fallback] = react.useState(() => `ic-${++idCounter}`);
|
|
10
|
+
return explicit !== null && explicit !== void 0 ? explicit : generated ? `ic-${generated.replace(/:/g, "")}` : fallback;
|
|
11
|
+
}
|
|
12
|
+
function classNames(...names) {
|
|
13
|
+
return names.filter(Boolean).join(" ");
|
|
14
|
+
}
|
|
15
|
+
function createComponents(api, hooks) {
|
|
16
|
+
function displayName(city, locale) {
|
|
17
|
+
return locale === "en" ? city.nameEn : city.fa;
|
|
18
|
+
}
|
|
19
|
+
function CityCombobox(props) {
|
|
20
|
+
const { value, defaultValue = null, onChange, province, label, placeholder, noResultsText = "شهری پیدا نشد", limit = 8, fuzzy = true, showProvince, locale = "fa", name, id, required, disabled, invalid, dir = "rtl", className, inputProps } = props;
|
|
21
|
+
const baseId = useStableId(id);
|
|
22
|
+
const inputId = `${baseId}-input`;
|
|
23
|
+
const listId = `${baseId}-list`;
|
|
24
|
+
const labelId = `${baseId}-label`;
|
|
25
|
+
const controlled = value !== void 0;
|
|
26
|
+
const [innerId, setInnerId] = react.useState(defaultValue);
|
|
27
|
+
const selectedId = controlled ? value !== null && value !== void 0 ? value : null : innerId;
|
|
28
|
+
const selected = selectedId === null ? void 0 : api.getCityById(selectedId);
|
|
29
|
+
const scope = province === void 0 || province === null || province === "" ? void 0 : api.getProvince(province);
|
|
30
|
+
const scopeId = scope === null || scope === void 0 ? void 0 : scope.id;
|
|
31
|
+
const [text, setText] = react.useState(() => selected ? displayName(selected, locale) : "");
|
|
32
|
+
const [open, setOpen] = react.useState(false);
|
|
33
|
+
const [active, setActive] = react.useState(-1);
|
|
34
|
+
const listRef = react.useRef(null);
|
|
35
|
+
react.useEffect(() => {
|
|
36
|
+
setText(selected ? displayName(selected, locale) : "");
|
|
37
|
+
}, [selected, locale]);
|
|
38
|
+
const results = react.useMemo(() => {
|
|
39
|
+
const found = api.searchCities(text, {
|
|
40
|
+
fuzzy,
|
|
41
|
+
emptyQuery: scopeId === void 0 ? "none" : "all",
|
|
42
|
+
limit: scopeId === void 0 ? limit : void 0
|
|
43
|
+
});
|
|
44
|
+
return (scopeId === void 0 ? found : found.filter((c) => c.provinceId === scopeId)).slice(0, limit);
|
|
45
|
+
}, [
|
|
46
|
+
text,
|
|
47
|
+
fuzzy,
|
|
48
|
+
limit,
|
|
49
|
+
scopeId
|
|
50
|
+
]);
|
|
51
|
+
const withProvince = showProvince !== null && showProvince !== void 0 ? showProvince : scopeId === void 0;
|
|
52
|
+
function select(city) {
|
|
53
|
+
if (!controlled) setInnerId(city ? city.id : null);
|
|
54
|
+
setText(city ? displayName(city, locale) : "");
|
|
55
|
+
setOpen(false);
|
|
56
|
+
setActive(-1);
|
|
57
|
+
onChange === null || onChange === void 0 || onChange(city);
|
|
58
|
+
}
|
|
59
|
+
function restore() {
|
|
60
|
+
setText(selected ? displayName(selected, locale) : "");
|
|
61
|
+
setOpen(false);
|
|
62
|
+
setActive(-1);
|
|
63
|
+
}
|
|
64
|
+
react.useEffect(() => {
|
|
65
|
+
if (active < 0 || !listRef.current) return;
|
|
66
|
+
const option = listRef.current.children[active];
|
|
67
|
+
if (option && typeof option.scrollIntoView === "function") option.scrollIntoView({ block: "nearest" });
|
|
68
|
+
}, [active]);
|
|
69
|
+
function onKeyDown(event) {
|
|
70
|
+
var _inputProps$onKeyDown;
|
|
71
|
+
inputProps === null || inputProps === void 0 || (_inputProps$onKeyDown = inputProps.onKeyDown) === null || _inputProps$onKeyDown === void 0 || _inputProps$onKeyDown.call(inputProps, event);
|
|
72
|
+
if (event.defaultPrevented) return;
|
|
73
|
+
switch (event.key) {
|
|
74
|
+
case "ArrowDown":
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
if (!open) setOpen(true);
|
|
77
|
+
setActive((i) => results.length === 0 ? -1 : (i + 1) % results.length);
|
|
78
|
+
break;
|
|
79
|
+
case "ArrowUp":
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
if (!open) setOpen(true);
|
|
82
|
+
setActive((i) => results.length === 0 ? -1 : i <= 0 ? results.length - 1 : i - 1);
|
|
83
|
+
break;
|
|
84
|
+
case "Home":
|
|
85
|
+
if (open && results.length > 0) {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
setActive(0);
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
case "End":
|
|
91
|
+
if (open && results.length > 0) {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
setActive(results.length - 1);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case "Enter":
|
|
97
|
+
if (open && active >= 0 && results[active]) {
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
select(results[active]);
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
case "Escape":
|
|
103
|
+
if (open) {
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
restore();
|
|
106
|
+
} else if (text) {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
select(null);
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
case "Tab": if (open) restore();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const expanded = open && !disabled;
|
|
115
|
+
const activeId = expanded && active >= 0 ? `${baseId}-option-${active}` : void 0;
|
|
116
|
+
return /* @__PURE__ */ react.createElement("div", {
|
|
117
|
+
className: classNames("ic-field", "ic-combobox", className),
|
|
118
|
+
dir,
|
|
119
|
+
"data-open": expanded ? "" : void 0,
|
|
120
|
+
"data-invalid": invalid ? "" : void 0,
|
|
121
|
+
"data-disabled": disabled ? "" : void 0
|
|
122
|
+
}, label !== void 0 ? /* @__PURE__ */ react.createElement("label", {
|
|
123
|
+
className: "ic-label",
|
|
124
|
+
id: labelId,
|
|
125
|
+
htmlFor: inputId
|
|
126
|
+
}, label) : null, /* @__PURE__ */ react.createElement("div", { className: "ic-control" }, /* @__PURE__ */ react.createElement("input", {
|
|
127
|
+
...inputProps,
|
|
128
|
+
id: inputId,
|
|
129
|
+
className: classNames("ic-input", inputProps === null || inputProps === void 0 ? void 0 : inputProps.className),
|
|
130
|
+
type: "text",
|
|
131
|
+
role: "combobox",
|
|
132
|
+
autoComplete: "off",
|
|
133
|
+
spellCheck: false,
|
|
134
|
+
"aria-autocomplete": "list",
|
|
135
|
+
"aria-expanded": expanded,
|
|
136
|
+
"aria-controls": listId,
|
|
137
|
+
"aria-activedescendant": activeId,
|
|
138
|
+
"aria-invalid": invalid || void 0,
|
|
139
|
+
"aria-required": required || void 0,
|
|
140
|
+
placeholder,
|
|
141
|
+
disabled,
|
|
142
|
+
value: text,
|
|
143
|
+
onChange: (event) => {
|
|
144
|
+
setText(event.target.value);
|
|
145
|
+
setOpen(true);
|
|
146
|
+
setActive(-1);
|
|
147
|
+
},
|
|
148
|
+
onFocus: (event) => {
|
|
149
|
+
var _inputProps$onFocus;
|
|
150
|
+
inputProps === null || inputProps === void 0 || (_inputProps$onFocus = inputProps.onFocus) === null || _inputProps$onFocus === void 0 || _inputProps$onFocus.call(inputProps, event);
|
|
151
|
+
if (scopeId !== void 0 || text) setOpen(true);
|
|
152
|
+
},
|
|
153
|
+
onBlur: (event) => {
|
|
154
|
+
var _inputProps$onBlur;
|
|
155
|
+
inputProps === null || inputProps === void 0 || (_inputProps$onBlur = inputProps.onBlur) === null || _inputProps$onBlur === void 0 || _inputProps$onBlur.call(inputProps, event);
|
|
156
|
+
restore();
|
|
157
|
+
},
|
|
158
|
+
onKeyDown
|
|
159
|
+
}), name ? /* @__PURE__ */ react.createElement("input", {
|
|
160
|
+
type: "hidden",
|
|
161
|
+
name,
|
|
162
|
+
value: selected ? String(selected.id) : ""
|
|
163
|
+
}) : null), /* @__PURE__ */ react.createElement("ul", {
|
|
164
|
+
ref: listRef,
|
|
165
|
+
id: listId,
|
|
166
|
+
className: "ic-listbox",
|
|
167
|
+
role: "listbox",
|
|
168
|
+
"aria-labelledby": label !== void 0 ? labelId : void 0,
|
|
169
|
+
hidden: !expanded
|
|
170
|
+
}, expanded && results.length === 0 ? /* @__PURE__ */ react.createElement("li", {
|
|
171
|
+
className: "ic-empty",
|
|
172
|
+
role: "presentation"
|
|
173
|
+
}, noResultsText) : null, expanded ? results.map((city, index) => /* @__PURE__ */ react.createElement("li", {
|
|
174
|
+
key: city.id,
|
|
175
|
+
id: `${baseId}-option-${index}`,
|
|
176
|
+
className: "ic-option",
|
|
177
|
+
role: "option",
|
|
178
|
+
"aria-selected": (selected === null || selected === void 0 ? void 0 : selected.id) === city.id,
|
|
179
|
+
"data-active": index === active ? "" : void 0,
|
|
180
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
181
|
+
onMouseMove: () => setActive(index),
|
|
182
|
+
onClick: () => select(city)
|
|
183
|
+
}, /* @__PURE__ */ react.createElement("span", { className: "ic-option-name" }, displayName(city, locale)), withProvince ? /* @__PURE__ */ react.createElement("span", { className: "ic-option-meta" }, locale === "en" ? city.provinceNameEn : city.provinceFa) : null)) : null));
|
|
184
|
+
}
|
|
185
|
+
function ProvinceCitySelect(props) {
|
|
186
|
+
const { value, defaultValue, onChange, provinceLabel = "استان", cityLabel = "شهر", provincePlaceholder = "انتخاب استان", cityPlaceholder = "انتخاب شهر", provinceName, cityName, locale = "fa", id, required, disabled, invalid, layout = "row", dir = "rtl", className } = props;
|
|
187
|
+
const baseId = useStableId(id);
|
|
188
|
+
const state = hooks.useProvinceCitySelect({
|
|
189
|
+
value,
|
|
190
|
+
onChange,
|
|
191
|
+
initialProvince: defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.provinceId,
|
|
192
|
+
initialCity: defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.cityId
|
|
193
|
+
});
|
|
194
|
+
const provinceList = state.provinces;
|
|
195
|
+
const sortedProvinces = react.useMemo(() => locale === "en" ? provinceList.slice().sort((a, b) => a.nameEn.localeCompare(b.nameEn, "en")) : provinceList.slice().sort((a, b) => a.fa.localeCompare(b.fa, "fa")), [provinceList, locale]);
|
|
196
|
+
const sortedCities = react.useMemo(() => locale === "en" ? state.cities.slice().sort((a, b) => a.nameEn.localeCompare(b.nameEn, "en")) : state.cities.slice().sort((a, b) => a.fa.localeCompare(b.fa, "fa")), [state.cities, locale]);
|
|
197
|
+
return /* @__PURE__ */ react.createElement("div", {
|
|
198
|
+
className: classNames("ic-group", className),
|
|
199
|
+
dir,
|
|
200
|
+
"data-layout": layout,
|
|
201
|
+
"data-invalid": invalid ? "" : void 0,
|
|
202
|
+
"data-disabled": disabled ? "" : void 0
|
|
203
|
+
}, /* @__PURE__ */ react.createElement("div", { className: "ic-field" }, /* @__PURE__ */ react.createElement("label", {
|
|
204
|
+
className: "ic-label",
|
|
205
|
+
htmlFor: `${baseId}-province`
|
|
206
|
+
}, provinceLabel), /* @__PURE__ */ react.createElement("select", {
|
|
207
|
+
id: `${baseId}-province`,
|
|
208
|
+
className: "ic-select",
|
|
209
|
+
name: provinceName,
|
|
210
|
+
value: state.provinceId === void 0 ? "" : String(state.provinceId),
|
|
211
|
+
required,
|
|
212
|
+
disabled,
|
|
213
|
+
"aria-invalid": invalid || void 0,
|
|
214
|
+
onChange: (event) => state.setProvince(event.target.value === "" ? "" : Number(event.target.value))
|
|
215
|
+
}, /* @__PURE__ */ react.createElement("option", { value: "" }, provincePlaceholder), sortedProvinces.map((p) => /* @__PURE__ */ react.createElement("option", {
|
|
216
|
+
key: p.id,
|
|
217
|
+
value: p.id
|
|
218
|
+
}, locale === "en" ? p.nameEn : p.fa)))), /* @__PURE__ */ react.createElement("div", { className: "ic-field" }, /* @__PURE__ */ react.createElement("label", {
|
|
219
|
+
className: "ic-label",
|
|
220
|
+
htmlFor: `${baseId}-city`
|
|
221
|
+
}, cityLabel), /* @__PURE__ */ react.createElement("select", {
|
|
222
|
+
id: `${baseId}-city`,
|
|
223
|
+
className: "ic-select",
|
|
224
|
+
name: cityName,
|
|
225
|
+
value: state.cityId === void 0 ? "" : String(state.cityId),
|
|
226
|
+
required,
|
|
227
|
+
disabled: disabled || state.provinceId === void 0,
|
|
228
|
+
"aria-invalid": invalid || void 0,
|
|
229
|
+
onChange: (event) => state.setCity(event.target.value === "" ? "" : Number(event.target.value))
|
|
230
|
+
}, /* @__PURE__ */ react.createElement("option", { value: "" }, cityPlaceholder), sortedCities.map((c) => /* @__PURE__ */ react.createElement("option", {
|
|
231
|
+
key: c.id,
|
|
232
|
+
value: c.id
|
|
233
|
+
}, locale === "en" ? c.nameEn : c.fa)))));
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
CityCombobox,
|
|
237
|
+
ProvinceCitySelect
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
Object.defineProperty(exports, "createComponents", {
|
|
241
|
+
enumerable: true,
|
|
242
|
+
get: function() {
|
|
243
|
+
return createComponents;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
//# sourceMappingURL=components-grWmOsaV.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components-grWmOsaV.cjs","names":["React"],"sources":["../src/components.tsx"],"sourcesContent":["import * as React from 'react';\r\nimport type {\r\n CityId,\r\n FlatCity,\r\n IranCities,\r\n IranCitiesHooks,\r\n ProvinceCityValue,\r\n ProvinceId,\r\n Query,\r\n} from './types';\r\n\r\nexport interface CityComboboxProps {\r\n value?: CityId | null;\r\n defaultValue?: CityId | null;\r\n onChange?: (city: FlatCity | null) => void;\r\n province?: Query | null;\r\n label?: React.ReactNode;\r\n placeholder?: string;\r\n noResultsText?: React.ReactNode;\r\n limit?: number;\r\n fuzzy?: boolean;\r\n showProvince?: boolean;\r\n locale?: 'fa' | 'en';\r\n name?: string;\r\n id?: string;\r\n required?: boolean;\r\n disabled?: boolean;\r\n invalid?: boolean;\r\n dir?: 'rtl' | 'ltr' | 'auto';\r\n className?: string;\r\n inputProps?: Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue' | 'onChange'>;\r\n}\r\n\r\nexport interface ProvinceCitySelectProps {\r\n value?: ProvinceCityValue;\r\n defaultValue?: ProvinceCityValue;\r\n onChange?: (value: ProvinceCityValue) => void;\r\n provinceLabel?: React.ReactNode;\r\n cityLabel?: React.ReactNode;\r\n provincePlaceholder?: string;\r\n cityPlaceholder?: string;\r\n provinceName?: string;\r\n cityName?: string;\r\n locale?: 'fa' | 'en';\r\n id?: string;\r\n required?: boolean;\r\n disabled?: boolean;\r\n invalid?: boolean;\r\n layout?: 'row' | 'column';\r\n dir?: 'rtl' | 'ltr' | 'auto';\r\n className?: string;\r\n}\r\n\r\nexport interface IranCitiesComponents {\r\n CityCombobox: (props: CityComboboxProps) => React.ReactElement;\r\n ProvinceCitySelect: (props: ProvinceCitySelectProps) => React.ReactElement;\r\n}\r\n\r\nlet idCounter = 0;\r\n\r\nfunction useStableId(explicit: string | undefined): string {\r\n const reactUseId = (React as unknown as { useId?: () => string }).useId;\r\n const generated = reactUseId ? reactUseId() : undefined;\r\n const [fallback] = React.useState(() => `ic-${++idCounter}`);\r\n return explicit ?? (generated ? `ic-${generated.replace(/:/g, '')}` : fallback);\r\n}\r\n\r\nfunction classNames(...names: (string | false | null | undefined)[]): string {\r\n return names.filter(Boolean).join(' ');\r\n}\r\n\r\nexport function createComponents(api: IranCities, hooks: IranCitiesHooks): IranCitiesComponents {\r\n function displayName(city: FlatCity, locale: 'fa' | 'en'): string {\r\n return locale === 'en' ? city.nameEn : city.fa;\r\n }\r\n\r\n function CityCombobox(props: CityComboboxProps): React.ReactElement {\r\n const {\r\n value,\r\n defaultValue = null,\r\n onChange,\r\n province,\r\n label,\r\n placeholder,\r\n noResultsText = 'شهری پیدا نشد',\r\n limit = 8,\r\n fuzzy = true,\r\n showProvince,\r\n locale = 'fa',\r\n name,\r\n id,\r\n required,\r\n disabled,\r\n invalid,\r\n dir = 'rtl',\r\n className,\r\n inputProps,\r\n } = props;\r\n\r\n const baseId = useStableId(id);\r\n const inputId = `${baseId}-input`;\r\n const listId = `${baseId}-list`;\r\n const labelId = `${baseId}-label`;\r\n\r\n const controlled = value !== undefined;\r\n const [innerId, setInnerId] = React.useState<CityId | null>(defaultValue);\r\n const selectedId = controlled ? value ?? null : innerId;\r\n const selected = selectedId === null ? undefined : api.getCityById(selectedId);\r\n\r\n const scope = province === undefined || province === null || province === '' ? undefined : api.getProvince(province);\r\n const scopeId: ProvinceId | undefined = scope?.id;\r\n\r\n const [text, setText] = React.useState(() => (selected ? displayName(selected, locale) : ''));\r\n const [open, setOpen] = React.useState(false);\r\n const [active, setActive] = React.useState(-1);\r\n const listRef = React.useRef<HTMLUListElement>(null);\r\n\r\n React.useEffect(() => {\r\n setText(selected ? displayName(selected, locale) : '');\r\n }, [selected, locale]);\r\n\r\n const results = React.useMemo(() => {\r\n const found = api.searchCities(text, {\r\n fuzzy,\r\n emptyQuery: scopeId === undefined ? 'none' : 'all',\r\n limit: scopeId === undefined ? limit : undefined,\r\n });\r\n const scoped = scopeId === undefined ? found : found.filter((c) => c.provinceId === scopeId);\r\n return scoped.slice(0, limit);\r\n }, [text, fuzzy, limit, scopeId]);\r\n\r\n const withProvince = showProvince ?? scopeId === undefined;\r\n\r\n function select(city: FlatCity | null): void {\r\n if (!controlled) setInnerId(city ? city.id : null);\r\n setText(city ? displayName(city, locale) : '');\r\n setOpen(false);\r\n setActive(-1);\r\n onChange?.(city);\r\n }\r\n\r\n function restore(): void {\r\n setText(selected ? displayName(selected, locale) : '');\r\n setOpen(false);\r\n setActive(-1);\r\n }\r\n\r\n React.useEffect(() => {\r\n if (active < 0 || !listRef.current) return;\r\n const option = listRef.current.children[active] as HTMLElement | undefined;\r\n if (option && typeof option.scrollIntoView === 'function') option.scrollIntoView({ block: 'nearest' });\r\n }, [active]);\r\n\r\n function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {\r\n inputProps?.onKeyDown?.(event);\r\n if (event.defaultPrevented) return;\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n if (!open) setOpen(true);\r\n setActive((i) => (results.length === 0 ? -1 : (i + 1) % results.length));\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n if (!open) setOpen(true);\r\n setActive((i) => (results.length === 0 ? -1 : i <= 0 ? results.length - 1 : i - 1));\r\n break;\r\n case 'Home':\r\n if (open && results.length > 0) {\r\n event.preventDefault();\r\n setActive(0);\r\n }\r\n break;\r\n case 'End':\r\n if (open && results.length > 0) {\r\n event.preventDefault();\r\n setActive(results.length - 1);\r\n }\r\n break;\r\n case 'Enter':\r\n if (open && active >= 0 && results[active]) {\r\n event.preventDefault();\r\n select(results[active] as FlatCity);\r\n }\r\n break;\r\n case 'Escape':\r\n if (open) {\r\n event.preventDefault();\r\n restore();\r\n } else if (text) {\r\n event.preventDefault();\r\n select(null);\r\n }\r\n break;\r\n case 'Tab':\r\n if (open) restore();\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n const expanded = open && !disabled;\r\n const activeId = expanded && active >= 0 ? `${baseId}-option-${active}` : undefined;\r\n\r\n return (\r\n <div\r\n className={classNames('ic-field', 'ic-combobox', className)}\r\n dir={dir}\r\n data-open={expanded ? '' : undefined}\r\n data-invalid={invalid ? '' : undefined}\r\n data-disabled={disabled ? '' : undefined}\r\n >\r\n {label !== undefined ? (\r\n <label className=\"ic-label\" id={labelId} htmlFor={inputId}>\r\n {label}\r\n </label>\r\n ) : null}\r\n <div className=\"ic-control\">\r\n <input\r\n {...inputProps}\r\n id={inputId}\r\n className={classNames('ic-input', inputProps?.className)}\r\n type=\"text\"\r\n role=\"combobox\"\r\n autoComplete=\"off\"\r\n spellCheck={false}\r\n aria-autocomplete=\"list\"\r\n aria-expanded={expanded}\r\n aria-controls={listId}\r\n aria-activedescendant={activeId}\r\n aria-invalid={invalid || undefined}\r\n aria-required={required || undefined}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n value={text}\r\n onChange={(event) => {\r\n setText(event.target.value);\r\n setOpen(true);\r\n setActive(-1);\r\n }}\r\n onFocus={(event) => {\r\n inputProps?.onFocus?.(event);\r\n if (scopeId !== undefined || text) setOpen(true);\r\n }}\r\n onBlur={(event) => {\r\n inputProps?.onBlur?.(event);\r\n restore();\r\n }}\r\n onKeyDown={onKeyDown}\r\n />\r\n {name ? <input type=\"hidden\" name={name} value={selected ? String(selected.id) : ''} /> : null}\r\n </div>\r\n <ul\r\n ref={listRef}\r\n id={listId}\r\n className=\"ic-listbox\"\r\n role=\"listbox\"\r\n aria-labelledby={label !== undefined ? labelId : undefined}\r\n hidden={!expanded}\r\n >\r\n {expanded && results.length === 0 ? (\r\n <li className=\"ic-empty\" role=\"presentation\">\r\n {noResultsText}\r\n </li>\r\n ) : null}\r\n {expanded\r\n ? results.map((city, index) => (\r\n <li\r\n key={city.id}\r\n id={`${baseId}-option-${index}`}\r\n className=\"ic-option\"\r\n role=\"option\"\r\n aria-selected={selected?.id === city.id}\r\n data-active={index === active ? '' : undefined}\r\n onMouseDown={(event) => event.preventDefault()}\r\n onMouseMove={() => setActive(index)}\r\n onClick={() => select(city)}\r\n >\r\n <span className=\"ic-option-name\">{displayName(city, locale)}</span>\r\n {withProvince ? (\r\n <span className=\"ic-option-meta\">{locale === 'en' ? city.provinceNameEn : city.provinceFa}</span>\r\n ) : null}\r\n </li>\r\n ))\r\n : null}\r\n </ul>\r\n </div>\r\n );\r\n }\r\n\r\n function ProvinceCitySelect(props: ProvinceCitySelectProps): React.ReactElement {\r\n const {\r\n value,\r\n defaultValue,\r\n onChange,\r\n provinceLabel = 'استان',\r\n cityLabel = 'شهر',\r\n provincePlaceholder = 'انتخاب استان',\r\n cityPlaceholder = 'انتخاب شهر',\r\n provinceName,\r\n cityName,\r\n locale = 'fa',\r\n id,\r\n required,\r\n disabled,\r\n invalid,\r\n layout = 'row',\r\n dir = 'rtl',\r\n className,\r\n } = props;\r\n\r\n const baseId = useStableId(id);\r\n const state = hooks.useProvinceCitySelect({\r\n value,\r\n onChange,\r\n initialProvince: defaultValue?.provinceId,\r\n initialCity: defaultValue?.cityId,\r\n });\r\n const provinceList = state.provinces;\r\n const sortedProvinces = React.useMemo(\r\n () =>\r\n locale === 'en'\r\n ? provinceList.slice().sort((a, b) => a.nameEn.localeCompare(b.nameEn, 'en'))\r\n : provinceList.slice().sort((a, b) => a.fa.localeCompare(b.fa, 'fa')),\r\n [provinceList, locale],\r\n );\r\n const sortedCities = React.useMemo(\r\n () =>\r\n locale === 'en'\r\n ? state.cities.slice().sort((a, b) => a.nameEn.localeCompare(b.nameEn, 'en'))\r\n : state.cities.slice().sort((a, b) => a.fa.localeCompare(b.fa, 'fa')),\r\n [state.cities, locale],\r\n );\r\n\r\n return (\r\n <div\r\n className={classNames('ic-group', className)}\r\n dir={dir}\r\n data-layout={layout}\r\n data-invalid={invalid ? '' : undefined}\r\n data-disabled={disabled ? '' : undefined}\r\n >\r\n <div className=\"ic-field\">\r\n <label className=\"ic-label\" htmlFor={`${baseId}-province`}>\r\n {provinceLabel}\r\n </label>\r\n <select\r\n id={`${baseId}-province`}\r\n className=\"ic-select\"\r\n name={provinceName}\r\n value={state.provinceId === undefined ? '' : String(state.provinceId)}\r\n required={required}\r\n disabled={disabled}\r\n aria-invalid={invalid || undefined}\r\n onChange={(event) => state.setProvince(event.target.value === '' ? '' : Number(event.target.value))}\r\n >\r\n <option value=\"\">{provincePlaceholder}</option>\r\n {sortedProvinces.map((p) => (\r\n <option key={p.id} value={p.id}>\r\n {locale === 'en' ? p.nameEn : p.fa}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n <div className=\"ic-field\">\r\n <label className=\"ic-label\" htmlFor={`${baseId}-city`}>\r\n {cityLabel}\r\n </label>\r\n <select\r\n id={`${baseId}-city`}\r\n className=\"ic-select\"\r\n name={cityName}\r\n value={state.cityId === undefined ? '' : String(state.cityId)}\r\n required={required}\r\n disabled={disabled || state.provinceId === undefined}\r\n aria-invalid={invalid || undefined}\r\n onChange={(event) => state.setCity(event.target.value === '' ? '' : Number(event.target.value))}\r\n >\r\n <option value=\"\">{cityPlaceholder}</option>\r\n {sortedCities.map((c) => (\r\n <option key={c.id} value={c.id}>\r\n {locale === 'en' ? c.nameEn : c.fa}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return { CityCombobox, ProvinceCitySelect };\r\n}\r\n"],"mappings":";;;;AA0DA,IAAI,YAAY;AAEhB,SAAS,YAAY,UAAsC;CACzD,MAAM,aAAcA,MAA8C;CAClE,MAAM,YAAY,aAAa,WAAW,IAAI,KAAA;CAC9C,MAAM,CAAC,YAAYA,MAAM,eAAe,MAAM,EAAE,WAAW;CAC3D,OAAO,aAAA,QAAA,aAAA,KAAA,IAAA,WAAa,YAAY,MAAM,UAAU,QAAQ,MAAM,EAAE,MAAM;AACxE;AAEA,SAAS,WAAW,GAAG,OAAsD;CAC3E,OAAO,MAAM,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AACvC;AAEA,SAAgB,iBAAiB,KAAiB,OAA8C;CAC9F,SAAS,YAAY,MAAgB,QAA6B;EAChE,OAAO,WAAW,OAAO,KAAK,SAAS,KAAK;CAC9C;CAEA,SAAS,aAAa,OAA8C;EAClE,MAAM,EACJ,OACA,eAAe,MACf,UACA,UACA,OACA,aACA,gBAAgB,iBAChB,QAAQ,GACR,QAAQ,MACR,cACA,SAAS,MACT,MACA,IACA,UACA,UACA,SACA,MAAM,OACN,WACA,eACE;EAEJ,MAAM,SAAS,YAAY,EAAE;EAC7B,MAAM,UAAU,GAAG,OAAO;EAC1B,MAAM,SAAS,GAAG,OAAO;EACzB,MAAM,UAAU,GAAG,OAAO;EAE1B,MAAM,aAAa,UAAU,KAAA;EAC7B,MAAM,CAAC,SAAS,cAAcA,MAAM,SAAwB,YAAY;EACxE,MAAM,aAAa,aAAa,UAAA,QAAA,UAAA,KAAA,IAAA,QAAS,OAAO;EAChD,MAAM,WAAW,eAAe,OAAO,KAAA,IAAY,IAAI,YAAY,UAAU;EAE7E,MAAM,QAAQ,aAAa,KAAA,KAAa,aAAa,QAAQ,aAAa,KAAK,KAAA,IAAY,IAAI,YAAY,QAAQ;EACnH,MAAM,UAAA,UAAA,QAAA,UAAA,KAAA,IAAA,KAAA,IAAkC,MAAO;EAE/C,MAAM,CAAC,MAAM,WAAWA,MAAM,eAAgB,WAAW,YAAY,UAAU,MAAM,IAAI,EAAG;EAC5F,MAAM,CAAC,MAAM,WAAWA,MAAM,SAAS,KAAK;EAC5C,MAAM,CAAC,QAAQ,aAAaA,MAAM,SAAS,EAAE;EAC7C,MAAM,UAAUA,MAAM,OAAyB,IAAI;EAEnDA,MAAM,gBAAgB;GACpB,QAAQ,WAAW,YAAY,UAAU,MAAM,IAAI,EAAE;EACvD,GAAG,CAAC,UAAU,MAAM,CAAC;EAErB,MAAM,UAAUA,MAAM,cAAc;GAClC,MAAM,QAAQ,IAAI,aAAa,MAAM;IACnC;IACA,YAAY,YAAY,KAAA,IAAY,SAAS;IAC7C,OAAO,YAAY,KAAA,IAAY,QAAQ,KAAA;GACzC,CAAC;GAED,QADe,YAAY,KAAA,IAAY,QAAQ,MAAM,QAAQ,MAAM,EAAE,eAAe,OAAO,EAAA,CAC7E,MAAM,GAAG,KAAK;EAC9B,GAAG;GAAC;GAAM;GAAO;GAAO;EAAO,CAAC;EAEhC,MAAM,eAAe,iBAAA,QAAA,iBAAA,KAAA,IAAA,eAAgB,YAAY,KAAA;EAEjD,SAAS,OAAO,MAA6B;GAC3C,IAAI,CAAC,YAAY,WAAW,OAAO,KAAK,KAAK,IAAI;GACjD,QAAQ,OAAO,YAAY,MAAM,MAAM,IAAI,EAAE;GAC7C,QAAQ,KAAK;GACb,UAAU,EAAE;GACZ,aAAA,QAAA,aAAA,KAAA,KAAA,SAAW,IAAI;EACjB;EAEA,SAAS,UAAgB;GACvB,QAAQ,WAAW,YAAY,UAAU,MAAM,IAAI,EAAE;GACrD,QAAQ,KAAK;GACb,UAAU,EAAE;EACd;EAEAA,MAAM,gBAAgB;GACpB,IAAI,SAAS,KAAK,CAAC,QAAQ,SAAS;GACpC,MAAM,SAAS,QAAQ,QAAQ,SAAS;GACxC,IAAI,UAAU,OAAO,OAAO,mBAAmB,YAAY,OAAO,eAAe,EAAE,OAAO,UAAU,CAAC;EACvG,GAAG,CAAC,MAAM,CAAC;EAEX,SAAS,UAAU,OAAoD;;GACrE,eAAA,QAAA,eAAA,KAAA,MAAA,wBAAA,WAAY,eAAA,QAAA,0BAAA,KAAA,KAAA,sBAAA,KAAA,YAAY,KAAK;GAC7B,IAAI,MAAM,kBAAkB;GAC5B,QAAQ,MAAM,KAAd;IACE,KAAK;KACH,MAAM,eAAe;KACrB,IAAI,CAAC,MAAM,QAAQ,IAAI;KACvB,WAAW,MAAO,QAAQ,WAAW,IAAI,MAAM,IAAI,KAAK,QAAQ,MAAO;KACvE;IACF,KAAK;KACH,MAAM,eAAe;KACrB,IAAI,CAAC,MAAM,QAAQ,IAAI;KACvB,WAAW,MAAO,QAAQ,WAAW,IAAI,KAAK,KAAK,IAAI,QAAQ,SAAS,IAAI,IAAI,CAAE;KAClF;IACF,KAAK;KACH,IAAI,QAAQ,QAAQ,SAAS,GAAG;MAC9B,MAAM,eAAe;MACrB,UAAU,CAAC;KACb;KACA;IACF,KAAK;KACH,IAAI,QAAQ,QAAQ,SAAS,GAAG;MAC9B,MAAM,eAAe;MACrB,UAAU,QAAQ,SAAS,CAAC;KAC9B;KACA;IACF,KAAK;KACH,IAAI,QAAQ,UAAU,KAAK,QAAQ,SAAS;MAC1C,MAAM,eAAe;MACrB,OAAO,QAAQ,OAAmB;KACpC;KACA;IACF,KAAK;KACH,IAAI,MAAM;MACR,MAAM,eAAe;MACrB,QAAQ;KACV,OAAO,IAAI,MAAM;MACf,MAAM,eAAe;MACrB,OAAO,IAAI;KACb;KACA;IACF,KAAK,OACH,IAAI,MAAM,QAAQ;GAItB;EACF;EAEA,MAAM,WAAW,QAAQ,CAAC;EAC1B,MAAM,WAAW,YAAY,UAAU,IAAI,GAAG,OAAO,UAAU,WAAW,KAAA;EAE1E,OACE,sBAAA,cAAC,OAAD;GACE,WAAW,WAAW,YAAY,eAAe,SAAS;GACrD;GACL,aAAW,WAAW,KAAK,KAAA;GAC3B,gBAAc,UAAU,KAAK,KAAA;GAC7B,iBAAe,WAAW,KAAK,KAAA;EA4E5B,GA1EF,UAAU,KAAA,IACT,sBAAA,cAAC,SAAD;GAAO,WAAU;GAAW,IAAI;GAAS,SAAS;EAE3C,GADJ,KACI,IACL,MACJ,sBAAA,cAAC,OAAD,EAAK,WAAU,aAkCV,GAjCH,sBAAA,cAAC,SAAD;GACE,GAAI;GACJ,IAAI;GACJ,WAAW,WAAW,YAAA,eAAA,QAAA,eAAA,KAAA,IAAA,KAAA,IAAY,WAAY,SAAS;GACvD,MAAK;GACL,MAAK;GACL,cAAa;GACb,YAAY;GACZ,qBAAkB;GAClB,iBAAe;GACf,iBAAe;GACf,yBAAuB;GACvB,gBAAc,WAAW,KAAA;GACzB,iBAAe,YAAY,KAAA;GACd;GACH;GACV,OAAO;GACP,WAAW,UAAU;IACnB,QAAQ,MAAM,OAAO,KAAK;IAC1B,QAAQ,IAAI;IACZ,UAAU,EAAE;GACd;GACA,UAAU,UAAU;;IAClB,eAAA,QAAA,eAAA,KAAA,MAAA,sBAAA,WAAY,aAAA,QAAA,wBAAA,KAAA,KAAA,oBAAA,KAAA,YAAU,KAAK;IAC3B,IAAI,YAAY,KAAA,KAAa,MAAM,QAAQ,IAAI;GACjD;GACA,SAAS,UAAU;;IACjB,eAAA,QAAA,eAAA,KAAA,MAAA,qBAAA,WAAY,YAAA,QAAA,uBAAA,KAAA,KAAA,mBAAA,KAAA,YAAS,KAAK;IAC1B,QAAQ;GACV;GACW;EACZ,CAAA,GACA,OAAO,sBAAA,cAAC,SAAD;GAAO,MAAK;GAAe;GAAM,OAAO,WAAW,OAAO,SAAS,EAAE,IAAI;EAAK,CAAA,IAAI,IACvF,GACL,sBAAA,cAAC,MAAD;GACE,KAAK;GACL,IAAI;GACJ,WAAU;GACV,MAAK;GACL,mBAAiB,UAAU,KAAA,IAAY,UAAU,KAAA;GACjD,QAAQ,CAAC;EA2BP,GAzBD,YAAY,QAAQ,WAAW,IAC9B,sBAAA,cAAC,MAAD;GAAI,WAAU;GAAW,MAAK;EAE1B,GADD,aACC,IACF,MACH,WACG,QAAQ,KAAK,MAAM,UACjB,sBAAA,cAAC,MAAD;GACE,KAAK,KAAK;GACV,IAAI,GAAG,OAAO,UAAU;GACxB,WAAU;GACV,MAAK;GACL,kBAAA,aAAA,QAAA,aAAA,KAAA,IAAA,KAAA,IAAe,SAAU,QAAO,KAAK;GACrC,eAAa,UAAU,SAAS,KAAK,KAAA;GACrC,cAAc,UAAU,MAAM,eAAe;GAC7C,mBAAmB,UAAU,KAAK;GAClC,eAAe,OAAO,IAAI;EAMxB,GAJF,sBAAA,cAAC,QAAD,EAAM,WAAU,iBAAkD,GAAhC,YAAY,MAAM,MAAM,CAAQ,GACjE,eACC,sBAAA,cAAC,QAAD,EAAM,WAAU,iBAAgF,GAA9D,WAAW,OAAO,KAAK,iBAAiB,KAAK,UAAiB,IAC9F,IACF,CACL,IACD,IACF,CACD;CAET;CAEA,SAAS,mBAAmB,OAAoD;EAC9E,MAAM,EACJ,OACA,cACA,UACA,gBAAgB,SAChB,YAAY,OACZ,sBAAsB,gBACtB,kBAAkB,cAClB,cACA,UACA,SAAS,MACT,IACA,UACA,UACA,SACA,SAAS,OACT,MAAM,OACN,cACE;EAEJ,MAAM,SAAS,YAAY,EAAE;EAC7B,MAAM,QAAQ,MAAM,sBAAsB;GACxC;GACA;GACA,iBAAA,iBAAA,QAAA,iBAAA,KAAA,IAAA,KAAA,IAAiB,aAAc;GAC/B,aAAA,iBAAA,QAAA,iBAAA,KAAA,IAAA,KAAA,IAAa,aAAc;EAC7B,CAAC;EACD,MAAM,eAAe,MAAM;EAC3B,MAAM,kBAAkBA,MAAM,cAE1B,WAAW,OACP,aAAa,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,cAAc,EAAE,QAAQ,IAAI,CAAC,IAC1E,aAAa,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,IAAI,IAAI,CAAC,GACxE,CAAC,cAAc,MAAM,CACvB;EACA,MAAM,eAAeA,MAAM,cAEvB,WAAW,OACP,MAAM,OAAO,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,cAAc,EAAE,QAAQ,IAAI,CAAC,IAC1E,MAAM,OAAO,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,IAAI,IAAI,CAAC,GACxE,CAAC,MAAM,QAAQ,MAAM,CACvB;EAEA,OACE,sBAAA,cAAC,OAAD;GACE,WAAW,WAAW,YAAY,SAAS;GACtC;GACL,eAAa;GACb,gBAAc,UAAU,KAAK,KAAA;GAC7B,iBAAe,WAAW,KAAK,KAAA;EA8C5B,GA5CH,sBAAA,cAAC,OAAD,EAAK,WAAU,WAqBV,GApBH,sBAAA,cAAC,SAAD;GAAO,WAAU;GAAW,SAAS,GAAG,OAAO;EAExC,GADJ,aACI,GACP,sBAAA,cAAC,UAAD;GACE,IAAI,GAAG,OAAO;GACd,WAAU;GACV,MAAM;GACN,OAAO,MAAM,eAAe,KAAA,IAAY,KAAK,OAAO,MAAM,UAAU;GAC1D;GACA;GACV,gBAAc,WAAW,KAAA;GACzB,WAAW,UAAU,MAAM,YAAY,MAAM,OAAO,UAAU,KAAK,KAAK,OAAO,MAAM,OAAO,KAAK,CAAC;EAQ5F,GANN,sBAAA,cAAC,UAAD,EAAQ,OAAM,GAAgC,GAA5B,mBAA4B,GAC7C,gBAAgB,KAAK,MACpB,sBAAA,cAAC,UAAD;GAAQ,KAAK,EAAE;GAAI,OAAO,EAAE;EAEpB,GADL,WAAW,OAAO,EAAE,SAAS,EAAE,EAC1B,CACT,CACK,CACL,GACL,sBAAA,cAAC,OAAD,EAAK,WAAU,WAqBV,GApBH,sBAAA,cAAC,SAAD;GAAO,WAAU;GAAW,SAAS,GAAG,OAAO;EAExC,GADJ,SACI,GACP,sBAAA,cAAC,UAAD;GACE,IAAI,GAAG,OAAO;GACd,WAAU;GACV,MAAM;GACN,OAAO,MAAM,WAAW,KAAA,IAAY,KAAK,OAAO,MAAM,MAAM;GAClD;GACV,UAAU,YAAY,MAAM,eAAe,KAAA;GAC3C,gBAAc,WAAW,KAAA;GACzB,WAAW,UAAU,MAAM,QAAQ,MAAM,OAAO,UAAU,KAAK,KAAK,OAAO,MAAM,OAAO,KAAK,CAAC;EAQxF,GANN,sBAAA,cAAC,UAAD,EAAQ,OAAM,GAA4B,GAAxB,eAAwB,GACzC,aAAa,KAAK,MACjB,sBAAA,cAAC,UAAD;GAAQ,KAAK,EAAE;GAAI,OAAO,EAAE;EAEpB,GADL,WAAW,OAAO,EAAE,SAAS,EAAE,EAC1B,CACT,CACK,CACL,CACF;CAET;CAEA,OAAO;EAAE;EAAc;CAAmB;AAC5C"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
:where(.ic-field, .ic-group) {
|
|
2
|
+
--ic-font: inherit;
|
|
3
|
+
--ic-font-size: 0.9375rem;
|
|
4
|
+
--ic-line-height: 1.5;
|
|
5
|
+
--ic-radius: 0.625rem;
|
|
6
|
+
--ic-gap: 0.75rem;
|
|
7
|
+
--ic-height: 2.75rem;
|
|
8
|
+
--ic-padding-inline: 0.875rem;
|
|
9
|
+
--ic-bg: #ffffff;
|
|
10
|
+
--ic-fg: #0f172a;
|
|
11
|
+
--ic-muted: #64748b;
|
|
12
|
+
--ic-border: #cbd5e1;
|
|
13
|
+
--ic-border-hover: #94a3b8;
|
|
14
|
+
--ic-accent: #0a7f5a;
|
|
15
|
+
--ic-accent-soft: rgba(10, 127, 90, 0.1);
|
|
16
|
+
--ic-ring: rgba(10, 127, 90, 0.28);
|
|
17
|
+
--ic-danger: #dc2626;
|
|
18
|
+
--ic-danger-ring: rgba(220, 38, 38, 0.22);
|
|
19
|
+
--ic-disabled-bg: #f1f5f9;
|
|
20
|
+
--ic-popover-bg: #ffffff;
|
|
21
|
+
--ic-shadow: 0 12px 32px -8px rgba(15, 23, 42, 0.18), 0 2px 6px rgba(15, 23, 42, 0.06);
|
|
22
|
+
--ic-listbox-max-height: 18rem;
|
|
23
|
+
--ic-transition: 150ms ease;
|
|
24
|
+
color-scheme: light;
|
|
25
|
+
font-family: var(--ic-font);
|
|
26
|
+
font-size: var(--ic-font-size);
|
|
27
|
+
line-height: var(--ic-line-height);
|
|
28
|
+
color: var(--ic-fg);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@media (prefers-color-scheme: dark) {
|
|
32
|
+
:where(.ic-field, .ic-group):not([data-theme='light'] *, [data-theme='light']) {
|
|
33
|
+
--ic-bg: #0f172a;
|
|
34
|
+
--ic-fg: #e2e8f0;
|
|
35
|
+
--ic-muted: #94a3b8;
|
|
36
|
+
--ic-border: #334155;
|
|
37
|
+
--ic-border-hover: #475569;
|
|
38
|
+
--ic-accent: #34d399;
|
|
39
|
+
--ic-accent-soft: rgba(52, 211, 153, 0.14);
|
|
40
|
+
--ic-ring: rgba(52, 211, 153, 0.32);
|
|
41
|
+
--ic-danger: #f87171;
|
|
42
|
+
--ic-danger-ring: rgba(248, 113, 113, 0.28);
|
|
43
|
+
--ic-disabled-bg: #1e293b;
|
|
44
|
+
--ic-popover-bg: #111c33;
|
|
45
|
+
--ic-shadow: 0 16px 40px -8px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
|
|
46
|
+
color-scheme: dark;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:where([data-theme='dark'] .ic-field, [data-theme='dark'] .ic-group, .ic-field[data-theme='dark'], .ic-group[data-theme='dark']) {
|
|
51
|
+
--ic-bg: #0f172a;
|
|
52
|
+
--ic-fg: #e2e8f0;
|
|
53
|
+
--ic-muted: #94a3b8;
|
|
54
|
+
--ic-border: #334155;
|
|
55
|
+
--ic-border-hover: #475569;
|
|
56
|
+
--ic-accent: #34d399;
|
|
57
|
+
--ic-accent-soft: rgba(52, 211, 153, 0.14);
|
|
58
|
+
--ic-ring: rgba(52, 211, 153, 0.32);
|
|
59
|
+
--ic-danger: #f87171;
|
|
60
|
+
--ic-danger-ring: rgba(248, 113, 113, 0.28);
|
|
61
|
+
--ic-disabled-bg: #1e293b;
|
|
62
|
+
--ic-popover-bg: #111c33;
|
|
63
|
+
--ic-shadow: 0 16px 40px -8px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
|
|
64
|
+
color-scheme: dark;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.ic-group > .ic-field,
|
|
68
|
+
.ic-field > .ic-label,
|
|
69
|
+
.ic-field > .ic-control,
|
|
70
|
+
.ic-field > .ic-listbox,
|
|
71
|
+
.ic-listbox > .ic-option,
|
|
72
|
+
.ic-listbox > .ic-empty {
|
|
73
|
+
margin: 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:where(.ic-group) {
|
|
77
|
+
display: grid;
|
|
78
|
+
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
|
79
|
+
gap: var(--ic-gap);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:where(.ic-group[data-layout='column']) {
|
|
83
|
+
grid-template-columns: minmax(0, 1fr);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:where(.ic-field) {
|
|
87
|
+
position: relative;
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-direction: column;
|
|
90
|
+
gap: 0.375rem;
|
|
91
|
+
min-inline-size: 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
:where(.ic-label) {
|
|
95
|
+
font-size: 0.875em;
|
|
96
|
+
font-weight: 500;
|
|
97
|
+
color: var(--ic-fg);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
:where(.ic-control) {
|
|
101
|
+
position: relative;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
:where(.ic-input, .ic-select) {
|
|
105
|
+
box-sizing: border-box;
|
|
106
|
+
inline-size: 100%;
|
|
107
|
+
block-size: var(--ic-height);
|
|
108
|
+
margin: 0;
|
|
109
|
+
padding-block: 0;
|
|
110
|
+
padding-inline: var(--ic-padding-inline);
|
|
111
|
+
font: inherit;
|
|
112
|
+
color: var(--ic-fg);
|
|
113
|
+
background-color: var(--ic-bg);
|
|
114
|
+
border: 1px solid var(--ic-border);
|
|
115
|
+
border-radius: var(--ic-radius);
|
|
116
|
+
outline: none;
|
|
117
|
+
transition: border-color var(--ic-transition), box-shadow var(--ic-transition), background-color var(--ic-transition);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
:where(.ic-input)::placeholder {
|
|
121
|
+
color: var(--ic-muted);
|
|
122
|
+
opacity: 1;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
:where(.ic-select) {
|
|
126
|
+
appearance: none;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
padding-inline-end: calc(var(--ic-padding-inline) + 1.25rem);
|
|
129
|
+
background-image: linear-gradient(45deg, transparent 50%, var(--ic-muted) 50%),
|
|
130
|
+
linear-gradient(135deg, var(--ic-muted) 50%, transparent 50%);
|
|
131
|
+
background-repeat: no-repeat;
|
|
132
|
+
background-size: 0.3125rem 0.3125rem, 0.3125rem 0.3125rem;
|
|
133
|
+
background-position: right calc(var(--ic-padding-inline) + 0.3125rem) center, right var(--ic-padding-inline) center;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
:where([dir='rtl']) :where(.ic-select),
|
|
137
|
+
:where(.ic-select[dir='rtl']) {
|
|
138
|
+
background-position: left var(--ic-padding-inline) center, left calc(var(--ic-padding-inline) + 0.3125rem) center;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
:where(.ic-input, .ic-select):hover:not(:disabled) {
|
|
142
|
+
border-color: var(--ic-border-hover);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
:where(.ic-input, .ic-select):focus-visible,
|
|
146
|
+
:where(.ic-combobox[data-open]) :where(.ic-input) {
|
|
147
|
+
border-color: var(--ic-accent);
|
|
148
|
+
box-shadow: 0 0 0 3px var(--ic-ring);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
:where(.ic-input, .ic-select):disabled {
|
|
152
|
+
cursor: not-allowed;
|
|
153
|
+
color: var(--ic-muted);
|
|
154
|
+
background-color: var(--ic-disabled-bg);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
:where([data-invalid]) :where(.ic-input, .ic-select),
|
|
158
|
+
:where(.ic-input, .ic-select)[aria-invalid='true'] {
|
|
159
|
+
border-color: var(--ic-danger);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
:where([data-invalid]) :where(.ic-input, .ic-select):focus-visible,
|
|
163
|
+
:where(.ic-input, .ic-select)[aria-invalid='true']:focus-visible {
|
|
164
|
+
box-shadow: 0 0 0 3px var(--ic-danger-ring);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
:where(.ic-listbox) {
|
|
168
|
+
position: absolute;
|
|
169
|
+
inset-inline: 0;
|
|
170
|
+
inset-block-start: calc(100% + 0.375rem);
|
|
171
|
+
z-index: 50;
|
|
172
|
+
box-sizing: border-box;
|
|
173
|
+
max-block-size: var(--ic-listbox-max-height);
|
|
174
|
+
margin: 0;
|
|
175
|
+
padding: 0.3125rem;
|
|
176
|
+
overflow-y: auto;
|
|
177
|
+
overscroll-behavior: contain;
|
|
178
|
+
list-style: none;
|
|
179
|
+
background-color: var(--ic-popover-bg);
|
|
180
|
+
border: 1px solid var(--ic-border);
|
|
181
|
+
border-radius: var(--ic-radius);
|
|
182
|
+
box-shadow: var(--ic-shadow);
|
|
183
|
+
animation: ic-pop var(--ic-transition);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
:where(.ic-listbox)[hidden] {
|
|
187
|
+
display: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
:where(.ic-option) {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: baseline;
|
|
193
|
+
justify-content: space-between;
|
|
194
|
+
gap: 0.75rem;
|
|
195
|
+
padding-block: 0.5rem;
|
|
196
|
+
padding-inline: 0.625rem;
|
|
197
|
+
border-radius: calc(var(--ic-radius) - 0.25rem);
|
|
198
|
+
cursor: pointer;
|
|
199
|
+
user-select: none;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
:where(.ic-option)[data-active] {
|
|
203
|
+
background-color: var(--ic-accent-soft);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
:where(.ic-option)[aria-selected='true'] {
|
|
207
|
+
font-weight: 600;
|
|
208
|
+
color: var(--ic-accent);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
:where(.ic-option-meta) {
|
|
212
|
+
flex-shrink: 0;
|
|
213
|
+
font-size: 0.8125em;
|
|
214
|
+
font-weight: 400;
|
|
215
|
+
color: var(--ic-muted);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
:where(.ic-empty) {
|
|
219
|
+
padding-block: 0.75rem;
|
|
220
|
+
padding-inline: 0.625rem;
|
|
221
|
+
color: var(--ic-muted);
|
|
222
|
+
text-align: center;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@keyframes ic-pop {
|
|
226
|
+
from {
|
|
227
|
+
opacity: 0;
|
|
228
|
+
transform: translateY(-0.25rem);
|
|
229
|
+
}
|
|
230
|
+
to {
|
|
231
|
+
opacity: 1;
|
|
232
|
+
transform: translateY(0);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@media (prefers-reduced-motion: reduce) {
|
|
237
|
+
:where(.ic-input, .ic-select, .ic-listbox) {
|
|
238
|
+
transition: none;
|
|
239
|
+
animation: none;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@media (forced-colors: active) {
|
|
244
|
+
:where(.ic-option)[data-active] {
|
|
245
|
+
outline: 2px solid Highlight;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
:where(.ic-input, .ic-select):focus-visible {
|
|
249
|
+
outline: 2px solid Highlight;
|
|
250
|
+
}
|
|
251
|
+
}
|