JGuang

JSON 输入

JsonInput · Mantine Core

交互预览
npm install @mantine/core@9.7.1 @mantine/hooks@9.7.1

JSON 输入

Mantine Core 的独立组件,请不要替换为 JGuang UI/Base UI 的同名 API。

安装

npm install @mantine/core@9.7.1 @mantine/hooks@9.7.1

入口引入 @mantine/core/styles.css,并在根组件使用 MantineProvider;通过 forceColorScheme 同步深浅色主题。

使用与验证

在左侧选择组件,在预览中操作它的状态;使用“查看代码”检查真实源码。安装后执行类型检查和构建,再验证键盘焦点、手机布局与深浅色主题。

来源

https://github.com/mantinedev/mantine/tree/f0e2bc6d28b0f0b8aaefb5b859937bf77f539df7 MIT 许可证;不包括付费内容。下方提供上游英文参考内容,中文使用指南已适配;上游详细参考暂保留英文。


版本与兼容性

固定的 Mantine Core 9.7.1 要求 React 和 React DOM 满足 ^19.2.0,并配套 @mantine/hooks@9.7.1。此条件来自实际 npm 包的 peerDependencies。React 18 或其他不兼容版本不能强行安装;先向项目负责人说明升级影响并确认方案,不使用 --force/--legacy-peer-deps 掩盖冲突。入口的原生 Provider 开启 theme.respectReducedMotion,并用 forceColorScheme 控制深浅色。

适用场景

编辑并格式化 JSON 文本。

本地示例使用的原生参数

以下参数由本地、经过类型检查的 JSX 示例提取,按所属组件区分。不是全部属性清单;完整签名和继承关系见下方固定源码参考。

组件参数说明
JsonInput.disabled禁用用户输入或操作,不等同于只读。
JsonInput.error本地错误展示,本身不执行校验。
JsonInput.readOnly阻止编辑并保留只读交互。
JsonInput.label可见标签或当前组件的标签内容。
JsonInput.defaultValue非受控初始值,不是持续更新的受控值。
JsonInput.formatOnBlur失去焦点时格式化合法 JSON。
JsonInput.autosize根据内容自动调整输入区域高度。

交互与状态检查

当前场景:默认、禁用、校验错误、只读。切换支持的禁用、错误或只读场景后检查真实行为;无此原生状态的组件不会被强行添加统一属性。验证键盘焦点和退出方式,修改值后按原生回调签名连接业务状态。

业务接入边界

格式化和本地 JSON 合法性检查不等于服务端 schema 校验,应保留未修正的输入文本。

宿主配置

先安装固定版本 @mantine/core 和 @mantine/hooks,在入口引入 @mantine/core/styles.css,并使用 MantineProvider。示例的 theme 和 variant 是 JGuang 编写的宿主参数,不是所有原生组件都接受的统一 API;通过 forceColorScheme 同步应用主题。源码面板中的原生实现仅供阅读,使用 npm 导出,不要单独复制内部实现。此批只覆盖 Core,不包括日期、图表和表单扩展包。上游详细说明保留英文,不宣称全文中文化。

可运行用法

以下代码使用资源原生 API;不是把其他设计系统的同名组件替换进来。

import { useState } from 'react';
import * as M from '@mantine/core';
import '@mantine/core/styles.css';


function ComponentPreview({ variant = 'Default' }: { variant?: string }) {
const disabled = variant === "Disabled";
const invalid = variant === "Invalid";
const readOnly = variant === "Read only";
return <M.JsonInput disabled={disabled} error={invalid ? "Invalid JSON / JSON 格式错误" : undefined} readOnly={readOnly} label="JSON" defaultValue={'{"name":"JGuang"}'} formatOnBlur autosize />;
}
export default function Example({ variant = 'Default', theme = 'light' }: { variant?: string; theme?: 'light' | 'dark' }) {
return <M.MantineProvider forceColorScheme={theme} theme={{ respectReducedMotion: true }}><ComponentPreview variant={variant} /></M.MantineProvider>;
}

可用状态与示例

默认、禁用、校验错误、只读

示例遵循 Mantine 原生 API。支持多状态的输入组件可将示例中的 variant 改为 Disabled、Invalid 或 Read only;这些只是示例标签,不是新增的组件属性。改造时保留组件要求的数据、受控值、store 和复合子组件结构。

Usage

JsonInput is based on the Textarea component. It includes JSON validation logic and an option to format the input value on blur:

Loading state

Set loading prop to display a loading indicator. By default, the loader is displayed on the right side of the input. You can change the position with the loadingPosition prop to 'left' or 'right'. This is useful for async operations like API calls, searches, or validations:

Controlled

import { useState } from 'react';
import { JsonInput } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState('');
  return <JsonInput value={value} onChange={setValue} />;
}

Uncontrolled

JsonInput can be used with uncontrolled forms the same way as a native textarea element. Set the name attribute to include json input value in FormData object on form submission. To control the initial value in uncontrolled forms, use the defaultValue prop.

Example usage of uncontrolled JsonInput with FormData:

import { JsonInput } from '@mantine/core';

function Demo() {
  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        const formData = new FormData(event.currentTarget);
        console.log('JSON input value:', formData.get('data'));
      }}
    >
      <JsonInput
        label="Enter JSON"
        name="data"
        defaultValue="{}"
        formatOnBlur
      />
      <button type="submit">Submit</button>
    </form>
  );
}

Custom serialization

You can provide custom serialize and deserialize functions to support data formats beyond standard JSON. This is useful when you need to handle types like Date, Map, Set, undefined, or other non-JSON-serializable values.

The example below shows how to use superjson library to handle extended data types:

import { useState } from 'react';
import { JsonInput } from '@mantine/core';
import superjson from 'superjson';

function Demo() {
  const [value, setValue] = useState(
    superjson.stringify(
      {
        name: 'John Doe',
        createdAt: new Date(),
        tags: new Set(['admin', 'user']),
        metadata: new Map([['role', 'developer']]),
      },
      null,
      2
    )
  );

  return (
    <JsonInput
      label="Extended JSON with superjson"
      description="Supports Date, Map, Set, BigInt, RegExp, and more"
      placeholder="Enter extended JSON"
      value={value}
      onChange={setValue}
      serialize={(val) => superjson.stringify(val, null, 2)}
      deserialize={superjson.parse}
      validationError="Invalid extended JSON format"
      formatOnBlur
      autosize
      minRows={6}
    />
  );
}

The deserialize function must throw an error when the input is invalid. Both serialize and deserialize functions are used for formatting when formatOnBlur is enabled.

Input props

Success state

Disabled state

源码参数参考

以下实现签名和类型从本地固定版本源码生成。保留可选属性、原生继承类型、联合分支和 never 限制;不会将其他设计系统的 API 混入。forwardRef 实现中的 ref 属于 React 引用,不是新增业务属性。此区域是原始类型参考,不是上游说明的全文翻译。

JsonInput(props)
export interface JsonInputProps extends Omit<TextareaProps, 'onChange'> {
  /** Controlled component value */
  value?: string;

  /** Uncontrolled component default value */
  defaultValue?: string;

  /** Called when value changes */
  onChange?: (value: string) => void;

  /** Determines whether the value should be formatted on blur @default false */
  formatOnBlur?: boolean;

  /** Error message shown when the input value is invalid JSON (checked on blur). If not provided, a generic error state is shown. Takes precedence over the `error` prop when validation fails. */
  validationError?: React.ReactNode;

  /** Function to serialize value into a string for formatting. Called with (value, null, 2) where 2 is the indentation level. @default JSON.stringify */
  serialize?: typeof JSON.stringify;

  /** Function to deserialize string value for formatting and validation. Must throw an error if the string is invalid JSON. @default JSON.parse */
  deserialize?: typeof JSON.parse;

  /** Number of spaces to use as white space for formatting. Passed as the third argument to `serialize` function. @default 2 */
  indentSpaces?: number;
}

export type JsonInputFactory = Factory<{
  props: JsonInputProps;
  ref: HTMLTextAreaElement;
  stylesNames: __InputStylesNames;
}>;

export type __InputStylesNames = InputStylesNames | InputWrapperStylesNames;

export type InputStylesNames = 'input' | 'wrapper' | 'section' | 'bottomSection';

export type InputWrapperStylesNames =
  | 'root'
  | InputLabelStylesNames
  | InputDescriptionStylesNames
  | InputErrorStylesNames
  | InputSuccessStylesNames;

原生与外部类型

以下外部类型仍由 React 或资源自身依赖定义,没有手工展开为虚构属性。实际可用类型以安装版本的 TypeScript 检查为准。

Factory<{
  props: JsonInputProps;
  ref: HTMLTextAreaElement;
  stylesNames: __InputStylesNames;
}>
Omit<TextareaProps, 'onChange'>
TextareaProps
React.ReactNode
HTMLTextAreaElement
InputLabelStylesNames
InputDescriptionStylesNames
InputErrorStylesNames
InputSuccessStylesNames