@nitrogenbuilder/connector-payload 0.1.35 → 0.1.36

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.
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import NitrogenDataViewerRuntime from './NitrogenDataViewerRuntime';
3
- const NitrogenDataViewer = ({ field, value }) => {
3
+ const NitrogenDataViewer = ({ field, path, value }) => {
4
4
  const label = typeof field.label === 'string' ? field.label : field.name;
5
5
  const description = typeof field.admin?.description === 'string' ? field.admin.description : undefined;
6
- return (_jsx(NitrogenDataViewerRuntime, { description: description, label: label, value: value }));
6
+ return (_jsx(NitrogenDataViewerRuntime, { description: description, initialValue: value, label: label, path: path }));
7
7
  };
8
8
  export default NitrogenDataViewer;
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
2
  declare const NitrogenDataViewerRuntime: React.FC<{
3
3
  description?: string;
4
+ initialValue?: unknown;
4
5
  label: string;
5
- value?: unknown;
6
+ path?: string;
6
7
  }>;
7
8
  export default NitrogenDataViewerRuntime;
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useCallback } from 'react';
3
+ import { useField } from '@payloadcms/ui';
4
+ import { useCallback, useMemo, useState } from 'react';
4
5
  function updateAtPath(root, path, newValue) {
5
6
  if (path.length === 0)
6
7
  return newValue;
@@ -73,10 +74,10 @@ function renameKeyAtPath(root, path, newKey) {
73
74
  return navigate(root, parentPath);
74
75
  }
75
76
  function addChildAtPath(root, path) {
76
- function getAt(node, p) {
77
- if (p.length === 0)
77
+ function getAt(node, currentPath) {
78
+ if (currentPath.length === 0)
78
79
  return node;
79
- const [head, ...rest] = p;
80
+ const [head, ...rest] = currentPath;
80
81
  if (Array.isArray(node))
81
82
  return getAt(node[head], rest);
82
83
  if (typeof node === 'object' && node !== null) {
@@ -91,88 +92,117 @@ function addChildAtPath(root, path) {
91
92
  if (typeof target === 'object' && target !== null) {
92
93
  const obj = target;
93
94
  let key = 'newKey';
94
- let i = 1;
95
- while (key in obj)
96
- key = `newKey${i++}`;
95
+ let index = 1;
96
+ while (key in obj) {
97
+ key = `newKey${index++}`;
98
+ }
97
99
  return updateAtPath(root, path, { ...obj, [key]: '' });
98
100
  }
99
101
  return root;
100
102
  }
101
- function InlineEdit({ display, onCommit, colorClass, }) {
103
+ function coerceDisplayValue(value) {
104
+ if (typeof value === 'string') {
105
+ return value;
106
+ }
107
+ return value != null ? JSON.stringify(value, null, 2) : '[]';
108
+ }
109
+ function parseJsonValue(value) {
110
+ if (typeof value === 'string') {
111
+ try {
112
+ return JSON.parse(value);
113
+ }
114
+ catch {
115
+ return [];
116
+ }
117
+ }
118
+ return value ?? [];
119
+ }
120
+ function InlineEdit({ colorClass, display, onCommit, }) {
102
121
  const [draft, setDraft] = useState(display);
103
122
  const commit = () => onCommit(draft);
104
- return (_jsx("input", { autoFocus: true, value: draft, onChange: (e) => setDraft(e.target.value), onBlur: commit, onKeyDown: (e) => {
105
- if (e.key === 'Enter') {
106
- e.preventDefault();
123
+ return (_jsx("input", { autoFocus: true, className: colorClass, onBlur: commit, onChange: (event) => setDraft(event.target.value), onClick: (event) => event.stopPropagation(), onKeyDown: (event) => {
124
+ if (event.key === 'Enter') {
125
+ event.preventDefault();
107
126
  commit();
108
127
  }
109
- if (e.key === 'Escape')
128
+ if (event.key === 'Escape') {
110
129
  onCommit(display);
111
- }, onClick: (e) => e.stopPropagation(), className: colorClass, style: {
130
+ }
131
+ }, style: {
112
132
  background: 'transparent',
113
133
  border: 'none',
114
134
  borderBottom: '1px solid currentColor',
115
135
  color: 'inherit',
116
136
  font: 'inherit',
117
- padding: '0 2px',
118
- outline: 'none',
137
+ maxWidth: '500px',
119
138
  minWidth: '4ch',
139
+ outline: 'none',
140
+ padding: '0 2px',
120
141
  width: `${Math.max(draft.length + 2, 4)}ch`,
121
- maxWidth: '500px',
122
- } }));
142
+ }, value: draft }));
123
143
  }
124
- function ActionBtn({ label, color, onClick, }) {
125
- return (_jsx("button", { type: "button", onClick: onClick, style: {
126
- marginLeft: 6,
127
- padding: '0 5px',
128
- fontSize: '10px',
129
- lineHeight: '16px',
144
+ function ActionButton({ color, label, onClick, }) {
145
+ return (_jsx("button", { onClick: onClick, style: {
130
146
  background: color,
131
- color: '#fff',
132
147
  border: 'none',
133
- borderRadius: '3px',
148
+ borderRadius: 3,
149
+ color: '#fff',
134
150
  cursor: 'pointer',
135
151
  flexShrink: 0,
152
+ fontSize: 10,
153
+ lineHeight: '16px',
154
+ marginLeft: 6,
136
155
  opacity: 0.85,
137
- }, children: label }));
156
+ padding: '0 5px',
157
+ }, type: "button", children: label }));
138
158
  }
139
- function JsonNode({ k, value, depth, forceOpen, path, unlocked, callbacks, }) {
159
+ function JsonNode({ callbacks, depth, forceOpen, k, path, unlocked, value, }) {
140
160
  const defaultOpen = forceOpen !== null ? forceOpen : depth < 2;
141
161
  const [open, setOpen] = useState(defaultOpen);
142
- const [editingValue, setEditingValue] = useState(false);
143
162
  const [editingKey, setEditingKey] = useState(false);
144
- const { onUpdate, onDelete, onRenameKey, onAddChild } = callbacks;
145
- const del = unlocked ? (_jsx(ActionBtn, { label: "\u00D7", color: "#ef4444", onClick: (e) => { e.stopPropagation(); onDelete(path); } })) : null;
146
- const keyEl = k === undefined ? null : (_jsxs(_Fragment, { children: [_jsxs("span", { className: "njv-key", children: ["\"", unlocked && editingKey ? (_jsx(InlineEdit, { display: k, colorClass: "njv-key", onCommit: (newKey) => {
163
+ const [editingValue, setEditingValue] = useState(false);
164
+ const { onAddChild, onDelete, onRenameKey, onUpdate } = callbacks;
165
+ const deleteButton = unlocked ? (_jsx(ActionButton, { color: "#ef4444", label: "\u00D7", onClick: (event) => {
166
+ event.stopPropagation();
167
+ onDelete(path);
168
+ } })) : null;
169
+ const keyElement = k === undefined ? null : (_jsxs(_Fragment, { children: [_jsxs("span", { className: "njv-key", children: ["\"", unlocked && editingKey ? (_jsx(InlineEdit, { colorClass: "njv-key", display: k, onCommit: (newKey) => {
147
170
  setEditingKey(false);
148
- if (newKey !== k)
171
+ if (newKey !== k) {
149
172
  onRenameKey(path, newKey);
150
- } })) : (_jsx("span", { onClick: unlocked ? (e) => { e.stopPropagation(); setEditingKey(true); } : undefined, style: unlocked ? { cursor: 'text', borderBottom: '1px dotted currentColor' } : undefined, children: k })), "\""] }), _jsx("span", { className: "njv-brace", children: ": " })] }));
173
+ }
174
+ } })) : (_jsx("span", { onClick: unlocked ? (event) => { event.stopPropagation(); setEditingKey(true); } : undefined, style: unlocked ? { borderBottom: '1px dotted currentColor', cursor: 'text' } : undefined, children: k })), "\""] }), _jsx("span", { className: "njv-brace", children: ": " })] }));
151
175
  if (value === null) {
152
- return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyEl, _jsx("span", { className: "njv-null", title: unlocked ? 'Click to convert to empty string' : undefined, onClick: unlocked ? (e) => { e.stopPropagation(); onUpdate(path, ''); } : undefined, style: unlocked ? { cursor: 'pointer', borderBottom: '1px dotted currentColor' } : undefined, children: "null" })] }), del] }));
176
+ return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyElement, _jsx("span", { className: "njv-null", onClick: unlocked ? (event) => { event.stopPropagation(); onUpdate(path, ''); } : undefined, style: unlocked ? { borderBottom: '1px dotted currentColor', cursor: 'pointer' } : undefined, title: unlocked ? 'Click to convert to empty string' : undefined, children: "null" })] }), deleteButton] }));
153
177
  }
154
178
  if (typeof value === 'string') {
155
- return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyEl, _jsxs("span", { className: "njv-string", children: ["\"", unlocked && editingValue ? (_jsx(InlineEdit, { display: value, colorClass: "njv-string", onCommit: (v) => {
179
+ return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyElement, _jsxs("span", { className: "njv-string", children: ["\"", unlocked && editingValue ? (_jsx(InlineEdit, { colorClass: "njv-string", display: value, onCommit: (nextValue) => {
156
180
  setEditingValue(false);
157
- onUpdate(path, v);
158
- } })) : (_jsx("span", { onClick: unlocked ? (e) => { e.stopPropagation(); setEditingValue(true); } : undefined, style: unlocked ? { cursor: 'text', borderBottom: '1px dotted currentColor' } : undefined, children: value.length > 120 ? value.slice(0, 120) + '…' : value })), "\""] })] }), del] }));
181
+ onUpdate(path, nextValue);
182
+ } })) : (_jsx("span", { onClick: unlocked ? (event) => { event.stopPropagation(); setEditingValue(true); } : undefined, style: unlocked ? { borderBottom: '1px dotted currentColor', cursor: 'text' } : undefined, children: value.length > 120 ? `${value.slice(0, 120)}…` : value })), "\""] })] }), deleteButton] }));
159
183
  }
160
184
  if (typeof value === 'number') {
161
- return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyEl, _jsx("span", { className: "njv-number", children: unlocked && editingValue ? (_jsx(InlineEdit, { display: String(value), colorClass: "njv-number", onCommit: (v) => {
185
+ return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyElement, _jsx("span", { className: "njv-number", children: unlocked && editingValue ? (_jsx(InlineEdit, { colorClass: "njv-number", display: String(value), onCommit: (nextValue) => {
162
186
  setEditingValue(false);
163
- const n = Number(v);
164
- onUpdate(path, Number.isNaN(n) ? v : n);
165
- } })) : (_jsx("span", { onClick: unlocked ? (e) => { e.stopPropagation(); setEditingValue(true); } : undefined, style: unlocked ? { cursor: 'text', borderBottom: '1px dotted currentColor' } : undefined, children: value })) })] }), del] }));
187
+ const numericValue = Number(nextValue);
188
+ onUpdate(path, Number.isNaN(numericValue) ? nextValue : numericValue);
189
+ } })) : (_jsx("span", { onClick: unlocked ? (event) => { event.stopPropagation(); setEditingValue(true); } : undefined, style: unlocked ? { borderBottom: '1px dotted currentColor', cursor: 'text' } : undefined, children: value })) })] }), deleteButton] }));
166
190
  }
167
191
  if (typeof value === 'boolean') {
168
- return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyEl, _jsx("span", { className: "njv-boolean", onClick: unlocked ? (e) => { e.stopPropagation(); onUpdate(path, !value); } : undefined, title: unlocked ? 'Click to toggle' : undefined, style: unlocked ? { cursor: 'pointer', borderBottom: '1px dotted currentColor' } : undefined, children: String(value) })] }), del] }));
192
+ return (_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20 }, children: [keyElement, _jsx("span", { className: "njv-boolean", onClick: unlocked ? (event) => { event.stopPropagation(); onUpdate(path, !value); } : undefined, style: unlocked ? { borderBottom: '1px dotted currentColor', cursor: 'pointer' } : undefined, title: unlocked ? 'Click to toggle' : undefined, children: String(value) })] }), deleteButton] }));
169
193
  }
170
194
  if (Array.isArray(value)) {
171
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20, cursor: 'pointer', userSelect: 'none' }, onClick: () => setOpen((o) => !o), children: [_jsx("span", { className: "njv-arrow", children: open ? '▼' : '▶' }), keyEl, _jsx("span", { className: "njv-brace", children: "[" }), !open && (_jsxs(_Fragment, { children: [_jsxs("span", { className: "njv-summary", children: [" ", value.length, " items "] }), _jsx("span", { className: "njv-brace", children: "]" })] }))] }), del] }), open && (_jsxs(_Fragment, { children: [value.map((item, i) => (_jsx(JsonNode, { value: item, depth: depth + 1, forceOpen: forceOpen, path: [...path, i], unlocked: unlocked, callbacks: callbacks }, i))), _jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsx("span", { className: "njv-code", style: { paddingLeft: (depth + 1) * 20 }, children: _jsx("span", { className: "njv-brace", children: "]" }) }), unlocked && (_jsx(ActionBtn, { label: "+ item", color: "#22c55e", onClick: (e) => { e.stopPropagation(); onAddChild(path); } }))] })] }))] }));
195
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", onClick: () => setOpen((current) => !current), style: { cursor: 'pointer', paddingLeft: depth * 20, userSelect: 'none' }, children: [_jsx("span", { className: "njv-arrow", children: open ? '▼' : '▶' }), keyElement, _jsx("span", { className: "njv-brace", children: "[" }), !open ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "njv-summary", children: [" ", value.length, " items "] }), _jsx("span", { className: "njv-brace", children: "]" })] })) : null] }), deleteButton] }), open ? (_jsxs(_Fragment, { children: [value.map((item, index) => (_jsx(JsonNode, { callbacks: callbacks, depth: depth + 1, forceOpen: forceOpen, path: [...path, index], unlocked: unlocked, value: item }, index))), _jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsx("span", { className: "njv-code", style: { paddingLeft: (depth + 1) * 20 }, children: _jsx("span", { className: "njv-brace", children: "]" }) }), unlocked ? (_jsx(ActionButton, { color: "#22c55e", label: "+ item", onClick: (event) => {
196
+ event.stopPropagation();
197
+ onAddChild(path);
198
+ } })) : null] })] })) : null] }));
172
199
  }
173
200
  if (typeof value === 'object') {
174
201
  const entries = Object.entries(value);
175
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", style: { paddingLeft: depth * 20, cursor: 'pointer', userSelect: 'none' }, onClick: () => setOpen((o) => !o), children: [_jsx("span", { className: "njv-arrow", children: open ? '▼' : '▶' }), keyEl, _jsx("span", { className: "njv-brace", children: '{' }), !open && (_jsxs(_Fragment, { children: [_jsxs("span", { className: "njv-summary", children: [" ", entries.length, " keys "] }), _jsx("span", { className: "njv-brace", children: '}' })] }))] }), del] }), open && (_jsxs(_Fragment, { children: [entries.map(([ek, ev]) => (_jsx(JsonNode, { k: ek, value: ev, depth: depth + 1, forceOpen: forceOpen, path: [...path, ek], unlocked: unlocked, callbacks: callbacks }, ek))), _jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsx("span", { className: "njv-code", style: { paddingLeft: (depth + 1) * 20 }, children: _jsx("span", { className: "njv-brace", children: '}' }) }), unlocked && (_jsx(ActionBtn, { label: "+ key", color: "#22c55e", onClick: (e) => { e.stopPropagation(); onAddChild(path); } }))] })] }))] }));
202
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsxs("span", { className: "njv-code", onClick: () => setOpen((current) => !current), style: { cursor: 'pointer', paddingLeft: depth * 20, userSelect: 'none' }, children: [_jsx("span", { className: "njv-arrow", children: open ? '▼' : '▶' }), keyElement, _jsx("span", { className: "njv-brace", children: '{' }), !open ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "njv-summary", children: [" ", entries.length, " keys "] }), _jsx("span", { className: "njv-brace", children: '}' })] })) : null] }), deleteButton] }), open ? (_jsxs(_Fragment, { children: [entries.map(([entryKey, entryValue]) => (_jsx(JsonNode, { callbacks: callbacks, depth: depth + 1, forceOpen: forceOpen, k: entryKey, path: [...path, entryKey], unlocked: unlocked, value: entryValue }, entryKey))), _jsxs("div", { className: "njv-line", style: { alignItems: 'center' }, children: [_jsx("span", { className: "njv-code", style: { paddingLeft: (depth + 1) * 20 }, children: _jsx("span", { className: "njv-brace", children: '}' }) }), unlocked ? (_jsx(ActionButton, { color: "#22c55e", label: "+ key", onClick: (event) => {
203
+ event.stopPropagation();
204
+ onAddChild(path);
205
+ } })) : null] })] })) : null] }));
176
206
  }
177
207
  return null;
178
208
  }
@@ -280,43 +310,86 @@ function ensureStyles() {
280
310
  `;
281
311
  document.head.appendChild(style);
282
312
  }
283
- const NitrogenDataViewerRuntime = ({ description, label, value }) => {
284
- const [copied, setCopied] = useState(false);
313
+ const NitrogenDataViewerRuntime = ({ description, initialValue, label, path }) => {
314
+ const field = path ? useField({ path }) : null;
315
+ const value = field?.value ?? initialValue;
316
+ const setValue = field?.setValue;
285
317
  const [collapsed, setCollapsed] = useState(true);
318
+ const [copied, setCopied] = useState(false);
286
319
  const [forceOpen, setForceOpen] = useState(null);
320
+ const [manualPasteValue, setManualPasteValue] = useState('');
321
+ const [pasteError, setPasteError] = useState('');
322
+ const [pasted, setPasted] = useState(false);
323
+ const [showPastePanel, setShowPastePanel] = useState(false);
287
324
  const [treeKey, setTreeKey] = useState(0);
325
+ const [unlocked, setUnlocked] = useState(false);
288
326
  ensureStyles();
289
- let parsed = [];
290
- try {
291
- parsed = typeof value === 'string' ? JSON.parse(value) : value;
292
- }
293
- catch {
294
- parsed = [];
295
- }
296
- const jsonString = value != null ? JSON.stringify(value, null, 2) : '[]';
327
+ const parsed = useMemo(() => parseJsonValue(value), [value]);
328
+ const jsonString = useMemo(() => coerceDisplayValue(value), [value]);
297
329
  const moduleCount = Array.isArray(parsed) ? parsed.length : null;
330
+ const applyValue = useCallback((nextValue) => {
331
+ if (!setValue)
332
+ return;
333
+ setValue(nextValue);
334
+ }, [setValue]);
335
+ const callbacks = useMemo(() => ({
336
+ onAddChild: (targetPath) => {
337
+ applyValue(addChildAtPath(parsed, targetPath));
338
+ },
339
+ onDelete: (targetPath) => {
340
+ applyValue(deleteAtPath(parsed, targetPath));
341
+ },
342
+ onRenameKey: (targetPath, newKey) => {
343
+ applyValue(renameKeyAtPath(parsed, targetPath, newKey));
344
+ },
345
+ onUpdate: (targetPath, nextValue) => {
346
+ applyValue(updateAtPath(parsed, targetPath, nextValue));
347
+ },
348
+ }), [applyValue, parsed]);
298
349
  const handleCopy = useCallback(() => {
299
350
  navigator.clipboard.writeText(jsonString).then(() => {
300
351
  setCopied(true);
301
352
  setTimeout(() => setCopied(false), 2000);
302
353
  });
303
354
  }, [jsonString]);
355
+ const applyPastedJson = useCallback((rawValue) => {
356
+ const trimmed = rawValue.trim();
357
+ if (!trimmed) {
358
+ setPasteError('Paste some JSON first.');
359
+ return;
360
+ }
361
+ try {
362
+ const parsedValue = JSON.parse(trimmed);
363
+ applyValue(parsedValue);
364
+ setManualPasteValue('');
365
+ setPasteError('');
366
+ setPasted(true);
367
+ setShowPastePanel(false);
368
+ setTreeKey((current) => current + 1);
369
+ setTimeout(() => setPasted(false), 2000);
370
+ }
371
+ catch {
372
+ setPasteError('That is not valid JSON.');
373
+ }
374
+ }, [applyValue]);
375
+ const handlePasteFromClipboard = useCallback(() => {
376
+ navigator.clipboard.readText().then((text) => {
377
+ applyPastedJson(text);
378
+ }, () => {
379
+ setPasteError('Clipboard access was blocked. Paste manually below.');
380
+ setShowPastePanel(true);
381
+ });
382
+ }, [applyPastedJson]);
304
383
  const expandAll = useCallback(() => {
305
384
  setForceOpen(true);
306
- setTreeKey((k) => k + 1);
385
+ setTreeKey((current) => current + 1);
307
386
  }, []);
308
387
  const collapseAll = useCallback(() => {
309
388
  setForceOpen(false);
310
- setTreeKey((k) => k + 1);
389
+ setTreeKey((current) => current + 1);
311
390
  }, []);
312
- const callbacks = {
313
- onUpdate: () => undefined,
314
- onDelete: () => undefined,
315
- onRenameKey: () => undefined,
316
- onAddChild: () => undefined,
317
- };
318
- const header = (_jsxs("span", { children: [label, moduleCount !== null && (_jsxs("span", { style: { opacity: 0.5, fontWeight: 400, marginLeft: 8 }, children: ["(", moduleCount, " item", moduleCount !== 1 ? 's' : '', ")"] }))] }));
319
- return (_jsxs("div", { className: "njv-root field-type", style: { marginBottom: '1.5rem' }, children: [_jsxs("div", { style: { border: '1px solid var(--njv-border)', borderRadius: '4px', overflow: 'hidden' }, children: [_jsxs("button", { type: "button", onClick: () => setCollapsed((current) => !current), style: {
391
+ const header = (_jsxs("span", { children: [label, moduleCount !== null ? (_jsxs("span", { style: { fontWeight: 400, marginLeft: 8, opacity: 0.5 }, children: ["(", moduleCount, " item", moduleCount !== 1 ? 's' : '', ")"] })) : null] }));
392
+ return (_jsxs("div", { className: "njv-root field-type", style: { marginBottom: '1.5rem' }, children: [_jsxs("div", { style: { border: '1px solid var(--njv-border)', borderRadius: 4, overflow: 'hidden' }, children: [_jsxs("button", { onClick: () => setCollapsed((current) => !current), style: {
320
393
  alignItems: 'center',
321
394
  background: 'var(--theme-elevation-50, #f8f8f8)',
322
395
  border: 'none',
@@ -326,12 +399,33 @@ const NitrogenDataViewerRuntime = ({ description, label, value }) => {
326
399
  justifyContent: 'space-between',
327
400
  padding: '12px 16px',
328
401
  width: '100%',
329
- }, children: [header, _jsx("span", { style: { fontSize: 12, opacity: 0.65 }, children: collapsed ? 'Show' : 'Hide' })] }), !collapsed && (_jsxs("div", { children: [_jsxs("div", { className: "njv-toolbar", children: [_jsx("button", { type: "button", className: "btn btn--size-small btn--style-secondary", onClick: handleCopy, children: copied ? '✓ Copied' : 'Copy' }), _jsx("button", { type: "button", className: "btn btn--size-small btn--style-secondary", onClick: expandAll, children: "Expand All" }), _jsx("button", { type: "button", className: "btn btn--size-small btn--style-secondary", onClick: collapseAll, children: "Collapse All" })] }), _jsx("div", { className: "njv-body", style: {
330
- maxHeight: '50vh',
331
- overflow: 'auto',
402
+ }, type: "button", children: [header, _jsx("span", { style: { fontSize: 12, opacity: 0.65 }, children: collapsed ? 'Show' : 'Hide' })] }), !collapsed ? (_jsxs("div", { children: [_jsxs("div", { className: "njv-toolbar", children: [_jsx("button", { className: "btn btn--size-small btn--style-secondary", onClick: handleCopy, type: "button", children: copied ? '✓ Copied' : 'Copy' }), _jsx("button", { className: "btn btn--size-small btn--style-secondary", onClick: () => setUnlocked((current) => !current), type: "button", children: unlocked ? 'Lock' : 'Unlock' }), unlocked ? (_jsxs(_Fragment, { children: [_jsx("button", { className: "btn btn--size-small btn--style-secondary", onClick: handlePasteFromClipboard, type: "button", children: pasted ? '✓ Pasted' : 'Paste' }), _jsx("button", { className: "btn btn--size-small btn--style-secondary", onClick: () => {
403
+ setShowPastePanel((current) => !current);
404
+ setPasteError('');
405
+ }, type: "button", children: showPastePanel ? 'Hide Paste Box' : 'Paste Manually' })] })) : null, _jsx("button", { className: "btn btn--size-small btn--style-secondary", onClick: expandAll, type: "button", children: "Expand All" }), _jsx("button", { className: "btn btn--size-small btn--style-secondary", onClick: collapseAll, type: "button", children: "Collapse All" })] }), unlocked && showPastePanel ? (_jsxs("div", { style: {
406
+ background: 'var(--theme-elevation-50, #f8f8f8)',
407
+ borderBottom: '1px solid var(--njv-border)',
408
+ display: 'grid',
409
+ gap: 8,
410
+ padding: 12,
411
+ }, children: [_jsx("textarea", { onChange: (event) => setManualPasteValue(event.target.value), placeholder: "Paste Nitrogen JSON here...", style: {
412
+ border: '1px solid var(--theme-elevation-150, #ddd)',
413
+ borderRadius: 4,
414
+ fontFamily: 'var(--font-mono, \"SF Mono\", Menlo, Consolas, monospace)',
415
+ fontSize: 12,
416
+ minHeight: 160,
417
+ padding: 12,
418
+ resize: 'vertical',
419
+ width: '100%',
420
+ }, value: manualPasteValue }), _jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 8 }, children: [_jsx("button", { className: "btn btn--size-small btn--style-primary", onClick: () => applyPastedJson(manualPasteValue), type: "button", children: "Apply Pasted JSON" }), _jsx("button", { className: "btn btn--size-small btn--style-secondary", onClick: () => {
421
+ setManualPasteValue('');
422
+ setPasteError('');
423
+ }, type: "button", children: "Clear" })] }), pasteError ? (_jsx("p", { style: { color: 'var(--theme-error-500, #dc2626)', fontSize: 12, margin: 0 }, children: pasteError })) : null] })) : null, _jsx("div", { className: "njv-body", style: {
424
+ backgroundColor: 'var(--njv-bg)',
332
425
  fontFamily: 'var(--font-mono, "SF Mono", Menlo, Consolas, monospace)',
333
426
  fontSize: 'var(--font-body-size, 13px)',
334
- backgroundColor: 'var(--njv-bg)',
335
- }, children: _jsx(JsonNode, { value: parsed ?? [], depth: 0, forceOpen: forceOpen, path: [], unlocked: false, callbacks: callbacks }, treeKey) })] }))] }), typeof description === 'string' && (_jsx("p", { style: { fontSize: '12px', color: '#888', marginTop: '4px' }, children: description }))] }));
427
+ maxHeight: '50vh',
428
+ overflow: 'auto',
429
+ }, children: _jsx(JsonNode, { callbacks: callbacks, depth: 0, forceOpen: forceOpen, path: [], unlocked: unlocked, value: parsed }, treeKey) })] })) : null] }), typeof description === 'string' ? (_jsx("p", { style: { color: '#888', fontSize: 12, marginTop: 4 }, children: description })) : null] }));
336
430
  };
337
431
  export default NitrogenDataViewerRuntime;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitrogenbuilder/connector-payload",
3
- "version": "0.1.35",
3
+ "version": "0.1.36",
4
4
  "description": "Nitrogen page builder connector plugin for Payload CMS 3.x",
5
5
  "author": "Leonardo Dentzien <leo@torchmedia.ca>",
6
6
  "type": "module",