UNPKG

@vtaits/react-form-schema-ui-vkui-v5

Version:

VKUI fields for @vtaits/form-schema

990 lines (979 loc) 26.5 kB
// 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