{"version":3,"file":"344.7c36b2f7d14a1c0f6a6d.js","mappings":"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","sources":["webpack://luis-portal/./src/core/components/EditableTitleTextField.tsx","webpack://luis-portal/./src/core/components/EditableTitle.tsx","webpack://luis-portal/./src/core/components/LuisSplitPane.tsx","webpack://luis-portal/./src/core/hooks/useFormState.ts","webpack://luis-portal/./src/core/hooks/useSplitPane.ts","webpack://luis-portal/./src/core/utils/resizeWatcher.ts"],"sourcesContent":["/**\r\n * Copyright (c) Microsoft. All rights reserved.\r\n */\r\n\r\nimport { IconButton } from '@fluentui/react/lib/Button';\r\nimport { ITextFieldStyleProps, ITextFieldStyles } from '@fluentui/react/lib/TextField';\r\nimport { classNamesFunction } from '@fluentui/react/lib/Utilities';\r\nimport * as React from 'react';\r\nimport { defineMessages } from 'react-intl';\r\nimport { LuisTextField } from 'src/core/components/LuisTextField';\r\nimport { useFormState } from 'src/core/hooks/useFormState';\r\nimport { useLocalization } from 'src/core/hooks/useLocalization';\r\nimport { getScopedTheme } from 'src/core/themes/luisStylist';\r\nimport { FormValidators } from 'src/core/utils/formValidators';\r\n\r\nexport type EditableTitleTextFieldProps = {\r\n /**\r\n * The initial value to populate the field with.\r\n */\r\n initialValue: string;\r\n\r\n /**\r\n * A callback for when the value is to be submitted\r\n * back to the caller.\r\n */\r\n onSubmit: (dto: EditableTitleTextFieldDto) => void;\r\n\r\n /**\r\n * A callback for when the field changes are to be\r\n * discarded and edit mode closed.\r\n */\r\n onCancel: () => void;\r\n};\r\n\r\nexport type EditableTitleTextFieldDto = {\r\n /**\r\n * The value that is being submitted.\r\n */\r\n value: string;\r\n\r\n /**\r\n * A flag indicating whether the value was changed\r\n * from the initial value passed to this component\r\n * or not.\r\n */\r\n changed: boolean;\r\n};\r\n\r\nconst messages = defineMessages({\r\n fieldPlaceholder: {\r\n id: 'core.editableTitle.fieldPlaceholder',\r\n defaultMessage: 'Enter title here ...'\r\n },\r\n acceptButtonAriaLabel: {\r\n id: 'core.editableTitle.acceptButtonAriaLabel',\r\n defaultMessage: 'Accept'\r\n }\r\n});\r\n\r\nconst editableTitleTheme = getScopedTheme('EditableTitle');\r\n\r\nconst textFieldStyles = classNamesFunction()({\r\n field: {\r\n fontSize: editableTitleTheme.fontSize,\r\n padding: 0,\r\n selectors: { '&::placeholder': { fontSize: editableTitleTheme.fontSize } }\r\n },\r\n fieldGroup: {\r\n height: editableTitleTheme.height\r\n }\r\n});\r\n\r\n/**\r\n * This is a text field that is to be used inside the EditableTitle\r\n * component, and it tracks the last initial value passed to it\r\n * in order to provide a check of whether the last initial value\r\n * is the same as the value after the user applied edits to the\r\n * text field.\r\n *\r\n * @param props The input to the text field.\r\n */\r\nexport const EditableTitleTextField = (props: EditableTitleTextFieldProps) => {\r\n const { initialValue, onSubmit, onCancel } = props;\r\n const { localize } = useLocalization();\r\n const { formState, updateFormState, formStateDto } = useFormState<{ fieldData: string }>({\r\n fieldData: [initialValue, FormValidators.createRequiredValidator(), FormValidators.createBlacklistValidator()]\r\n });\r\n\r\n /**\r\n * Checks if the value is valid or not, and if it is sends it\r\n * back to the caller along with a flag that indicates whether this\r\n * value is new or did the value remain the same from the last time\r\n * the input field was open.\r\n */\r\n const submitValue = () => {\r\n if (!formState.form.valid) {\r\n return;\r\n }\r\n\r\n const trimmedValue = formStateDto.fieldData.trim();\r\n\r\n onSubmit({\r\n value: trimmedValue,\r\n changed: trimmedValue !== initialValue.trim()\r\n });\r\n };\r\n\r\n /**\r\n * Submits the value of the text field if the enter key was\r\n * pressed and signals the parent to close the input field\r\n * and the edit mode when the escape key is pressed.\r\n *\r\n * @param event The event fired by the keypress.\r\n */\r\n const onKeyDown = (event: React.KeyboardEvent) => {\r\n if (event.key === 'Enter') {\r\n submitValue();\r\n } else if (event.key === 'Escape') {\r\n onCancel();\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n updateFormState({ fieldData })}\r\n onKeyDown={onKeyDown}\r\n />\r\n\r\n \r\n \r\n );\r\n};\r\n","/**\r\n * Copyright (c) Microsoft. All rights reserved.\r\n */\r\n\r\nimport { IButton, IconButton } from '@fluentui/react/lib/Button';\r\nimport { Shimmer, ShimmerElementType } from '@fluentui/react/lib/Shimmer';\r\nimport { Alignment, IStackProps, Stack } from '@fluentui/react/lib/Stack';\r\nimport { ITextProps, ITextStyles } from '@fluentui/react/lib/Text';\r\nimport { classNamesFunction } from '@fluentui/react/lib/Utilities';\r\nimport * as React from 'react';\r\nimport { defineMessages } from 'react-intl';\r\nimport { CalloutButton } from 'src/core/components/CalloutButton';\r\nimport { EditableTitleTextField, EditableTitleTextFieldDto } from 'src/core/components/EditableTitleTextField';\r\nimport { LuisText, LuisTextProps } from 'src/core/components/LuisText';\r\nimport { LuisTooltip } from 'src/core/components/LuisTooltip';\r\nimport { useLocalization } from 'src/core/hooks/useLocalization';\r\nimport { getScopedTheme, getStylistV2 } from 'src/core/themes/luisStylist';\r\n\r\nconst messages = defineMessages({\r\n editIconAriaLabel: {\r\n id: 'core.pageTitle.editIconAriaLabel',\r\n defaultMessage: 'Edit title'\r\n }\r\n});\r\n\r\nconst { styleComponent } = getStylistV2('EditableTitle');\r\nconst scopedTheme = getScopedTheme('EditableTitle');\r\n\r\nconst Root = styleComponent(Stack)('Root', {\r\n marginBottom: 8\r\n});\r\n\r\n// Hidden border is added to make the title the same hight as the edit text box\r\nconst defaultTitleStyles = classNamesFunction()({\r\n root: { lineHeight: scopedTheme.lineHeight, borderBottom: '1px solid transparent' }\r\n});\r\n\r\nexport type EditableTitleProps = {\r\n /**\r\n * Title to be displayed.\r\n */\r\n title: string;\r\n /**\r\n * Optional: class name to style the component.\r\n */\r\n className?: string;\r\n /**\r\n * Optional: text props for the title.\r\n */\r\n titleTextProps?: LuisTextProps;\r\n /**\r\n * Optional: subtitle.\r\n */\r\n subtitle?: string | JSX.Element;\r\n /**\r\n * Optional: Indicates if the title is editable.\r\n */\r\n isEditable?: boolean;\r\n /**\r\n * Optional: Indicates if the title is loading.\r\n */\r\n isLoading?: boolean;\r\n /**\r\n * Optional: Title description (e.g. docs).\r\n */\r\n description?: React.ReactNode;\r\n /**\r\n * Optional: Alignment of the description element relative to the title.\r\n */\r\n descriptionAlignment?: Alignment;\r\n /**\r\n * Optional: Renderer for title element.\r\n */\r\n onRenderTitle?: (props: EditableTitleProps, defaultRender: (props: EditableTitleProps) => React.ReactNode) => React.ReactNode;\r\n /**\r\n * Optional: callback for when title is updated.\r\n */\r\n onUpdateTitle?: (newTitle: string) => void;\r\n /**\r\n * Optional: Aria-label for callout button.\r\n */\r\n descriptionAriaLabel?: string;\r\n /**\r\n * Optional: Data-utomation-id for test.\r\n */\r\n dataAutomationId?: string;\r\n};\r\n\r\nconst defaultRender = ({\r\n subtitle,\r\n title,\r\n description,\r\n descriptionAlignment = 'baseline',\r\n titleTextProps,\r\n descriptionAriaLabel,\r\n dataAutomationId\r\n}: EditableTitleProps) => (\r\n \r\n \r\n \r\n {title}\r\n \r\n {description && }\r\n \r\n {subtitle && {subtitle}}\r\n \r\n);\r\n\r\nexport const EditableTitle = (props: EditableTitleProps) => {\r\n const { title, isLoading = false, isEditable = false, onUpdateTitle, onRenderTitle, className } = props;\r\n\r\n const { localize } = useLocalization();\r\n const [isEditMode, setIsEditMode] = React.useState(false);\r\n const [editableTitle, setEditableTitle] = React.useState(title);\r\n const iconButtonRef = React.useRef();\r\n\r\n /**\r\n * This ensures that when the title is changed back in the\r\n * event of web api failure, it is reflected in the component.\r\n */\r\n React.useEffect(() => setEditableTitle(title), [title]);\r\n\r\n /**\r\n * Submits the value of the input field to the consumer\r\n * (parent) component only if the value of has actually\r\n * been changed than the last time it was edited.\r\n *\r\n * @param dto The data received from the text field.\r\n */\r\n const submitTitle = (dto: EditableTitleTextFieldDto) => {\r\n closeEditMode();\r\n\r\n setEditableTitle(dto.value);\r\n\r\n if (onUpdateTitle && dto.changed) {\r\n onUpdateTitle(dto.value);\r\n }\r\n };\r\n\r\n /**\r\n * Closes edit mode by setting the state flag and refocusing\r\n * on the edit button.\r\n */\r\n const closeEditMode = () => {\r\n setIsEditMode(false);\r\n requestAnimationFrame(() => iconButtonRef.current.focus());\r\n };\r\n\r\n return (\r\n \r\n {isLoading ? (\r\n \r\n ) : isEditMode ? (\r\n \r\n ) : (\r\n <>\r\n {onRenderTitle ? onRenderTitle(props, defaultRender) : defaultRender({ ...props, title: editableTitle })}\r\n {isEditable ? (\r\n \r\n setIsEditMode(true)}\r\n iconProps={{ iconName: 'Edit' }}\r\n />\r\n \r\n ) : null}\r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nEditableTitle.displayName = 'PageTitleV2';\r\n","/**\r\n * Copyright (c) Microsoft. All rights reserved.\r\n */\r\n\r\nimport { default as SplitPane, SplitPaneProps } from 'react-split-pane';\r\nimport { getStylistV2 } from 'src/core/themes/luisStylist';\r\n\r\nconst { styleComponent } = getStylistV2('LuisSplitPane');\r\n\r\n/**\r\n * Provides a styled SplitPane from react-split-pane\r\n */\r\nexport const LuisSplitPane = styleComponent(SplitPane)('LuisSplitPane', theme => ({\r\n $nest: {\r\n '& .Resizer': {\r\n borderWidth: '0',\r\n zIndex: 1,\r\n boxSizing: 'border-box',\r\n backgroundClip: 'padding-box'\r\n },\r\n '& .Resizer.vertical': {\r\n borderLeft: '5px solid transparent',\r\n borderRight: '5px solid transparent',\r\n cursor: 'ew-resize',\r\n margin: '0 -5px',\r\n minWidth: '1px',\r\n pointerEvents: 'all',\r\n width: '11px',\r\n zIndex: 2,\r\n $nest: {\r\n '&::after': {\r\n background: theme.resizerBackgroundColor,\r\n content: '\"\"',\r\n display: 'block',\r\n height: '100%',\r\n width: '1px'\r\n }\r\n }\r\n },\r\n '& .Resizer.horizontal': {\r\n borderTop: '5px solid transparent',\r\n borderBottom: '5px solid transparent',\r\n cursor: 'ns-resize',\r\n zIndex: 1,\r\n margin: '-5px 0',\r\n minHeight: '1px',\r\n pointerEvents: 'all',\r\n height: '11px',\r\n $nest: {\r\n '&::after': {\r\n background: theme.resizerBackgroundColor,\r\n content: '\"\"',\r\n display: 'block',\r\n height: '1px',\r\n width: '100%'\r\n }\r\n }\r\n },\r\n '& .Resizer.disabled': {\r\n cursor: 'default'\r\n }\r\n }\r\n}));\r\n","/**\r\n * Copyright (c) Microsoft. All rights reserved.\r\n */\r\n\r\nimport * as React from 'react';\r\nimport { useLocalization } from 'src/core/hooks/useLocalization';\r\nimport { FormFieldSchema, FormFieldState, FormFieldValue, FormSchema, FormState, ValidatorErrorMessage } from 'src/core/types/form';\r\n\r\n/**\r\n * Creates a react hook for creating and updating form state. Given an initial form\r\n * schema, this hook outputs a form state object, an updater function for that form\r\n * state, and a Dto object that matches the signature of the generic type T given.\r\n * Note that T is used for type safety and intellisense.\r\n *\r\n * @param formSchema The form schema to base the form state on.\r\n */\r\nexport const useFormState = >(formSchema: FormSchema) => {\r\n const { localize } = useLocalization();\r\n const [formState, setState] = React.useState(getNextFormState(undefined, undefined, formSchema, localize));\r\n\r\n const updateFormState = (partial: Partial): void => {\r\n setState(prevState => getNextFormState(prevState, partial, formSchema, localize));\r\n };\r\n\r\n const formStateDto = getFormStateDto(formState);\r\n\r\n const resetFormState = () => setState(getNextFormState(undefined, undefined, formSchema, localize));\r\n\r\n return { formState, updateFormState, formStateDto, resetFormState };\r\n};\r\n\r\n/**\r\n * Gets the next form state by processing the validity of the existing form\r\n * state and the new partial updates created by the user when changing the\r\n * form. To derive the new state, the original form schema is needed to\r\n * validate the new values. In the case of the first form render, the\r\n * previous state and partial updates are undefined, and the form schema\r\n * only is used to derive the new (and initial) state.\r\n *\r\n * @param prevState Previous form state before new changes occurred. This value\r\n * is undefined on the first render.\r\n * @param partial Partial updates caused by user change in form values. This\r\n * value is undefined on the first render.\r\n * @param formSchema The original form schema that contains the initial values\r\n * and the validators for each field.\r\n * @returns A new state object derived from the previous state and the new\r\n * partial change values.\r\n */\r\nconst getNextFormState = >(\r\n prevState: FormState,\r\n partial: Partial,\r\n formSchema: FormSchema,\r\n localize: ReactIntl.InjectedIntl['formatMessage']\r\n): FormState => {\r\n const keys = formSchema ? Object.keys(formSchema) : [];\r\n\r\n const newFields = keys.reduce((acc, key) => {\r\n let newVal: FormFieldValue;\r\n let touched: boolean;\r\n\r\n /**\r\n * The value and touched parameter can be fetched from either\r\n * of these cases:\r\n *\r\n * - A partial update was incurred by the a user change, check\r\n * if the key exists in that partial object. If it does, then\r\n * that is the new value of the key/field and should be used\r\n * as the new value of the field in the new state object. The\r\n * user changed the field value, therefore it has been touched.\r\n * A partial can only be undefined in the case when the form\r\n * is rendering for the first time.\r\n *\r\n * - If not found, then both the value and the touched parameter\r\n * will be carried over from the previous state object, on the\r\n * condition that the previous state object is defined. The\r\n * previous state can be undefined in the case of the render\r\n * (initialization).\r\n *\r\n * - In the case of the first render, the previous state is not\r\n * defined, and the partial update is empty, therefor the value\r\n * for the state rendering is defined by the initial value of\r\n * the field as defined in the form schema object and since this\r\n * is the initial render, the fields have not been touched.\r\n */\r\n if (partial && key in partial) {\r\n newVal = partial[key];\r\n touched = true;\r\n } else if (prevState) {\r\n newVal = prevState.fields[key].value;\r\n touched = prevState.fields[key].touched;\r\n } else {\r\n [newVal] = formSchema[key];\r\n touched = false;\r\n }\r\n\r\n return { ...acc, [key]: getNextFormFieldState(newVal, touched, formSchema[key], localize) };\r\n }, <{ [key in keyof T]: FormFieldState }>{});\r\n\r\n const isFormValid = Object.keys(newFields).every(key => newFields[key].valid);\r\n\r\n return {\r\n fields: newFields,\r\n form: {\r\n valid: isFormValid\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * Gets the next state for a field in the form. Derives the new field state\r\n * using the new value and the current form field schema, which contains the\r\n * validators to fire to check the new value.\r\n *\r\n * @param newValue The value to use to create the new state.\r\n * @param formFieldSchema The schema of the current field. Used to evaluate the\r\n * new value's validity.\r\n * @returns A new form field state derived from the new value and the schema.\r\n */\r\nconst getNextFormFieldState = (\r\n newValue: T,\r\n touched: boolean,\r\n formFieldSchema: FormFieldSchema,\r\n localize: ReactIntl.InjectedIntl['formatMessage']\r\n): FormFieldState => {\r\n const [, ...validators] = formFieldSchema;\r\n let errorMessage: ValidatorErrorMessage;\r\n\r\n for (const validator of validators) {\r\n errorMessage = validator(newValue);\r\n\r\n if (errorMessage) {\r\n if (errorMessage !== undefined) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n value: newValue,\r\n valid: errorMessage === undefined,\r\n errorMessage: touched ? getErrorMessage(errorMessage, localize) : undefined,\r\n touched\r\n };\r\n};\r\n\r\n/**\r\n * Gets the error string message from the validator error object.\r\n */\r\nconst getErrorMessage = (errorMsg: ValidatorErrorMessage, localize: ReactIntl.InjectedIntl['formatMessage']): string => {\r\n if (!errorMsg) {\r\n return;\r\n }\r\n\r\n if (typeof errorMsg === 'string') {\r\n return errorMsg;\r\n }\r\n const { messageDescriptor, params } = errorMsg;\r\n\r\n return localize(messageDescriptor, params);\r\n};\r\n\r\n/**\r\n * Exports the form state as a DTO object that is a slimmed down version\r\n * of the form state with only the keys and their values in the object.\r\n *\r\n * @param formState The current state of the form.\r\n * @returns A dto object of type T that has the keys and values of the state.\r\n */\r\nconst getFormStateDto = >(formState: FormState): T => {\r\n const keys = formState ? Object.keys(formState.fields) : [];\r\n\r\n return keys.reduce((acc, key: keyof T) => ({ ...acc, [key]: formState.fields[key].value }), {});\r\n};\r\n","/**\r\n * Copyright (c) Microsoft. All rights reserved.\r\n */\r\n\r\nimport debounce from 'lodash.debounce';\r\nimport * as React from 'react';\r\nimport { getLifetime } from 'src/core/utils/lifetime';\r\nimport { watchResize } from 'src/core/utils/resizeWatcher';\r\n\r\nexport const useSplitPane = (\r\n options: {\r\n defaultSize: number | string;\r\n maxSize: number | string;\r\n },\r\n delay: number = 50\r\n) => {\r\n const [size, setSize] = React.useState(options.defaultSize ?? 0);\r\n const [maxSize, setMaxSize] = React.useState(options.maxSize ?? 0);\r\n\r\n // Keeps the size in sync.\r\n React.useEffect(() => {\r\n setSize(options.defaultSize ?? 0);\r\n }, [options.defaultSize]);\r\n\r\n // Keeps the max size in sync.\r\n React.useEffect(() => {\r\n setMaxSize(options.maxSize ?? 0);\r\n }, [options.maxSize]);\r\n\r\n // Debounced setter for size\r\n const debouncedSetSize = debounce(setSize, delay);\r\n\r\n return { size, setSize: debouncedSetSize, maxSize, setMaxSize };\r\n};\r\n\r\nexport const useVerticalSplitPane = (element: Element, mainMinWidth: number, sideMinWidth: number) => {\r\n const { size, setSize, maxSize, setMaxSize } = useSplitPane({\r\n defaultSize: sideMinWidth,\r\n maxSize: 0\r\n });\r\n\r\n const recalculateSizeAllowance = (totalWidth: number) => {\r\n // Max allowed width for the side pane\r\n const newMaxWidth = totalWidth - mainMinWidth;\r\n // If current side pane width is bigger than the new max allowed width, update the width\r\n const newWidth = Math.min(size, newMaxWidth);\r\n setSize(newWidth);\r\n\r\n // If max allowed width is less than min side pane width, update max allowed side pane with to min side pane width\r\n if (newMaxWidth < sideMinWidth) {\r\n setMaxSize(sideMinWidth);\r\n } else if (maxSize !== newMaxWidth) {\r\n // Update max allowed width if it's a new value\r\n setMaxSize(newMaxWidth);\r\n }\r\n };\r\n\r\n React.useEffect(() => {\r\n const lifetime = getLifetime();\r\n\r\n if (element) {\r\n const watcher = watchResize(element, dim => {\r\n // On resize re-calculate max width side pane allowance\r\n recalculateSizeAllowance(dim.width);\r\n });\r\n lifetime.add(watcher.unobserve);\r\n }\r\n\r\n return lifetime.dispose;\r\n });\r\n\r\n return { size, setSize, maxSize, setMaxSize };\r\n};\r\n","/**\r\n * Copyright (c) Microsoft. All rights reserved.\r\n */\r\n\r\ndeclare class ResizeObserver {\r\n constructor(callback: IResizeObserverCallback);\r\n /**\r\n * Starts to observe an element.\r\n */\r\n public observe(target: Element): void;\r\n\r\n /**\r\n * Stop observing an element.\r\n */\r\n public unobserve(target: Element): void;\r\n\r\n /**\r\n * Disconnects the observer.\r\n */\r\n public disconnect(): void;\r\n}\r\n\r\n/**\r\n * The watch result entry\r\n */\r\ninterface IResizeObserverEntry {\r\n readonly target: Element;\r\n readonly contentRect: {\r\n readonly x: number;\r\n readonly y: number;\r\n readonly width: number;\r\n readonly height: number;\r\n readonly top: number;\r\n readonly right: number;\r\n readonly bottom: number;\r\n readonly left: number;\r\n };\r\n}\r\n\r\ndeclare type IResizeObserverCallback = (entries: IResizeObserverEntry[], observer: ResizeObserver) => void;\r\n\r\nexport type SizeChanged = (rect: { width: number; height: number }) => void;\r\n\r\n/**\r\n * The element being watched needs to be either relative or absolute positioned.\r\n * @param element\r\n * @param callback\r\n */\r\nconst watchByPolyfill = (element: Element, callback: SizeChanged) => {\r\n let curWidth = 0;\r\n let curHeight = 0;\r\n\r\n const setSize = (width: number, height: number) => {\r\n const [lastWidth, lastHeight] = [curWidth, curHeight];\r\n\r\n [curWidth, curHeight] = [width, height];\r\n\r\n if (curWidth !== lastWidth || curHeight !== lastHeight) {\r\n callback({ width, height });\r\n }\r\n };\r\n\r\n const css = `position:absolute;\r\n left:0;\r\n top:-100%;\r\n width:100%;\r\n height:100%;\r\n margin:1px 0 0;\r\n border:none;\r\n opacity:0;\r\n pointer-events:none;`;\r\n\r\n const frame = document.createElement('iframe');\r\n frame.style.cssText = css;\r\n\r\n frame.onload = () => {\r\n setSize(element.clientWidth, element.clientHeight);\r\n };\r\n\r\n element.appendChild(frame);\r\n\r\n frame.contentWindow.onresize = () => {\r\n setSize(element.clientWidth, element.clientHeight);\r\n };\r\n\r\n return { unobserve: () => element.removeChild(frame) };\r\n};\r\n\r\nconst watchByObserver = (element: Element, callback: SizeChanged) => {\r\n const ro = new ResizeObserver(entries => {\r\n const entry = entries[0];\r\n callback(entry.contentRect);\r\n });\r\n\r\n ro.observe(element);\r\n\r\n return { unobserve: () => ro.unobserve(element) };\r\n};\r\n\r\nexport const watchResize = (window).ResizeObserver ? watchByObserver : watchByPolyfill;\r\n"],"names":["messages","fieldPlaceholder","id","defaultMessage","acceptButtonAriaLabel","editableTitleTheme","textFieldStyles","classNamesFunction","field","fontSize","padding","selectors","fieldGroup","height","EditableTitleTextField","props","initialValue","onSubmit","onCancel","localize","useLocalization","formState","updateFormState","formStateDto","useFormState","fieldData","createRequiredValidator","createBlacklistValidator","submitValue","form","valid","trimmedValue","trim","value","changed","LuisTextField","autoFocus","underlined","styles","placeholder","fields","errorMessage","onChange","_","onKeyDown","event","key","IconButton","onClick","disabled","iconProps","iconName","ariaLabel","editIconAriaLabel","styleComponent","scopedTheme","Root","Stack","marginBottom","defaultTitleStyles","root","lineHeight","borderBottom","defaultRender","subtitle","title","description","descriptionAlignment","titleTextProps","descriptionAriaLabel","dataAutomationId","tokens","childrenGap","verticalAlign","horizontal","LuisText","as","fontWeight","variant","CalloutButton","content","EditableTitle","isLoading","isEditable","onUpdateTitle","onRenderTitle","className","isEditMode","setIsEditMode","editableTitle","setEditableTitle","iconButtonRef","closeEditMode","requestAnimationFrame","current","focus","Shimmer","width","shimmerElements","type","line","dto","LuisTooltip","componentRef","displayName","LuisSplitPane","theme","$nest","borderWidth","zIndex","boxSizing","backgroundClip","borderLeft","borderRight","cursor","margin","minWidth","pointerEvents","background","resizerBackgroundColor","display","borderTop","minHeight","formSchema","setState","getNextFormState","undefined","partial","prevState","getFormStateDto","resetFormState","newFields","Object","keys","reduce","acc","newVal","touched","getNextFormFieldState","isFormValid","every","newValue","formFieldSchema","validators","validator","getErrorMessage","errorMsg","messageDescriptor","params","useSplitPane","options","delay","size","setSize","defaultSize","maxSize","setMaxSize","watchResize","window","ResizeObserver","element","callback","ro","entries","entry","contentRect","observe","unobserve","curWidth","curHeight","lastWidth","lastHeight","frame","document","createElement","style","cssText","onload","clientWidth","clientHeight","appendChild","contentWindow","onresize","removeChild"],"sourceRoot":""}