@vtaits/react-form-schema-ui-vkui-v5
Version:
VKUI fields for @vtaits/form-schema
990 lines (979 loc) • 26.5 kB
JavaScript
// src/edit/VKUIProvider.tsx
import {
BaseUIContext
} from "@vtaits/react-form-schema-base-ui";
import { useMemo } from "react";
// src/edit/contextValue.tsx
import {
Icon12Add,
Icon16Attach,
Icon16Delete,
Icon16DocumentOutline
} from "@vkontakte/icons";
import {
Button,
CardGrid,
Checkbox,
unstable_ChipsSelect as ChipsSelect,
ContentCard,
CustomSelectOption,
DateInput,
File,
Footnote,
FormItem,
FormStatus,
IconButton,
Input,
Radio,
Select,
Textarea,
Title
} from "@vkontakte/vkui";
import {
ChipsAsyncPaginate,
CustomAsyncPaginate
} from "select-async-paginate-vkui-v5";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
function defaultRenderChipSelectOption(renderProps) {
return /* @__PURE__ */ jsx(CustomSelectOption, { ...renderProps });
}
function getContextValue({
cardMode
}) {
return {
renderAsyncSelect: ({
clearable,
disabled,
autoFocus,
additional,
initialAdditional,
optionsCacheRef,
loadOptions,
placeholder,
value,
onChange,
getOptionValue,
getOptionLabel,
renderOption
}) => /* @__PURE__ */ jsx(
CustomAsyncPaginate,
{
allowClearButton: clearable,
autoFocus,
disabled,
onChange: (event) => {
const nextValue = event.target.value;
const selectedOption = typeof nextValue === "string" || typeof nextValue === "number" ? optionsCacheRef.current[nextValue] : null;
onChange(selectedOption);
},
placeholder,
valueWithLabel: value ? {
value: getOptionValue(value),
label: getOptionLabel(value),
source: value
} : null,
additional,
initialAdditional,
loadOptions,
searchable: true,
renderOption: renderOption ? (renderProps) => renderOption(
renderProps.option,
renderProps
) : void 0
}
),
renderAsyncMultiSelect: ({
disabled,
autoFocus,
additional,
initialAdditional,
loadOptions,
value,
onChange,
getOptionLabel,
getOptionValue,
renderOption
}) => /* @__PURE__ */ jsx(
ChipsAsyncPaginate,
{
autoFocus,
disabled,
onChange,
value: value ? value.map((option) => ({
label: getOptionLabel(option),
value: getOptionValue(option),
source: option
})) : [],
additional,
initialAdditional,
loadOptions,
renderOption: renderOption ? (renderProps) => renderOption(
renderProps.option,
renderProps
) : defaultRenderChipSelectOption
}
),
renderCheckbox: ({
checked,
disabled,
autoFocus,
name,
onChange,
children
}) => /* @__PURE__ */ jsx(
Checkbox,
{
autoFocus,
disabled,
name,
checked,
onChange: (event) => {
onChange(event.target.checked);
},
children
}
),
renderCheckboxGroup: ({
disabled,
name,
value,
onChange,
options,
getOptionLabel,
getOptionValue
}) => {
const selectedValuesSet = new Set(
(value || []).map((option) => getOptionValue(option))
);
return /* @__PURE__ */ jsx("div", { children: options.map((option) => {
const optionValue = getOptionValue(option);
const checked = selectedValuesSet.has(optionValue);
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Checkbox,
{
checked,
disabled,
name,
onChange: () => {
if (checked) {
onChange(
value.filter(
(valueItem) => getOptionValue(valueItem) !== optionValue
)
);
} else {
onChange([...value, option]);
}
},
children: getOptionLabel(option)
}
) }, optionValue);
}) });
},
renderDatePicker: ({ disabled, autoFocus, name, onChange, value }) => /* @__PURE__ */ jsx("div", { style: { display: "flex" }, children: /* @__PURE__ */ jsx(
DateInput,
{
autoFocus,
disabled,
name,
value: value || void 0,
onChange
}
) }),
renderDateTimePicker: ({ disabled, autoFocus, name, onChange, value }) => /* @__PURE__ */ jsx("div", { style: { display: "flex" }, children: /* @__PURE__ */ jsx(
DateInput,
{
autoFocus,
disabled,
name,
enableTime: true,
value: value || void 0,
onChange
}
) }),
renderFileInput: ({
accept,
children,
disabled,
name,
onSelectFile,
selectedFile
}) => /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
File,
{
accept,
before: /* @__PURE__ */ jsx(Icon16DocumentOutline, { role: "presentation" }),
disabled,
name,
mode: "secondary",
onChange: (event) => {
onSelectFile(event.target.files?.[0] || null);
event.target.value = "";
},
children
}
),
selectedFile && /* @__PURE__ */ jsxs(
"p",
{
style: {
display: "flex",
alignItems: "center",
gap: "10px"
},
children: [
/* @__PURE__ */ jsx(Icon16Attach, {}),
selectedFile,
/* @__PURE__ */ jsx(
IconButton,
{
disabled,
label: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
onClick: () => {
onSelectFile(null);
},
children: /* @__PURE__ */ jsx(Icon16Delete, {})
}
)
]
}
)
] }),
renderForm: ({ actions, error, fields, formProps, title }) => /* @__PURE__ */ jsxs("form", { ...formProps, children: [
title && /* @__PURE__ */ jsx(
Title,
{
level: "3",
style: {
marginBottom: "30px"
},
children: title
}
),
fields,
error && /* @__PURE__ */ jsx(
"div",
{
style: {
marginTop: "20px",
marginBottom: "20px"
},
children: /* @__PURE__ */ jsx(FormStatus, { mode: "error", "data-testid": "@@form/error", children: error })
}
),
/* @__PURE__ */ jsx(FormItem, { children: actions })
] }),
renderInput: ({
disabled,
inputProps: { ref, size, ...inputProps } = {},
autoFocus,
onChange,
options,
name
}) => {
const wrappedOnChange = (event) => {
onChange(event.target.value);
};
if (options && options.length > 0) {
const listId = `${name}-datalist`;
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
Input,
{
autoFocus,
disabled,
list: `${name}-datalist`,
name,
...inputProps,
onChange: wrappedOnChange
}
),
/* @__PURE__ */ jsx("datalist", { id: listId, children: options.map((option) => /* @__PURE__ */ jsx("option", { value: option }, option)) })
] });
}
return /* @__PURE__ */ jsx(
Input,
{
autoFocus,
disabled,
name,
...inputProps,
onChange: wrappedOnChange
}
);
},
renderListAddButton: ({ children, disabled, onClick }) => /* @__PURE__ */ jsx(
Button,
{
before: /* @__PURE__ */ jsx(Icon12Add, {}),
disabled,
mode: "link",
onClick,
"data-testid": "@@list/add",
children
}
),
renderListItemWrapper: ({
children,
compact,
disabled,
handleRemove,
title,
name
}) => {
const testId = `@@list-item/${name}`;
if (compact) {
return /* @__PURE__ */ jsxs("div", { "data-testid": testId, children: [
title && /* @__PURE__ */ jsx("div", { children: title }),
/* @__PURE__ */ jsxs(
"div",
{
style: {
display: "grid",
gap: 6,
gridTemplateColumns: "1fr auto",
alignItems: "center"
},
children: [
/* @__PURE__ */ jsx(
"div",
{
style: {
marginLeft: -12,
marginRight: -12
},
children
}
),
handleRemove && /* @__PURE__ */ jsx(
IconButton,
{
disabled,
label: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
onClick: handleRemove,
children: /* @__PURE__ */ jsx(Icon16Delete, {})
}
)
]
}
)
] });
}
return /* @__PURE__ */ jsx(CardGrid, { size: "l", "data-testid": testId, children: /* @__PURE__ */ jsx(
ContentCard,
{
mode: cardMode,
header: /* @__PURE__ */ jsxs(
"div",
{
style: {
display: "flex",
alignItems: "center",
justifyContent: "space-between"
},
children: [
/* @__PURE__ */ jsx("div", { children: title }),
handleRemove && /* @__PURE__ */ jsx(
IconButton,
{
disabled,
label: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
onClick: handleRemove,
children: /* @__PURE__ */ jsx(Icon16Delete, {})
}
)
]
}
),
text: children
}
) });
},
renderListWrapper: ({
actions,
error,
hint,
items,
label,
name,
required
}) => {
return /* @__PURE__ */ jsx(
FormItem,
{
top: required ? /* @__PURE__ */ jsxs(Fragment, { children: [
label,
/* @__PURE__ */ jsx(
"span",
{
style: {
color: "#e64646"
},
children: " *"
}
)
] }) : label,
bottom: /* @__PURE__ */ jsxs(Fragment, { children: [
hint && /* @__PURE__ */ jsx(
"p",
{
style: {
color: "gray"
},
children: hint
}
),
actions && /* @__PURE__ */ jsx(
"div",
{
style: {
marginTop: "8px"
},
children: actions
}
),
error && /* @__PURE__ */ jsx(
"p",
{
style: {
color: "red"
},
role: "alert",
children: error
}
)
] }),
"data-testid": `@@list/${name}`,
required,
children: /* @__PURE__ */ jsx("div", { role: "list", children: items })
}
);
},
renderMultiSelect: ({
disabled,
autoFocus,
options,
optionsCacheRef,
value,
onChange,
getOptionLabel,
getOptionValue,
renderOption
}) => /* @__PURE__ */ jsx(
ChipsSelect,
{
autoFocus,
disabled,
onChange: (nextSelectValue) => {
const nextValue = [];
for (const selectedChip of nextSelectValue) {
const selectedOption = optionsCacheRef.current[selectedChip.value];
if (selectedOption) {
nextValue.push(selectedOption);
}
}
onChange(nextValue);
},
value: value ? value.map((option) => ({
label: getOptionLabel(option),
value: getOptionValue(option),
source: option
})) : [],
options: options.map((option) => ({
label: getOptionLabel(option),
value: getOptionValue(option),
source: option
})),
renderOption: renderOption ? (renderProps) => renderOption(
renderProps.option,
renderProps
) : defaultRenderChipSelectOption
}
),
renderRadioGroup: ({
disabled,
name,
value,
onChange,
options,
getOptionLabel,
getOptionValue
}) => {
const selectedValue = value ? getOptionValue(value) : null;
return /* @__PURE__ */ jsx("div", { children: options.map((option) => {
const optionValue = getOptionValue(option);
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
Radio,
{
checked: optionValue === selectedValue,
disabled,
name,
onChange: () => {
onChange(option);
},
children: getOptionLabel(option)
}
) }, optionValue);
}) });
},
renderSelect: ({
clearable,
disabled,
autoFocus,
options,
optionsCacheRef,
placeholder,
value,
onChange,
getOptionLabel,
getOptionValue,
renderOption
}) => /* @__PURE__ */ jsx(
Select,
{
allowClearButton: clearable,
autoFocus,
disabled,
onChange: (event) => {
const nextValue = event.target.value;
const selectedOption = optionsCacheRef.current[nextValue];
onChange(selectedOption);
},
placeholder,
value: value ? getOptionValue(value) : "",
options: options.map((option) => ({
label: getOptionLabel(option),
value: getOptionValue(option),
source: option
})),
renderOption: renderOption ? (renderProps) => renderOption(
renderProps.option,
renderProps
) : void 0,
searchable: true
}
),
renderSet: ({ children, label, rootProps }) => /* @__PURE__ */ jsx(CardGrid, { size: "l", ...rootProps, children: /* @__PURE__ */ jsx(ContentCard, { mode: cardMode, header: label, text: children }) }),
renderTags: ({ disabled, autoFocus, name, onChange, options, value }) => /* @__PURE__ */ jsx(
ChipsSelect,
{
autoFocus,
creatable: true,
disabled,
name,
onChange: (nextOptions) => {
onChange(nextOptions.map(({ value: option }) => option));
},
options: options ? options.map((option) => ({
value: option,
label: option
})) : [],
value: (value || []).map((option) => ({
value: option,
label: option
}))
}
),
renderTextArea: ({
disabled,
autoFocus,
textAreaProps: { ref, size, defaultValue, ...textAreaProps } = {},
name
}) => /* @__PURE__ */ jsx(
Textarea,
{
autoFocus,
disabled,
name,
...textAreaProps,
defaultValue
}
),
renderWrapper: ({ children, error, hint, label, required }) => {
return /* @__PURE__ */ jsxs(
FormItem,
{
top: required ? /* @__PURE__ */ jsxs(Fragment, { children: [
label,
/* @__PURE__ */ jsx(
"span",
{
style: {
color: "#e64646"
},
children: " *"
}
)
] }) : label,
bottom: error,
status: error ? "error" : void 0,
required,
children: [
children,
hint && /* @__PURE__ */ jsx(
Footnote,
{
style: {
color: "gray",
paddingTop: 6
},
children: hint
}
)
]
}
);
}
};
}
// src/edit/VKUIProvider.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
function VKUIProvider({
cardMode = void 0,
children = void 0,
ui = void 0
}) {
const contextValue = useMemo(() => {
const baseUI = getContextValue({
cardMode
});
return {
...baseUI,
...ui
};
}, [cardMode, ui]);
return /* @__PURE__ */ jsx2(BaseUIContext.Provider, { value: contextValue, children });
}
// src/show/VKUIShowProvider.tsx
import {
BaseUIContext as BaseUIContext2
} from "@vtaits/react-form-schema-base-ui";
import { useMemo as useMemo2 } from "react";
// src/show/contextValue.tsx
import { Icon16Attach as Icon16Attach2 } from "@vkontakte/icons";
import {
CardGrid as CardGrid2,
ContentCard as ContentCard2,
Counter,
Footnote as Footnote2,
FormItem as FormItem2,
FormStatus as FormStatus2,
Title as Title2
} from "@vkontakte/vkui";
// ../../node_modules/@vtaits/form-schema/dist/chunk-4VOZ33ZJ.js
import { parse } from "date-fns/parse";
import { parseISO } from "date-fns/parseISO";
import { isValid } from "date-fns/isValid";
import { format } from "date-fns/format";
import { formatISO } from "date-fns/formatISO";
// ../../node_modules/@date-fns/utc/date/mini.js
var UTCDateMini = class extends Date {
constructor() {
super();
this.setTime(arguments.length === 0 ? (
// Enables Sinon's fake timers that override the constructor
Date.now()
) : arguments.length === 1 ? typeof arguments[0] === "string" ? +new Date(arguments[0]) : arguments[0] : Date.UTC(...arguments));
}
getTimezoneOffset() {
return 0;
}
};
var re = /^(get|set)(?!UTC)/;
Object.getOwnPropertyNames(Date.prototype).forEach((method) => {
if (re.test(method)) {
const utcMethod = Date.prototype[method.replace(re, "$1UTC")];
if (utcMethod) UTCDateMini.prototype[method] = utcMethod;
}
});
// ../../node_modules/@date-fns/utc/date/index.js
var weekdayFormat = new Intl.DateTimeFormat("en-US", {
weekday: "short",
timeZone: "UTC"
});
var dateFormat = new Intl.DateTimeFormat("en-US", {
month: "short",
day: "numeric",
timeZone: "UTC"
});
var timeFormat = new Intl.DateTimeFormat("en-GB", {
hour12: false,
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZone: "UTC"
});
// ../../node_modules/@vtaits/form-schema/dist/fields_date.js
var DEFAULT_DISPLAY_DATE_FORMAT = "yyyy-MM-dd";
// ../../node_modules/@vtaits/form-schema/dist/fields_datetime.js
var DEFAULT_DISPLAY_DATE_FORMAT2 = "yyyy-MM-dd HH:mm";
// src/show/contextValue.tsx
import { format as format2 } from "date-fns/format";
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
function Flex({
gap,
children
}) {
return /* @__PURE__ */ jsx3(
"div",
{
style: {
display: "flex",
flexWrap: "wrap",
gap: gap === "s" ? 6 : void 0
},
children
}
);
}
function getContextValue2({
cardMode
}) {
return {
renderAsyncSelect: ({ value, getOptionLabel }) => {
if (value) {
return getOptionLabel(value);
}
return null;
},
renderAsyncMultiSelect: ({ value, getOptionLabel, getOptionValue }) => {
if (value) {
return /* @__PURE__ */ jsx3(Flex, { gap: "s", children: value.map((option) => /* @__PURE__ */ jsx3(Counter, { children: getOptionLabel(option) }, getOptionValue(option))) });
}
return null;
},
renderCheckbox: ({ checked }) => {
if (checked) {
return "\u0414\u0430";
}
return "\u041D\u0435\u0442";
},
renderCheckboxGroup: ({ value, getOptionLabel, getOptionValue }) => {
if (value) {
return /* @__PURE__ */ jsx3(Flex, { gap: "s", children: value.map((option) => /* @__PURE__ */ jsx3(Counter, { children: getOptionLabel(option) }, getOptionValue(option))) });
}
return null;
},
renderDatePicker: ({ value, displayDateFormat = DEFAULT_DISPLAY_DATE_FORMAT }) => {
if (value) {
return format2(value, displayDateFormat);
}
return null;
},
renderDateTimePicker: ({
value,
displayDateFormat = DEFAULT_DISPLAY_DATE_FORMAT2
}) => {
if (value) {
return format2(value, displayDateFormat);
}
return null;
},
renderFileInput: ({ selectedFile }) => {
if (selectedFile) {
return /* @__PURE__ */ jsxs2(
"p",
{
style: {
display: "flex",
alignItems: "center",
gap: "10px"
},
children: [
/* @__PURE__ */ jsx3(Icon16Attach2, {}),
selectedFile
]
}
);
}
return null;
},
renderForm: ({ actions, error, fields, title }) => /* @__PURE__ */ jsxs2("div", { children: [
title && /* @__PURE__ */ jsx3(
Title2,
{
level: "3",
style: {
marginBottom: "30px"
},
children: title
}
),
fields,
error && /* @__PURE__ */ jsx3(
"div",
{
style: {
marginTop: "20px",
marginBottom: "20px"
},
children: /* @__PURE__ */ jsx3(FormStatus2, { mode: "error", "data-testid": "@@form/error", children: error })
}
),
/* @__PURE__ */ jsx3(FormItem2, { children: actions })
] }),
renderInput: ({ inputProps: { value } = {} }) => {
return value;
},
renderListAddButton: () => null,
renderListItemWrapper: ({ children, compact, title, name }) => {
const testId = `@@list-item/${name}`;
if (compact) {
return /* @__PURE__ */ jsxs2(
"div",
{
"data-testid": testId,
style: {
margin: -12
},
children: [
title && /* @__PURE__ */ jsx3("div", { children: title }),
/* @__PURE__ */ jsx3("div", { children })
]
}
);
}
return /* @__PURE__ */ jsx3(CardGrid2, { size: "l", "data-testid": testId, children: /* @__PURE__ */ jsx3(ContentCard2, { mode: cardMode, header: title, text: children }) });
},
renderListWrapper: ({
actions,
error,
hint,
inline,
items,
label,
name
}) => {
return /* @__PURE__ */ jsx3(
FormItem2,
{
top: label,
bottom: /* @__PURE__ */ jsxs2(Fragment2, { children: [
hint && /* @__PURE__ */ jsx3(
"p",
{
style: {
color: "gray"
},
children: hint
}
),
actions && /* @__PURE__ */ jsx3(
"div",
{
style: {
marginTop: "8px"
},
children: actions
}
),
error && /* @__PURE__ */ jsx3(
"p",
{
style: {
color: "red"
},
role: "alert",
children: error
}
)
] }),
"data-testid": `@@list/${name}`,
children: /* @__PURE__ */ jsx3(
"div",
{
role: "list",
style: inline ? {
display: "flex",
flexWrap: "wrap",
gap: 6
} : void 0,
children: items
}
)
}
);
},
renderMultiSelect: ({ value, getOptionLabel, getOptionValue }) => {
if (value) {
return /* @__PURE__ */ jsx3(Flex, { gap: "s", children: value.map((option) => /* @__PURE__ */ jsx3(Counter, { children: getOptionLabel(option) }, getOptionValue(option))) });
}
return null;
},
renderRadioGroup: ({ value, getOptionLabel }) => {
if (value) {
return getOptionLabel(value);
}
return null;
},
renderSelect: ({ value, getOptionLabel }) => {
if (value) {
return getOptionLabel(value);
}
return null;
},
renderTags: ({ value }) => {
return /* @__PURE__ */ jsx3(Flex, { gap: "s", children: value.map((tag, index) => (
// biome-ignore lint/suspicious/noArrayIndexKey: there is no id
/* @__PURE__ */ jsx3(Counter, { children: tag }, index)
)) });
},
renderSet: ({ children, label, rootProps }) => /* @__PURE__ */ jsx3(CardGrid2, { size: "l", ...rootProps, children: /* @__PURE__ */ jsx3(ContentCard2, { mode: cardMode, title: label, description: children }) }),
renderTextArea: ({ textAreaProps: { defaultValue, value } = {} }) => /* @__PURE__ */ jsx3(
"div",
{
style: {
whiteSpace: "pre-wrap"
},
children: String(value ?? defaultValue)
}
),
renderWrapper: ({ children, error, hint, label }) => {
return /* @__PURE__ */ jsxs2(
FormItem2,
{
top: label,
bottom: error,
status: error ? "error" : void 0,
children: [
children,
hint && /* @__PURE__ */ jsx3(
Footnote2,
{
style: {
color: "gray",
paddingTop: 6
},
children: hint
}
)
]
}
);
}
};
}
// src/show/VKUIShowProvider.tsx
import { jsx as jsx4 } from "react/jsx-runtime";
function VKUIShowProvider({
cardMode = void 0,
children = void 0,
ui = void 0
}) {
const contextValue = useMemo2(() => {
const baseUI = getContextValue2({
cardMode
});
return {
...baseUI,
...ui
};
}, [cardMode, ui]);
return /* @__PURE__ */ jsx4(BaseUIContext2.Provider, { value: contextValue, children });
}
export {
VKUIProvider,
VKUIShowProvider
};
//# sourceMappingURL=index.js.map