cf-json-schema-viz 0.1.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.
@@ -0,0 +1,480 @@
1
+ /* JSON Schema Viewer - Pure CSS with CSS Custom Properties */
2
+
3
+ /* ========================================
4
+ Theme Variables - Light Mode (default)
5
+ Define at :root so portaled elements inherit them
6
+ ======================================== */
7
+ :root {
8
+ --jsv-font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
9
+ --jsv-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
10
+ --jsv-font-size: 0.875rem;
11
+
12
+ /* Colors - Light Mode defaults */
13
+ --jsv-color-body: #1a1a1a;
14
+ --jsv-color-muted: #6b7280;
15
+ --jsv-color-border: #e5e7eb;
16
+ --jsv-color-canvas: #f4f4f5;
17
+ --jsv-color-canvas-tint: #f4f4f5;
18
+ --jsv-color-bg: #ffffff;
19
+
20
+ /* Semantic colors - Cloudflare orange as primary */
21
+ --jsv-color-primary: #f6821f;
22
+ --jsv-color-danger: #dc2626;
23
+ --jsv-color-warning: #f97316;
24
+ --jsv-color-success: #16a34a;
25
+ }
26
+
27
+ /* ========================================
28
+ Theme Variables - Dark Mode
29
+ Cloudflare docs dark theme colors
30
+ ======================================== */
31
+ :root[data-theme="dark"],
32
+ [data-theme="dark"] {
33
+ --jsv-color-body: #e4e4e7;
34
+ --jsv-color-muted: #a1a1aa;
35
+ --jsv-color-border: #3f3f46;
36
+ --jsv-color-canvas: #27272a;
37
+ --jsv-color-canvas-tint: #3f3f46;
38
+ --jsv-color-bg: #18181b;
39
+
40
+ --jsv-color-primary: #f6821f;
41
+ --jsv-color-danger: #f87171;
42
+ --jsv-color-warning: #fb923c;
43
+ --jsv-color-success: #4ade80;
44
+ }
45
+
46
+ /* ========================================
47
+ Base Styles
48
+ ======================================== */
49
+ .jsv-root {
50
+ font-size: var(--jsv-font-size);
51
+ font-family: var(--jsv-font-sans);
52
+ color: var(--jsv-color-body);
53
+ line-height: 1.5;
54
+ position: relative;
55
+ }
56
+
57
+ .jsv-content {
58
+ padding-left: 2rem;
59
+ padding-right: 1rem;
60
+ padding-bottom: 0.5rem;
61
+ padding-top: 0.375rem;
62
+ }
63
+
64
+ /* ========================================
65
+ Schema Row
66
+ ======================================== */
67
+ .jsv-row {
68
+ position: relative;
69
+ padding-top: 0.25rem;
70
+ padding-bottom: 0.25rem;
71
+ display: flex;
72
+ align-items: flex-start;
73
+ max-width: 100%;
74
+ }
75
+
76
+ .jsv-row-content {
77
+ display: flex;
78
+ flex-direction: column;
79
+ gap: 0.125rem;
80
+ max-width: 100%;
81
+ flex: 1;
82
+ min-width: 0;
83
+ }
84
+
85
+ .jsv-row-header {
86
+ display: flex;
87
+ align-items: center;
88
+ max-width: 100%;
89
+ gap: 0.25rem;
90
+ }
91
+
92
+ /* Nubbin - horizontal connector from left border to property */
93
+ .jsv-nubbin {
94
+ width: 0.75rem;
95
+ height: 0;
96
+ border-top: 1px solid var(--jsv-color-border);
97
+ flex-shrink: 0;
98
+ margin-top: 0.5rem;
99
+ margin-right: 0.5rem;
100
+ margin-left: -1rem;
101
+ }
102
+
103
+ .jsv-nubbin-short {
104
+ width: 0.25rem;
105
+ }
106
+
107
+ /* ========================================
108
+ Child Stack (nested content with left border)
109
+ ======================================== */
110
+ .jsv-child-stack {
111
+ font-size: var(--jsv-font-size);
112
+ }
113
+
114
+ .jsv-child-stack-nested {
115
+ border-left: 1px solid var(--jsv-color-border);
116
+ margin-left: 0.5rem;
117
+ padding-left: 1rem;
118
+ margin-top: 0.25rem;
119
+ }
120
+
121
+ /* ========================================
122
+ Property Name
123
+ ======================================== */
124
+ .jsv-property-name {
125
+ font-family: var(--jsv-font-mono);
126
+ font-weight: 600;
127
+ margin-right: 0.5rem;
128
+ flex-shrink: 0;
129
+ }
130
+
131
+ /* ========================================
132
+ Type Display
133
+ ======================================== */
134
+ .jsv-type {
135
+ color: var(--jsv-color-muted);
136
+ overflow: hidden;
137
+ text-overflow: ellipsis;
138
+ white-space: nowrap;
139
+ }
140
+
141
+ .jsv-types-container {
142
+ display: flex;
143
+ align-items: baseline;
144
+ font-size: var(--jsv-font-size);
145
+ min-width: 0;
146
+ }
147
+
148
+ /* ========================================
149
+ Badges (required, deprecated, read-only)
150
+ ======================================== */
151
+ .jsv-badges {
152
+ display: flex;
153
+ align-items: center;
154
+ gap: 0.5rem;
155
+ flex-shrink: 0;
156
+ }
157
+
158
+ .jsv-badge {
159
+ font-size: 0.75rem;
160
+ }
161
+
162
+ .jsv-badge-required {
163
+ color: var(--jsv-color-warning);
164
+ }
165
+
166
+ .jsv-badge-deprecated {
167
+ color: var(--jsv-color-warning);
168
+ }
169
+
170
+ .jsv-badge-readonly {
171
+ color: var(--jsv-color-muted);
172
+ }
173
+
174
+ /* ========================================
175
+ Divider (horizontal line on hover)
176
+ ======================================== */
177
+ .jsv-divider {
178
+ height: 1px;
179
+ flex: 1;
180
+ margin-left: 0.75rem;
181
+ margin-right: 0.75rem;
182
+ min-width: 1rem;
183
+ background-color: transparent;
184
+ transition: background-color 0.15s ease;
185
+ }
186
+
187
+ .jsv-divider-visible {
188
+ background-color: var(--jsv-color-border);
189
+ }
190
+
191
+ /* ========================================
192
+ Description
193
+ ======================================== */
194
+ .jsv-description {
195
+ font-size: var(--jsv-font-size);
196
+ color: var(--jsv-color-muted);
197
+ margin-top: 0.0625rem;
198
+ line-height: 1.4;
199
+ }
200
+
201
+ /* ========================================
202
+ Validations
203
+ ======================================== */
204
+ .jsv-validations {
205
+ display: flex;
206
+ flex-wrap: wrap;
207
+ gap: 0.25rem;
208
+ align-items: center;
209
+ margin-top: 0.125rem;
210
+ }
211
+
212
+ .jsv-validations-row {
213
+ display: flex;
214
+ flex-wrap: wrap;
215
+ gap: 0.25rem;
216
+ align-items: center;
217
+ }
218
+
219
+ .jsv-validation {
220
+ display: flex;
221
+ align-items: baseline;
222
+ gap: 0.375rem;
223
+ color: var(--jsv-color-muted);
224
+ font-size: 0.75rem;
225
+ }
226
+
227
+ .jsv-validation-label {
228
+ flex-shrink: 0;
229
+ }
230
+
231
+ .jsv-validation-values {
232
+ display: flex;
233
+ flex-wrap: wrap;
234
+ gap: 0.25rem;
235
+ flex: 1;
236
+ }
237
+
238
+ .jsv-validation-value {
239
+ padding: 0.0625rem 0.375rem;
240
+ background-color: var(--jsv-color-canvas-tint);
241
+ color: var(--jsv-color-muted);
242
+ border: 1px solid var(--jsv-color-border);
243
+ border-radius: 0.25rem;
244
+ font-family: var(--jsv-font-mono);
245
+ font-size: 0.75rem;
246
+ word-break: break-all;
247
+ }
248
+
249
+ /* ========================================
250
+ Caret (expand/collapse icon)
251
+ ======================================== */
252
+ .jsv-caret {
253
+ width: 1.25rem;
254
+ height: 1.25rem;
255
+ margin-left: -1.5rem;
256
+ margin-right: 0.25rem;
257
+ color: var(--jsv-color-muted);
258
+ display: flex;
259
+ justify-content: center;
260
+ align-items: center;
261
+ cursor: pointer;
262
+ flex-shrink: 0;
263
+ transition: transform 0.15s ease;
264
+ }
265
+
266
+ .jsv-caret:hover {
267
+ color: var(--jsv-color-body);
268
+ }
269
+
270
+ .jsv-caret-expanded {
271
+ transform: rotate(90deg);
272
+ }
273
+
274
+ /* ========================================
275
+ Error Display
276
+ ======================================== */
277
+ .jsv-error {
278
+ color: var(--jsv-color-danger);
279
+ display: flex;
280
+ align-items: center;
281
+ gap: 0.25rem;
282
+ font-size: 0.75rem;
283
+ }
284
+
285
+ /* ========================================
286
+ Change Annotations (added/removed/modified)
287
+ ======================================== */
288
+ .jsv-annotation {
289
+ position: absolute;
290
+ width: 0.25rem;
291
+ height: 1rem;
292
+ border-radius: 0.125rem;
293
+ top: 50%;
294
+ transform: translateY(-50%);
295
+ }
296
+
297
+ .jsv-annotation-added {
298
+ background-color: var(--jsv-color-success);
299
+ }
300
+
301
+ .jsv-annotation-removed {
302
+ background-color: var(--jsv-color-danger);
303
+ }
304
+
305
+ .jsv-annotation-modified {
306
+ background-color: var(--jsv-color-warning);
307
+ }
308
+
309
+ /* ========================================
310
+ Path Crumbs (sticky breadcrumb header)
311
+ Wrapper is sticky with height:0 (no layout impact)
312
+ Inner crumbs div is absolute, overlays content
313
+ ======================================== */
314
+ .jsv-crumbs {
315
+ height: 2rem;
316
+ padding-left: 2rem;
317
+ padding-right: 1rem;
318
+ font-family: var(--jsv-font-mono);
319
+ font-size: var(--jsv-font-size);
320
+ line-height: 1;
321
+ z-index: 20;
322
+ background-color: var(--sl-color-bg, var(--jsv-color-bg, #fff));
323
+ color: var(--jsv-color-muted);
324
+ display: flex;
325
+ align-items: center;
326
+ gap: 0.25rem;
327
+ border-bottom: 1px solid var(--jsv-color-border);
328
+ border-top-left-radius: 0.5rem;
329
+ border-top-right-radius: 0.5rem;
330
+ box-sizing: border-box;
331
+ /* Hidden by default */
332
+ opacity: 0;
333
+ pointer-events: none;
334
+ }
335
+
336
+ [data-theme="dark"] .jsv-crumbs,
337
+ :root[data-theme="dark"] .jsv-crumbs {
338
+ border-bottom-color: var(--sl-color-gray-5, #52525b);
339
+ }
340
+
341
+ .jsv-crumbs[data-visible="true"] {
342
+ opacity: 1;
343
+ pointer-events: auto;
344
+ }
345
+
346
+ .jsv-crumb-current {
347
+ color: var(--jsv-color-body);
348
+ font-weight: 600;
349
+ }
350
+
351
+ /* ========================================
352
+ Select / Menu Dropdown
353
+ ======================================== */
354
+ .jsv-select-trigger {
355
+ display: inline-flex;
356
+ align-items: center;
357
+ gap: 0.375rem;
358
+ padding: 0.125rem 0.5rem;
359
+ font-size: var(--jsv-font-size);
360
+ font-family: var(--jsv-font-sans);
361
+ background-color: transparent;
362
+ border: 1px solid var(--jsv-color-border);
363
+ border-radius: 0.25rem;
364
+ cursor: pointer;
365
+ color: var(--jsv-color-muted);
366
+ line-height: 1.4;
367
+ transition: background-color 0.15s ease, border-color 0.15s ease;
368
+ }
369
+
370
+ .jsv-select-trigger:hover {
371
+ background-color: var(--jsv-color-canvas);
372
+ border-color: var(--jsv-color-muted);
373
+ }
374
+
375
+ .jsv-select-trigger:focus {
376
+ outline: none;
377
+ box-shadow: 0 0 0 2px var(--jsv-color-primary);
378
+ }
379
+
380
+ .jsv-select-positioner {
381
+ z-index: 9999 !important;
382
+ position: relative;
383
+ }
384
+
385
+ .jsv-select-popup {
386
+ background-color: var(--jsv-color-bg);
387
+ border: 1px solid var(--jsv-color-border);
388
+ border-radius: 0.375rem;
389
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1);
390
+ padding: 0.25rem 0;
391
+ min-width: 10rem;
392
+ overflow: hidden;
393
+ font-family: var(--jsv-font-sans);
394
+ font-size: var(--jsv-font-size);
395
+ }
396
+
397
+ .jsv-select-item {
398
+ padding: 0.5rem 0.75rem;
399
+ padding-left: 2rem;
400
+ font-size: var(--jsv-font-size);
401
+ cursor: pointer;
402
+ display: flex;
403
+ align-items: center;
404
+ gap: 0.5rem;
405
+ outline: none;
406
+ color: var(--jsv-color-body);
407
+ background-color: var(--jsv-color-bg);
408
+ position: relative;
409
+ transition: background-color 0.1s ease;
410
+ }
411
+
412
+ .jsv-select-item:hover,
413
+ .jsv-select-item:focus,
414
+ .jsv-select-item[data-highlighted] {
415
+ background-color: var(--jsv-color-canvas);
416
+ }
417
+
418
+ .jsv-select-item[data-selected] {
419
+ font-weight: 600;
420
+ }
421
+
422
+ .jsv-select-item-indicator {
423
+ position: absolute;
424
+ left: 0.625rem;
425
+ top: 50%;
426
+ transform: translateY(-50%);
427
+ display: flex;
428
+ align-items: center;
429
+ justify-content: center;
430
+ color: var(--jsv-color-primary);
431
+ }
432
+
433
+ /* ========================================
434
+ Top Level Styles
435
+ ======================================== */
436
+ .jsv-top-label {
437
+ font-family: var(--jsv-font-mono);
438
+ font-weight: 600;
439
+ font-size: var(--jsv-font-size);
440
+ padding-bottom: 0.5rem;
441
+ }
442
+
443
+ .jsv-top-section {
444
+ display: flex;
445
+ align-items: center;
446
+ gap: 0.75rem;
447
+ padding-bottom: 0.5rem;
448
+ }
449
+
450
+ .jsv-combiner-label {
451
+ display: flex;
452
+ align-items: center;
453
+ color: var(--jsv-color-muted);
454
+ font-size: var(--jsv-font-size);
455
+ }
456
+
457
+ /* ========================================
458
+ Link Styles
459
+ ======================================== */
460
+ .jsv-link {
461
+ color: var(--jsv-color-primary);
462
+ cursor: pointer;
463
+ text-decoration: none;
464
+ margin-left: 0.5rem;
465
+ }
466
+
467
+ .jsv-link:hover {
468
+ text-decoration: underline;
469
+ }
470
+
471
+ /* ========================================
472
+ Misc Helpers
473
+ ======================================== */
474
+ .jsv-cursor-pointer {
475
+ cursor: pointer;
476
+ }
477
+
478
+ .jsv-ml-2 {
479
+ margin-left: 0.5rem;
480
+ }
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "cf-json-schema-viz",
3
+ "version": "0.1.0",
4
+ "description": "A lightweight, CSS-in-JS-free React component for rendering JSON Schema definitions. Fork of @stoplight/json-schema-viewer.",
5
+ "keywords": [
6
+ "json-schema",
7
+ "react",
8
+ "schema-viewer",
9
+ "cloudflare",
10
+ "documentation"
11
+ ],
12
+ "sideEffects": false,
13
+ "license": "Apache-2.0",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/mattrothenberg/cf-json-schema-viz.git"
17
+ },
18
+ "homepage": "https://github.com/mattrothenberg/cf-json-schema-viz#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/mattrothenberg/cf-json-schema-viz/issues"
21
+ },
22
+ "author": "Matt Rothenberg",
23
+ "type": "module",
24
+ "main": "./dist/index.js",
25
+ "module": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js"
31
+ },
32
+ "./styles.css": "./dist/styles.css"
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "peerDependencies": {
38
+ "react": "^18.0.0 || ^19.0.0",
39
+ "react-dom": "^18.0.0 || ^19.0.0"
40
+ },
41
+ "dependencies": {
42
+ "@base-ui/react": "^1.2.0",
43
+ "@phosphor-icons/react": "^2.1.7",
44
+ "@stoplight/json": "^3.21.7",
45
+ "@stoplight/json-schema-tree": "^4.0.0",
46
+ "@types/json-schema": "^7.0.15",
47
+ "clsx": "^2.1.1",
48
+ "jotai": "^2.10.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.0.0",
52
+ "@types/react": "^19.0.0",
53
+ "@types/react-dom": "^19.0.0",
54
+ "@vitejs/plugin-react": "^4.3.0",
55
+ "react": "^19.0.0",
56
+ "react-dom": "^19.0.0",
57
+ "tsup": "^8.3.0",
58
+ "typescript": "^5.6.0",
59
+ "vite": "^6.0.0",
60
+ "vitest": "^2.0.0"
61
+ },
62
+ "scripts": {
63
+ "build": "tsup",
64
+ "dev": "tsup --watch",
65
+ "typecheck": "tsc --noEmit",
66
+ "playground": "vite",
67
+ "test": "vitest run",
68
+ "test:watch": "vitest"
69
+ }
70
+ }