@particle-academy/react-fancy 5.15.0 → 5.17.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.
Files changed (143) hide show
  1. package/dist/badge.cjs +3 -2
  2. package/dist/badge.js +2 -1
  3. package/dist/button.cjs +4 -3
  4. package/dist/button.js +2 -1
  5. package/dist/callout.cjs +3 -2
  6. package/dist/callout.js +2 -1
  7. package/dist/{chunk-VE3EM4K2.cjs → chunk-23CLGUMT.cjs} +2 -2
  8. package/dist/{chunk-VE3EM4K2.cjs.map → chunk-23CLGUMT.cjs.map} +1 -1
  9. package/dist/{chunk-C4Z4S3CX.js → chunk-2ICXWLKS.js} +2 -2
  10. package/dist/{chunk-C4Z4S3CX.js.map → chunk-2ICXWLKS.js.map} +1 -1
  11. package/dist/chunk-3I2KWNXT.cjs +4 -0
  12. package/dist/chunk-3I2KWNXT.cjs.map +1 -0
  13. package/dist/{chunk-7C7VF4WY.cjs → chunk-6FYMMQ3G.cjs} +2 -2
  14. package/dist/{chunk-7C7VF4WY.cjs.map → chunk-6FYMMQ3G.cjs.map} +1 -1
  15. package/dist/{chunk-WEGL4S52.js → chunk-6RYZ2MOE.js} +2 -2
  16. package/dist/{chunk-WEGL4S52.js.map → chunk-6RYZ2MOE.js.map} +1 -1
  17. package/dist/{chunk-2CNSZCVE.cjs → chunk-6Y2QO7YV.cjs} +4 -4
  18. package/dist/{chunk-2CNSZCVE.cjs.map → chunk-6Y2QO7YV.cjs.map} +1 -1
  19. package/dist/chunk-AR2IBCX7.cjs +1354 -0
  20. package/dist/chunk-AR2IBCX7.cjs.map +1 -0
  21. package/dist/{chunk-CTMJYV3O.js → chunk-B4JLRS5E.js} +2 -2
  22. package/dist/{chunk-CTMJYV3O.js.map → chunk-B4JLRS5E.js.map} +1 -1
  23. package/dist/{chunk-ECZ66DKF.js → chunk-BWT2L6XP.js} +2 -2
  24. package/dist/{chunk-ECZ66DKF.js.map → chunk-BWT2L6XP.js.map} +1 -1
  25. package/dist/{chunk-O432BDEO.js → chunk-CEEEENPW.js} +6 -3
  26. package/dist/chunk-CEEEENPW.js.map +1 -0
  27. package/dist/{chunk-MILTPAF6.js → chunk-CQWPMRYS.js} +2 -2
  28. package/dist/{chunk-MILTPAF6.js.map → chunk-CQWPMRYS.js.map} +1 -1
  29. package/dist/{chunk-C5AZNBVB.js → chunk-DDRHCFUE.js} +2 -2
  30. package/dist/{chunk-C5AZNBVB.js.map → chunk-DDRHCFUE.js.map} +1 -1
  31. package/dist/{chunk-FA3D4GFC.cjs → chunk-EQGY3QDJ.cjs} +5 -5
  32. package/dist/{chunk-FA3D4GFC.cjs.map → chunk-EQGY3QDJ.cjs.map} +1 -1
  33. package/dist/{chunk-DOSSIU6S.cjs → chunk-FO4GCX67.cjs} +6 -3
  34. package/dist/chunk-FO4GCX67.cjs.map +1 -0
  35. package/dist/chunk-GNHQVPZP.js +3 -0
  36. package/dist/chunk-GNHQVPZP.js.map +1 -0
  37. package/dist/{chunk-GZIUE4DE.js → chunk-HNITJ2UR.js} +3 -3
  38. package/dist/{chunk-GZIUE4DE.js.map → chunk-HNITJ2UR.js.map} +1 -1
  39. package/dist/{chunk-XZYKPGSK.cjs → chunk-HTKDPFLJ.cjs} +2 -2
  40. package/dist/{chunk-XZYKPGSK.cjs.map → chunk-HTKDPFLJ.cjs.map} +1 -1
  41. package/dist/chunk-HXLSEBAL.cjs +4 -0
  42. package/dist/chunk-HXLSEBAL.cjs.map +1 -0
  43. package/dist/{chunk-GKPCXPCD.js → chunk-I2JXK25I.js} +51 -12
  44. package/dist/chunk-I2JXK25I.js.map +1 -0
  45. package/dist/chunk-IQ4KQJAO.js +3 -0
  46. package/dist/chunk-IQ4KQJAO.js.map +1 -0
  47. package/dist/chunk-J324MF75.js +3 -0
  48. package/dist/chunk-J324MF75.js.map +1 -0
  49. package/dist/{chunk-PZIAL4OP.cjs → chunk-JU5W65N3.cjs} +2 -2
  50. package/dist/{chunk-PZIAL4OP.cjs.map → chunk-JU5W65N3.cjs.map} +1 -1
  51. package/dist/{chunk-2G3L4BLU.cjs → chunk-KKYP5R3G.cjs} +2 -2
  52. package/dist/{chunk-2G3L4BLU.cjs.map → chunk-KKYP5R3G.cjs.map} +1 -1
  53. package/dist/chunk-LQ4ICCN2.js +3 -0
  54. package/dist/chunk-LQ4ICCN2.js.map +1 -0
  55. package/dist/{chunk-IF3T3ZCB.cjs → chunk-LYFUPTLG.cjs} +51 -12
  56. package/dist/chunk-LYFUPTLG.cjs.map +1 -0
  57. package/dist/chunk-M5MUGSON.cjs +4 -0
  58. package/dist/chunk-M5MUGSON.cjs.map +1 -0
  59. package/dist/{chunk-UH2YXQ2B.cjs → chunk-MPDLL4X3.cjs} +2 -2
  60. package/dist/{chunk-UH2YXQ2B.cjs.map → chunk-MPDLL4X3.cjs.map} +1 -1
  61. package/dist/chunk-NMXCQOHV.js +3 -0
  62. package/dist/chunk-NMXCQOHV.js.map +1 -0
  63. package/dist/chunk-NW3GJWJ7.js +3 -0
  64. package/dist/chunk-NW3GJWJ7.js.map +1 -0
  65. package/dist/chunk-OYZDSMNP.cjs +4 -0
  66. package/dist/chunk-OYZDSMNP.cjs.map +1 -0
  67. package/dist/{chunk-UWVVEB2N.js → chunk-P7AJAN62.js} +2 -2
  68. package/dist/{chunk-UWVVEB2N.js.map → chunk-P7AJAN62.js.map} +1 -1
  69. package/dist/{chunk-NPKE2IX6.js → chunk-PITWDKKY.js} +2 -2
  70. package/dist/{chunk-NPKE2IX6.js.map → chunk-PITWDKKY.js.map} +1 -1
  71. package/dist/{chunk-7AFEKDUS.js → chunk-PJ4TQ6YO.js} +4 -4
  72. package/dist/{chunk-7AFEKDUS.js.map → chunk-PJ4TQ6YO.js.map} +1 -1
  73. package/dist/chunk-QGPMVFZJ.cjs +4 -0
  74. package/dist/chunk-QGPMVFZJ.cjs.map +1 -0
  75. package/dist/{chunk-W2Q4OWHX.cjs → chunk-RMFLRBUC.cjs} +6 -6
  76. package/dist/{chunk-W2Q4OWHX.cjs.map → chunk-RMFLRBUC.cjs.map} +1 -1
  77. package/dist/chunk-SHDSKHCC.js +3 -0
  78. package/dist/chunk-SHDSKHCC.js.map +1 -0
  79. package/dist/chunk-TMR56BBE.js +3 -0
  80. package/dist/chunk-TMR56BBE.js.map +1 -0
  81. package/dist/chunk-URTLYNZI.cjs +4 -0
  82. package/dist/chunk-URTLYNZI.cjs.map +1 -0
  83. package/dist/chunk-V4EARA4F.js +3 -0
  84. package/dist/chunk-V4EARA4F.js.map +1 -0
  85. package/dist/chunk-VBWRH4UW.cjs +4 -0
  86. package/dist/chunk-VBWRH4UW.cjs.map +1 -0
  87. package/dist/{chunk-K2DZEYBF.js → chunk-WNIP443K.js} +3 -3
  88. package/dist/{chunk-K2DZEYBF.js.map → chunk-WNIP443K.js.map} +1 -1
  89. package/dist/{chunk-2S7WRR5P.cjs → chunk-X5VZRFQD.cjs} +2 -2
  90. package/dist/{chunk-2S7WRR5P.cjs.map → chunk-X5VZRFQD.cjs.map} +1 -1
  91. package/dist/chunk-XFBLUPKF.cjs +4 -0
  92. package/dist/chunk-XFBLUPKF.cjs.map +1 -0
  93. package/dist/chunk-XURQVDCN.cjs +4 -0
  94. package/dist/chunk-XURQVDCN.cjs.map +1 -0
  95. package/dist/{chunk-WVO2EKE6.cjs → chunk-Y5V5GBN4.cjs} +2 -2
  96. package/dist/{chunk-WVO2EKE6.cjs.map → chunk-Y5V5GBN4.cjs.map} +1 -1
  97. package/dist/chunk-Y6DK4CGY.js +1341 -0
  98. package/dist/chunk-Y6DK4CGY.js.map +1 -0
  99. package/dist/color-picker.cjs +3 -2
  100. package/dist/color-picker.d.cts +10 -1
  101. package/dist/color-picker.d.ts +10 -1
  102. package/dist/color-picker.js +2 -1
  103. package/dist/date-picker.cjs +3 -2
  104. package/dist/date-picker.js +2 -1
  105. package/dist/index-BfFk-CIv.d.ts +330 -0
  106. package/dist/index-BypPN_6l.d.cts +330 -0
  107. package/dist/index.cjs +123 -65
  108. package/dist/index.d.cts +1 -0
  109. package/dist/index.d.ts +1 -0
  110. package/dist/index.js +28 -18
  111. package/dist/input.cjs +3 -2
  112. package/dist/input.js +2 -1
  113. package/dist/inputs.cjs +26 -22
  114. package/dist/inputs.js +10 -6
  115. package/dist/json-editor.cjs +77 -0
  116. package/dist/json-editor.cjs.map +1 -0
  117. package/dist/json-editor.d.cts +4 -0
  118. package/dist/json-editor.d.ts +4 -0
  119. package/dist/json-editor.js +28 -0
  120. package/dist/json-editor.js.map +1 -0
  121. package/dist/magic-wand.cjs +6 -4
  122. package/dist/magic-wand.js +5 -3
  123. package/dist/prompt-input.cjs +4 -3
  124. package/dist/prompt-input.js +3 -2
  125. package/dist/reason-tag.cjs +4 -3
  126. package/dist/reason-tag.js +3 -2
  127. package/dist/select.cjs +3 -2
  128. package/dist/select.js +2 -1
  129. package/dist/styles.css +0 -3
  130. package/dist/styles.css.map +1 -1
  131. package/dist/switch.cjs +3 -2
  132. package/dist/switch.js +2 -1
  133. package/dist/table.cjs +11 -11
  134. package/dist/table.d.cts +18 -9
  135. package/dist/table.d.ts +18 -9
  136. package/dist/table.js +1 -1
  137. package/dist/text.cjs +3 -2
  138. package/dist/text.js +2 -1
  139. package/package.json +12 -2
  140. package/dist/chunk-DOSSIU6S.cjs.map +0 -1
  141. package/dist/chunk-GKPCXPCD.js.map +0 -1
  142. package/dist/chunk-IF3T3ZCB.cjs.map +0 -1
  143. package/dist/chunk-O432BDEO.js.map +0 -1
@@ -0,0 +1,1354 @@
1
+ 'use strict';
2
+
3
+ var chunkMPDLL4X3_cjs = require('./chunk-MPDLL4X3.cjs');
4
+ var chunkKKYP5R3G_cjs = require('./chunk-KKYP5R3G.cjs');
5
+ var chunk6FYMMQ3G_cjs = require('./chunk-6FYMMQ3G.cjs');
6
+ var chunkJU5W65N3_cjs = require('./chunk-JU5W65N3.cjs');
7
+ var chunk23CLGUMT_cjs = require('./chunk-23CLGUMT.cjs');
8
+ var chunk5I4PR2KV_cjs = require('./chunk-5I4PR2KV.cjs');
9
+ var chunk6BW5BQMN_cjs = require('./chunk-6BW5BQMN.cjs');
10
+ var chunkYLGTDBB2_cjs = require('./chunk-YLGTDBB2.cjs');
11
+ var chunkFO4GCX67_cjs = require('./chunk-FO4GCX67.cjs');
12
+ var chunkX5VZRFQD_cjs = require('./chunk-X5VZRFQD.cjs');
13
+ var chunkHTKDPFLJ_cjs = require('./chunk-HTKDPFLJ.cjs');
14
+ var chunkY5V5GBN4_cjs = require('./chunk-Y5V5GBN4.cjs');
15
+ var chunkKJ22KE56_cjs = require('./chunk-KJ22KE56.cjs');
16
+ var chunk3Z6ALUWP_cjs = require('./chunk-3Z6ALUWP.cjs');
17
+ var react = require('react');
18
+ var jsxRuntime = require('react/jsx-runtime');
19
+
20
+ // src/components/JsonEditor/JsonEditor.paths.ts
21
+ function isJsonObject(value) {
22
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23
+ }
24
+ function isJsonArray(value) {
25
+ return Array.isArray(value);
26
+ }
27
+ function isContainerValue(value) {
28
+ return isJsonObject(value) || isJsonArray(value);
29
+ }
30
+ function parsePath(path) {
31
+ if (!path) return [];
32
+ const segments = [];
33
+ let current = "";
34
+ let escaped = false;
35
+ for (const char of path) {
36
+ if (escaped) {
37
+ current += char;
38
+ escaped = false;
39
+ continue;
40
+ }
41
+ if (char === "\\") {
42
+ escaped = true;
43
+ continue;
44
+ }
45
+ if (char === ".") {
46
+ segments.push(current);
47
+ current = "";
48
+ continue;
49
+ }
50
+ current += char;
51
+ }
52
+ if (escaped) current += "\\";
53
+ segments.push(current);
54
+ return segments;
55
+ }
56
+ function pathToString(segments) {
57
+ return segments.map((segment) => segment.replace(/\\/g, "\\\\").replace(/\./g, "\\.")).join(".");
58
+ }
59
+ function getAtPath(value, segments) {
60
+ let current = value;
61
+ for (const segment of segments) {
62
+ if (isJsonArray(current)) {
63
+ const index = Number(segment);
64
+ if (!Number.isInteger(index)) return void 0;
65
+ current = current[index];
66
+ } else if (isJsonObject(current)) {
67
+ if (!Object.prototype.hasOwnProperty.call(current, segment)) return void 0;
68
+ current = current[segment];
69
+ } else {
70
+ return void 0;
71
+ }
72
+ if (current === void 0) return void 0;
73
+ }
74
+ return current;
75
+ }
76
+ function updateContainer(value, segments, updater) {
77
+ if (segments.length === 0) {
78
+ if (!isContainerValue(value)) return value;
79
+ const next = updater(value);
80
+ return next === void 0 ? value : next;
81
+ }
82
+ const [head, ...rest] = segments;
83
+ if (isJsonArray(value)) {
84
+ const index = Number(head);
85
+ if (!Number.isInteger(index) || index < 0 || index >= value.length) return value;
86
+ const child = updateContainer(value[index], rest, updater);
87
+ if (child === value[index]) return value;
88
+ const clone = value.slice();
89
+ clone[index] = child;
90
+ return clone;
91
+ }
92
+ if (isJsonObject(value)) {
93
+ if (!Object.prototype.hasOwnProperty.call(value, head)) return value;
94
+ const child = updateContainer(value[head], rest, updater);
95
+ if (child === value[head]) return value;
96
+ return { ...value, [head]: child };
97
+ }
98
+ return value;
99
+ }
100
+ function applyJsonEdit(value, edit) {
101
+ const segments = parsePath(edit.path);
102
+ switch (edit.op) {
103
+ case "set": {
104
+ if (segments.length === 0) return edit.value;
105
+ const parent = segments.slice(0, -1);
106
+ const key = segments[segments.length - 1];
107
+ return updateContainer(value, parent, (container) => {
108
+ if (isJsonArray(container)) {
109
+ const index = Number(key);
110
+ if (!Number.isInteger(index) || index < 0 || index >= container.length) return void 0;
111
+ const clone = container.slice();
112
+ clone[index] = edit.value;
113
+ return clone;
114
+ }
115
+ return { ...container, [key]: edit.value };
116
+ });
117
+ }
118
+ case "remove": {
119
+ if (segments.length === 0) return value;
120
+ const parent = segments.slice(0, -1);
121
+ const key = segments[segments.length - 1];
122
+ return updateContainer(value, parent, (container) => {
123
+ if (isJsonArray(container)) {
124
+ const index = Number(key);
125
+ if (!Number.isInteger(index) || index < 0 || index >= container.length) return void 0;
126
+ return container.filter((_, i) => i !== index);
127
+ }
128
+ if (!Object.prototype.hasOwnProperty.call(container, key)) return void 0;
129
+ const clone = {};
130
+ for (const [k, v] of Object.entries(container)) {
131
+ if (k !== key) clone[k] = v;
132
+ }
133
+ return clone;
134
+ });
135
+ }
136
+ case "rename": {
137
+ if (segments.length === 0) return value;
138
+ const parent = segments.slice(0, -1);
139
+ const key = segments[segments.length - 1];
140
+ return updateContainer(value, parent, (container) => {
141
+ if (!isJsonObject(container)) return void 0;
142
+ if (!Object.prototype.hasOwnProperty.call(container, key)) return void 0;
143
+ if (edit.key === key) return void 0;
144
+ if (Object.prototype.hasOwnProperty.call(container, edit.key)) return void 0;
145
+ const clone = {};
146
+ for (const [k, v] of Object.entries(container)) {
147
+ clone[k === key ? edit.key : k] = v;
148
+ }
149
+ return clone;
150
+ });
151
+ }
152
+ case "insert": {
153
+ return updateContainer(value, segments, (container) => {
154
+ if (isJsonArray(container)) return [...container, edit.value];
155
+ if (edit.key === void 0 || edit.key === "") return void 0;
156
+ if (Object.prototype.hasOwnProperty.call(container, edit.key)) return void 0;
157
+ return { ...container, [edit.key]: edit.value };
158
+ });
159
+ }
160
+ case "move": {
161
+ if (segments.length === 0) return value;
162
+ const parent = segments.slice(0, -1);
163
+ const from = Number(segments[segments.length - 1]);
164
+ return updateContainer(value, parent, (container) => {
165
+ if (!isJsonArray(container)) return void 0;
166
+ if (!Number.isInteger(from) || from < 0 || from >= container.length) return void 0;
167
+ const to = Math.min(Math.max(edit.to, 0), container.length - 1);
168
+ if (to === from) return void 0;
169
+ const clone = container.slice();
170
+ const [moved] = clone.splice(from, 1);
171
+ clone.splice(to, 0, moved);
172
+ return clone;
173
+ });
174
+ }
175
+ }
176
+ }
177
+ function describeEdit(edit) {
178
+ const at = edit.path === "" ? "the document" : edit.path;
179
+ switch (edit.op) {
180
+ case "set":
181
+ return `set ${at}`;
182
+ case "remove":
183
+ return `remove ${at}`;
184
+ case "rename":
185
+ return `rename ${at} to ${edit.key}`;
186
+ case "insert":
187
+ return edit.key === void 0 ? `append to ${at}` : `add ${edit.key} to ${at}`;
188
+ case "move":
189
+ return `move ${at} to index ${edit.to}`;
190
+ }
191
+ }
192
+
193
+ // src/components/JsonEditor/JsonEditor.types.ts
194
+ var JSON_FIELD_TYPES = [
195
+ "string",
196
+ "text",
197
+ "number",
198
+ "integer",
199
+ "boolean",
200
+ "date",
201
+ "datetime",
202
+ "enum",
203
+ "secret",
204
+ "url",
205
+ "email",
206
+ "color",
207
+ "json",
208
+ "object",
209
+ "array"
210
+ ];
211
+
212
+ // src/components/JsonEditor/JsonEditor.keymap.ts
213
+ var TYPE_NAMES = new Set(JSON_FIELD_TYPES);
214
+ function isTypeName(value) {
215
+ return typeof value === "string" && TYPE_NAMES.has(value);
216
+ }
217
+ function issue(kind, path, message) {
218
+ return { kind, path, message };
219
+ }
220
+ function parseKeyMap(source) {
221
+ if (source === void 0 || source === null || source.trim() === "") {
222
+ return { ok: true, rules: [], issues: [] };
223
+ }
224
+ let parsed;
225
+ try {
226
+ parsed = JSON.parse(source);
227
+ } catch (error) {
228
+ return {
229
+ ok: false,
230
+ rules: [],
231
+ issues: [
232
+ issue(
233
+ "keymap",
234
+ "",
235
+ `keyMap is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
236
+ )
237
+ ]
238
+ };
239
+ }
240
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
241
+ return {
242
+ ok: false,
243
+ rules: [],
244
+ issues: [
245
+ issue(
246
+ "keymap",
247
+ "",
248
+ `keyMap must be a JSON object of path \u2192 type, got ${describeValue(parsed)}.`
249
+ )
250
+ ]
251
+ };
252
+ }
253
+ const rules = [];
254
+ const issues = [];
255
+ let order = 0;
256
+ for (const [key, raw] of Object.entries(parsed)) {
257
+ const rule = normalizeRule(key, raw, issues);
258
+ if (!rule) continue;
259
+ const pattern = parsePath(key);
260
+ rules.push({
261
+ pattern,
262
+ rule,
263
+ source: key,
264
+ literals: pattern.reduce((n, segment) => n + (segment === "*" ? 0 : 1), 0),
265
+ order: order++
266
+ });
267
+ }
268
+ return { ok: true, rules, issues };
269
+ }
270
+ function normalizeRule(key, raw, issues) {
271
+ let candidate;
272
+ if (typeof raw === "string") {
273
+ candidate = { type: raw };
274
+ } else if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
275
+ candidate = raw;
276
+ } else {
277
+ issues.push(
278
+ issue(
279
+ "rule",
280
+ key,
281
+ `Expected a type name or a rule object, got ${describeValue(raw)}.`
282
+ )
283
+ );
284
+ return void 0;
285
+ }
286
+ if (!isTypeName(candidate.type)) {
287
+ issues.push(
288
+ issue(
289
+ "rule",
290
+ key,
291
+ `Unknown type ${JSON.stringify(candidate.type)}. Known types: ${JSON_FIELD_TYPES.join(", ")}.`
292
+ )
293
+ );
294
+ return void 0;
295
+ }
296
+ if (candidate.options !== void 0 && !Array.isArray(candidate.options)) {
297
+ issues.push(issue("rule", key, "`options` must be an array."));
298
+ return void 0;
299
+ }
300
+ if (candidate.type === "enum" && (!candidate.options || candidate.options.length === 0)) {
301
+ issues.push(issue("rule", key, "`enum` requires a non-empty `options` array."));
302
+ return void 0;
303
+ }
304
+ return candidate;
305
+ }
306
+ function resolveKeyRule(rules, segments) {
307
+ let best;
308
+ for (const entry of rules) {
309
+ if (!matches(entry.pattern, segments)) continue;
310
+ if (!best || entry.literals > best.literals || entry.literals === best.literals && entry.order > best.order) {
311
+ best = entry;
312
+ }
313
+ }
314
+ return best?.rule;
315
+ }
316
+ function matches(pattern, segments) {
317
+ if (pattern.length !== segments.length) return false;
318
+ return pattern.every((p, i) => p === "*" || p === segments[i]);
319
+ }
320
+ function describeValue(value) {
321
+ if (value === void 0) return "undefined";
322
+ if (value === null) return "null";
323
+ if (Array.isArray(value)) return "array";
324
+ return typeof value;
325
+ }
326
+ function inferType(value) {
327
+ if (Array.isArray(value)) return "array";
328
+ if (value === null || value === void 0) {
329
+ return "json";
330
+ }
331
+ if (typeof value === "object") return "object";
332
+ if (typeof value === "boolean") return "boolean";
333
+ if (typeof value === "number") return "number";
334
+ return "string";
335
+ }
336
+ function enumValues(rule) {
337
+ return (rule.options ?? []).map((option) => chunkYLGTDBB2_cjs.resolveOption(option).value);
338
+ }
339
+ function typeMatches(rule, value) {
340
+ switch (rule.type) {
341
+ case "string":
342
+ case "text":
343
+ case "url":
344
+ case "email":
345
+ case "secret":
346
+ case "color":
347
+ return typeof value === "string";
348
+ case "number":
349
+ return typeof value === "number" && Number.isFinite(value);
350
+ case "integer":
351
+ return typeof value === "number" && Number.isInteger(value);
352
+ case "boolean":
353
+ return typeof value === "boolean";
354
+ case "date":
355
+ case "datetime":
356
+ return typeof value === "string" && value !== "" && !Number.isNaN(Date.parse(value));
357
+ case "enum":
358
+ return (typeof value === "string" || typeof value === "number" || typeof value === "boolean") && enumValues(rule).some((option) => String(option) === String(value));
359
+ case "object":
360
+ return isJsonObject(value);
361
+ case "array":
362
+ return isJsonArray(value);
363
+ case "json":
364
+ if (typeof value !== "string") return true;
365
+ try {
366
+ JSON.parse(value);
367
+ return true;
368
+ } catch {
369
+ return false;
370
+ }
371
+ }
372
+ }
373
+ function conflictMessage(rule, value) {
374
+ if (rule.type === "enum") {
375
+ return `${JSON.stringify(value)} is not one of the declared options (${enumValues(rule).map((option) => JSON.stringify(option)).join(", ")}).`;
376
+ }
377
+ if (rule.type === "json") {
378
+ return "Raw text is not valid JSON.";
379
+ }
380
+ if (rule.type === "date" || rule.type === "datetime") {
381
+ return `Declared ${rule.type}, got ${describeValue(value)} that is not a parseable date.`;
382
+ }
383
+ return `Declared ${rule.type}, got ${describeValue(value)}.`;
384
+ }
385
+ function findJsonConflicts(value, rules) {
386
+ const issues = [];
387
+ if (rules.length === 0) return issues;
388
+ const walk = (node, segments) => {
389
+ if (segments.length > 0) {
390
+ const rule = resolveKeyRule(rules, segments);
391
+ if (rule && !typeMatches(rule, node)) {
392
+ issues.push({
393
+ kind: "type",
394
+ path: pathToString(segments),
395
+ message: conflictMessage(rule, node),
396
+ expected: rule.type,
397
+ actual: describeValue(node)
398
+ });
399
+ }
400
+ }
401
+ if (isJsonArray(node)) {
402
+ node.forEach((child, index) => walk(child, [...segments, String(index)]));
403
+ } else if (isJsonObject(node)) {
404
+ for (const [key, child] of Object.entries(node)) walk(child, [...segments, key]);
405
+ }
406
+ };
407
+ walk(value, []);
408
+ for (const entry of rules) {
409
+ if (!entry.rule.required) continue;
410
+ if (entry.pattern.includes("*")) continue;
411
+ if (getAtPath(value, entry.pattern) !== void 0) continue;
412
+ issues.push({
413
+ kind: "type",
414
+ path: entry.source,
415
+ message: `Required key is missing (declared ${entry.rule.type}).`,
416
+ expected: entry.rule.type,
417
+ actual: "undefined"
418
+ });
419
+ }
420
+ return issues;
421
+ }
422
+ function seedValue(type, rule) {
423
+ switch (type) {
424
+ case "number":
425
+ case "integer":
426
+ return 0;
427
+ case "boolean":
428
+ return false;
429
+ case "object":
430
+ return {};
431
+ case "array":
432
+ return [];
433
+ case "json":
434
+ return null;
435
+ case "enum":
436
+ return rule?.options?.length ? chunkYLGTDBB2_cjs.resolveOption(rule.options[0]).value : "";
437
+ default:
438
+ return "";
439
+ }
440
+ }
441
+ var JsonEditorContext = react.createContext(null);
442
+ function useJsonEditorContext() {
443
+ const context = react.useContext(JsonEditorContext);
444
+ if (!context) {
445
+ throw new Error("JsonEditor rows must be rendered inside a <JsonEditor>.");
446
+ }
447
+ return context;
448
+ }
449
+ var COLOR_PICKER_SIZE = {
450
+ xs: "sm",
451
+ sm: "sm",
452
+ md: "md",
453
+ lg: "lg",
454
+ xl: "lg"
455
+ };
456
+ function isRawTextType(type) {
457
+ return type === "number" || type === "integer" || type === "json";
458
+ }
459
+ function toText(value) {
460
+ if (value === void 0) return "";
461
+ if (typeof value === "string") return value;
462
+ return JSON.stringify(value) ?? "";
463
+ }
464
+ function fromText(text, type) {
465
+ switch (type) {
466
+ case "number":
467
+ case "integer": {
468
+ const trimmed = text.trim();
469
+ if (trimmed === "") return text;
470
+ const parsed = Number(trimmed);
471
+ return Number.isFinite(parsed) ? parsed : text;
472
+ }
473
+ case "boolean": {
474
+ const trimmed = text.trim().toLowerCase();
475
+ if (trimmed === "true") return true;
476
+ if (trimmed === "false") return false;
477
+ return text;
478
+ }
479
+ case "json":
480
+ case "object":
481
+ case "array":
482
+ try {
483
+ return JSON.parse(text);
484
+ } catch {
485
+ return text;
486
+ }
487
+ default:
488
+ return text;
489
+ }
490
+ }
491
+ function JsonEditorValue({ node, mode, size, readOnly, id, onCommit }) {
492
+ const locked = readOnly || node.rule?.readOnly === true;
493
+ const resolvedMode = locked ? "view" : mode;
494
+ const { value, rule } = node;
495
+ if (node.conflict || isRawTextType(node.type)) {
496
+ return /* @__PURE__ */ jsxRuntime.jsx(
497
+ RawValueEditor,
498
+ {
499
+ id,
500
+ text: toText(value),
501
+ type: node.type,
502
+ mode: resolvedMode,
503
+ size,
504
+ disabled: locked,
505
+ multiline: node.type === "json" || typeof value === "object",
506
+ placeholder: rule?.placeholder,
507
+ onCommitText: (text) => onCommit(fromText(text, node.type))
508
+ }
509
+ );
510
+ }
511
+ const common = { id, size, mode: resolvedMode, disabled: locked };
512
+ switch (node.type) {
513
+ case "boolean":
514
+ return /* @__PURE__ */ jsxRuntime.jsx(
515
+ chunkMPDLL4X3_cjs.Switch,
516
+ {
517
+ ...common,
518
+ checked: value === true,
519
+ onCheckedChange: (next) => onCommit(next)
520
+ }
521
+ );
522
+ case "enum": {
523
+ const options = rule?.options ?? [];
524
+ return /* @__PURE__ */ jsxRuntime.jsx(
525
+ chunkJU5W65N3_cjs.Select,
526
+ {
527
+ ...common,
528
+ list: options,
529
+ value: String(value),
530
+ onValueChange: (next) => {
531
+ const match = options.map((option) => chunkYLGTDBB2_cjs.resolveOption(option)).find((option) => String(option.value) === next);
532
+ onCommit(match?.value ?? next);
533
+ }
534
+ }
535
+ );
536
+ }
537
+ case "date":
538
+ case "datetime":
539
+ return /* @__PURE__ */ jsxRuntime.jsx(
540
+ chunkKKYP5R3G_cjs.DatePicker,
541
+ {
542
+ ...common,
543
+ includeTime: node.type === "datetime",
544
+ min: rule?.min === void 0 ? void 0 : String(rule.min),
545
+ max: rule?.max === void 0 ? void 0 : String(rule.max),
546
+ value: typeof value === "string" ? value : "",
547
+ onValueChange: (next) => onCommit(next)
548
+ }
549
+ );
550
+ case "color":
551
+ return /* @__PURE__ */ jsxRuntime.jsx(
552
+ chunkFO4GCX67_cjs.ColorPicker,
553
+ {
554
+ size: COLOR_PICKER_SIZE[size],
555
+ mode: resolvedMode,
556
+ disabled: locked,
557
+ value: typeof value === "string" ? value : "",
558
+ onChange: (next) => onCommit(next)
559
+ }
560
+ );
561
+ case "text":
562
+ return /* @__PURE__ */ jsxRuntime.jsx(
563
+ chunk5I4PR2KV_cjs.Textarea,
564
+ {
565
+ ...common,
566
+ minRows: 2,
567
+ autoResize: true,
568
+ placeholder: rule?.placeholder,
569
+ value: typeof value === "string" ? value : "",
570
+ onValueChange: (next) => onCommit(next)
571
+ }
572
+ );
573
+ case "secret":
574
+ return /* @__PURE__ */ jsxRuntime.jsx(
575
+ chunk6FYMMQ3G_cjs.Input,
576
+ {
577
+ ...common,
578
+ type: "password",
579
+ reveal: true,
580
+ placeholder: rule?.placeholder,
581
+ value: typeof value === "string" ? value : "",
582
+ onValueChange: (next) => onCommit(next)
583
+ }
584
+ );
585
+ case "url":
586
+ case "email":
587
+ case "string":
588
+ default:
589
+ return /* @__PURE__ */ jsxRuntime.jsx(
590
+ chunk6FYMMQ3G_cjs.Input,
591
+ {
592
+ ...common,
593
+ type: node.type === "url" ? "url" : node.type === "email" ? "email" : "text",
594
+ placeholder: rule?.placeholder,
595
+ value: typeof value === "string" ? value : "",
596
+ onValueChange: (next) => onCommit(next)
597
+ }
598
+ );
599
+ }
600
+ }
601
+ function RawValueEditor({
602
+ id,
603
+ text,
604
+ type,
605
+ mode,
606
+ size,
607
+ disabled,
608
+ multiline,
609
+ placeholder,
610
+ onCommitText
611
+ }) {
612
+ const { showControl, interactive, enterEdit, exitEdit } = chunkKJ22KE56_cjs.useInlineEdit(mode, disabled);
613
+ if (!showControl) {
614
+ return /* @__PURE__ */ jsxRuntime.jsx(chunk6BW5BQMN_cjs.DisplayValue, { size, interactive, onActivate: enterEdit, children: text });
615
+ }
616
+ const commit = (next) => {
617
+ if (next !== text) onCommitText(next);
618
+ };
619
+ if (multiline) {
620
+ return /* @__PURE__ */ jsxRuntime.jsx(
621
+ chunk5I4PR2KV_cjs.Textarea,
622
+ {
623
+ id,
624
+ size,
625
+ mode: "edit",
626
+ minRows: 3,
627
+ disabled,
628
+ placeholder,
629
+ defaultValue: text,
630
+ spellCheck: false,
631
+ autoFocus: interactive,
632
+ className: "font-mono",
633
+ onBlur: (event) => {
634
+ commit(event.currentTarget.value);
635
+ exitEdit();
636
+ }
637
+ },
638
+ text
639
+ );
640
+ }
641
+ return /* @__PURE__ */ jsxRuntime.jsx(
642
+ chunk6FYMMQ3G_cjs.Input,
643
+ {
644
+ id,
645
+ size,
646
+ mode: "edit",
647
+ type: "text",
648
+ inputMode: type === "number" || type === "integer" ? "decimal" : void 0,
649
+ disabled,
650
+ placeholder,
651
+ defaultValue: text,
652
+ spellCheck: false,
653
+ autoFocus: interactive,
654
+ onKeyDown: (event) => {
655
+ if (event.key === "Enter") event.currentTarget.blur();
656
+ },
657
+ onBlur: (event) => {
658
+ commit(event.currentTarget.value);
659
+ exitEdit();
660
+ }
661
+ },
662
+ text
663
+ );
664
+ }
665
+ var INDENT = 18;
666
+ function JsonEditorRow({ node }) {
667
+ const ctx = useJsonEditorContext();
668
+ const { dotted, key, depth, container, conflict } = node;
669
+ const expanded = container ? ctx.isExpanded(dotted) : void 0;
670
+ const pending = ctx.pendingFor(dotted);
671
+ const renameable = ctx.allowRename && !ctx.readOnly && node.parentKind === "object" && ctx.mode === "edit";
672
+ const label = node.rule?.label ?? key;
673
+ return /* @__PURE__ */ jsxRuntime.jsxs(
674
+ "div",
675
+ {
676
+ "data-react-fancy-json-editor-row": "",
677
+ "data-path": dotted,
678
+ "data-key": key,
679
+ "data-type": node.type,
680
+ "data-depth": depth,
681
+ "data-declared": node.declared ? "true" : "false",
682
+ "data-conflict": conflict ? "true" : void 0,
683
+ "data-pending": pending.length > 0 ? "true" : void 0,
684
+ role: "treeitem",
685
+ "aria-level": depth + 1,
686
+ "aria-expanded": expanded,
687
+ className: chunk3Z6ALUWP_cjs.cn(
688
+ "border-b border-zinc-100 py-1 last:border-b-0 dark:border-zinc-800",
689
+ conflict && "bg-red-50/60 dark:bg-red-950/20",
690
+ pending.length > 0 && "bg-violet-50/60 dark:bg-violet-950/20"
691
+ ),
692
+ children: [
693
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 px-2", style: { paddingInlineStart: depth * INDENT + 8 }, children: [
694
+ container ? /* @__PURE__ */ jsxRuntime.jsx(
695
+ chunkHTKDPFLJ_cjs.Button,
696
+ {
697
+ variant: "ghost",
698
+ size: "xs",
699
+ "data-react-fancy-json-editor-toggle": "",
700
+ "data-path": dotted,
701
+ "aria-label": expanded ? `Collapse ${label}` : `Expand ${label}`,
702
+ "aria-expanded": expanded,
703
+ icon: expanded ? "chevron-down" : "chevron-right",
704
+ onClick: () => ctx.toggleExpanded(dotted)
705
+ }
706
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "inline-block w-6 shrink-0" }),
707
+ /* @__PURE__ */ jsxRuntime.jsxs(
708
+ "div",
709
+ {
710
+ "data-react-fancy-json-editor-key": "",
711
+ "data-path": dotted,
712
+ className: "w-1/3 min-w-0 shrink-0",
713
+ children: [
714
+ renameable ? /* @__PURE__ */ jsxRuntime.jsx(
715
+ chunk6FYMMQ3G_cjs.Input,
716
+ {
717
+ size: ctx.size,
718
+ mode: "edit",
719
+ defaultValue: key,
720
+ spellCheck: false,
721
+ "aria-label": `Key of ${dotted}`,
722
+ onKeyDown: (event) => {
723
+ if (event.key === "Enter") event.currentTarget.blur();
724
+ },
725
+ onBlur: (event) => {
726
+ const next = event.currentTarget.value;
727
+ if (next !== key) ctx.renameAt(node, next);
728
+ }
729
+ },
730
+ key
731
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
732
+ chunk23CLGUMT_cjs.Text,
733
+ {
734
+ as: "span",
735
+ size: "sm",
736
+ weight: "medium",
737
+ color: node.parentKind === "array" ? "muted" : "default",
738
+ className: "block truncate py-1 font-mono",
739
+ title: dotted,
740
+ children: node.parentKind === "array" ? `[${key}]` : label
741
+ }
742
+ ),
743
+ node.rule?.description && /* @__PURE__ */ jsxRuntime.jsx(chunk23CLGUMT_cjs.Text, { as: "span", size: "xs", color: "muted", className: "block truncate", children: node.rule.description })
744
+ ]
745
+ }
746
+ ),
747
+ /* @__PURE__ */ jsxRuntime.jsx(
748
+ "div",
749
+ {
750
+ "data-react-fancy-json-editor-value": "",
751
+ "data-path": dotted,
752
+ "data-type": node.type,
753
+ className: "min-w-0 flex-1",
754
+ children: container ? /* @__PURE__ */ jsxRuntime.jsx(chunk23CLGUMT_cjs.Text, { as: "span", size: "sm", color: "muted", className: "block py-1 font-mono", children: node.type === "array" ? `[ ${node.childCount} ${node.childCount === 1 ? "item" : "items"} ]` : `{ ${node.childCount} ${node.childCount === 1 ? "key" : "keys"} }` }) : /* @__PURE__ */ jsxRuntime.jsx(
755
+ JsonEditorValue,
756
+ {
757
+ node,
758
+ mode: ctx.mode,
759
+ size: ctx.size,
760
+ readOnly: ctx.readOnly,
761
+ id: `${ctx.idPrefix}-${dotted}`,
762
+ onCommit: (next) => ctx.setValueAt(node, next)
763
+ }
764
+ )
765
+ }
766
+ ),
767
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-0.5 pt-0.5", children: [
768
+ node.declared && /* @__PURE__ */ jsxRuntime.jsx(chunkX5VZRFQD_cjs.Badge, { size: "sm", variant: "soft", color: conflict ? "red" : "zinc", children: node.type }),
769
+ container && ctx.allowAdd && !ctx.readOnly && /* @__PURE__ */ jsxRuntime.jsx(
770
+ chunkHTKDPFLJ_cjs.Button,
771
+ {
772
+ variant: "ghost",
773
+ size: "xs",
774
+ "data-react-fancy-json-editor-add": "",
775
+ "data-path": dotted,
776
+ "aria-label": `Add to ${label}`,
777
+ icon: "plus",
778
+ onClick: () => ctx.setAddingAt(ctx.addingAt === dotted ? null : dotted)
779
+ }
780
+ ),
781
+ ctx.allowReorder && !ctx.readOnly && node.parentKind === "array" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
782
+ /* @__PURE__ */ jsxRuntime.jsx(
783
+ chunkHTKDPFLJ_cjs.Button,
784
+ {
785
+ variant: "ghost",
786
+ size: "xs",
787
+ "data-react-fancy-json-editor-move-up": "",
788
+ "data-path": dotted,
789
+ "aria-label": `Move ${dotted} up`,
790
+ icon: "arrow-up",
791
+ onClick: () => ctx.moveAt(node, Number(key) - 1)
792
+ }
793
+ ),
794
+ /* @__PURE__ */ jsxRuntime.jsx(
795
+ chunkHTKDPFLJ_cjs.Button,
796
+ {
797
+ variant: "ghost",
798
+ size: "xs",
799
+ "data-react-fancy-json-editor-move-down": "",
800
+ "data-path": dotted,
801
+ "aria-label": `Move ${dotted} down`,
802
+ icon: "arrow-down",
803
+ onClick: () => ctx.moveAt(node, Number(key) + 1)
804
+ }
805
+ )
806
+ ] }),
807
+ ctx.allowRemove && !ctx.readOnly && node.parentKind !== "root" && /* @__PURE__ */ jsxRuntime.jsx(
808
+ chunkHTKDPFLJ_cjs.Button,
809
+ {
810
+ variant: "ghost",
811
+ size: "xs",
812
+ color: "red",
813
+ "data-react-fancy-json-editor-remove": "",
814
+ "data-path": dotted,
815
+ "aria-label": `Remove ${dotted}`,
816
+ icon: "trash-2",
817
+ onClick: () => ctx.removeAt(node)
818
+ }
819
+ )
820
+ ] })
821
+ ] }),
822
+ conflict && /* @__PURE__ */ jsxRuntime.jsx(
823
+ chunk23CLGUMT_cjs.Text,
824
+ {
825
+ as: "span",
826
+ size: "xs",
827
+ color: "danger",
828
+ "data-react-fancy-json-editor-conflict": "",
829
+ "data-path": dotted,
830
+ className: "block px-2 pb-1",
831
+ style: { paddingInlineStart: depth * INDENT + 40 },
832
+ children: conflict.message
833
+ }
834
+ ),
835
+ pending.map((edit) => /* @__PURE__ */ jsxRuntime.jsxs(
836
+ "div",
837
+ {
838
+ "data-react-fancy-json-editor-pending": "",
839
+ "data-id": edit.id,
840
+ "data-path": dotted,
841
+ className: "flex items-center gap-2 px-2 pb-1",
842
+ style: { paddingInlineStart: depth * INDENT + 40 },
843
+ children: [
844
+ /* @__PURE__ */ jsxRuntime.jsx(chunkX5VZRFQD_cjs.Badge, { size: "sm", variant: "soft", color: "violet", children: "proposed" }),
845
+ /* @__PURE__ */ jsxRuntime.jsxs(chunk23CLGUMT_cjs.Text, { as: "span", size: "xs", color: "muted", className: "min-w-0 truncate font-mono", children: [
846
+ edit.label ?? describeEdit(edit),
847
+ edit.op === "set" || edit.op === "insert" ? ` \u2192 ${toText(edit.value)}` : ""
848
+ ] }),
849
+ /* @__PURE__ */ jsxRuntime.jsx(
850
+ chunkHTKDPFLJ_cjs.Button,
851
+ {
852
+ size: "xs",
853
+ color: "emerald",
854
+ "data-react-fancy-json-editor-accept": "",
855
+ "data-id": edit.id,
856
+ onClick: () => ctx.acceptPending(edit.id),
857
+ children: "Accept"
858
+ }
859
+ ),
860
+ /* @__PURE__ */ jsxRuntime.jsx(
861
+ chunkHTKDPFLJ_cjs.Button,
862
+ {
863
+ size: "xs",
864
+ variant: "ghost",
865
+ "data-react-fancy-json-editor-reject": "",
866
+ "data-id": edit.id,
867
+ onClick: () => ctx.rejectPending(edit.id),
868
+ children: "Reject"
869
+ }
870
+ )
871
+ ]
872
+ },
873
+ edit.id
874
+ ))
875
+ ]
876
+ }
877
+ );
878
+ }
879
+ function JsonEditorAddForm({ path, kind, depth, suggestedType }) {
880
+ const ctx = useJsonEditorContext();
881
+ const [key, setKey] = react.useState("");
882
+ const [type, setType] = react.useState(suggestedType ?? "string");
883
+ return /* @__PURE__ */ jsxRuntime.jsxs(
884
+ "div",
885
+ {
886
+ "data-react-fancy-json-editor-add-form": "",
887
+ "data-path": path,
888
+ className: "flex items-center gap-2 border-b border-zinc-100 px-2 py-1.5 dark:border-zinc-800",
889
+ style: { paddingInlineStart: depth * INDENT + 32 },
890
+ children: [
891
+ kind === "object" && /* @__PURE__ */ jsxRuntime.jsx(
892
+ chunk6FYMMQ3G_cjs.Input,
893
+ {
894
+ size: ctx.size,
895
+ mode: "edit",
896
+ value: key,
897
+ placeholder: "key",
898
+ "aria-label": "New key",
899
+ spellCheck: false,
900
+ "data-react-fancy-json-editor-add-key": "",
901
+ onValueChange: setKey
902
+ }
903
+ ),
904
+ /* @__PURE__ */ jsxRuntime.jsx(
905
+ chunkJU5W65N3_cjs.Select,
906
+ {
907
+ size: ctx.size,
908
+ mode: "edit",
909
+ "aria-label": "New value type",
910
+ "data-react-fancy-json-editor-add-type": "",
911
+ list: [...JSON_FIELD_TYPES],
912
+ value: type,
913
+ onValueChange: (next) => setType(next)
914
+ }
915
+ ),
916
+ /* @__PURE__ */ jsxRuntime.jsx(
917
+ chunkHTKDPFLJ_cjs.Button,
918
+ {
919
+ size: "xs",
920
+ color: "blue",
921
+ "data-react-fancy-json-editor-add-confirm": "",
922
+ onClick: () => ctx.insertInto(path, kind === "object" ? key : void 0, type),
923
+ children: "Add"
924
+ }
925
+ ),
926
+ /* @__PURE__ */ jsxRuntime.jsx(
927
+ chunkHTKDPFLJ_cjs.Button,
928
+ {
929
+ size: "xs",
930
+ variant: "ghost",
931
+ "data-react-fancy-json-editor-add-cancel": "",
932
+ onClick: () => ctx.setAddingAt(null),
933
+ children: "Cancel"
934
+ }
935
+ )
936
+ ]
937
+ }
938
+ );
939
+ }
940
+ function collectContainerPaths(value) {
941
+ const out = [];
942
+ const walk = (node, segments) => {
943
+ if (!isContainerValue(node)) return;
944
+ if (segments.length > 0) out.push(pathToString(segments));
945
+ if (isJsonArray(node)) {
946
+ node.forEach((child, index) => walk(child, [...segments, String(index)]));
947
+ } else if (isJsonObject(node)) {
948
+ for (const [key, child] of Object.entries(node)) walk(child, [...segments, key]);
949
+ }
950
+ };
951
+ walk(value, []);
952
+ return out;
953
+ }
954
+ var JsonEditor = react.forwardRef(function JsonEditor2({
955
+ value,
956
+ onChange,
957
+ keyMap,
958
+ mode = "view",
959
+ size = "sm",
960
+ readOnly = false,
961
+ expanded,
962
+ defaultExpanded,
963
+ onExpandedChange,
964
+ showIssues = true,
965
+ onIssuesChange,
966
+ pendingMode = false,
967
+ pending,
968
+ onPendingChange,
969
+ onActivity,
970
+ allowAdd = true,
971
+ allowRemove = true,
972
+ allowRename = true,
973
+ allowReorder = true,
974
+ rootLabel = "value",
975
+ emptyLabel = "No keys yet.",
976
+ idPrefix,
977
+ className,
978
+ ...rest
979
+ }, ref) {
980
+ const autoId = react.useId();
981
+ const prefix = idPrefix ?? autoId;
982
+ const editSeq = react.useRef(0);
983
+ const parsedKeyMap = react.useMemo(() => parseKeyMap(keyMap), [keyMap]);
984
+ const rules = parsedKeyMap.rules;
985
+ const conflicts = react.useMemo(() => findJsonConflicts(value, rules), [value, rules]);
986
+ const [editIssues, setEditIssues] = react.useState([]);
987
+ const issues = react.useMemo(
988
+ () => [...parsedKeyMap.issues, ...conflicts, ...editIssues],
989
+ [parsedKeyMap.issues, conflicts, editIssues]
990
+ );
991
+ const onIssuesChangeRef = react.useRef(onIssuesChange);
992
+ onIssuesChangeRef.current = onIssuesChange;
993
+ const lastIssueSignature = react.useRef(null);
994
+ react.useEffect(() => {
995
+ const signature = JSON.stringify(issues);
996
+ if (signature === lastIssueSignature.current) return;
997
+ lastIssueSignature.current = signature;
998
+ onIssuesChangeRef.current?.(issues);
999
+ }, [issues]);
1000
+ const expandedControlled = expanded !== void 0;
1001
+ const [expandedUncontrolled, setExpandedUncontrolled] = react.useState(
1002
+ defaultExpanded ?? null
1003
+ );
1004
+ const expandedList = expandedControlled ? expanded : expandedUncontrolled;
1005
+ const isExpanded = react.useCallback(
1006
+ (dotted) => expandedList === null || expandedList.includes(dotted),
1007
+ [expandedList]
1008
+ );
1009
+ const toggleExpanded = react.useCallback(
1010
+ (dotted) => {
1011
+ const current = expandedList ?? collectContainerPaths(value);
1012
+ const next = current.includes(dotted) ? current.filter((path) => path !== dotted) : [...current, dotted];
1013
+ if (!expandedControlled) setExpandedUncontrolled(next);
1014
+ onExpandedChange?.(next);
1015
+ },
1016
+ [expandedList, expandedControlled, onExpandedChange, value]
1017
+ );
1018
+ const [addingAt, setAddingAt] = react.useState(null);
1019
+ const stagedPending = react.useMemo(() => pending ?? [], [pending]);
1020
+ const commit = react.useCallback(
1021
+ (edit) => {
1022
+ setEditIssues([]);
1023
+ if (pendingMode) {
1024
+ const staged = {
1025
+ ...edit,
1026
+ id: edit.id ?? `${prefix}-edit-${editSeq.current++}`,
1027
+ label: edit.label ?? describeEdit(edit)
1028
+ };
1029
+ onPendingChange?.([...stagedPending, staged]);
1030
+ onActivity?.({ type: "stage", edit: staged });
1031
+ return;
1032
+ }
1033
+ const next = applyJsonEdit(value, edit);
1034
+ if (next === value) return;
1035
+ onChange?.(next, edit);
1036
+ onActivity?.({ type: "commit", edit });
1037
+ },
1038
+ [pendingMode, prefix, stagedPending, onPendingChange, onActivity, value, onChange]
1039
+ );
1040
+ const refuse = react.useCallback((path, message) => {
1041
+ setEditIssues([{ kind: "edit", path, message }]);
1042
+ }, []);
1043
+ const setValueAt = react.useCallback(
1044
+ (node, next) => {
1045
+ commit({ op: "set", path: node.dotted, value: next });
1046
+ },
1047
+ [commit]
1048
+ );
1049
+ const removeAt = react.useCallback(
1050
+ (node) => {
1051
+ commit({ op: "remove", path: node.dotted });
1052
+ },
1053
+ [commit]
1054
+ );
1055
+ const moveAt = react.useCallback(
1056
+ (node, to) => {
1057
+ commit({ op: "move", path: node.dotted, to });
1058
+ },
1059
+ [commit]
1060
+ );
1061
+ const renameAt = react.useCallback(
1062
+ (node, key) => {
1063
+ if (key === node.key) return;
1064
+ if (key.trim() === "") {
1065
+ refuse(node.dotted, "A key cannot be empty.");
1066
+ return;
1067
+ }
1068
+ const parent = getAtPath(value, node.path.slice(0, -1));
1069
+ if (isJsonObject(parent) && Object.prototype.hasOwnProperty.call(parent, key)) {
1070
+ refuse(node.dotted, `A key named "${key}" already exists here \u2014 rename refused.`);
1071
+ return;
1072
+ }
1073
+ commit({ op: "rename", path: node.dotted, key });
1074
+ },
1075
+ [commit, refuse, value]
1076
+ );
1077
+ const insertInto = react.useCallback(
1078
+ (dotted, key, type) => {
1079
+ const segments = parsePath(dotted);
1080
+ const container = dotted === "" ? value : getAtPath(value, segments);
1081
+ const isArray = isJsonArray(container);
1082
+ if (!isArray) {
1083
+ if (key === void 0 || key.trim() === "") {
1084
+ refuse(dotted, "A new key needs a name.");
1085
+ return;
1086
+ }
1087
+ if (isJsonObject(container) && Object.prototype.hasOwnProperty.call(container, key)) {
1088
+ refuse(dotted, `A key named "${key}" already exists here.`);
1089
+ return;
1090
+ }
1091
+ }
1092
+ const rule = resolveKeyRule(rules, [...segments, isArray ? "*" : key]);
1093
+ setAddingAt(null);
1094
+ commit({
1095
+ op: "insert",
1096
+ path: dotted,
1097
+ key: isArray ? void 0 : key,
1098
+ value: seedValue(type, rule)
1099
+ });
1100
+ },
1101
+ [commit, refuse, rules, value]
1102
+ );
1103
+ const pendingFor = react.useCallback(
1104
+ (dotted) => stagedPending.filter((edit) => edit.path === dotted),
1105
+ [stagedPending]
1106
+ );
1107
+ const acceptPending = react.useCallback(
1108
+ (id) => {
1109
+ const edit = stagedPending.find((candidate) => candidate.id === id);
1110
+ if (!edit) return;
1111
+ const next = applyJsonEdit(value, edit);
1112
+ onPendingChange?.(stagedPending.filter((candidate) => candidate.id !== id));
1113
+ if (next !== value) {
1114
+ onChange?.(next, edit);
1115
+ onActivity?.({ type: "accept", edit });
1116
+ }
1117
+ },
1118
+ [stagedPending, value, onPendingChange, onChange, onActivity]
1119
+ );
1120
+ const rejectPending = react.useCallback(
1121
+ (id) => {
1122
+ const edit = stagedPending.find((candidate) => candidate.id === id);
1123
+ onPendingChange?.(stagedPending.filter((candidate) => candidate.id !== id));
1124
+ if (edit) onActivity?.({ type: "reject", edit });
1125
+ },
1126
+ [stagedPending, onPendingChange, onActivity]
1127
+ );
1128
+ const items = react.useMemo(
1129
+ () => buildItems({
1130
+ value,
1131
+ rules,
1132
+ conflicts,
1133
+ isExpanded,
1134
+ addingAt,
1135
+ rootLabel
1136
+ }),
1137
+ [value, rules, conflicts, isExpanded, addingAt, rootLabel]
1138
+ );
1139
+ const rootIsContainer = isContainerValue(value);
1140
+ const rootKind = isJsonArray(value) ? "array" : "object";
1141
+ const attachedIds = new Set(
1142
+ items.flatMap((item) => item.kind === "node" ? [item.node.dotted] : [])
1143
+ );
1144
+ const orphanPending = stagedPending.filter((edit) => !attachedIds.has(edit.path));
1145
+ const context = react.useMemo(
1146
+ () => ({
1147
+ mode: readOnly ? "view" : mode,
1148
+ size,
1149
+ readOnly,
1150
+ allowAdd: allowAdd && !readOnly,
1151
+ allowRemove: allowRemove && !readOnly,
1152
+ allowRename: allowRename && !readOnly,
1153
+ allowReorder: allowReorder && !readOnly,
1154
+ pendingMode,
1155
+ idPrefix: prefix,
1156
+ isExpanded,
1157
+ toggleExpanded,
1158
+ setValueAt,
1159
+ removeAt,
1160
+ renameAt,
1161
+ moveAt,
1162
+ insertInto,
1163
+ addingAt,
1164
+ setAddingAt,
1165
+ pendingFor,
1166
+ acceptPending,
1167
+ rejectPending
1168
+ }),
1169
+ [
1170
+ mode,
1171
+ size,
1172
+ readOnly,
1173
+ allowAdd,
1174
+ allowRemove,
1175
+ allowRename,
1176
+ allowReorder,
1177
+ pendingMode,
1178
+ prefix,
1179
+ isExpanded,
1180
+ toggleExpanded,
1181
+ setValueAt,
1182
+ removeAt,
1183
+ renameAt,
1184
+ moveAt,
1185
+ insertInto,
1186
+ addingAt,
1187
+ pendingFor,
1188
+ acceptPending,
1189
+ rejectPending
1190
+ ]
1191
+ );
1192
+ return /* @__PURE__ */ jsxRuntime.jsx(JsonEditorContext.Provider, { value: context, children: /* @__PURE__ */ jsxRuntime.jsxs(
1193
+ "div",
1194
+ {
1195
+ ref,
1196
+ ...rest,
1197
+ "data-react-fancy-json-editor": "",
1198
+ "data-issues": String(issues.length),
1199
+ "data-keymap-error": parsedKeyMap.ok ? void 0 : "true",
1200
+ "data-mode": readOnly ? "readonly" : mode,
1201
+ className: chunk3Z6ALUWP_cjs.cn(
1202
+ "overflow-hidden rounded-lg border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100",
1203
+ className
1204
+ ),
1205
+ children: [
1206
+ showIssues && issues.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-react-fancy-json-editor-issues": "", className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsxs(chunkY5V5GBN4_cjs.Callout, { color: parsedKeyMap.ok ? "amber" : "red", children: [
1207
+ /* @__PURE__ */ jsxRuntime.jsx(chunk23CLGUMT_cjs.Text, { size: "sm", weight: "semibold", className: "mb-1", children: parsedKeyMap.ok ? `${issues.length} ${issues.length === 1 ? "issue" : "issues"}` : "The keyMap could not be used \u2014 values are shown untyped." }),
1208
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-0.5", children: issues.map((issue2, index) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(chunk23CLGUMT_cjs.Text, { as: "span", size: "xs", "data-react-fancy-json-editor-issue": "", "data-kind": issue2.kind, "data-path": issue2.path, children: [
1209
+ issue2.path ? `${issue2.path} \u2014 ` : "",
1210
+ issue2.message
1211
+ ] }) }, `${issue2.kind}-${issue2.path}-${index}`)) })
1212
+ ] }) }),
1213
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-react-fancy-json-editor-tree": "", role: "tree", "aria-label": rest["aria-label"] ?? "JSON document", children: items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunk23CLGUMT_cjs.Text, { as: "p", size: "sm", color: "muted", className: "px-3 py-4", children: emptyLabel }) : items.map(
1214
+ (item) => item.kind === "node" ? /* @__PURE__ */ jsxRuntime.jsx(JsonEditorRow, { node: item.node }, `row:${item.node.dotted}`) : /* @__PURE__ */ jsxRuntime.jsx(
1215
+ JsonEditorAddForm,
1216
+ {
1217
+ path: item.path,
1218
+ kind: item.containerKind,
1219
+ depth: item.depth,
1220
+ suggestedType: item.suggestedType
1221
+ },
1222
+ `add:${item.path}`
1223
+ )
1224
+ ) }),
1225
+ orphanPending.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-react-fancy-json-editor-orphan-pending": "", className: "border-t border-zinc-100 p-2 dark:border-zinc-800", children: orphanPending.map((edit) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 py-0.5", children: [
1226
+ /* @__PURE__ */ jsxRuntime.jsx(chunk23CLGUMT_cjs.Text, { as: "span", size: "xs", color: "muted", className: "min-w-0 flex-1 truncate font-mono", children: edit.label ?? describeEdit(edit) }),
1227
+ /* @__PURE__ */ jsxRuntime.jsx(
1228
+ chunkHTKDPFLJ_cjs.Button,
1229
+ {
1230
+ size: "xs",
1231
+ color: "emerald",
1232
+ "data-react-fancy-json-editor-accept": "",
1233
+ "data-id": edit.id,
1234
+ onClick: () => acceptPending(edit.id),
1235
+ children: "Accept"
1236
+ }
1237
+ ),
1238
+ /* @__PURE__ */ jsxRuntime.jsx(
1239
+ chunkHTKDPFLJ_cjs.Button,
1240
+ {
1241
+ size: "xs",
1242
+ variant: "ghost",
1243
+ "data-react-fancy-json-editor-reject": "",
1244
+ "data-id": edit.id,
1245
+ onClick: () => rejectPending(edit.id),
1246
+ children: "Reject"
1247
+ }
1248
+ )
1249
+ ] }, edit.id)) }),
1250
+ rootIsContainer && allowAdd && !readOnly && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-zinc-100 p-2 dark:border-zinc-800", children: /* @__PURE__ */ jsxRuntime.jsx(
1251
+ chunkHTKDPFLJ_cjs.Button,
1252
+ {
1253
+ variant: "ghost",
1254
+ size: "xs",
1255
+ icon: "plus",
1256
+ "data-react-fancy-json-editor-add": "",
1257
+ "data-path": "",
1258
+ onClick: () => setAddingAt(addingAt === "" ? null : ""),
1259
+ children: rootKind === "array" ? "Append item" : "Add key"
1260
+ }
1261
+ ) })
1262
+ ]
1263
+ }
1264
+ ) });
1265
+ });
1266
+ function buildItems({
1267
+ value,
1268
+ rules,
1269
+ conflicts,
1270
+ isExpanded,
1271
+ addingAt,
1272
+ rootLabel
1273
+ }) {
1274
+ const out = [];
1275
+ const conflictByPath = /* @__PURE__ */ new Map();
1276
+ for (const issue2 of conflicts) {
1277
+ if (issue2.kind === "type" && !conflictByPath.has(issue2.path)) conflictByPath.set(issue2.path, issue2);
1278
+ }
1279
+ const makeNode = (segments, node, depth, parentKind) => {
1280
+ const rule = segments.length > 0 ? resolveKeyRule(rules, segments) : void 0;
1281
+ const type = rule?.type ?? inferType(node);
1282
+ const dotted = pathToString(segments);
1283
+ const conflict = conflictByPath.get(dotted);
1284
+ const container = !conflict && type !== "json" && isContainerValue(node);
1285
+ return {
1286
+ path: segments,
1287
+ dotted,
1288
+ key: segments[segments.length - 1] ?? rootLabel,
1289
+ depth,
1290
+ value: node,
1291
+ parentKind,
1292
+ rule,
1293
+ type,
1294
+ declared: rule !== void 0,
1295
+ container,
1296
+ childCount: isJsonArray(node) ? node.length : isJsonObject(node) ? Object.keys(node).length : 0,
1297
+ conflict
1298
+ };
1299
+ };
1300
+ const emitChildren = (node, segments, depth) => {
1301
+ if (isJsonArray(node)) {
1302
+ node.forEach((child, index) => emit(child, [...segments, String(index)], depth, "array"));
1303
+ } else if (isJsonObject(node)) {
1304
+ for (const [key, child] of Object.entries(node)) {
1305
+ emit(child, [...segments, key], depth, "object");
1306
+ }
1307
+ }
1308
+ };
1309
+ const emit = (node, segments, depth, parentKind) => {
1310
+ const built = makeNode(segments, node, depth, parentKind);
1311
+ out.push({ kind: "node", node: built });
1312
+ if (!built.container || !isExpanded(built.dotted)) return;
1313
+ emitChildren(node, segments, depth + 1);
1314
+ if (addingAt === built.dotted) {
1315
+ out.push({
1316
+ kind: "add",
1317
+ path: built.dotted,
1318
+ containerKind: isJsonArray(node) ? "array" : "object",
1319
+ depth: depth + 1,
1320
+ suggestedType: resolveKeyRule(rules, [...segments, "*"])?.type
1321
+ });
1322
+ }
1323
+ };
1324
+ if (isContainerValue(value)) {
1325
+ emitChildren(value, [], 0);
1326
+ if (addingAt === "") {
1327
+ out.push({
1328
+ kind: "add",
1329
+ path: "",
1330
+ containerKind: isJsonArray(value) ? "array" : "object",
1331
+ depth: 0,
1332
+ suggestedType: resolveKeyRule(rules, ["*"])?.type
1333
+ });
1334
+ }
1335
+ } else {
1336
+ out.push({ kind: "node", node: makeNode([], value, 0, "root") });
1337
+ }
1338
+ return out;
1339
+ }
1340
+
1341
+ exports.JSON_FIELD_TYPES = JSON_FIELD_TYPES;
1342
+ exports.JsonEditor = JsonEditor;
1343
+ exports.applyJsonEdit = applyJsonEdit;
1344
+ exports.describeEdit = describeEdit;
1345
+ exports.findJsonConflicts = findJsonConflicts;
1346
+ exports.getAtPath = getAtPath;
1347
+ exports.inferType = inferType;
1348
+ exports.parseKeyMap = parseKeyMap;
1349
+ exports.parsePath = parsePath;
1350
+ exports.pathToString = pathToString;
1351
+ exports.resolveKeyRule = resolveKeyRule;
1352
+ exports.typeMatches = typeMatches;
1353
+ //# sourceMappingURL=chunk-AR2IBCX7.cjs.map
1354
+ //# sourceMappingURL=chunk-AR2IBCX7.cjs.map