├── .browserslistrc
├── .commitlintrc.json
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .github
├── FUNDING.yml
├── dependabot.yml
└── workflows
│ ├── build-and-test.yml
│ ├── codeql-analysis.yml
│ ├── lint-check.yml
│ └── release-please.yml
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── .release-please-manifest.json
├── .yarn
├── plugins
│ └── @yarnpkg
│ │ └── plugin-interactive-tools.cjs
└── releases
│ └── yarn-3.2.4.cjs
├── .yarnrc.yml
├── 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
├── theme.config.js
└── tsconfig.json
├── package.json
├── 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
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | # sync with https://github.com/mui/material-ui/blob/v5.12.1/.browserslistrc#L12-L27
2 | and_chr 91
3 | and_ff 89
4 | and_qq 10.4
5 | and_uc 12.12
6 | # > I recommend removing android from the list because from polyfill side it is very close to and_chr or chrome
7 | # https://github.com/browserslist/browserslist/issues/753
8 | # android 91
9 | baidu 7.12
10 | chrome 90
11 | edge 91
12 | firefox 78
13 | # 12.4 but 12.2-12.5 are treated equally in caniuse-lite.
14 | # Though caniuse-lite does not supporting finding an exact version in a range which is why `12.4` would result in "Unknown version 12.4 of ios_saf"
15 | ios_saf 12.2
16 | kaios 2.5
17 | op_mini all
18 | # 76 -> 73 as caniuse database doesn't have 76 :/
19 | op_mob 73
20 |
--------------------------------------------------------------------------------
/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "@commitlint/config-angular"
4 | ],
5 | "rules": {
6 | "scope-case": [
7 | 2,
8 | "always",
9 | "pascal-case"
10 | ],
11 | "type-enum": [
12 | 2,
13 | "always",
14 | [
15 | "chore",
16 | "build",
17 | "ci",
18 | "docs",
19 | "feat",
20 | "fix",
21 | "perf",
22 | "refactor",
23 | "revert",
24 | "style",
25 | "test",
26 | "types",
27 | "workflow",
28 | "wip"
29 | ]
30 | ]
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/.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 | .yarn
3 | node_modules
4 |
--------------------------------------------------------------------------------
/.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/member-delimiter-style': [
122 | 'error', {
123 | multiline: {
124 | delimiter: 'none', requireLast: true
125 | },
126 | singleline: {
127 | delimiter: 'semi', requireLast: false
128 | }
129 | }],
130 | '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports', disallowTypeAnnotations: false }],
131 | '@typescript-eslint/explicit-function-return-type': 'off',
132 | 'react-hooks/rules-of-hooks': 'error',
133 | 'react-hooks/exhaustive-deps': 'warn',
134 | 'no-restricted-imports': 'off',
135 | '@typescript-eslint/no-restricted-imports': [
136 | 'error',
137 | {
138 | patterns: [
139 | {
140 | group: ['**/dist'],
141 | message: 'Don\'t import from dist',
142 | allowTypeImports: false
143 | }
144 | ]
145 | }
146 | ]
147 | },
148 | overrides: [
149 | {
150 | files: ['*.d.ts'],
151 | rules: {
152 | 'no-undef': 'off'
153 | }
154 | },
155 | {
156 | files: ['*.test.ts', '*.test.tsx'], env: { jest: true }
157 | }
158 | ]
159 | }
160 |
--------------------------------------------------------------------------------
/.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 | open-pull-requests-limit: 3
9 |
--------------------------------------------------------------------------------
/.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@v3
21 | with:
22 | fetch-depth: 0
23 | - name: Use Node.js LTS
24 | uses: actions/setup-node@v3
25 | with:
26 | node-version-file: '.nvmrc'
27 | cache: 'yarn'
28 | - name: Get yarn cache directory path
29 | id: yarn-cache-dir-path
30 | run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
31 | - uses: actions/cache@v3
32 | id: yarn-cache
33 | with:
34 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
35 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
36 | restore-keys: |
37 | ${{ runner.os }}-yarn-
38 | - name: Install Dependencies
39 | run: yarn install
40 | - name: Build
41 | run: yarn build
42 | - name: Test with Coverage
43 | run: yarn coverage
44 | - uses: codecov/codecov-action@v3
45 | with:
46 | token: ${{ secrets.CODECOV_TOKEN }}
47 |
--------------------------------------------------------------------------------
/.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@v3
30 | - name: Initialize CodeQL
31 | uses: github/codeql-action/init@v2
32 | with:
33 | languages: ${{ matrix.language }}
34 | - name: Autobuild
35 | uses: github/codeql-action/autobuild@v2
36 | - name: Perform CodeQL Analysis
37 | uses: github/codeql-action/analyze@v2
38 | with:
39 | category: "/language:${{matrix.language}}"
40 |
--------------------------------------------------------------------------------
/.github/workflows/lint-check.yml:
--------------------------------------------------------------------------------
1 | name: Lint Check
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 | paths:
15 | - '**.tsx?'
16 | - '**.jsx?'
17 | jobs:
18 | lint-check:
19 | name: ESLint check
20 | runs-on: ubuntu-latest
21 | steps:
22 | - uses: actions/checkout@v3
23 | with:
24 | fetch-depth: 0
25 | - name: Use Node.js LTS
26 | uses: actions/setup-node@v3
27 | with:
28 | node-version-file: '.nvmrc'
29 | cache: 'yarn'
30 | - name: Get yarn cache directory path
31 | id: yarn-cache-dir-path
32 | run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
33 | - uses: actions/cache@v3
34 | id: yarn-cache
35 | with:
36 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
37 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
38 | restore-keys: |
39 | ${{ runner.os }}-yarn-
40 | - name: Install Dependencies
41 | run: yarn install
42 | - name: Lint
43 | run: yarn lint:ci
44 |
--------------------------------------------------------------------------------
/.github/workflows/release-please.yml:
--------------------------------------------------------------------------------
1 | name: Release Please
2 | on:
3 | push:
4 | branches:
5 | - main
6 | jobs:
7 | release-please:
8 | runs-on: ubuntu-latest
9 | outputs:
10 | releases_created: ${{ steps.release.outputs.releases_created }}
11 | steps:
12 | - uses: google-github-actions/release-please-action@v3
13 | id: release
14 | with:
15 | command: manifest
16 | token: ${{secrets.GITHUB_TOKEN}}
17 | publish-json-viewer:
18 | name: 'Publish @textea/json-viewer'
19 | needs: release-please
20 | if: ${{ needs.release-please.outputs.releases_created }}
21 | runs-on: ubuntu-latest
22 | steps:
23 | - name: Checkout repository
24 | uses: actions/checkout@v3
25 | - name: Use Node.js LTS
26 | uses: actions/setup-node@v3
27 | with:
28 | node-version-file: '.nvmrc'
29 | cache: 'yarn'
30 | registry-url: 'https://registry.npmjs.org'
31 | - name: Get yarn cache directory path
32 | id: yarn-cache-dir-path
33 | run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
34 | - uses: actions/cache@v3
35 | id: yarn-release-cache
36 | with:
37 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
38 | key: ${{ runner.os }}-yarn-release-${{ hashFiles('**/yarn.lock') }}
39 | restore-keys: |
40 | ${{ runner.os }}-yarn-release
41 | - name: Install Dependencies
42 | run: |
43 | yarn install
44 | - name: Prepack
45 | run: yarn run prepack
46 | - name: Build
47 | run: npm run build
48 | - name: Delete Scripts
49 | run: npm pkg delete scripts
50 | - name: Delete Workspaces
51 | run: npm pkg delete workspaces
52 | - uses: JS-DevTools/npm-publish@v1
53 | name: Publish to npm
54 | with:
55 | access: 'public'
56 | token: ${{ secrets.NPM_TOKEN }}
57 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.yarn/*
2 | **/!.yarn/patches
3 | **/!.yarn/plugins
4 | **/!.yarn/releases
5 | **/!.yarn/sdks
6 | **/!.yarn/versions
7 |
8 | # Swap the comments on the following lines if you don't wish to use zero-installs
9 | # Documentation here: https://yarnpkg.com/features/zero-installs
10 | #!.yarn/cache
11 | .pnp.*
12 |
13 | dist
14 | tsconfig.tsbuildinfo
15 | .eslintcache
16 | node_modules
17 |
18 | .next
19 | .vercel
20 | coverage
21 |
22 | .idea
23 | .vscode
24 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx --no-install commitlint --edit $1
5 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx --no-install lint-staged
5 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/*
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .github/
2 | .husky/
3 | package.json
4 | yarn-error.log
5 | yarn.lock
6 |
7 | *generated*
8 | storybook-static
9 |
10 | # document
11 | *.mdx
12 |
13 | # VSCode personal settings
14 | .vscode/launch.json
15 | .vscode/tasks.json
16 |
17 | # JetBrain personal settings
18 | .idea
19 |
20 | # testing
21 | /reports
22 | /junit.xml
23 |
24 | # Build out
25 | dist/*
26 | /build
27 | /storybook-static
28 |
29 | # Environment files
30 | .env.local
31 | .env.development.local
32 | .env.test.local
33 | .env.production.local
34 |
35 | # Block-chain contract files
36 | /contracts
37 |
38 | # Temp profiles
39 | .firefox
40 | .chrome
41 |
42 | # Following content is copied from https://github.com/github/gitignore/blob/master/Node.gitignore
43 | # Logs
44 | logs
45 | *.log
46 | npm-debug.log*
47 | yarn-debug.log*
48 | yarn-error.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 |
153 | # yarn v2
154 | .yarn/cache
155 | .yarn/unplugged
156 | .yarn/build-state.yml
157 | .yarn/install-state.gz
158 | .pnp.*
159 |
--------------------------------------------------------------------------------
/.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 | ".": "3.0.0"
3 | }
4 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nmMode: hardlinks-local
2 |
3 | nodeLinker: node-modules
4 |
5 | npmAuthToken: "${NODE_AUTH_TOKEN:-NONE}"
6 |
7 | npmPublishAccess: public
8 |
9 | npmPublishRegistry: "https://registry.npmjs.org"
10 |
11 | plugins:
12 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
13 | spec: "@yarnpkg/plugin-interactive-tools"
14 |
15 | yarnPath: .yarn/releases/yarn-3.2.4.cjs
16 |
--------------------------------------------------------------------------------
/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-v2-afaey9?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 | //