@miman/json-schema-viewer-react 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,434 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("react/jsx-runtime"),j=require("react");function q(){return`
2
+ :root {
3
+ --bg-color: #1e1e1e;
4
+ --text-color: #d4d4d4;
5
+ --border-color: #3c3c3c;
6
+ --header-bg: #252526;
7
+ --type-string: #ce9178;
8
+ --type-number: #b5cea8;
9
+ --type-boolean: #569cd6;
10
+ --type-array: #dcdcaa;
11
+ --type-object: #4ec9b0;
12
+ --type-null: #808080;
13
+ --required-color: #d18616; /* Orange */
14
+ --missing-color: #f14c4c; /* Red */
15
+ --description-color: #6a9955;
16
+ --property-name: #9cdcfe;
17
+ --expand-icon: #808080;
18
+ --hover-bg: #2a2d2e;
19
+ }
20
+
21
+ @media (prefers-color-scheme: light) {
22
+ :root {
23
+ --bg-color: #ffffff;
24
+ --text-color: #333333;
25
+ --border-color: #e0e0e0;
26
+ --header-bg: #f5f5f5;
27
+ --type-string: #a31515;
28
+ --type-number: #098658;
29
+ --type-boolean: #0000ff;
30
+ --type-array: #795e26;
31
+ --type-object: #267f99;
32
+ --type-null: #808080;
33
+ --required-color: #b85a00; /* Darker Orange */
34
+ --missing-color: #d32f2f; /* Darker Red */
35
+ --description-color: #008000;
36
+ --property-name: #001080;
37
+ --expand-icon: #666666;
38
+ --hover-bg: #f0f0f0;
39
+ }
40
+ }
41
+
42
+ * {
43
+ box-sizing: border-box;
44
+ margin: 0;
45
+ padding: 0;
46
+ }
47
+
48
+ body {
49
+ font-family: var(--vscode-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif);
50
+ font-size: 13px;
51
+ line-height: 1.5;
52
+ color: var(--text-color);
53
+ background-color: var(--bg-color);
54
+ padding: 16px;
55
+ }
56
+
57
+ .schema-container {
58
+ max-width: 1200px;
59
+ margin: 0 auto;
60
+ }
61
+
62
+ .schema-header {
63
+ background: var(--header-bg);
64
+ padding: 16px;
65
+ border-radius: 8px;
66
+ margin-bottom: 16px;
67
+ border: 1px solid var(--border-color);
68
+ }
69
+
70
+ .schema-title {
71
+ font-size: 24px;
72
+ font-weight: 600;
73
+ margin-bottom: 8px;
74
+ color: var(--type-object);
75
+ }
76
+
77
+ .schema-description {
78
+ color: var(--description-color);
79
+ font-style: italic;
80
+ }
81
+
82
+ .schema-meta {
83
+ display: flex;
84
+ gap: 16px;
85
+ margin-top: 12px;
86
+ font-size: 12px;
87
+ }
88
+
89
+ .schema-meta-item {
90
+ display: flex;
91
+ align-items: center;
92
+ gap: 4px;
93
+ }
94
+
95
+ .schema-meta-label {
96
+ color: var(--expand-icon);
97
+ }
98
+
99
+ .schema-meta-value {
100
+ color: var(--type-string);
101
+ }
102
+
103
+ .definitions-section {
104
+ margin-top: 24px;
105
+ }
106
+
107
+ .section-title {
108
+ font-size: 18px;
109
+ font-weight: 600;
110
+ margin-bottom: 12px;
111
+ padding-bottom: 8px;
112
+ border-bottom: 1px solid var(--border-color);
113
+ }
114
+
115
+ .schema-object {
116
+ border: 1px solid var(--border-color);
117
+ border-radius: 6px;
118
+ margin-bottom: 8px;
119
+ overflow: hidden;
120
+ }
121
+
122
+ .schema-object-header {
123
+ display: flex;
124
+ align-items: center;
125
+ padding: 10px 12px;
126
+ background: var(--header-bg);
127
+ cursor: pointer;
128
+ user-select: none;
129
+ transition: background-color 0.15s ease;
130
+ }
131
+
132
+ .schema-object-header:hover {
133
+ background: var(--hover-bg);
134
+ }
135
+
136
+ .expand-icon {
137
+ width: 16px;
138
+ height: 16px;
139
+ margin-right: 8px;
140
+ color: var(--expand-icon);
141
+ transition: transform 0.2s ease;
142
+ flex-shrink: 0;
143
+ }
144
+
145
+ .expand-icon.expanded {
146
+ transform: rotate(90deg);
147
+ }
148
+
149
+ .property-name {
150
+ font-weight: 600;
151
+ color: var(--property-name);
152
+ margin-right: 8px;
153
+ }
154
+
155
+ .property-type {
156
+ font-size: 12px;
157
+ padding: 2px 8px;
158
+ border-radius: 4px;
159
+ margin-right: 8px;
160
+ }
161
+
162
+ .type-string { background: rgba(206, 145, 120, 0.2); color: var(--type-string); }
163
+ .type-integer, .type-number { background: rgba(181, 206, 168, 0.2); color: var(--type-number); }
164
+ .type-boolean { background: rgba(86, 156, 214, 0.2); color: var(--type-boolean); }
165
+ .type-array { background: rgba(220, 220, 170, 0.2); color: var(--type-array); }
166
+ .type-object { background: rgba(78, 201, 176, 0.2); color: var(--type-object); }
167
+ .type-null { background: rgba(128, 128, 128, 0.2); color: var(--type-null); }
168
+
169
+ .required-badge {
170
+ font-size: 10px;
171
+ padding: 2px 6px;
172
+ border-radius: 4px;
173
+ background: rgba(209, 134, 22, 0.2);
174
+ color: var(--required-color);
175
+ margin-right: 8px;
176
+ text-transform: uppercase;
177
+ font-weight: 600;
178
+ }
179
+
180
+ .missing-badge {
181
+ font-size: 10px;
182
+ padding: 2px 6px;
183
+ border-radius: 4px;
184
+ background: rgba(241, 76, 76, 0.2);
185
+ color: var(--missing-color);
186
+ margin-right: 8px;
187
+ text-transform: uppercase;
188
+ font-weight: 600;
189
+ }
190
+
191
+ .imported-badge {
192
+ font-size: 10px;
193
+ padding: 2px 6px;
194
+ border-radius: 4px;
195
+ background: rgba(86, 156, 214, 0.2);
196
+ color: var(--type-boolean);
197
+ margin-right: 8px;
198
+ text-transform: uppercase;
199
+ font-weight: 600;
200
+ }
201
+
202
+
203
+ .property-description {
204
+ color: var(--description-color);
205
+ font-size: 12px;
206
+ flex: 1;
207
+ overflow: hidden;
208
+ text-overflow: ellipsis;
209
+ white-space: nowrap;
210
+ }
211
+
212
+ .schema-object-content {
213
+ display: none;
214
+ padding: 12px;
215
+ border-top: 1px solid var(--border-color);
216
+ }
217
+
218
+ .schema-object-content.expanded {
219
+ display: block;
220
+ }
221
+
222
+ .property-details {
223
+ font-size: 12px;
224
+ margin-bottom: 12px;
225
+ padding: 8px;
226
+ background: var(--header-bg);
227
+ border-radius: 4px;
228
+ }
229
+
230
+ .property-detail-row {
231
+ display: flex;
232
+ margin-bottom: 4px;
233
+ }
234
+
235
+ .property-detail-row:last-child {
236
+ margin-bottom: 0;
237
+ }
238
+
239
+ .property-detail-label {
240
+ color: var(--expand-icon);
241
+ min-width: 120px;
242
+ }
243
+
244
+ .property-detail-value {
245
+ color: var(--text-color);
246
+ }
247
+
248
+ .nested-properties {
249
+ margin-left: 16px;
250
+ padding-left: 16px;
251
+ border-left: 2px solid var(--border-color);
252
+ }
253
+
254
+ .array-items-label {
255
+ font-size: 11px;
256
+ color: var(--expand-icon);
257
+ margin-bottom: 8px;
258
+ text-transform: uppercase;
259
+ letter-spacing: 0.5px;
260
+ }
261
+
262
+ .enum-values {
263
+ display: flex;
264
+ flex-wrap: wrap;
265
+ gap: 4px;
266
+ margin-top: 4px;
267
+ }
268
+
269
+ .enum-value {
270
+ font-size: 11px;
271
+ padding: 2px 6px;
272
+ background: var(--header-bg);
273
+ border: 1px solid var(--border-color);
274
+ border-radius: 3px;
275
+ color: var(--type-string);
276
+ }
277
+
278
+ .ref-link {
279
+ color: var(--type-object);
280
+ cursor: pointer;
281
+ text-decoration: underline;
282
+ }
283
+
284
+ .ref-link:hover {
285
+ opacity: 0.8;
286
+ }
287
+
288
+ .no-properties {
289
+ color: var(--expand-icon);
290
+ font-style: italic;
291
+ padding: 8px;
292
+ }
293
+
294
+ .root-type-badge {
295
+ font-size: 12px;
296
+ padding: 4px 12px;
297
+ border-radius: 4px;
298
+ display: inline-block;
299
+ margin-top: 8px;
300
+ }
301
+
302
+ .view-toggle {
303
+ display: inline-flex;
304
+ margin-bottom: 12px;
305
+ border: 1px solid var(--border-color);
306
+ border-radius: 4px;
307
+ overflow: hidden;
308
+ font-size: 11px;
309
+ }
310
+
311
+ .view-toggle-btn {
312
+ padding: 4px 12px;
313
+ border: none;
314
+ background: transparent;
315
+ color: var(--text-color);
316
+ cursor: pointer;
317
+ font-size: 11px;
318
+ font-family: inherit;
319
+ transition: background-color 0.15s ease;
320
+ }
321
+
322
+ .view-toggle-btn:hover {
323
+ background: var(--hover-bg);
324
+ }
325
+
326
+ .view-toggle-btn.active {
327
+ background: var(--type-object);
328
+ color: #ffffff;
329
+ }
330
+
331
+ .view-toggle-btn:first-child {
332
+ border-right: 1px solid var(--border-color);
333
+ }
334
+
335
+ .object-example-view {
336
+ background: var(--bg-color);
337
+ border: 1px solid var(--border-color);
338
+ border-radius: 4px;
339
+ padding: 12px;
340
+ margin-top: 8px;
341
+ overflow-x: auto;
342
+ }
343
+
344
+ .object-example-view pre {
345
+ margin: 0;
346
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
347
+ font-size: 12px;
348
+ line-height: 1.4;
349
+ white-space: pre-wrap;
350
+ word-break: break-word;
351
+ }
352
+
353
+ .example-view {
354
+ background: var(--header-bg);
355
+ border: 1px solid var(--border-color);
356
+ border-radius: 6px;
357
+ padding: 16px;
358
+ overflow-x: auto;
359
+ }
360
+
361
+ .example-view pre {
362
+ margin: 0;
363
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
364
+ font-size: 13px;
365
+ line-height: 1.5;
366
+ white-space: pre-wrap;
367
+ word-break: break-word;
368
+ }
369
+
370
+ .example-view .json-key {
371
+ color: var(--property-name);
372
+ }
373
+
374
+ .example-view .json-string {
375
+ color: var(--type-string);
376
+ }
377
+
378
+ .example-view .json-number {
379
+ color: var(--type-number);
380
+ }
381
+
382
+ .example-view .json-boolean {
383
+ color: var(--type-boolean);
384
+ }
385
+
386
+ .example-view .json-null {
387
+ color: var(--type-null);
388
+ }
389
+
390
+ /* Styles for the new Imported Files section */
391
+ .imported-files-container {
392
+ margin-top: 12px; /* Adjust margin as section-title now precedes it */
393
+ padding: 16px;
394
+ border: 1px solid var(--border-color);
395
+ border-radius: 8px;
396
+ background: var(--header-bg);
397
+ }
398
+
399
+ .imported-files-container ul {
400
+ list-style: none; /* Remove default list bullets */
401
+ padding-left: 0;
402
+ }
403
+
404
+ .imported-files-container li {
405
+ margin-bottom: 8px;
406
+ color: var(--text-color);
407
+ }
408
+ `}const k="json-schema-viewer-styles";function M(){if(typeof document>"u"||document.getElementById(k))return;const e=document.createElement("style");e.id=k,e.textContent=q(),document.head.appendChild(e)}function O(e){const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return t>=0?e.slice(t+1):e}function h(e){if(!e||typeof e!="object")return!1;for(const t in e){if(!Object.prototype.hasOwnProperty.call(e,t))continue;const a=e[t];if(t==="$ref"&&typeof a=="string"&&a.includes(".json")||h(a))return!0}return!1}function v(e,t,a){if(!e||!e.$ref)return e||{};const s=e.$ref,d=a||{};let n=null,i=!1;if(s.includes(".json#/")){const[r,l]=s.split("#"),c=O(r),f=d[c];if(!f)return{$ref:s,__isMissing:!0};let m=f;const o=(l||"").split("/").slice(1);for(const u of o)if(m&&typeof m=="object"&&u in m)m=m[u];else return{$ref:s,__isMissing:!0};n=m,i=!0}else if(s.includes(".json")){const r=O(s.split("#")[0]);if(n=d[r],!n)return{$ref:s,__isMissing:!0};i=!0}else if(s.startsWith("#/")){let r=t;const l=s.split("/").slice(1);for(const c of l)if(r&&typeof r=="object"&&c in r)r=r[c];else return{$ref:s,__isMissing:!0};n=r}if(n&&i){const r={...n};return Object.defineProperty(r,"__isImported",{value:!0,enumerable:!1}),r}return n||e}function w(e){return e?e.__isMissing?"missing":e.$ref?"ref":e.type?Array.isArray(e.type)?e.type.join(" | "):e.type:e.enum?"enum":e.oneOf?"oneOf":e.anyOf?"anyOf":e.allOf?"allOf":e.properties?"object":e.items?"array":"any":"any"}function C(e){return e?!!(e.properties||e.items||e.oneOf||e.anyOf||e.allOf||e.description||e.enum||e.default!==void 0||e.example!==void 0||e.format||e.pattern||e.minimum!==void 0||e.maximum!==void 0||e.minLength!==void 0||e.maxLength!==void 0):!1}function g(e,t,a,s){if(!e)return null;if(e.$ref){if(s.has(e.$ref))return"...";s.add(e.$ref);const n=v(e,t,a),i=g(n,t,a,s);return s.delete(e.$ref),i}if(e.example!==void 0)return e.example;if(e.default!==void 0)return e.default;if(e.enum&&e.enum.length>0)return e.enum[0];if(e.const!==void 0)return e.const;if(e.oneOf&&e.oneOf.length>0)return g(e.oneOf[0],t,a,s);if(e.anyOf&&e.anyOf.length>0)return g(e.anyOf[0],t,a,s);if(e.allOf&&e.allOf.length>0){let n={};for(const i of e.allOf){const r=v(i,t,a);if(r.properties){const l=g(r,t,a,s);n={...n,...l}}}return n}const d=Array.isArray(e.type)?e.type[0]:e.type;switch(d){case"object":{if(e.properties){const n={};for(const[i,r]of Object.entries(e.properties))n[i]=g(r,t,a,s);return n}return{}}case"array":return e.items?[g(e.items,t,a,s)]:[];case"string":return e.format==="date-time"?new Date().toISOString():e.format==="date"?new Date().toISOString().split("T")[0]:e.format==="time"?"12:00:00":e.format==="email"?"user@example.com":e.format==="uri"||e.format==="url"?"https://example.com":e.format==="uuid"?"550e8400-e29b-41d4-a716-446655440000":e.minLength?"x".repeat(e.minLength):"string";case"number":case"integer":return e.minimum!==void 0?e.minimum:e.maximum!==void 0?e.maximum:0;case"boolean":return!0;case"null":return null;default:{if(e.properties){const n={};for(const[i,r]of Object.entries(e.properties))n[i]=g(r,t,a,s);return n}return e.items?[g(e.items,t,a,s)]:null}}}function L(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\\"])*")(\s*:)?/g,t=>{let a="json-string";return/:$/.test(t)&&(a="json-key"),'<span class="'+a+'">'+t+"</span>"}).replace(/\b(true|false)\b/g,'<span class="json-boolean">$1</span>').replace(/\bnull\b/g,'<span class="json-null">null</span>').replace(/\b(-?\d+(\.\d+)?([eE][+-]?\d+)?)\b/g,'<span class="json-number">$1</span>')}function p(e){if(typeof e!="string")return String(e??"");const t=document.createElement("div");return t.textContent=e,t.innerHTML}function S(e,t){const a=t.schema,s=t.bundle??{},d=t.importedFileNames??[],n=t.missingFileNames??[];if(e.innerHTML="",e.classList.add("schema-container"),!a){const o=document.createElement("div");o.className="loading",o.textContent="Loading schema...",e.appendChild(o);return}const i=document.createElement("div");i.className="schema-header";const r=a.title||"JSON Schema",l=a.description||"",c=a.$schema||"",f=a.$id||"";if(i.innerHTML=`
409
+ <div class="schema-title">${p(r)}</div>
410
+ ${l?`<div class="schema-description">${p(l)}</div>`:""}
411
+ <div class="schema-meta">
412
+ ${c?`<div class="schema-meta-item"><span class="schema-meta-label">Schema:</span><span class="schema-meta-value">${p(c)}</span></div>`:""}
413
+ ${f?`<div class="schema-meta-item"><span class="schema-meta-label">ID:</span><span class="schema-meta-value">${p(f)}</span></div>`:""}
414
+ </div>
415
+ ${a.type?`<div class="root-type-badge type-${p(a.type)}">${p(a.type)}</div>`:""}
416
+ `,e.appendChild(i),a.properties){const o=document.createElement("div");o.innerHTML='<div class="section-title">Properties</div>';const u=a.required||[];E(o,a.properties,u,a,s),e.appendChild(o)}const m=a.definitions||a.$defs||{};if(Object.keys(m).length>0){const o=document.createElement("div");o.className="definitions-section",o.innerHTML='<div class="section-title">Definitions</div>';for(const[u,b]of Object.entries(m)){const y=z(String(u),b,a,s);o.appendChild(y)}e.appendChild(o)}if(d.length>0){const o=document.createElement("h2");o.className="section-title",o.textContent="Imported files",e.appendChild(o);const u=document.createElement("div");u.className="imported-files-container";const b=document.createElement("ul");d.forEach(y=>{const x=document.createElement("li");if(x.textContent=y,n.includes(y)){const $=document.createElement("span");$.className="missing-badge",$.textContent="file not found",x.appendChild(document.createTextNode(" ")),x.appendChild($)}b.appendChild(x)}),u.appendChild(b),e.appendChild(u)}}function E(e,t,a,s,d){for(const[n,i]of Object.entries(t)){const r=a.includes(n),l=I(n,i,r,s,d);e.appendChild(l)}}function I(e,t,a,s,d){const n=document.createElement("div");n.className="schema-object";const i=v(t,s,d),r=w(i),l=C(i),c=i.description||"",f=i.__isImported||h(t),m=i.__isMissing,o=document.createElement("div");if(o.className="schema-object-header",o.innerHTML=`
417
+ ${l?'<svg class="expand-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>':'<div style="width: 24px;"></div>'}
418
+ <span class="property-name">${p(e)}</span>
419
+ <span class="property-type type-${p(r)}">${r==="missing"?"file not found":p(r)}</span>
420
+ ${a?'<span class="required-badge">required</span>':""}
421
+ ${f?'<span class="imported-badge">imported</span>':""}
422
+ ${m?'<span class="missing-badge">file not found</span>':""}
423
+ ${c?`<span class="property-description">${p(c)}</span>`:""}
424
+ `,l&&o.addEventListener("click",()=>{const u=n.querySelector(".schema-object-content"),b=o.querySelector(".expand-icon");u?.classList.toggle("expanded"),b?.classList.toggle("expanded")}),n.appendChild(o),l&&!m){const u=document.createElement("div");u.className="schema-object-content",T(u,i,s,d),n.appendChild(u)}return n}function T(e,t,a,s){if(!(t.properties||t.items||t.oneOf||t.anyOf||t.allOf)){N(e,t,a,s);return}let n="schema";const i=document.createElement("div");i.className="view-toggle",i.innerHTML=`
425
+ <button class="view-toggle-btn" data-view="example">Example Value</button>
426
+ <button class="view-toggle-btn active" data-view="schema">Schema</button>
427
+ `;const r=document.createElement("div");r.className="property-content-area";const l=()=>{if(r.innerHTML="",i.querySelectorAll(".view-toggle-btn").forEach(c=>{c.classList.toggle("active",c.dataset.view===n)}),n==="example"){const c=document.createElement("div");c.className="object-example-view";const f=g(t,a,s,new Set),m=L(JSON.stringify(f,null,2));c.innerHTML=`<pre>${m}</pre>`,r.appendChild(c)}else N(r,t,a,s)};i.addEventListener("click",c=>{const f=c.target?.closest(".view-toggle-btn");f&&f.dataset.view&&f.dataset.view!==n&&(n=f.dataset.view,l())}),e.appendChild(i),e.appendChild(r),l()}function N(e,t,a,s){const d=document.createElement("div");d.className="property-details";let n="";if(t.description&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Description:</span><span class="property-detail-value">${p(t.description)}</span></div>`),t.default!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Default:</span><span class="property-detail-value">${p(JSON.stringify(t.default))}</span></div>`),t.example!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Example:</span><span class="property-detail-value">${p(JSON.stringify(t.example))}</span></div>`),t.format&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Format:</span><span class="property-detail-value">${p(t.format)}</span></div>`),t.pattern&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Pattern:</span><span class="property-detail-value">${p(t.pattern)}</span></div>`),t.minimum!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Minimum:</span><span class="property-detail-value">${String(t.minimum)}</span></div>`),t.maximum!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Maximum:</span><span class="property-detail-value">${String(t.maximum)}</span></div>`),t.minLength!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Min Length:</span><span class="property-detail-value">${String(t.minLength)}</span></div>`),t.maxLength!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Max Length:</span><span class="property-detail-value">${String(t.maxLength)}</span></div>`),t.minItems!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Min Items:</span><span class="property-detail-value">${String(t.minItems)}</span></div>`),t.maxItems!==void 0&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Max Items:</span><span class="property-detail-value">${String(t.maxItems)}</span></div>`),t.enum&&(n+=`<div class="property-detail-row"><span class="property-detail-label">Enum Values:</span><span class="property-detail-value"><div class="enum-values">${t.enum.map(i=>`<span class="enum-value">${p(JSON.stringify(i))}</span>`).join("")}</div></span></div>`),n&&(d.innerHTML=n,e.appendChild(d)),t.properties){const i=document.createElement("div");i.className="nested-properties";const r=t.required||[];E(i,t.properties,r,a,s),e.appendChild(i)}if(t.items){const i=document.createElement("div");i.className="array-items-label",i.textContent="Array Items:",e.appendChild(i);const r=v(t.items,a,s);if(r.properties){const l=document.createElement("div");l.className="nested-properties";const c=r.required||[];E(l,r.properties,c,a,s),e.appendChild(l)}else{const l=w(r),c=document.createElement("div");c.innerHTML=`<span class="property-type type-${p(l)}">${p(l)}</span>`,r.description&&(c.innerHTML+=` <span class="property-description">${p(r.description)}</span>`),e.appendChild(c)}}["oneOf","anyOf","allOf"].forEach(i=>{if(t[i]){const r=document.createElement("div");r.className="array-items-label",r.textContent=i+":",e.appendChild(r),t[i].forEach((l,c)=>{const f=v(l,a,s),m=I(`Option ${c+1}`,f,!1,a,s);e.appendChild(m)})}})}function z(e,t,a,s){const d=document.createElement("div");d.className="schema-object",d.id=`def-${e}`;const n=v(t,a,s),i=w(n),r=C(n),l=n.description||"",c=n.__isImported||h(t),f=n.__isMissing,m=document.createElement("div");if(m.className="schema-object-header",m.innerHTML=`
428
+ ${r?'<svg class="expand-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>':'<div style="width: 24px;"></div>'}
429
+ <span class="property-name">${p(e)}</span>
430
+ <span class="property-type type-${p(i)}">${i==="missing"?"file not found":p(i)}</span>
431
+ ${c?'<span class="imported-badge">imported</span>':""}
432
+ ${f?'<span class="missing-badge">file not found</span>':""}
433
+ ${l?`<span class="property-description">${p(l)}</span>`:""}
434
+ `,r&&m.addEventListener("click",()=>{const o=d.querySelector(".schema-object-content"),u=m.querySelector(".expand-icon");o?.classList.toggle("expanded"),u?.classList.toggle("expanded")}),d.appendChild(m),r&&!f){const o=document.createElement("div");o.className="schema-object-content",T(o,n,a,s),d.appendChild(o)}return d}function H(e){const t=j.useRef(null),a=j.useMemo(()=>({schema:e.schema,bundle:e.bundle??{},importedFileNames:e.importedFileNames??[],missingFileNames:e.missingFileNames??[]}),[e.schema,e.bundle,e.importedFileNames,e.missingFileNames]);return j.useEffect(()=>{M(),t.current&&S(t.current,a)},[a]),_.jsx("div",{ref:t,className:e.className})}exports.SchemaViewer=H;exports.ensureSchemaViewerStyles=M;exports.escapeHtml=p;exports.generateExampleValue=g;exports.getType=w;exports.hasNestedContent=C;exports.hasRemoteRef=h;exports.renderSchemaInto=S;exports.resolveRef=v;exports.syntaxHighlightJson=L;
package/dist/index.js ADDED
@@ -0,0 +1,735 @@
1
+ import { jsx as M } from "react/jsx-runtime";
2
+ import { useRef as I, useMemo as S, useEffect as _ } from "react";
3
+ function T() {
4
+ return `
5
+ :root {
6
+ --bg-color: #1e1e1e;
7
+ --text-color: #d4d4d4;
8
+ --border-color: #3c3c3c;
9
+ --header-bg: #252526;
10
+ --type-string: #ce9178;
11
+ --type-number: #b5cea8;
12
+ --type-boolean: #569cd6;
13
+ --type-array: #dcdcaa;
14
+ --type-object: #4ec9b0;
15
+ --type-null: #808080;
16
+ --required-color: #d18616; /* Orange */
17
+ --missing-color: #f14c4c; /* Red */
18
+ --description-color: #6a9955;
19
+ --property-name: #9cdcfe;
20
+ --expand-icon: #808080;
21
+ --hover-bg: #2a2d2e;
22
+ }
23
+
24
+ @media (prefers-color-scheme: light) {
25
+ :root {
26
+ --bg-color: #ffffff;
27
+ --text-color: #333333;
28
+ --border-color: #e0e0e0;
29
+ --header-bg: #f5f5f5;
30
+ --type-string: #a31515;
31
+ --type-number: #098658;
32
+ --type-boolean: #0000ff;
33
+ --type-array: #795e26;
34
+ --type-object: #267f99;
35
+ --type-null: #808080;
36
+ --required-color: #b85a00; /* Darker Orange */
37
+ --missing-color: #d32f2f; /* Darker Red */
38
+ --description-color: #008000;
39
+ --property-name: #001080;
40
+ --expand-icon: #666666;
41
+ --hover-bg: #f0f0f0;
42
+ }
43
+ }
44
+
45
+ * {
46
+ box-sizing: border-box;
47
+ margin: 0;
48
+ padding: 0;
49
+ }
50
+
51
+ body {
52
+ font-family: var(--vscode-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif);
53
+ font-size: 13px;
54
+ line-height: 1.5;
55
+ color: var(--text-color);
56
+ background-color: var(--bg-color);
57
+ padding: 16px;
58
+ }
59
+
60
+ .schema-container {
61
+ max-width: 1200px;
62
+ margin: 0 auto;
63
+ }
64
+
65
+ .schema-header {
66
+ background: var(--header-bg);
67
+ padding: 16px;
68
+ border-radius: 8px;
69
+ margin-bottom: 16px;
70
+ border: 1px solid var(--border-color);
71
+ }
72
+
73
+ .schema-title {
74
+ font-size: 24px;
75
+ font-weight: 600;
76
+ margin-bottom: 8px;
77
+ color: var(--type-object);
78
+ }
79
+
80
+ .schema-description {
81
+ color: var(--description-color);
82
+ font-style: italic;
83
+ }
84
+
85
+ .schema-meta {
86
+ display: flex;
87
+ gap: 16px;
88
+ margin-top: 12px;
89
+ font-size: 12px;
90
+ }
91
+
92
+ .schema-meta-item {
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 4px;
96
+ }
97
+
98
+ .schema-meta-label {
99
+ color: var(--expand-icon);
100
+ }
101
+
102
+ .schema-meta-value {
103
+ color: var(--type-string);
104
+ }
105
+
106
+ .definitions-section {
107
+ margin-top: 24px;
108
+ }
109
+
110
+ .section-title {
111
+ font-size: 18px;
112
+ font-weight: 600;
113
+ margin-bottom: 12px;
114
+ padding-bottom: 8px;
115
+ border-bottom: 1px solid var(--border-color);
116
+ }
117
+
118
+ .schema-object {
119
+ border: 1px solid var(--border-color);
120
+ border-radius: 6px;
121
+ margin-bottom: 8px;
122
+ overflow: hidden;
123
+ }
124
+
125
+ .schema-object-header {
126
+ display: flex;
127
+ align-items: center;
128
+ padding: 10px 12px;
129
+ background: var(--header-bg);
130
+ cursor: pointer;
131
+ user-select: none;
132
+ transition: background-color 0.15s ease;
133
+ }
134
+
135
+ .schema-object-header:hover {
136
+ background: var(--hover-bg);
137
+ }
138
+
139
+ .expand-icon {
140
+ width: 16px;
141
+ height: 16px;
142
+ margin-right: 8px;
143
+ color: var(--expand-icon);
144
+ transition: transform 0.2s ease;
145
+ flex-shrink: 0;
146
+ }
147
+
148
+ .expand-icon.expanded {
149
+ transform: rotate(90deg);
150
+ }
151
+
152
+ .property-name {
153
+ font-weight: 600;
154
+ color: var(--property-name);
155
+ margin-right: 8px;
156
+ }
157
+
158
+ .property-type {
159
+ font-size: 12px;
160
+ padding: 2px 8px;
161
+ border-radius: 4px;
162
+ margin-right: 8px;
163
+ }
164
+
165
+ .type-string { background: rgba(206, 145, 120, 0.2); color: var(--type-string); }
166
+ .type-integer, .type-number { background: rgba(181, 206, 168, 0.2); color: var(--type-number); }
167
+ .type-boolean { background: rgba(86, 156, 214, 0.2); color: var(--type-boolean); }
168
+ .type-array { background: rgba(220, 220, 170, 0.2); color: var(--type-array); }
169
+ .type-object { background: rgba(78, 201, 176, 0.2); color: var(--type-object); }
170
+ .type-null { background: rgba(128, 128, 128, 0.2); color: var(--type-null); }
171
+
172
+ .required-badge {
173
+ font-size: 10px;
174
+ padding: 2px 6px;
175
+ border-radius: 4px;
176
+ background: rgba(209, 134, 22, 0.2);
177
+ color: var(--required-color);
178
+ margin-right: 8px;
179
+ text-transform: uppercase;
180
+ font-weight: 600;
181
+ }
182
+
183
+ .missing-badge {
184
+ font-size: 10px;
185
+ padding: 2px 6px;
186
+ border-radius: 4px;
187
+ background: rgba(241, 76, 76, 0.2);
188
+ color: var(--missing-color);
189
+ margin-right: 8px;
190
+ text-transform: uppercase;
191
+ font-weight: 600;
192
+ }
193
+
194
+ .imported-badge {
195
+ font-size: 10px;
196
+ padding: 2px 6px;
197
+ border-radius: 4px;
198
+ background: rgba(86, 156, 214, 0.2);
199
+ color: var(--type-boolean);
200
+ margin-right: 8px;
201
+ text-transform: uppercase;
202
+ font-weight: 600;
203
+ }
204
+
205
+
206
+ .property-description {
207
+ color: var(--description-color);
208
+ font-size: 12px;
209
+ flex: 1;
210
+ overflow: hidden;
211
+ text-overflow: ellipsis;
212
+ white-space: nowrap;
213
+ }
214
+
215
+ .schema-object-content {
216
+ display: none;
217
+ padding: 12px;
218
+ border-top: 1px solid var(--border-color);
219
+ }
220
+
221
+ .schema-object-content.expanded {
222
+ display: block;
223
+ }
224
+
225
+ .property-details {
226
+ font-size: 12px;
227
+ margin-bottom: 12px;
228
+ padding: 8px;
229
+ background: var(--header-bg);
230
+ border-radius: 4px;
231
+ }
232
+
233
+ .property-detail-row {
234
+ display: flex;
235
+ margin-bottom: 4px;
236
+ }
237
+
238
+ .property-detail-row:last-child {
239
+ margin-bottom: 0;
240
+ }
241
+
242
+ .property-detail-label {
243
+ color: var(--expand-icon);
244
+ min-width: 120px;
245
+ }
246
+
247
+ .property-detail-value {
248
+ color: var(--text-color);
249
+ }
250
+
251
+ .nested-properties {
252
+ margin-left: 16px;
253
+ padding-left: 16px;
254
+ border-left: 2px solid var(--border-color);
255
+ }
256
+
257
+ .array-items-label {
258
+ font-size: 11px;
259
+ color: var(--expand-icon);
260
+ margin-bottom: 8px;
261
+ text-transform: uppercase;
262
+ letter-spacing: 0.5px;
263
+ }
264
+
265
+ .enum-values {
266
+ display: flex;
267
+ flex-wrap: wrap;
268
+ gap: 4px;
269
+ margin-top: 4px;
270
+ }
271
+
272
+ .enum-value {
273
+ font-size: 11px;
274
+ padding: 2px 6px;
275
+ background: var(--header-bg);
276
+ border: 1px solid var(--border-color);
277
+ border-radius: 3px;
278
+ color: var(--type-string);
279
+ }
280
+
281
+ .ref-link {
282
+ color: var(--type-object);
283
+ cursor: pointer;
284
+ text-decoration: underline;
285
+ }
286
+
287
+ .ref-link:hover {
288
+ opacity: 0.8;
289
+ }
290
+
291
+ .no-properties {
292
+ color: var(--expand-icon);
293
+ font-style: italic;
294
+ padding: 8px;
295
+ }
296
+
297
+ .root-type-badge {
298
+ font-size: 12px;
299
+ padding: 4px 12px;
300
+ border-radius: 4px;
301
+ display: inline-block;
302
+ margin-top: 8px;
303
+ }
304
+
305
+ .view-toggle {
306
+ display: inline-flex;
307
+ margin-bottom: 12px;
308
+ border: 1px solid var(--border-color);
309
+ border-radius: 4px;
310
+ overflow: hidden;
311
+ font-size: 11px;
312
+ }
313
+
314
+ .view-toggle-btn {
315
+ padding: 4px 12px;
316
+ border: none;
317
+ background: transparent;
318
+ color: var(--text-color);
319
+ cursor: pointer;
320
+ font-size: 11px;
321
+ font-family: inherit;
322
+ transition: background-color 0.15s ease;
323
+ }
324
+
325
+ .view-toggle-btn:hover {
326
+ background: var(--hover-bg);
327
+ }
328
+
329
+ .view-toggle-btn.active {
330
+ background: var(--type-object);
331
+ color: #ffffff;
332
+ }
333
+
334
+ .view-toggle-btn:first-child {
335
+ border-right: 1px solid var(--border-color);
336
+ }
337
+
338
+ .object-example-view {
339
+ background: var(--bg-color);
340
+ border: 1px solid var(--border-color);
341
+ border-radius: 4px;
342
+ padding: 12px;
343
+ margin-top: 8px;
344
+ overflow-x: auto;
345
+ }
346
+
347
+ .object-example-view pre {
348
+ margin: 0;
349
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
350
+ font-size: 12px;
351
+ line-height: 1.4;
352
+ white-space: pre-wrap;
353
+ word-break: break-word;
354
+ }
355
+
356
+ .example-view {
357
+ background: var(--header-bg);
358
+ border: 1px solid var(--border-color);
359
+ border-radius: 6px;
360
+ padding: 16px;
361
+ overflow-x: auto;
362
+ }
363
+
364
+ .example-view pre {
365
+ margin: 0;
366
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
367
+ font-size: 13px;
368
+ line-height: 1.5;
369
+ white-space: pre-wrap;
370
+ word-break: break-word;
371
+ }
372
+
373
+ .example-view .json-key {
374
+ color: var(--property-name);
375
+ }
376
+
377
+ .example-view .json-string {
378
+ color: var(--type-string);
379
+ }
380
+
381
+ .example-view .json-number {
382
+ color: var(--type-number);
383
+ }
384
+
385
+ .example-view .json-boolean {
386
+ color: var(--type-boolean);
387
+ }
388
+
389
+ .example-view .json-null {
390
+ color: var(--type-null);
391
+ }
392
+
393
+ /* Styles for the new Imported Files section */
394
+ .imported-files-container {
395
+ margin-top: 12px; /* Adjust margin as section-title now precedes it */
396
+ padding: 16px;
397
+ border: 1px solid var(--border-color);
398
+ border-radius: 8px;
399
+ background: var(--header-bg);
400
+ }
401
+
402
+ .imported-files-container ul {
403
+ list-style: none; /* Remove default list bullets */
404
+ padding-left: 0;
405
+ }
406
+
407
+ .imported-files-container li {
408
+ margin-bottom: 8px;
409
+ color: var(--text-color);
410
+ }
411
+ `;
412
+ }
413
+ const E = "json-schema-viewer-styles";
414
+ function z() {
415
+ if (typeof document > "u" || document.getElementById(E)) return;
416
+ const e = document.createElement("style");
417
+ e.id = E, e.textContent = T(), document.head.appendChild(e);
418
+ }
419
+ function C(e) {
420
+ const t = Math.max(e.lastIndexOf("/"), e.lastIndexOf("\\"));
421
+ return t >= 0 ? e.slice(t + 1) : e;
422
+ }
423
+ function $(e) {
424
+ if (!e || typeof e != "object")
425
+ return !1;
426
+ for (const t in e) {
427
+ if (!Object.prototype.hasOwnProperty.call(e, t)) continue;
428
+ const a = e[t];
429
+ if (t === "$ref" && typeof a == "string" && a.includes(".json") || $(a))
430
+ return !0;
431
+ }
432
+ return !1;
433
+ }
434
+ function b(e, t, a) {
435
+ if (!e || !e.$ref)
436
+ return e || {};
437
+ const s = e.$ref, d = a || {};
438
+ let n = null, i = !1;
439
+ if (s.includes(".json#/")) {
440
+ const [r, l] = s.split("#"), c = C(r), f = d[c];
441
+ if (!f)
442
+ return { $ref: s, __isMissing: !0 };
443
+ let m = f;
444
+ const o = (l || "").split("/").slice(1);
445
+ for (const u of o)
446
+ if (m && typeof m == "object" && u in m)
447
+ m = m[u];
448
+ else
449
+ return { $ref: s, __isMissing: !0 };
450
+ n = m, i = !0;
451
+ } else if (s.includes(".json")) {
452
+ const r = C(s.split("#")[0]);
453
+ if (n = d[r], !n)
454
+ return { $ref: s, __isMissing: !0 };
455
+ i = !0;
456
+ } else if (s.startsWith("#/")) {
457
+ let r = t;
458
+ const l = s.split("/").slice(1);
459
+ for (const c of l)
460
+ if (r && typeof r == "object" && c in r)
461
+ r = r[c];
462
+ else
463
+ return { $ref: s, __isMissing: !0 };
464
+ n = r;
465
+ }
466
+ if (n && i) {
467
+ const r = { ...n };
468
+ return Object.defineProperty(r, "__isImported", { value: !0, enumerable: !1 }), r;
469
+ }
470
+ return n || e;
471
+ }
472
+ function j(e) {
473
+ return e ? e.__isMissing ? "missing" : e.$ref ? "ref" : e.type ? Array.isArray(e.type) ? e.type.join(" | ") : e.type : e.enum ? "enum" : e.oneOf ? "oneOf" : e.anyOf ? "anyOf" : e.allOf ? "allOf" : e.properties ? "object" : e.items ? "array" : "any" : "any";
474
+ }
475
+ function O(e) {
476
+ return e ? !!(e.properties || e.items || e.oneOf || e.anyOf || e.allOf || e.description || e.enum || e.default !== void 0 || e.example !== void 0 || e.format || e.pattern || e.minimum !== void 0 || e.maximum !== void 0 || e.minLength !== void 0 || e.maxLength !== void 0) : !1;
477
+ }
478
+ function g(e, t, a, s) {
479
+ if (!e) return null;
480
+ if (e.$ref) {
481
+ if (s.has(e.$ref))
482
+ return "...";
483
+ s.add(e.$ref);
484
+ const n = b(e, t, a), i = g(n, t, a, s);
485
+ return s.delete(e.$ref), i;
486
+ }
487
+ if (e.example !== void 0) return e.example;
488
+ if (e.default !== void 0) return e.default;
489
+ if (e.enum && e.enum.length > 0) return e.enum[0];
490
+ if (e.const !== void 0) return e.const;
491
+ if (e.oneOf && e.oneOf.length > 0)
492
+ return g(e.oneOf[0], t, a, s);
493
+ if (e.anyOf && e.anyOf.length > 0)
494
+ return g(e.anyOf[0], t, a, s);
495
+ if (e.allOf && e.allOf.length > 0) {
496
+ let n = {};
497
+ for (const i of e.allOf) {
498
+ const r = b(i, t, a);
499
+ if (r.properties) {
500
+ const l = g(r, t, a, s);
501
+ n = { ...n, ...l };
502
+ }
503
+ }
504
+ return n;
505
+ }
506
+ const d = Array.isArray(e.type) ? e.type[0] : e.type;
507
+ switch (d) {
508
+ case "object": {
509
+ if (e.properties) {
510
+ const n = {};
511
+ for (const [i, r] of Object.entries(e.properties))
512
+ n[i] = g(r, t, a, s);
513
+ return n;
514
+ }
515
+ return {};
516
+ }
517
+ case "array":
518
+ return e.items ? [g(e.items, t, a, s)] : [];
519
+ case "string":
520
+ return e.format === "date-time" ? (/* @__PURE__ */ new Date()).toISOString() : e.format === "date" ? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : e.format === "time" ? "12:00:00" : e.format === "email" ? "user@example.com" : e.format === "uri" || e.format === "url" ? "https://example.com" : e.format === "uuid" ? "550e8400-e29b-41d4-a716-446655440000" : e.minLength ? "x".repeat(e.minLength) : "string";
521
+ case "number":
522
+ case "integer":
523
+ return e.minimum !== void 0 ? e.minimum : e.maximum !== void 0 ? e.maximum : 0;
524
+ case "boolean":
525
+ return !0;
526
+ case "null":
527
+ return null;
528
+ default: {
529
+ if (e.properties) {
530
+ const n = {};
531
+ for (const [i, r] of Object.entries(e.properties))
532
+ n[i] = g(r, t, a, s);
533
+ return n;
534
+ }
535
+ return e.items ? [g(e.items, t, a, s)] : null;
536
+ }
537
+ }
538
+ }
539
+ function q(e) {
540
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\\"])*")(\s*:)?/g, (t) => {
541
+ let a = "json-string";
542
+ return /:$/.test(t) && (a = "json-key"), '<span class="' + a + '">' + t + "</span>";
543
+ }).replace(/\b(true|false)\b/g, '<span class="json-boolean">$1</span>').replace(/\bnull\b/g, '<span class="json-null">null</span>').replace(/\b(-?\d+(\.\d+)?([eE][+-]?\d+)?)\b/g, '<span class="json-number">$1</span>');
544
+ }
545
+ function p(e) {
546
+ if (typeof e != "string") return String(e ?? "");
547
+ const t = document.createElement("div");
548
+ return t.textContent = e, t.innerHTML;
549
+ }
550
+ function H(e, t) {
551
+ const a = t.schema, s = t.bundle ?? {}, d = t.importedFileNames ?? [], n = t.missingFileNames ?? [];
552
+ if (e.innerHTML = "", e.classList.add("schema-container"), !a) {
553
+ const o = document.createElement("div");
554
+ o.className = "loading", o.textContent = "Loading schema...", e.appendChild(o);
555
+ return;
556
+ }
557
+ const i = document.createElement("div");
558
+ i.className = "schema-header";
559
+ const r = a.title || "JSON Schema", l = a.description || "", c = a.$schema || "", f = a.$id || "";
560
+ if (i.innerHTML = `
561
+ <div class="schema-title">${p(r)}</div>
562
+ ${l ? `<div class="schema-description">${p(l)}</div>` : ""}
563
+ <div class="schema-meta">
564
+ ${c ? `<div class="schema-meta-item"><span class="schema-meta-label">Schema:</span><span class="schema-meta-value">${p(c)}</span></div>` : ""}
565
+ ${f ? `<div class="schema-meta-item"><span class="schema-meta-label">ID:</span><span class="schema-meta-value">${p(f)}</span></div>` : ""}
566
+ </div>
567
+ ${a.type ? `<div class="root-type-badge type-${p(a.type)}">${p(a.type)}</div>` : ""}
568
+ `, e.appendChild(i), a.properties) {
569
+ const o = document.createElement("div");
570
+ o.innerHTML = '<div class="section-title">Properties</div>';
571
+ const u = a.required || [];
572
+ w(o, a.properties, u, a, s), e.appendChild(o);
573
+ }
574
+ const m = a.definitions || a.$defs || {};
575
+ if (Object.keys(m).length > 0) {
576
+ const o = document.createElement("div");
577
+ o.className = "definitions-section", o.innerHTML = '<div class="section-title">Definitions</div>';
578
+ for (const [u, v] of Object.entries(m)) {
579
+ const x = F(String(u), v, a, s);
580
+ o.appendChild(x);
581
+ }
582
+ e.appendChild(o);
583
+ }
584
+ if (d.length > 0) {
585
+ const o = document.createElement("h2");
586
+ o.className = "section-title", o.textContent = "Imported files", e.appendChild(o);
587
+ const u = document.createElement("div");
588
+ u.className = "imported-files-container";
589
+ const v = document.createElement("ul");
590
+ d.forEach((x) => {
591
+ const y = document.createElement("li");
592
+ if (y.textContent = x, n.includes(x)) {
593
+ const h = document.createElement("span");
594
+ h.className = "missing-badge", h.textContent = "file not found", y.appendChild(document.createTextNode(" ")), y.appendChild(h);
595
+ }
596
+ v.appendChild(y);
597
+ }), u.appendChild(v), e.appendChild(u);
598
+ }
599
+ }
600
+ function w(e, t, a, s, d) {
601
+ for (const [n, i] of Object.entries(t)) {
602
+ const r = a.includes(n), l = N(n, i, r, s, d);
603
+ e.appendChild(l);
604
+ }
605
+ }
606
+ function N(e, t, a, s, d) {
607
+ const n = document.createElement("div");
608
+ n.className = "schema-object";
609
+ const i = b(t, s, d), r = j(i), l = O(i), c = i.description || "", f = i.__isImported || $(t), m = i.__isMissing, o = document.createElement("div");
610
+ if (o.className = "schema-object-header", o.innerHTML = `
611
+ ${l ? '<svg class="expand-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>' : '<div style="width: 24px;"></div>'}
612
+ <span class="property-name">${p(e)}</span>
613
+ <span class="property-type type-${p(r)}">${r === "missing" ? "file not found" : p(r)}</span>
614
+ ${a ? '<span class="required-badge">required</span>' : ""}
615
+ ${f ? '<span class="imported-badge">imported</span>' : ""}
616
+ ${m ? '<span class="missing-badge">file not found</span>' : ""}
617
+ ${c ? `<span class="property-description">${p(c)}</span>` : ""}
618
+ `, l && o.addEventListener("click", () => {
619
+ const u = n.querySelector(".schema-object-content"), v = o.querySelector(".expand-icon");
620
+ u?.classList.toggle("expanded"), v?.classList.toggle("expanded");
621
+ }), n.appendChild(o), l && !m) {
622
+ const u = document.createElement("div");
623
+ u.className = "schema-object-content", L(u, i, s, d), n.appendChild(u);
624
+ }
625
+ return n;
626
+ }
627
+ function L(e, t, a, s) {
628
+ if (!(t.properties || t.items || t.oneOf || t.anyOf || t.allOf)) {
629
+ k(e, t, a, s);
630
+ return;
631
+ }
632
+ let n = "schema";
633
+ const i = document.createElement("div");
634
+ i.className = "view-toggle", i.innerHTML = `
635
+ <button class="view-toggle-btn" data-view="example">Example Value</button>
636
+ <button class="view-toggle-btn active" data-view="schema">Schema</button>
637
+ `;
638
+ const r = document.createElement("div");
639
+ r.className = "property-content-area";
640
+ const l = () => {
641
+ if (r.innerHTML = "", i.querySelectorAll(".view-toggle-btn").forEach((c) => {
642
+ c.classList.toggle("active", c.dataset.view === n);
643
+ }), n === "example") {
644
+ const c = document.createElement("div");
645
+ c.className = "object-example-view";
646
+ const f = g(t, a, s, /* @__PURE__ */ new Set()), m = q(JSON.stringify(f, null, 2));
647
+ c.innerHTML = `<pre>${m}</pre>`, r.appendChild(c);
648
+ } else
649
+ k(r, t, a, s);
650
+ };
651
+ i.addEventListener("click", (c) => {
652
+ const f = c.target?.closest(".view-toggle-btn");
653
+ f && f.dataset.view && f.dataset.view !== n && (n = f.dataset.view, l());
654
+ }), e.appendChild(i), e.appendChild(r), l();
655
+ }
656
+ function k(e, t, a, s) {
657
+ const d = document.createElement("div");
658
+ d.className = "property-details";
659
+ let n = "";
660
+ if (t.description && (n += `<div class="property-detail-row"><span class="property-detail-label">Description:</span><span class="property-detail-value">${p(t.description)}</span></div>`), t.default !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Default:</span><span class="property-detail-value">${p(JSON.stringify(t.default))}</span></div>`), t.example !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Example:</span><span class="property-detail-value">${p(JSON.stringify(t.example))}</span></div>`), t.format && (n += `<div class="property-detail-row"><span class="property-detail-label">Format:</span><span class="property-detail-value">${p(t.format)}</span></div>`), t.pattern && (n += `<div class="property-detail-row"><span class="property-detail-label">Pattern:</span><span class="property-detail-value">${p(t.pattern)}</span></div>`), t.minimum !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Minimum:</span><span class="property-detail-value">${String(t.minimum)}</span></div>`), t.maximum !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Maximum:</span><span class="property-detail-value">${String(t.maximum)}</span></div>`), t.minLength !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Min Length:</span><span class="property-detail-value">${String(t.minLength)}</span></div>`), t.maxLength !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Max Length:</span><span class="property-detail-value">${String(t.maxLength)}</span></div>`), t.minItems !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Min Items:</span><span class="property-detail-value">${String(t.minItems)}</span></div>`), t.maxItems !== void 0 && (n += `<div class="property-detail-row"><span class="property-detail-label">Max Items:</span><span class="property-detail-value">${String(t.maxItems)}</span></div>`), t.enum && (n += `<div class="property-detail-row"><span class="property-detail-label">Enum Values:</span><span class="property-detail-value"><div class="enum-values">${t.enum.map((i) => `<span class="enum-value">${p(JSON.stringify(i))}</span>`).join("")}</div></span></div>`), n && (d.innerHTML = n, e.appendChild(d)), t.properties) {
661
+ const i = document.createElement("div");
662
+ i.className = "nested-properties";
663
+ const r = t.required || [];
664
+ w(i, t.properties, r, a, s), e.appendChild(i);
665
+ }
666
+ if (t.items) {
667
+ const i = document.createElement("div");
668
+ i.className = "array-items-label", i.textContent = "Array Items:", e.appendChild(i);
669
+ const r = b(t.items, a, s);
670
+ if (r.properties) {
671
+ const l = document.createElement("div");
672
+ l.className = "nested-properties";
673
+ const c = r.required || [];
674
+ w(l, r.properties, c, a, s), e.appendChild(l);
675
+ } else {
676
+ const l = j(r), c = document.createElement("div");
677
+ c.innerHTML = `<span class="property-type type-${p(l)}">${p(l)}</span>`, r.description && (c.innerHTML += ` <span class="property-description">${p(r.description)}</span>`), e.appendChild(c);
678
+ }
679
+ }
680
+ ["oneOf", "anyOf", "allOf"].forEach((i) => {
681
+ if (t[i]) {
682
+ const r = document.createElement("div");
683
+ r.className = "array-items-label", r.textContent = i + ":", e.appendChild(r), t[i].forEach((l, c) => {
684
+ const f = b(l, a, s), m = N(`Option ${c + 1}`, f, !1, a, s);
685
+ e.appendChild(m);
686
+ });
687
+ }
688
+ });
689
+ }
690
+ function F(e, t, a, s) {
691
+ const d = document.createElement("div");
692
+ d.className = "schema-object", d.id = `def-${e}`;
693
+ const n = b(t, a, s), i = j(n), r = O(n), l = n.description || "", c = n.__isImported || $(t), f = n.__isMissing, m = document.createElement("div");
694
+ if (m.className = "schema-object-header", m.innerHTML = `
695
+ ${r ? '<svg class="expand-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>' : '<div style="width: 24px;"></div>'}
696
+ <span class="property-name">${p(e)}</span>
697
+ <span class="property-type type-${p(i)}">${i === "missing" ? "file not found" : p(i)}</span>
698
+ ${c ? '<span class="imported-badge">imported</span>' : ""}
699
+ ${f ? '<span class="missing-badge">file not found</span>' : ""}
700
+ ${l ? `<span class="property-description">${p(l)}</span>` : ""}
701
+ `, r && m.addEventListener("click", () => {
702
+ const o = d.querySelector(".schema-object-content"), u = m.querySelector(".expand-icon");
703
+ o?.classList.toggle("expanded"), u?.classList.toggle("expanded");
704
+ }), d.appendChild(m), r && !f) {
705
+ const o = document.createElement("div");
706
+ o.className = "schema-object-content", L(o, n, a, s), d.appendChild(o);
707
+ }
708
+ return d;
709
+ }
710
+ function V(e) {
711
+ const t = I(null), a = S(
712
+ () => ({
713
+ schema: e.schema,
714
+ bundle: e.bundle ?? {},
715
+ importedFileNames: e.importedFileNames ?? [],
716
+ missingFileNames: e.missingFileNames ?? []
717
+ }),
718
+ [e.schema, e.bundle, e.importedFileNames, e.missingFileNames]
719
+ );
720
+ return _(() => {
721
+ z(), t.current && H(t.current, a);
722
+ }, [a]), /* @__PURE__ */ M("div", { ref: t, className: e.className });
723
+ }
724
+ export {
725
+ V as SchemaViewer,
726
+ z as ensureSchemaViewerStyles,
727
+ p as escapeHtml,
728
+ g as generateExampleValue,
729
+ j as getType,
730
+ O as hasNestedContent,
731
+ $ as hasRemoteRef,
732
+ H as renderSchemaInto,
733
+ b as resolveRef,
734
+ q as syntaxHighlightJson
735
+ };
@@ -0,0 +1,4 @@
1
+ export { SchemaViewer, type SchemaViewerProps } from './react';
2
+ export { ensureSchemaViewerStyles } from './styles/ensureStyles';
3
+ export { escapeHtml, generateExampleValue, getType, hasNestedContent, hasRemoteRef, resolveRef, syntaxHighlightJson, type SchemaBundle } from './viewerCore';
4
+ export { renderSchemaInto, type RenderSchemaOptions } from './viewerDom';
@@ -0,0 +1,9 @@
1
+ import type { SchemaBundle } from '../viewerCore';
2
+ export type SchemaViewerProps = {
3
+ schema: any;
4
+ bundle?: SchemaBundle;
5
+ importedFileNames?: string[];
6
+ missingFileNames?: string[];
7
+ className?: string;
8
+ };
9
+ export declare function SchemaViewer(props: SchemaViewerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export { SchemaViewer, type SchemaViewerProps } from './SchemaViewer';
@@ -0,0 +1 @@
1
+ export declare function ensureSchemaViewerStyles(): void;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * This function returns a string containing all the CSS styles for the schema viewer.
3
+ * It includes styles for both light and dark themes, using CSS variables.
4
+ *
5
+ * @returns {string} The CSS styles for the viewer.
6
+ */
7
+ export declare function getStyles(): string;
@@ -0,0 +1,15 @@
1
+ export type SchemaBundle = Record<string, any>;
2
+ export declare function hasRemoteRef(obj: any): boolean;
3
+ /**
4
+ * Resolves a $ref pointer.
5
+ * Supports:
6
+ * - local refs: "#/..."
7
+ * - file refs: "other.schema.json"
8
+ * - file + pointer: "other.schema.json#/$defs/X"
9
+ */
10
+ export declare function resolveRef(schema: any, rootSchema: any, bundle: SchemaBundle): any;
11
+ export declare function getType(prop: any): string;
12
+ export declare function hasNestedContent(prop: any): boolean;
13
+ export declare function generateExampleValue(prop: any, rootSchema: any, bundle: SchemaBundle, visitedRefs: Set<string>): any;
14
+ export declare function syntaxHighlightJson(json: string): string;
15
+ export declare function escapeHtml(text: unknown): string;
@@ -0,0 +1,8 @@
1
+ import { type SchemaBundle } from './viewerCore';
2
+ export type RenderSchemaOptions = {
3
+ schema: any;
4
+ bundle?: SchemaBundle;
5
+ importedFileNames?: string[];
6
+ missingFileNames?: string[];
7
+ };
8
+ export declare function renderSchemaInto(container: HTMLElement, options: RenderSchemaOptions): void;
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@miman/json-schema-viewer-react",
3
+ "version": "1.2.0",
4
+ "description": "React component for visualizing JSON Schema files",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "vite build --config vite.config.ts && tsc -p tsconfig.json"
8
+ },
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.js",
11
+ "types": "./dist/types/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/types/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "peerDependencies": {
23
+ "react": "^18.0.0 || ^19.0.0",
24
+ "react-dom": "^18.0.0 || ^19.0.0"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/miman/json-schema-viewer.git",
29
+ "directory": "web"
30
+ },
31
+ "license": "MIT",
32
+ "keywords": [
33
+ "json-schema",
34
+ "viewer",
35
+ "react",
36
+ "backstage"
37
+ ]
38
+ }