├── .browserslistrc
├── .commitlintrc.json
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .github
├── FUNDING.yml
├── dependabot.yml
└── workflows
│ ├── build-and-test.yml
│ ├── codeql-analysis.yml
│ └── release-please.yml
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── .release-please-manifest.json
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── docs
├── .gitignore
├── examples
│ ├── JsonViewerCustomizeDate.tsx
│ ├── JsonViewerPreview.tsx
│ ├── JsonViewerToggleBoolean.tsx
│ ├── JsonViewerWithImage.tsx
│ ├── JsonViewerWithURL.tsx
│ └── JsonViewerWithWidget.tsx
├── hooks
│ └── useTheme.ts
├── lib
│ └── shared.ts
├── next.config.mjs
├── package.json
├── pages
│ ├── _app.mdx
│ ├── _meta.json
│ ├── apis.mdx
│ ├── full
│ │ └── index.tsx
│ ├── how-to
│ │ ├── _meta.json
│ │ ├── built-in-types.mdx
│ │ ├── data-types.mdx
│ │ └── styling.mdx
│ ├── index.mdx
│ └── migration
│ │ ├── _meta.json
│ │ ├── migration-v3.mdx
│ │ └── migration-v4.mdx
├── theme.config.js
└── tsconfig.json
├── package.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── public
├── avatar-preview.png
└── ocean-theme.png
├── release-please-config.json
├── rollup.config.ts
├── src
├── browser.tsx
├── components
│ ├── DataKeyPair.tsx
│ ├── DataTypeLabel.tsx
│ ├── DataTypes
│ │ ├── Boolean.tsx
│ │ ├── Date.tsx
│ │ ├── Function.tsx
│ │ ├── Null.tsx
│ │ ├── Number.tsx
│ │ ├── Object.tsx
│ │ ├── String.tsx
│ │ ├── Undefined.tsx
│ │ ├── defineEasyType.tsx
│ │ └── index.ts
│ ├── Icons.tsx
│ └── mui
│ │ └── DataBox.tsx
├── hooks
│ ├── useColor.ts
│ ├── useCopyToClipboard.ts
│ ├── useInspect.ts
│ ├── useIsCycleReference.ts
│ └── useThemeDetector.ts
├── index.tsx
├── stores
│ ├── JsonViewerStore.ts
│ └── typeRegistry.tsx
├── theme
│ └── base16.ts
├── type.ts
└── utils
│ └── index.ts
├── tests
├── index.test.tsx
├── setup.ts
├── tsconfig.json
└── util.test.tsx
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
/.browserslistrc:
--------------------------------------------------------------------------------
1 | # sync with https://github.com/mui/material-ui/blob/v6.1.0/.browserslistrc#L17-L73
2 | and_chr 122
3 | and_chr 121
4 | and_ff 123
5 | and_ff 122
6 | and_qq 14.9
7 | and_uc 15.5
8 | # android 122
9 | # android 121
10 | chrome 122
11 | chrome 121
12 | chrome 120
13 | chrome 119
14 | chrome 109
15 | edge 122
16 | edge 121
17 | firefox 123
18 | firefox 122
19 | firefox 115
20 | ios_saf 17.4
21 | ios_saf 17.3
22 | ios_saf 17.2
23 | ios_saf 17.1
24 | ios_saf 17.0
25 | ios_saf 16.6-16.7
26 | ios_saf 16.5
27 | ios_saf 16.4
28 | ios_saf 16.3
29 | ios_saf 16.2
30 | ios_saf 16.1
31 | ios_saf 16.0
32 | ios_saf 15.6-15.8
33 | ios_saf 15.5
34 | ios_saf 15.4
35 | kaios 3.0-3.1
36 | kaios 2.5
37 | op_mini all
38 | op_mob 80
39 | opera 108
40 | opera 107
41 | opera 106
42 | safari 17.4
43 | safari 17.3
44 | safari 17.2
45 | safari 17.1
46 | safari 17.0
47 | safari 16.6
48 | safari 16.5
49 | safari 16.4
50 | safari 16.3
51 | safari 16.2
52 | safari 16.1
53 | safari 16.0
54 | safari 15.6
55 | safari 15.5
56 | safari 15.4
57 | samsung 23
58 | samsung 22
59 |
--------------------------------------------------------------------------------
/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@commitlint/config-conventional"],
3 | "rules": {
4 | "scope-case": [2, "always", "lower-case"],
5 | "type-enum": [
6 | 2,
7 | "always",
8 | [
9 | "chore",
10 | "build",
11 | "ci",
12 | "docs",
13 | "feat",
14 | "fix",
15 | "perf",
16 | "refactor",
17 | "revert",
18 | "style",
19 | "test",
20 | "types",
21 | "workflow",
22 | "wip"
23 | ]
24 | ]
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 |
7 | [{*.js, *.jsx, *.ts, *.tsx, *.json, *.yml, *.yaml}]
8 | charset = utf-8
9 | indent_style = space
10 | indent_size = 2
11 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | settings: {
4 | react: {
5 | version: 'detect'
6 | }
7 | },
8 | env: {
9 | browser: true, es6: true
10 | },
11 | extends: [
12 | 'eslint:recommended',
13 | 'plugin:react/recommended',
14 | 'plugin:react/jsx-runtime',
15 | 'standard'
16 | ],
17 | globals: {
18 | Atomics: 'readonly', SharedArrayBuffer: 'readonly'
19 | },
20 | parser: '@typescript-eslint/parser',
21 | parserOptions: {
22 | ecmaFeatures: {
23 | globalReturn: false, impliedStrict: true, jsx: true
24 | },
25 | ecmaVersion: 'latest',
26 | sourceType: 'module'
27 | },
28 | plugins: [
29 | 'react',
30 | 'react-hooks',
31 | '@typescript-eslint',
32 | 'simple-import-sort',
33 | 'import',
34 | 'unused-imports'
35 | ],
36 | rules: {
37 | eqeqeq: 'error',
38 | 'no-eval': 'error',
39 | 'no-var': 'error',
40 | 'prefer-const': 'error',
41 | 'sort-imports': 'off',
42 | 'import/order': 'off',
43 | 'simple-import-sort/imports': 'error',
44 | 'simple-import-sort/exports': 'error',
45 | 'import/first': 'error',
46 | 'import/newline-after-import': 'error',
47 | 'import/no-duplicates': 'error',
48 | 'no-unused-vars': 'off',
49 | 'unused-imports/no-unused-imports': 'error',
50 | 'unused-imports/no-unused-vars': [
51 | 'warn', {
52 | vars: 'all',
53 | varsIgnorePattern: '^_',
54 | args: 'after-used',
55 | argsIgnorePattern: '^_'
56 | }],
57 | 'no-use-before-define': 'off',
58 | '@typescript-eslint/no-use-before-define': ['error'],
59 | 'no-redeclare': 'off',
60 | '@typescript-eslint/no-redeclare': ['error'],
61 | 'no-unused-expressions': 'warn',
62 | 'react/jsx-filename-extension': [
63 | 1, {
64 | extensions: ['.js', '.jsx', '.ts', '.tsx']
65 | }],
66 | 'import/prefer-default-export': 'off',
67 | 'jsx-quotes': ['error', 'prefer-single'],
68 | camelcase: 'off',
69 | 'react/prop-types': 'off',
70 | 'react/display-name': 'off',
71 | indent: ['error', 2, {
72 | SwitchCase: 1,
73 | offsetTernaryExpressions: true,
74 | // from: https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/style.js
75 | ignoredNodes: [
76 | 'JSXElement',
77 | 'JSXElement :not(JSXExpressionContainer, JSXExpressionContainer *)',
78 | 'JSXAttribute',
79 | 'JSXIdentifier',
80 | 'JSXNamespacedName',
81 | 'JSXMemberExpression',
82 | 'JSXSpreadAttribute',
83 | 'JSXOpeningElement',
84 | 'JSXClosingElement',
85 | 'JSXFragment',
86 | 'JSXOpeningFragment',
87 | 'JSXClosingFragment',
88 | 'JSXText',
89 | 'JSXEmptyExpression',
90 | 'JSXSpreadChild'
91 | ]
92 | }],
93 | 'react/jsx-indent': ['error', 2, { checkAttributes: false, indentLogicalExpressions: true }],
94 | 'react/jsx-indent-props': ['error', 2],
95 | 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
96 | 'react/jsx-closing-bracket-location': ['error', 'tag-aligned'],
97 | 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
98 | 'react/jsx-tag-spacing': ['error', {
99 | closingSlash: 'never',
100 | beforeSelfClosing: 'always',
101 | afterOpening: 'never',
102 | beforeClosing: 'never'
103 | }],
104 | 'react/jsx-wrap-multilines': ['error', {
105 | declaration: 'parens-new-line',
106 | assignment: 'parens-new-line',
107 | return: 'parens-new-line',
108 | arrow: 'parens-new-line',
109 | condition: 'parens-new-line',
110 | logical: 'parens-new-line',
111 | prop: 'parens-new-line'
112 | }],
113 | 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
114 | 'react/jsx-curly-newline': ['error', {
115 | multiline: 'consistent',
116 | singleline: 'consistent'
117 | }],
118 | '@typescript-eslint/no-var-requires': 'off',
119 | '@typescript-eslint/camelcase': 'off',
120 | '@typescript-eslint/ban-ts-ignore': 'off',
121 | '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports', disallowTypeAnnotations: false }],
122 | '@typescript-eslint/explicit-function-return-type': 'off',
123 | 'react-hooks/rules-of-hooks': 'error',
124 | 'react-hooks/exhaustive-deps': 'warn',
125 | 'no-restricted-imports': 'off',
126 | '@typescript-eslint/no-restricted-imports': [
127 | 'error',
128 | {
129 | patterns: [
130 | {
131 | group: ['**/dist'],
132 | message: 'Don\'t import from dist',
133 | allowTypeImports: false
134 | }
135 | ]
136 | }
137 | ]
138 | },
139 | overrides: [
140 | {
141 | files: ['*.d.ts'],
142 | rules: {
143 | 'no-undef': 'off'
144 | }
145 | },
146 | {
147 | files: ['*.test.ts', '*.test.tsx'], env: { jest: true }
148 | }
149 | ]
150 | }
151 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [TexteaInc]
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: weekly
7 | versioning-strategy: increase # Update package.json too
8 | groups:
9 | patterns:
10 | update-types:
11 | - "minor"
12 | - "patch"
--------------------------------------------------------------------------------
/.github/workflows/build-and-test.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - '**.tsx?'
9 | - '**.jsx?'
10 | pull_request:
11 | branches:
12 | - main
13 | - v3.x
14 |
15 | jobs:
16 | test:
17 | name: Running vitest
18 | runs-on: ubuntu-latest
19 | steps:
20 | - uses: actions/checkout@v4
21 | with:
22 | fetch-depth: 0
23 |
24 | - name: Install pnpm
25 | uses: pnpm/action-setup@v4
26 |
27 | - name: Use Node.js LTS
28 | uses: actions/setup-node@v4
29 | with:
30 | node-version-file: '.nvmrc'
31 | cache: 'pnpm'
32 |
33 | - name: Install Dependencies
34 | run: pnpm install
35 |
36 | - name: Lint
37 | run: pnpm run lint:ci
38 |
39 | - name: Build
40 | run: pnpm run build
41 |
42 | - name: Test with Coverage
43 | run: pnpm run coverage
44 |
45 | - uses: codecov/codecov-action@v4
46 | with:
47 | token: ${{ secrets.CODECOV_TOKEN }}
48 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - '**.tsx?'
9 | - '**.jsx?'
10 | pull_request:
11 | branches:
12 | - main
13 | - v3.x
14 |
15 | jobs:
16 | analyze:
17 | name: Analyze
18 | runs-on: ubuntu-latest
19 | permissions:
20 | actions: read
21 | contents: read
22 | security-events: write
23 | strategy:
24 | fail-fast: false
25 | matrix:
26 | language: [ 'javascript' ]
27 | steps:
28 | - name: Checkout repository
29 | uses: actions/checkout@v4
30 | - name: Initialize CodeQL
31 | uses: github/codeql-action/init@v3
32 | with:
33 | languages: ${{ matrix.language }}
34 | - name: Autobuild
35 | uses: github/codeql-action/autobuild@v3
36 | - name: Perform CodeQL Analysis
37 | uses: github/codeql-action/analyze@v3
38 | with:
39 | category: "/language:${{matrix.language}}"
40 |
--------------------------------------------------------------------------------
/.github/workflows/release-please.yml:
--------------------------------------------------------------------------------
1 | name: Release Please
2 | on:
3 | push:
4 | branches:
5 | - main
6 | jobs:
7 | release:
8 | name: 'Release Please'
9 | runs-on: ubuntu-latest
10 | outputs:
11 | release_created: ${{ steps.release.outputs.release_created }}
12 | steps:
13 | - uses: googleapis/release-please-action@v4
14 | id: release
15 | with:
16 | token: ${{secrets.GITHUB_TOKEN}}
17 | publish:
18 | name: 'Publish @textea/json-viewer'
19 | needs: release
20 | if: needs.release.outputs.release_created
21 | runs-on: ubuntu-latest
22 | permissions:
23 | contents: read
24 | id-token: write
25 | steps:
26 | - name: Checkout repository
27 | uses: actions/checkout@v4
28 |
29 | - name: Use Node.js LTS
30 | uses: actions/setup-node@v4
31 | with:
32 | node-version: 20
33 | cache: 'pnpm'
34 |
35 | - name: Install pnpm
36 | uses: pnpm/action-setup@v4
37 |
38 | - name: Use Node.js LTS
39 | uses: actions/setup-node@v4
40 | with:
41 | node-version-file: '.nvmrc'
42 | cache: 'pnpm'
43 |
44 | - name: Install Dependencies
45 | run: pnpm install
46 |
47 | - name: Prepack
48 | run: pnpm run prepack
49 |
50 | - name: Build
51 | run: npm run build
52 |
53 | - name: Clean package.json
54 | run: |
55 | npm pkg delete scripts
56 | npm pkg delete lint-staged
57 |
58 | - name: Publish to npm
59 | run: npm publish --provenance --access public
60 | env:
61 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 | pnpm-debug.log*
10 | lerna-debug.log*
11 |
12 | # yarn
13 | **/.yarn/*
14 | **/!.yarn/patches
15 | **/!.yarn/plugins
16 | **/!.yarn/releases
17 | **/!.yarn/sdks
18 | **/!.yarn/versions
19 |
20 | node_modules
21 | dist
22 | dist-ssr
23 | coverage
24 | *.local
25 | .idea
26 | .vscode
27 | .next
28 | .vercel
29 |
30 | # Editor directories and files
31 | .vscode/*
32 | !.vscode/extensions.json
33 | .idea
34 | .DS_Store
35 | *.suo
36 | *.ntvs*
37 | *.njsproj
38 | *.sln
39 | *.sw?
40 |
41 | # cache
42 | tsconfig.tsbuildinfo
43 | .eslintcache
44 | node_modules
45 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | npx --no-install commitlint --edit $1
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx --no-install lint-staged
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/*
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .github/
2 | .husky/
3 | package.json
4 | pnpm-lock.yaml
5 |
6 | *generated*
7 | storybook-static
8 |
9 | # document
10 | *.mdx
11 |
12 | # VSCode personal settings
13 | .vscode/launch.json
14 | .vscode/tasks.json
15 |
16 | # JetBrain personal settings
17 | .idea
18 |
19 | # testing
20 | /reports
21 | /junit.xml
22 |
23 | # Build out
24 | dist/*
25 | /build
26 | /storybook-static
27 |
28 | # Environment files
29 | .env.local
30 | .env.development.local
31 | .env.test.local
32 | .env.production.local
33 |
34 | # Block-chain contract files
35 | /contracts
36 |
37 | # Temp profiles
38 | .firefox
39 | .chrome
40 |
41 | # Following content is copied from https://github.com/github/gitignore/blob/master/Node.gitignore
42 | # Logs
43 | logs
44 | *.log
45 | npm-debug.log*
46 | yarn-debug.log*
47 | yarn-error.log*
48 | pnpm-debug.log*
49 | lerna-debug.log*
50 |
51 | # Diagnostic reports (https://nodejs.org/api/report.html)
52 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
53 |
54 | # Runtime data
55 | pids
56 | *.pid
57 | *.seed
58 | *.pid.lock
59 |
60 | # Directory for instrumented libs generated by jscoverage/JSCover
61 | lib-cov
62 |
63 | # Coverage directory used by tools like istanbul
64 | coverage
65 | *.lcov
66 |
67 | # nyc test coverage
68 | .nyc_output
69 |
70 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
71 | .grunt
72 |
73 | # Bower dependency directory (https://bower.io/)
74 | bower_components
75 |
76 | # node-waf configuration
77 | .lock-wscript
78 |
79 | # Compiled binary addons (https://nodejs.org/api/addons.html)
80 | build/Release
81 |
82 | # Dependency directories
83 | node_modules/
84 | jspm_packages/
85 |
86 | # Snowpack dependency directory (https://snowpack.dev/)
87 | web_modules/
88 |
89 | # TypeScript cache
90 | *.tsbuildinfo
91 |
92 | # Optional npm cache directory
93 | .npm
94 |
95 | # Optional eslint cache
96 | .eslintcache
97 |
98 | # Microbundle cache
99 | .rpt2_cache/
100 | .rts2_cache_cjs/
101 | .rts2_cache_es/
102 | .rts2_cache_umd/
103 |
104 | # Optional REPL history
105 | .node_repl_history
106 |
107 | # Output of 'npm pack'
108 | *.tgz
109 |
110 | # Yarn Integrity file
111 | .yarn-integrity
112 |
113 | # dotenv environment variables file
114 | .env
115 | .env.test
116 |
117 | # parcel-bundler cache (https://parceljs.org/)
118 | .cache
119 | .parcel-cache
120 |
121 | # Next.js build output
122 | .next
123 | out
124 |
125 | # Nuxt.js build / generate output
126 | .nuxt
127 | dist
128 |
129 | # Gatsby files
130 | .cache/
131 | # Comment in the public line in if your project uses Gatsby and not Next.js
132 | # https://nextjs.org/blog/next-9-1#public-directory-support
133 | # public
134 |
135 | # vuepress build output
136 | .vuepress/dist
137 |
138 | # Serverless directories
139 | .serverless/
140 |
141 | # FuseBox cache
142 | .fusebox/
143 |
144 | # DynamoDB Local files
145 | .dynamodb/
146 |
147 | # TernJS port file
148 | .tern-port
149 |
150 | # Stores VSCode versions used for testing VSCode extensions
151 | .vscode-test
152 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "semi": false,
4 | "singleQuote": true,
5 | "trailingComma": "none",
6 | "bracketSameLine": true
7 | }
8 |
--------------------------------------------------------------------------------
/.release-please-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | ".": "4.0.1"
3 | }
4 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | bao at textea dot co.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-2023 Textea, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # @textea/json-viewer
2 |
3 | [](https://www.npmjs.com/package/@textea/json-viewer)
4 | [](https://www.npmjs.com/package/@textea/json-viewer)
5 | [](https://github.com/TexteaInc/json-viewer/blob/main/LICENSE)
6 | [](https://codecov.io/gh/TexteaInc/json-viewer)
7 | [](https://viewer.textea.io)
8 |
9 | `@textea/json-viewer` is a React component that can be used to view and display any kind of data, not just JSON.
10 |
11 | ~~Json Viewer?~~
12 | **ANY Data Viewer** ✅
13 |
14 | [](https://stackblitz.com/edit/textea-json-viewer-v4-b4wgxq-qzsnukyr?file=pages%2Findex.js)
15 |
16 | ## Features 🚀
17 |
18 | - 🦾 100% TypeScript
19 | - 🎨 Customizable: Key, value, editable, copy, select... Anything you can think of!
20 | - 🌈 Theme support: light or dark, or use [Base16](https://github.com/chriskempson/base16) themes.
21 | - ⚛️ SSR Ready
22 | - 📋 Copy to Clipboard
23 | - 🔍 Inspect anything: `Object`, `Array`, primitive types, and even `Map` and `Set`.
24 | - 📊 Metadata preview: Total items, length of string...
25 | - ✏️ Editor: Comes with an editor for basic types, which you can also customize to fit your use case.
26 |
27 | ## Installation
28 |
29 | `@textea/json-viewer` is using [Material-UI](https://mui.com/) as the base component library, so you need to install it and its peer dependencies first.
30 |
31 | ```sh
32 | npm install @textea/json-viewer @mui/material @emotion/react @emotion/styled
33 | ```
34 |
35 | ### CDN
36 |
37 | ```html
38 |
39 |
40 |
41 |
42 |
43 |
50 |
51 |
52 | ```
53 |
54 | ## Usage
55 |
56 | Here is a basic example:
57 |
58 | ```jsx
59 | import { JsonViewer } from '@textea/json-viewer'
60 |
61 | const object = {
62 | /* my json object */
63 | }
64 | const Component = () =>
65 | ```
66 |
67 | ### Customization
68 |
69 | You can define custom data types to handle data that is not supported out of the box. Here is an example of how to display an image:
70 |
71 | ```jsx
72 | import { JsonViewer, defineDataType } from '@textea/json-viewer'
73 |
74 | const object = {
75 | image: 'https://i.imgur.com/1bX5QH6.jpg'
76 | // ... other values
77 | }
78 |
79 | // Let's define a data type for image
80 | const imageDataType = defineDataType({
81 | is: (value) => typeof value === 'string' && value.startsWith('https://i.imgur.com'),
82 | Component: (props) =>
83 | })
84 |
85 | const Component = () =>
86 | ```
87 |
88 | 
89 |
90 | [see the full code](docs/pages/full/index.tsx)
91 |
92 | ## Theme
93 |
94 | Please refer to [Styling and Theming](https://viewer.textea.io/how-to/styling)
95 |
96 | 
97 |
98 | ## Contributors
99 |
100 |
101 |
102 | ## Acknowledge
103 |
104 | This package is originally based on [mac-s-g/react-json-view](https://github.com/mac-s-g/react-json-view).
105 |
106 | Also thanks open source projects that make this possible.
107 |
108 | ## Sponsoring services
109 |
110 | 
111 |
112 | [Netlify](https://www.netlify.com/) lets us distribute the [site](https://viewer.textea.io).
113 |
114 | ## LICENSE
115 |
116 | This project is licensed under the terms of the [MIT license](LICENSE).
117 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
38 | # nextra
39 | public/feed.xml
40 |
--------------------------------------------------------------------------------
/docs/examples/JsonViewerCustomizeDate.tsx:
--------------------------------------------------------------------------------
1 | import { defineEasyType, JsonViewer } from '@textea/json-viewer'
2 | import type { FC } from 'react'
3 |
4 | import { useNextraTheme } from '../hooks/useTheme'
5 |
6 | const myDateType = defineEasyType({
7 | is: (value) => value instanceof Date,
8 | type: 'date',
9 | colorKey: 'base0D',
10 | Renderer: ({ value }) => <>{value.toISOString().split('T')[0]}>
11 | })
12 |
13 | const value = {
14 | date: new Date('2023/04/12 12:34:56')
15 | }
16 |
17 | const Example: FC = () => {
18 | const theme = useNextraTheme()
19 | return (
20 |
27 | )
28 | }
29 |
30 | export default Example
31 |
--------------------------------------------------------------------------------
/docs/examples/JsonViewerPreview.tsx:
--------------------------------------------------------------------------------
1 | import type { JsonViewerProps } from '@textea/json-viewer'
2 | import { JsonViewer } from '@textea/json-viewer'
3 | import type { FC } from 'react'
4 |
5 | import { useNextraTheme } from '../hooks/useTheme'
6 |
7 | export const JsonViewerPreview: FC = (props) => {
8 | const theme = useNextraTheme()
9 | return (
10 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/docs/examples/JsonViewerToggleBoolean.tsx:
--------------------------------------------------------------------------------
1 | import type { JsonViewerOnChange } from '@textea/json-viewer'
2 | import { applyValue, booleanType, defineDataType, defineEasyType, JsonViewer } from '@textea/json-viewer'
3 | import type { FC } from 'react'
4 | import { useCallback, useMemo, useState } from 'react'
5 |
6 | import { useNextraTheme } from '../hooks/useTheme'
7 |
8 | const value = {
9 | agree: true,
10 | disagree: false,
11 | description: 'Click the ✔️ ❌ to toggle the boolean value'
12 | }
13 |
14 | export const JsonViewerToggleBoolean1: FC = () => {
15 | const theme = useNextraTheme()
16 | const [src, setSrc] = useState(value)
17 | const onChange = useCallback(
18 | (path, oldValue, newValue) => {
19 | setSrc(src => applyValue(src, path, newValue))
20 | }, [])
21 |
22 | const toggleBoolType = useMemo(() => {
23 | return defineDataType({
24 | ...booleanType,
25 | Component: ({ value, path }) => (
26 | onChange(path, value, !value)}>
27 | {value ? '✔️' : '❌'}
28 |
29 | )
30 | })
31 | }, [onChange])
32 |
33 | return (
34 |
42 | )
43 | }
44 |
45 | export const JsonViewerToggleBoolean2: FC = () => {
46 | const theme = useNextraTheme()
47 | const [src, setSrc] = useState(value)
48 | const onChange = useCallback(
49 | (path, oldValue, newValue) => {
50 | setSrc(src => applyValue(src, path, newValue))
51 | }, [])
52 |
53 | const toggleBoolType = useMemo(() => {
54 | return defineEasyType({
55 | ...booleanType,
56 | type: 'bool',
57 | colorKey: 'base0E',
58 | Renderer: ({ value, path }) => (
59 | onChange(path, value, !value)}>
60 | {value ? '✔️' : '❌'}
61 |
62 | )
63 | })
64 | }, [onChange])
65 |
66 | return (
67 |
75 | )
76 | }
77 |
--------------------------------------------------------------------------------
/docs/examples/JsonViewerWithImage.tsx:
--------------------------------------------------------------------------------
1 | import { defineDataType, JsonViewer } from '@textea/json-viewer'
2 | import type { FC } from 'react'
3 |
4 | import { useNextraTheme } from '../hooks/useTheme'
5 |
6 | const imageType = defineDataType({
7 | is: (value) => {
8 | if (typeof value !== 'string') return false
9 | try {
10 | const url = new URL(value)
11 | return url.pathname.endsWith('.jpg')
12 | } catch {
13 | return false
14 | }
15 | },
16 | Component: (props) => {
17 | return (
18 |
25 | )
26 | }
27 | })
28 |
29 | const value = {
30 | image: 'https://i.imgur.com/1bX5QH6.jpg'
31 | }
32 |
33 | const Example: FC = () => {
34 | const theme = useNextraTheme()
35 | return (
36 |
43 | )
44 | }
45 |
46 | export default Example
47 |
--------------------------------------------------------------------------------
/docs/examples/JsonViewerWithURL.tsx:
--------------------------------------------------------------------------------
1 | import { defineDataType, JsonViewer } from '@textea/json-viewer'
2 | import type { FC } from 'react'
3 |
4 | import { useNextraTheme } from '../hooks/useTheme'
5 |
6 | const urlType = defineDataType({
7 | is: (value) => value instanceof URL,
8 | Component: (props) => {
9 | const url = props.value.toString()
10 | return (
11 |
21 | {url}
22 |
23 | )
24 | }
25 | })
26 |
27 | const value = {
28 | string: 'this is a string',
29 | url: new URL('https://example.com')
30 | }
31 |
32 | const Example: FC = () => {
33 | const theme = useNextraTheme()
34 | return (
35 |
42 | )
43 | }
44 |
45 | export default Example
46 |
--------------------------------------------------------------------------------
/docs/examples/JsonViewerWithWidget.tsx:
--------------------------------------------------------------------------------
1 | import type { SvgIconProps } from '@mui/material'
2 | import { Button, SvgIcon } from '@mui/material'
3 | import { defineDataType, JsonViewer, stringType } from '@textea/json-viewer'
4 | import type { FC } from 'react'
5 |
6 | import { useNextraTheme } from '../hooks/useTheme'
7 |
8 | const LinkIcon = (props: SvgIconProps) => (
9 | //