diff --git a/src/lib/unstable/core/index.ts b/src/lib/unstable/core/index.ts index 23cbad0f..a0284e74 100644 --- a/src/lib/unstable/core/index.ts +++ b/src/lib/unstable/core/index.ts @@ -9,4 +9,5 @@ export { type UseSchemaRendererReturn, useSchemaRenderer, useSchemaRendererMutators, + useUserContext, } from './useSchemaRenderer'; diff --git a/src/lib/unstable/core/useSchemaRenderer/constants.ts b/src/lib/unstable/core/useSchemaRenderer/constants.ts index 0215fc69..d04d0615 100644 --- a/src/lib/unstable/core/useSchemaRenderer/constants.ts +++ b/src/lib/unstable/core/useSchemaRenderer/constants.ts @@ -1 +1,2 @@ export const ENTITY_SERVICE_FIELD = 'ENTITY_SERVICE_FIELD'; +export const USER_CONTEXT_SERVICE_FIELD = 'USER_CONTEXT_SERVICE_FIELD'; diff --git a/src/lib/unstable/core/useSchemaRenderer/hooks/index.ts b/src/lib/unstable/core/useSchemaRenderer/hooks/index.ts index 374eb734..cf608ccc 100644 --- a/src/lib/unstable/core/useSchemaRenderer/hooks/index.ts +++ b/src/lib/unstable/core/useSchemaRenderer/hooks/index.ts @@ -1,2 +1,3 @@ export {useEntitiesState} from './useEntitiesState'; export {useSchemaRendererMutators} from './useSchemaRendererMutators'; +export {useUserContext} from './useUserContext'; diff --git a/src/lib/unstable/core/useSchemaRenderer/hooks/useSchemaRendererMutators.ts b/src/lib/unstable/core/useSchemaRenderer/hooks/useSchemaRendererMutators.ts index 7421744f..4f358e44 100644 --- a/src/lib/unstable/core/useSchemaRenderer/hooks/useSchemaRendererMutators.ts +++ b/src/lib/unstable/core/useSchemaRenderer/hooks/useSchemaRendererMutators.ts @@ -1,6 +1,7 @@ import {useForm} from 'react-final-form'; import type { + RemoveAndSetExternalErrorsMutator, RemoveAndSetSchemaMutatorsMutator, RemoveExternalErrorsMutator, RemoveSchemaMutatorsMutator, @@ -8,11 +9,15 @@ import type { SetAsyncValidationWaitersMutator, SetExternalErrorsMutator, SetSchemaMutatorsMutator, + SetUserContextMutator, TriggerFieldsMutator, } from '../mutators'; -export const useSchemaRendererMutators = () => { +export const useSchemaRendererMutators = < + Context extends Record = Record, +>() => { const { + removeAndSetExternalErrors, removeAndSetSchemaMutators, removeExternalErrors, removeSchemaMutators, @@ -20,8 +25,10 @@ export const useSchemaRendererMutators = () => { setAsyncValidationWaiters, setExternalErrors, setSchemaMutators, + setUserContext, triggerFields, } = useForm().mutators as { + removeAndSetExternalErrors: RemoveAndSetExternalErrorsMutator | undefined; removeAndSetSchemaMutators: RemoveAndSetSchemaMutatorsMutator | undefined; removeExternalErrors: RemoveExternalErrorsMutator | undefined; removeSchemaMutators: RemoveSchemaMutatorsMutator | undefined; @@ -29,10 +36,12 @@ export const useSchemaRendererMutators = () => { setAsyncValidationWaiters: SetAsyncValidationWaitersMutator | undefined; setExternalErrors: SetExternalErrorsMutator | undefined; setSchemaMutators: SetSchemaMutatorsMutator | undefined; + setUserContext: SetUserContextMutator | undefined; triggerFields: TriggerFieldsMutator | undefined; }; return { + removeAndSetExternalErrors, removeAndSetSchemaMutators, removeExternalErrors, removeSchemaMutators, @@ -40,6 +49,7 @@ export const useSchemaRendererMutators = () => { setAsyncValidationWaiters, setExternalErrors, setSchemaMutators, + setUserContext, triggerFields, }; }; diff --git a/src/lib/unstable/core/useSchemaRenderer/hooks/useUserContext.ts b/src/lib/unstable/core/useSchemaRenderer/hooks/useUserContext.ts new file mode 100644 index 00000000..4d90f416 --- /dev/null +++ b/src/lib/unstable/core/useSchemaRenderer/hooks/useUserContext.ts @@ -0,0 +1,26 @@ +import React from 'react'; + +import {useField, useForm} from 'react-final-form'; + +import {USER_CONTEXT_SERVICE_FIELD} from '../constants'; +import type {UserContextState} from '../mutators'; +import {guessHeadName} from '../utils'; + +export const useUserContext = = Record>( + name: string, +): UserContextState> => { + const form = useForm(); + + const headName = React.useMemo( + () => guessHeadName(form.getRegisteredFields(), name), + [form, name], + ); + + const field = useField(`${USER_CONTEXT_SERVICE_FIELD}.${headName}`, { + subscription: {data: true}, + }); + + const userContext = (field.meta.data || {}) as UserContextState>; + + return userContext; +}; diff --git a/src/lib/unstable/core/useSchemaRenderer/index.ts b/src/lib/unstable/core/useSchemaRenderer/index.ts index e25b60e1..6f67ccbf 100644 --- a/src/lib/unstable/core/useSchemaRenderer/index.ts +++ b/src/lib/unstable/core/useSchemaRenderer/index.ts @@ -1,4 +1,4 @@ -export {useEntitiesState, useSchemaRendererMutators} from './hooks'; +export {useEntitiesState, useSchemaRendererMutators, useUserContext} from './hooks'; export {schemaRendererMutators} from './mutators'; export { type UseSchemaRendererParams, diff --git a/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/external-errors.ts b/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/external-errors.ts index 03bc68fd..41109c82 100644 --- a/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/external-errors.ts +++ b/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/external-errors.ts @@ -3,7 +3,11 @@ import omit from 'lodash/omit'; import {ENTITY_SERVICE_FIELD} from '../../constants'; import {guessHeadName} from '../../utils'; -import type {RemoveExternalErrorsFunction, SetExternalErrorsFunction} from './types'; +import type { + RemoveAndSetExternalErrorsFunction, + RemoveExternalErrorsFunction, + SetExternalErrorsFunction, +} from './types'; export const setExternalErrors: SetExternalErrorsFunction = ( [{priorityErrors, regularErrors}], @@ -92,3 +96,12 @@ export const removeExternalErrors: RemoveExternalErrorsFunction = ( }); } }; + +export const removeAndSetExternalErrors: RemoveAndSetExternalErrorsFunction = ( + [{priorityErrors, removeFunctionOrNames, regularErrors}], + mutableState, + tools, +) => { + removeExternalErrors([{removeFunctionOrNames}], mutableState, tools); + setExternalErrors([{priorityErrors, regularErrors}], mutableState, tools); +}; diff --git a/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/types.ts b/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/types.ts index 798beb79..c1381a1e 100644 --- a/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/types.ts +++ b/src/lib/unstable/core/useSchemaRenderer/mutators/external-errors/types.ts @@ -47,3 +47,18 @@ export type RemoveExternalErrorsFunction< ) => void; export type RemoveExternalErrorsMutator = (params: RemoveExternalErrorsParams) => void; + +export interface RemoveAndSetExternalErrorsParams + extends RemoveExternalErrorsParams, + SetExternalErrorsParams {} + +export type RemoveAndSetExternalErrorsFunction< + FormValues = object, + InitialFormValues = Partial, +> = ( + args: [RemoveAndSetExternalErrorsParams], + state: MutableState, + tools: Tools, +) => void; + +export type RemoveAndSetExternalErrorsMutator = (params: RemoveAndSetExternalErrorsParams) => void; diff --git a/src/lib/unstable/core/useSchemaRenderer/mutators/index.ts b/src/lib/unstable/core/useSchemaRenderer/mutators/index.ts index b226e62f..fb4ffb90 100644 --- a/src/lib/unstable/core/useSchemaRenderer/mutators/index.ts +++ b/src/lib/unstable/core/useSchemaRenderer/mutators/index.ts @@ -1,18 +1,25 @@ import {setAsyncValidationCache, setAsyncValidationWaiters} from './async-validation'; -import {removeExternalErrors, setExternalErrors} from './external-errors'; +import { + removeAndSetExternalErrors, + removeExternalErrors, + setExternalErrors, +} from './external-errors'; import { removeAndSetSchemaMutators, removeSchemaMutators, setSchemaMutators, } from './schema-mutators'; import {triggerFields} from './trigger-fields'; +import {setUserContext} from './user-context'; export type * from './async-validation'; export type * from './external-errors'; export type * from './schema-mutators'; export type * from './trigger-fields'; +export type * from './user-context'; export const schemaRendererMutators = { + removeAndSetExternalErrors, removeAndSetSchemaMutators, removeExternalErrors, removeSchemaMutators, @@ -20,5 +27,6 @@ export const schemaRendererMutators = { setAsyncValidationWaiters, setExternalErrors, setSchemaMutators, + setUserContext, triggerFields, }; diff --git a/src/lib/unstable/core/useSchemaRenderer/mutators/schema-mutators/schema-mutators.ts b/src/lib/unstable/core/useSchemaRenderer/mutators/schema-mutators/schema-mutators.ts index 35898fc5..6a3a57bf 100644 --- a/src/lib/unstable/core/useSchemaRenderer/mutators/schema-mutators/schema-mutators.ts +++ b/src/lib/unstable/core/useSchemaRenderer/mutators/schema-mutators/schema-mutators.ts @@ -2,6 +2,7 @@ import type {MutableState} from 'final-form'; import cloneDeep from 'lodash/cloneDeep'; import get from 'lodash/get'; import isEqual from 'lodash/isEqual'; +import set from 'lodash/set'; import type {EntityState} from '../../../Entity'; import {getSchemaPath, getValuePaths, parseSchemaPath, smartSet} from '../../../utils'; @@ -18,9 +19,11 @@ import type { const applyMutators = ({ mutableState, mutators, + replace = false, }: { mutableState: MutableState; mutators: SetSchemaMutatorsParams['mutators']; + replace?: boolean; }) => { const registeredFields = Object.keys(mutableState.fields); @@ -36,7 +39,11 @@ const applyMutators = ({ const schemaPath = getSchemaPath(m.name, headName, mutatedSchema); if (schemaPath) { - smartSet(mutatedSchema, schemaPath, m.schema); + if (replace) { + set(mutatedSchema, schemaPath, m.schema); + } else { + smartSet(mutatedSchema, schemaPath, m.schema); + } const schemaField = mutableState.fields[m.name]; @@ -114,6 +121,7 @@ export const removeSchemaMutators: RemoveSchemaMutatorsFunction = ( : {}, }; }), + replace: true, }); headField.data.mutators = []; diff --git a/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/index.ts b/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/index.ts new file mode 100644 index 00000000..5936d544 --- /dev/null +++ b/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * from './user-context'; diff --git a/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/types.ts b/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/types.ts new file mode 100644 index 00000000..67dd3037 --- /dev/null +++ b/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/types.ts @@ -0,0 +1,26 @@ +import type {MutableState, Tools} from 'final-form'; +import type {MonacoEditorProps} from 'react-monaco-editor/lib/types'; + +export type UserContextState = Record> = + Context & {headName: string; MonacoEditor?: React.ComponentType}; + +export interface SetUserContextParams< + Context extends Record = Record, +> { + name: string; + userContext: + | Partial, 'headName'>> + | (( + userContext: Omit, 'headName'>, + ) => Partial, 'headName'>>); +} + +export type SetUserContextFunction> = ( + args: [SetUserContextParams], + state: MutableState, + tools: Tools, +) => void; + +export type SetUserContextMutator< + Context extends Record = Record, +> = (params: SetUserContextParams) => void; diff --git a/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/user-context.ts b/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/user-context.ts new file mode 100644 index 00000000..3c42328a --- /dev/null +++ b/src/lib/unstable/core/useSchemaRenderer/mutators/user-context/user-context.ts @@ -0,0 +1,26 @@ +import omit from 'lodash/omit'; + +import {USER_CONTEXT_SERVICE_FIELD} from '../../constants'; +import {guessHeadName} from '../../utils'; + +import type {SetUserContextFunction, UserContextState} from './types'; + +export const setUserContext: SetUserContextFunction = ([{name, userContext}], mutableState) => { + const registeredFields = Object.keys(mutableState.fields); + const headName = guessHeadName(registeredFields, name); + + if (headName) { + const field = mutableState.fields[`${USER_CONTEXT_SERVICE_FIELD}.${headName}`]; + + if (field) { + const currentUserContext = field.data as UserContextState; + + field.data = { + ...(typeof userContext === 'function' + ? userContext(omit(currentUserContext, 'headName')) + : {...currentUserContext, ...userContext}), + headName, + }; + } + } +}; diff --git a/src/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.ts b/src/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.ts index 56f13cbc..72e63294 100644 --- a/src/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.ts +++ b/src/lib/unstable/core/useSchemaRenderer/useSchemaRenderer.ts @@ -14,8 +14,9 @@ import type { SyncValidateError, } from '../types'; -import {ENTITY_SERVICE_FIELD} from './constants'; +import {ENTITY_SERVICE_FIELD, USER_CONTEXT_SERVICE_FIELD} from './constants'; import {useSchemaRendererMutators} from './hooks'; +import type {UserContextState} from './mutators'; import {getValidate} from './utils'; export interface UseSchemaRendererParams { @@ -40,6 +41,7 @@ export interface UseSchemaRendererParams { */ name: string; schema: JsonSchema; + userContext?: Omit; } export type UseSchemaRendererReturn = { @@ -54,6 +56,7 @@ export const useSchemaRenderer = ({ mode, name, schema: originalSchema, + userContext, }: UseSchemaRendererParams) => { const form = useForm(); const {setAsyncValidationCache, setAsyncValidationWaiters, triggerFields} = @@ -154,6 +157,18 @@ export const useSchemaRenderer = ({ return () => unsubscribe(); }, [config, form, mode, name]); + React.useLayoutEffect(() => { + const data = {...userContext, headName: name}; + const unsubscribe = form.registerField( + `${USER_CONTEXT_SERVICE_FIELD}.${name}`, + noop, + EMPTY_OBJECT, + {data}, + ); + + return () => unsubscribe(); + }, [form, name, userContext]); + React.useLayoutEffect(() => { if (fieldsToTrigger.length) { triggerFields?.({fields: fieldsToTrigger}); diff --git a/src/lib/unstable/kit/constants/config.ts b/src/lib/unstable/kit/constants/config.ts index d24a19d7..79991792 100644 --- a/src/lib/unstable/kit/constants/config.ts +++ b/src/lib/unstable/kit/constants/config.ts @@ -11,6 +11,7 @@ import { FewOfNested, FileInput, Label, + Monaco, MultiSelect, NumberBase, NumberWithScale, @@ -118,6 +119,7 @@ export const untypedConfig = { label: {Component: Label}, alert: {Component: Alert}, string_number_with_scale: {Component: StringNumberWithScale}, + monaco: {Component: Monaco}, }, views: {}, wrappers: { diff --git a/src/lib/unstable/kit/controls/Monaco/Monaco.scss b/src/lib/unstable/kit/controls/Monaco/Monaco.scss new file mode 100644 index 00000000..bbf2c12b --- /dev/null +++ b/src/lib/unstable/kit/controls/Monaco/Monaco.scss @@ -0,0 +1,39 @@ +@import '../../styles/functions.scss'; +@import '../../styles/variables.scss'; + +.#{$ns}monaco { + &_error { + .#{$ns}monaco__container { + border-color: var(--g-color-text-danger); + } + } + + &__container { + position: relative; + border: 1px solid var(--g-color-line-generic); + border-radius: 6px; + overflow: hidden; + } + + &__header { + padding: spacing(1.5) spacing(4); + border-bottom: 1px solid var(--g-color-line-generic); + background-color: var(--g-color-base-float-hover); + } + + &__control { + position: relative; + } + + &__control-inner { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + } + + &__dialog-body { + padding: spacing(4); + } +} diff --git a/src/lib/unstable/kit/controls/Monaco/Monaco.tsx b/src/lib/unstable/kit/controls/Monaco/Monaco.tsx new file mode 100644 index 00000000..357fd419 --- /dev/null +++ b/src/lib/unstable/kit/controls/Monaco/Monaco.tsx @@ -0,0 +1,187 @@ +import React from 'react'; + +import {ChevronsCollapseUpRight, ChevronsExpandUpRight, Code} from '@gravity-ui/icons'; +import {Button, Dialog, Flex, Icon, Text} from '@gravity-ui/uikit'; +import type {MonacoEditorProps} from 'react-monaco-editor/lib/types'; + +import { + type Control, + type JsonSchemaString, + useSchemaRendererMutators, + useUserContext, +} from '../../../core'; +import {ControlContainer} from '../../components'; +import {block, getBooleanValidationState} from '../../utils'; + +import './Monaco.scss'; + +const b = block('monaco'); + +export interface MonacoProps + extends Omit { + withoutDialog?: boolean; + ignoreMonacoErrors?: boolean; +} + +const Component: Control = ({controlProps, input, meta, schema}) => { + const {name, onBlur, onChange, onFocus, value} = input; + const { + language = 'plaintext', + options: optionsProps, + withoutDialog = true, + ignoreMonacoErrors = false, + width = '100%', + height = 350, + ...restControlProps + } = controlProps; + + const {MonacoEditor} = useUserContext(name); + const {removeExternalErrors, setExternalErrors} = useSchemaRendererMutators(); + + const modelUrisRef = React.useRef([]); + const innerErrorRef = React.useRef(null); + const [dialogOpen, setDialogOpen] = React.useState(false); + + const toggleDialogOpen = React.useCallback(() => setDialogOpen((f) => !f), []); + + const options: MonacoEditorProps['options'] = React.useMemo( + () => ({ + fontSize: 12, + readOnly: schema.readOnly, + formatOnPaste: true, + formatOnType: true, + contextmenu: false, + minimap: {enabled: false}, + autoClosingBrackets: 'languageDefined', + automaticLayout: true, + ...optionsProps, + }), + [optionsProps, schema.readOnly], + ); + + const onUpdate = React.useCallback( + (value: string) => { + onFocus(); + onChange(value); + onBlur(); + }, + [onFocus, onChange, onBlur], + ); + + const Container: React.FC< + React.PropsWithChildren<{ + dialog?: boolean; + width: string | number; + height: string | number; + }> + > = React.useCallback( + ({children, dialog, width, height}) => ( +
+ + + + {language} + + {withoutDialog ? ( + + ) : null} + +
+
{children}
+
+
+ ), + [name, language, withoutDialog, toggleDialogOpen], + ); + + const editorDidMount: MonacoEditorProps['editorDidMount'] = React.useMemo(() => { + if (ignoreMonacoErrors) { + return undefined; + } + + return (editor, monaco) => { + const model = editor.getModel(); + + if (model) { + const modelUri = model.uri.toString(); + + modelUrisRef.current.push(modelUri); + + model.onWillDispose(() => { + modelUrisRef.current = modelUrisRef.current.filter((u) => u !== modelUri); + }); + + monaco.editor.onDidChangeMarkers((uris) => { + const editedUri = uris.find((u) => modelUrisRef.current.includes(u.toString())); + + if (!editedUri) { + return; + } + + const marker = monaco.editor + .getModelMarkers({resource: editedUri}) + .find((m) => m.severity === monaco.MarkerSeverity.Error); + + if (marker) { + const error = `${marker.message}${ + marker.message[marker.message.length - 1] === '.' ? '' : '.' + } ${marker.source}(${marker.code}) [Line ${ + marker.startLineNumber + }, Column ${marker.startColumn}]`; + + if (innerErrorRef.current !== error) { + innerErrorRef.current = error; + setExternalErrors?.({regularErrors: {[name]: error}}); + } + } else if (innerErrorRef.current) { + innerErrorRef.current = null; + removeExternalErrors?.({removeFunctionOrNames: [name]}); + } + }); + } + + return; + }; + }, [name, ignoreMonacoErrors, setExternalErrors, removeExternalErrors]); + + if (!MonacoEditor) { + return null; + } + + const control = ( + + ); + + return ( + + + {control} + + + + + {control} + + + + + ); +}; + +export const Monaco = React.memo(Component); diff --git a/src/lib/unstable/kit/controls/Monaco/index.ts b/src/lib/unstable/kit/controls/Monaco/index.ts new file mode 100644 index 00000000..7dee9fda --- /dev/null +++ b/src/lib/unstable/kit/controls/Monaco/index.ts @@ -0,0 +1 @@ +export {Monaco, type MonacoProps} from './Monaco'; diff --git a/src/lib/unstable/kit/controls/RangeInput/RangeInput.tsx b/src/lib/unstable/kit/controls/RangeInput/RangeInput.tsx index d17fad7e..52e7d543 100644 --- a/src/lib/unstable/kit/controls/RangeInput/RangeInput.tsx +++ b/src/lib/unstable/kit/controls/RangeInput/RangeInput.tsx @@ -33,7 +33,7 @@ const Component: Control = ({controlProps, in const fromName = `${name}.${fromKey}`; const toName = `${name}.${toKey}`; - React.useLayoutEffect(() => { + React.useEffect(() => { const mutatorsToRemove: {name: string; schema: JsonSchema}[] = []; const mutators: {name: string; schema: JsonSchema}[] = []; @@ -77,7 +77,7 @@ const Component: Control = ({controlProps, in } prevValueRef.current = inputValue; - }, [inputValue]); + }, [inputValue?.[fromKey], inputValue?.[toKey]]); return ( diff --git a/src/lib/unstable/kit/controls/index.ts b/src/lib/unstable/kit/controls/index.ts index 64588dbe..4c9ee712 100644 --- a/src/lib/unstable/kit/controls/index.ts +++ b/src/lib/unstable/kit/controls/index.ts @@ -8,6 +8,7 @@ export {DateInput, type DateInputProps} from './DateInput'; export {FewOfNested, type FewOfNestedProps} from './FewOfNested'; export {FileInput, type FileInputProps} from './FileInput'; export {Label, type LabelProps} from './Label'; +export {Monaco, type MonacoProps} from './Monaco'; export {MultiSelect, type MultiSelectProps} from './MultiSelect'; export {NumberBase, type NumberBaseProps} from './NumberBase'; export {NumberWithScale, type NumberWithScaleProps} from './NumberWithScale'; diff --git a/src/stories/Unstable.stories.tsx b/src/stories/Unstable.stories.tsx index 63b5bb02..b3b7ae76 100644 --- a/src/stories/Unstable.stories.tsx +++ b/src/stories/Unstable.stories.tsx @@ -4,6 +4,7 @@ import {Button} from '@gravity-ui/uikit'; import type {StoryFn} from '@storybook/react'; import {noop} from 'lodash'; import {Form} from 'react-final-form'; +import MonacoEditor from 'react-monaco-editor'; import {ObjectBase} from '../lib'; import {SchemaRenderer, schemaRendererMutators} from '../lib/unstable/core'; @@ -1018,6 +1019,43 @@ export default { const schema: JsonSchemaObject = { type: JsonSchemaType.Object, properties: { + monaco: { + default: JSON.stringify( + { + extends: '@gravity-ui/tsconfig/tsconfig.json', + include: ['src/**/*.ts', 'src/**/*.tsx'], + exclude: ['src/stories'], + compilerOptions: { + outDir: 'build/esm', + module: 'esnext', + jsx: 'react', + resolveJsonModule: true, + baseUrl: '.', + declaration: true, + allowJs: true, + importHelpers: true, + paths: { + '@gravity-ui/dynamic-forms/unstable': ['./src/unstable.ts'], + '@gravity-ui/uikit/unstable': [ + 'node_modules/@gravity-ui/uikit/build/esm/unstable', + ], + }, + }, + }, + null, + 2, + ), + type: JsonSchemaType.String, + title: 'monaco', + entityParameters: { + type: EntityType.String, + controlType: 'monaco', + controlWrapperType: 'row', + controlProps: { + language: 'json', + }, + }, + }, string_number_with_scale: { default: '1000', type: JsonSchemaType.String, @@ -1810,6 +1848,8 @@ const value = { }, }; +const userContext = {MonacoEditor}; + const template = () => { const Template: StoryFn = (__) => (
@@ -1820,6 +1860,7 @@ const template = () => { schema={schema} config={config} mode={SchemaRendererMode.Form} + userContext={userContext} /> {/*