@petrarca/sonnet-core 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -77,6 +77,306 @@ function pluralize(count, word) {
77
77
  return `${count} ${word}${count !== 1 ? "s" : ""}`;
78
78
  }
79
79
 
80
+ // src/dateParser.ts
81
+ var VALID_SEPARATORS = ["/", "-", "."];
82
+ function compileDateFormat(options = {}) {
83
+ const format = options.format ?? "DD/MM/YYYY";
84
+ const yearThreshold = options.yearThreshold ?? (/* @__PURE__ */ new Date()).getFullYear() % 100;
85
+ const parts = format.split(/[^A-Z]+/);
86
+ const dayIndex = parts.findIndex((p) => p === "DD");
87
+ const monthIndex = parts.findIndex((p) => p === "MM");
88
+ const yearIndex = parts.findIndex((p) => p === "YYYY" || p === "YY");
89
+ const has2DigitYear = yearIndex !== -1 && parts[yearIndex] === "YY";
90
+ if (dayIndex === -1 && monthIndex === -1 && yearIndex === -1) {
91
+ throw new Error(
92
+ "Invalid date format. Must contain at least one of DD, MM, or YYYY/YY."
93
+ );
94
+ }
95
+ return {
96
+ format,
97
+ yearThreshold,
98
+ dayIndex,
99
+ monthIndex,
100
+ yearIndex,
101
+ has2DigitYear,
102
+ validSeparators: VALID_SEPARATORS
103
+ };
104
+ }
105
+ function cleanInput(input, fmt) {
106
+ return input.replace(
107
+ new RegExp(
108
+ `[^0-9${fmt.validSeparators.map((s) => "\\" + s).join("")}+-]`,
109
+ "g"
110
+ ),
111
+ ""
112
+ );
113
+ }
114
+ function expandYear(yearStr, fmt) {
115
+ const year = parseInt(yearStr, 10);
116
+ if (yearStr.length >= 4) return year;
117
+ const refYear = fmt.yearThreshold + Math.floor((/* @__PURE__ */ new Date()).getFullYear() / 100) * 100;
118
+ const century = Math.floor(refYear / 100) * 100;
119
+ if (fmt.yearThreshold === 0) return century + year;
120
+ if (fmt.yearThreshold === -1) return century - 100 + year;
121
+ return year > fmt.yearThreshold ? century - 100 + year : century + year;
122
+ }
123
+ function parseWithSeparators(input, fmt) {
124
+ const parts = input.split(
125
+ new RegExp(`[${fmt.validSeparators.map((s) => "\\" + s).join("")}]`)
126
+ );
127
+ const result = {
128
+ day: null,
129
+ month: null,
130
+ year: null
131
+ };
132
+ for (let i = 0; i < parts.length; i++) {
133
+ if (!parts[i]) continue;
134
+ if (i === fmt.dayIndex) result.day = parseInt(parts[i], 10);
135
+ else if (i === fmt.monthIndex) result.month = parseInt(parts[i], 10);
136
+ else if (i === fmt.yearIndex) result.year = expandYear(parts[i], fmt);
137
+ }
138
+ return result;
139
+ }
140
+ function parseWithoutSeparators(input, fmt) {
141
+ const result = {
142
+ day: null,
143
+ month: null,
144
+ year: null
145
+ };
146
+ const yearLength = fmt.has2DigitYear ? 2 : 4;
147
+ const components = [
148
+ { type: "day", index: fmt.dayIndex, length: 2 },
149
+ { type: "month", index: fmt.monthIndex, length: 2 },
150
+ { type: "year", index: fmt.yearIndex, length: yearLength }
151
+ ].filter((c) => c.index !== -1).sort((a, b) => a.index - b.index);
152
+ let remaining = input;
153
+ for (const c of components) {
154
+ if (!remaining.length) break;
155
+ const len = Math.min(c.length, remaining.length);
156
+ const val = remaining.substring(0, len);
157
+ remaining = remaining.substring(len);
158
+ if (c.type === "day") result.day = parseInt(val, 10);
159
+ else if (c.type === "month") result.month = parseInt(val, 10);
160
+ else if (c.type === "year") result.year = expandYear(val, fmt);
161
+ }
162
+ return result;
163
+ }
164
+ function daysInMonth(month, year) {
165
+ if (month === 2) {
166
+ const leap = year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
167
+ return leap ? 29 : 28;
168
+ }
169
+ return [4, 6, 9, 11].includes(month) ? 30 : 31;
170
+ }
171
+ function isValidDate(day, month, year) {
172
+ if (month < 1 || month > 12) return false;
173
+ if (year < 1900 || year > 2100) return false;
174
+ if (day < 1 || day > daysInMonth(month, year)) return false;
175
+ return true;
176
+ }
177
+ function buildDateResult(parsed, fmt) {
178
+ const today = /* @__PURE__ */ new Date();
179
+ const day = parsed.day ?? today.getDate();
180
+ const month = parsed.month ?? today.getMonth() + 1;
181
+ const year = parsed.year ?? today.getFullYear();
182
+ if (!isValidDate(day, month, year)) {
183
+ return { value: "", date: null, error: "Invalid date" };
184
+ }
185
+ const date = new Date(year, month - 1, day);
186
+ return { value: formatDateInput(date, fmt), date, error: "" };
187
+ }
188
+ function parseDate(input, fmt) {
189
+ if (!input || !input.trim()) return { value: "", date: null, error: "" };
190
+ if ([".", "t", "today"].includes(input.trim().toLowerCase())) {
191
+ const today = /* @__PURE__ */ new Date();
192
+ return { value: formatDateInput(today, fmt), date: today, error: "" };
193
+ }
194
+ const cleaned = cleanInput(input, fmt);
195
+ if (!cleaned) {
196
+ return { value: "", date: null, error: "Invalid characters in date" };
197
+ }
198
+ const hasSeparators = fmt.validSeparators.some((s) => cleaned.includes(s));
199
+ try {
200
+ const parsed = hasSeparators ? parseWithSeparators(cleaned, fmt) : parseWithoutSeparators(cleaned, fmt);
201
+ return buildDateResult(parsed, fmt);
202
+ } catch (e) {
203
+ return {
204
+ value: "",
205
+ date: null,
206
+ error: e instanceof Error ? e.message : "Invalid date format"
207
+ };
208
+ }
209
+ }
210
+ function formatDateInput(date, fmt) {
211
+ if (!date || isNaN(date.getTime())) return "";
212
+ const tokens = {
213
+ DD: date.getDate().toString().padStart(2, "0"),
214
+ MM: (date.getMonth() + 1).toString().padStart(2, "0"),
215
+ YYYY: date.getFullYear().toString(),
216
+ YY: date.getFullYear().toString().slice(-2)
217
+ };
218
+ return fmt.format.replace(/DD|MM|YYYY|YY/g, (m) => tokens[m]);
219
+ }
220
+ function isDateEqual(a, b) {
221
+ if (!a || !b) return false;
222
+ return a.getDate() === b.getDate() && a.getMonth() === b.getMonth() && a.getFullYear() === b.getFullYear();
223
+ }
224
+ function formatIsoDate(date, precision = "day") {
225
+ if (!date || isNaN(date.getTime())) return "";
226
+ const year = date.getFullYear().toString().padStart(4, "0");
227
+ if (precision === "year") return year;
228
+ const month = (date.getMonth() + 1).toString().padStart(2, "0");
229
+ if (precision === "month") return `${year}-${month}`;
230
+ const day = date.getDate().toString().padStart(2, "0");
231
+ return `${year}-${month}-${day}`;
232
+ }
233
+ function parseIsoDate(iso) {
234
+ if (!iso) return null;
235
+ const match = iso.match(/^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$/);
236
+ if (!match) return null;
237
+ const [, year, month, day] = match;
238
+ const date = new Date(
239
+ Number(year),
240
+ month ? Number(month) - 1 : 0,
241
+ day ? Number(day) : 1
242
+ );
243
+ return isNaN(date.getTime()) ? null : date;
244
+ }
245
+ function isoDatePrecision(iso) {
246
+ if (!iso) return "day";
247
+ if (/^\d{4}$/.test(iso)) return "year";
248
+ if (/^\d{4}-\d{2}$/.test(iso)) return "month";
249
+ return "day";
250
+ }
251
+
252
+ // src/timeParser.ts
253
+ function splitDigits(digits) {
254
+ if (digits.length <= 2) return [Number(digits)];
255
+ if (digits.length <= 4) {
256
+ return [
257
+ Number(digits.slice(0, digits.length - 2)),
258
+ Number(digits.slice(-2))
259
+ ];
260
+ }
261
+ return [
262
+ Number(digits.slice(0, digits.length - 4)),
263
+ Number(digits.slice(-4, -2)),
264
+ Number(digits.slice(-2))
265
+ ];
266
+ }
267
+ function extractParts(input) {
268
+ if (input.includes(":")) {
269
+ const parts = input.split(":");
270
+ if (parts.length > 3 || parts[parts.length - 1] === "") {
271
+ return [];
272
+ }
273
+ return parts.map((p) => Number(p));
274
+ }
275
+ return splitDigits(input);
276
+ }
277
+ function isValidTime(hour, minute, second) {
278
+ const inRange = (n, max) => Number.isInteger(n) && n >= 0 && n <= max;
279
+ return inRange(hour, 23) && inRange(minute, 59) && inRange(second, 59);
280
+ }
281
+ function formatIsoTime(hour, minute, second, granularity = "minute") {
282
+ const hh = hour.toString().padStart(2, "0");
283
+ const mm = minute.toString().padStart(2, "0");
284
+ if (granularity === "minute") return `${hh}:${mm}`;
285
+ const ss = second.toString().padStart(2, "0");
286
+ return `${hh}:${mm}:${ss}`;
287
+ }
288
+ function parseTime(input, granularity = "minute") {
289
+ if (!input || !input.trim()) return { value: "", error: "" };
290
+ if ([".", "n", "now"].includes(input.trim().toLowerCase())) {
291
+ const now = /* @__PURE__ */ new Date();
292
+ return {
293
+ value: formatIsoTime(
294
+ now.getHours(),
295
+ now.getMinutes(),
296
+ now.getSeconds(),
297
+ granularity
298
+ ),
299
+ error: ""
300
+ };
301
+ }
302
+ const cleaned = input.replace(/[^0-9:]/g, "");
303
+ if (!cleaned) return { value: "", error: "Invalid characters in time" };
304
+ return parseCleanedTime(cleaned, granularity);
305
+ }
306
+ function parseCleanedTime(cleaned, granularity) {
307
+ const parts = extractParts(cleaned);
308
+ if (!parts.length) return { value: "", error: "Invalid time format" };
309
+ const hour = parts[0] ?? 0;
310
+ const minute = parts[1] ?? 0;
311
+ const second = parts[2] ?? 0;
312
+ if (!isValidTime(hour, minute, second)) {
313
+ return { value: "", error: "Invalid time" };
314
+ }
315
+ return { value: formatIsoTime(hour, minute, second, granularity), error: "" };
316
+ }
317
+ function normalizeTime(iso, granularity = "minute") {
318
+ if (!iso) return "";
319
+ return parseTime(iso, granularity).value;
320
+ }
321
+ function splitDateTime(iso) {
322
+ if (!iso) return { date: "", time: "" };
323
+ const [date, time] = iso.split("T");
324
+ return { date: date ?? "", time: time ?? "" };
325
+ }
326
+ function joinDateTime(date, time) {
327
+ if (!date) return "";
328
+ return time ? `${date}T${time}` : date;
329
+ }
330
+
331
+ // src/localeFormat.ts
332
+ function dayFormatFromParts(locale) {
333
+ const parts = new Intl.DateTimeFormat(locale, {
334
+ year: "numeric",
335
+ month: "2-digit",
336
+ day: "2-digit"
337
+ }).formatToParts(new Date(2023, 0, 2));
338
+ const tokens = [];
339
+ let separator = "/";
340
+ for (const part of parts) {
341
+ if (part.type === "day") tokens.push("DD");
342
+ else if (part.type === "month") tokens.push("MM");
343
+ else if (part.type === "year") tokens.push("YYYY");
344
+ else if (part.type === "literal") {
345
+ const trimmed = part.value.trim();
346
+ if (trimmed) separator = trimmed[0];
347
+ }
348
+ }
349
+ if (tokens.length !== 3) return "DD/MM/YYYY";
350
+ return tokens.join(separator);
351
+ }
352
+ function getLocaleDateFormats(locale) {
353
+ const day = dayFormatFromParts(locale);
354
+ const month = day.replace(/DD.|.DD/, "");
355
+ return { year: "YYYY", month, day };
356
+ }
357
+ function getLocaleDateFormat(locale, precision) {
358
+ return getLocaleDateFormats(locale)[precision];
359
+ }
360
+ function getWeekdayLabels(locale) {
361
+ const first = getFirstDayOfWeek(locale);
362
+ const formatter = new Intl.DateTimeFormat(locale, { weekday: "short" });
363
+ return Array.from(
364
+ { length: 7 },
365
+ (_, i) => formatter.format(new Date(2023, 0, 1 + (first + i) % 7))
366
+ );
367
+ }
368
+ function getFirstDayOfWeek(locale) {
369
+ try {
370
+ const loc = new Intl.Locale(locale);
371
+ const info = loc.getWeekInfo?.() ?? loc.weekInfo;
372
+ if (info?.firstDay !== void 0) {
373
+ return info.firstDay === 7 ? 0 : info.firstDay;
374
+ }
375
+ } catch {
376
+ }
377
+ return 1;
378
+ }
379
+
80
380
  // src/jsonUtils.ts
81
381
  function escapeHtml(value) {
82
382
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
@@ -395,23 +695,39 @@ export {
395
695
  FORM_ITEM_ID_FIELD,
396
696
  JSON_CSS_VARIABLES,
397
697
  cn,
698
+ compileDateFormat,
398
699
  copyTextToClipboard,
399
700
  devLog,
400
701
  errorLog,
401
702
  escapeHtml,
402
703
  formatDate,
704
+ formatDateInput,
403
705
  formatDateTime,
404
706
  formatDateTimeTz,
707
+ formatIsoDate,
708
+ formatIsoTime,
405
709
  formatJsonValue,
406
710
  formatNumber,
407
711
  formatNumberCompact,
408
712
  generateId,
713
+ getFirstDayOfWeek,
714
+ getLocaleDateFormat,
715
+ getLocaleDateFormats,
716
+ getWeekdayLabels,
409
717
  infoLog,
718
+ isDateEqual,
410
719
  isEqual,
720
+ isoDatePrecision,
721
+ joinDateTime,
411
722
  normalizeError,
723
+ normalizeTime,
724
+ parseDate,
725
+ parseIsoDate,
726
+ parseTime,
412
727
  pluralize,
413
728
  resolvePointerRanges,
414
729
  snakeCaseToTitleCase_default as snakeCaseToTitleCase,
730
+ splitDateTime,
415
731
  toPageResult,
416
732
  useComposedRefs,
417
733
  warnLog
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/format.ts","../src/jsonUtils.ts","../src/utils/copyTextToClipboard.tsx","../src/utils/snakeCaseToTitleCase.ts","../src/errorNormalizer.ts","../src/compose-refs.ts","../src/resolvePointerRanges.ts","../src/pagination.ts"],"sourcesContent":["// Reusable formatting utilities.\n// Thin wrappers around Intl for consistent output across the app.\n\nconst numberFormatter = new Intl.NumberFormat(undefined, {\n maximumFractionDigits: 0,\n});\n\nexport function formatNumber(\n value: number | string | undefined | null,\n): string {\n if (value === null || value === undefined) return \"0\";\n const num = typeof value === \"string\" ? Number(value) : value;\n if (!Number.isFinite(num)) return String(value);\n return numberFormatter.format(num as number);\n}\n\nexport function formatNumberCompact(\n value: number | string | undefined | null,\n): string {\n if (value === null || value === undefined) return \"0\";\n const num = typeof value === \"string\" ? Number(value) : value;\n if (!Number.isFinite(num)) return String(value);\n return new Intl.NumberFormat(undefined, {\n notation: \"compact\",\n maximumFractionDigits: 1,\n }).format(num as number);\n}\n\n/** Format an ISO 8601 string as a short date (e.g. \"Jan 15, 2026\"). */\nexport function formatDate(iso: string | null | undefined): string {\n if (!iso) return \"\\u2014\";\n return new Date(iso).toLocaleDateString(undefined, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Format an ISO 8601 string as date + time (e.g. \"Jan 15, 2026, 09:32 AM\"). */\nexport function formatDateTime(iso: string | null | undefined): string {\n if (!iso) return \"\\u2014\";\n return new Date(iso).toLocaleString(undefined, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/**\n * Format a timezone-aware ISO 8601 string preserving the original offset.\n *\n * Parses the date/time components and offset directly from the string so\n * the emitter's local time and offset are shown exactly as recorded --\n * independent of the viewer's timezone.\n *\n * Examples:\n * \"2026-02-22T10:00:00+01:00\" -> \"22 Feb 2026 at 10:00 +01:00\"\n * \"2026-02-22T09:00:00Z\" -> \"22 Feb 2026 at 09:00 UTC\"\n */\nexport function formatDateTimeTz(iso: string | null | undefined): string {\n if (!iso) return \"\\u2014\";\n\n // Match ISO 8601: date, time (HH:MM), optional seconds, offset or Z.\n const match = iso.match(\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$/,\n );\n if (!match) return iso;\n\n const [, year, month, day, hour, minute, rawOffset] = match;\n\n const months = [\n \"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\",\n ];\n const monthName = months[parseInt(month, 10) - 1];\n const offset = rawOffset === \"Z\" ? \"UTC\" : rawOffset;\n\n return `${parseInt(day, 10)} ${monthName} ${year} at ${hour}:${minute} ${offset}`;\n}\n\n/** Return \"{count} {word}\" with the word pluralized when count != 1. */\nexport function pluralize(count: number, word: string): string {\n return `${count} ${word}${count !== 1 ? \"s\" : \"\"}`;\n}\n","/**\n * Escapes HTML characters to prevent XSS and rendering issues\n */\nexport function escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n\n/**\n * Formats a JSON value into colored HTML with proper syntax highlighting\n * @param value - The value to format (any JSON-serializable type)\n * @param indent - Current indentation level for nested objects/arrays\n * @returns HTML string with syntax highlighting\n */\nfunction jsonSpan(cssVar: string, content: string): string {\n return `<span style=\"color: var(${cssVar})\">${content}</span>`;\n}\n\nfunction formatPrimitive(value: unknown): string | null {\n if (value === null) return jsonSpan(\"--json-null\", \"null\");\n if (typeof value === \"undefined\") return jsonSpan(\"--json-null\", \"undefined\");\n if (typeof value === \"boolean\")\n return jsonSpan(\"--json-boolean\", String(value));\n if (typeof value === \"number\")\n return jsonSpan(\"--json-number\", String(value));\n if (typeof value === \"string\")\n return jsonSpan(\"--json-string\", `\"${escapeHtml(value)}\"`);\n return null;\n}\n\nfunction formatArray(value: unknown[], indent: number): string {\n if (value.length === 0) return jsonSpan(\"--json-punctuation\", \"[]\");\n const indentStr = \" \".repeat(indent);\n const items = value\n .map((item) => `${indentStr} ${formatJsonValue(item, indent + 1)}`)\n .join(\",\\n\");\n return `${jsonSpan(\"--json-punctuation\", \"[\")}\\n${items}\\n${indentStr}${jsonSpan(\"--json-punctuation\", \"]\")}`;\n}\n\nfunction formatObject(value: object, indent: number): string {\n const entries = Object.entries(value);\n if (entries.length === 0) return jsonSpan(\"--json-punctuation\", \"{}\");\n const indentStr = \" \".repeat(indent);\n const items = entries\n .map(\n ([key, val]) =>\n `${indentStr} ${jsonSpan(\"--json-key\", `\"${escapeHtml(key)}\"`)}${jsonSpan(\"--json-punctuation\", \":\")} ${formatJsonValue(val, indent + 1)}`,\n )\n .join(\",\\n\");\n return `${jsonSpan(\"--json-punctuation\", \"{\")}\\n${items}\\n${indentStr}${jsonSpan(\"--json-punctuation\", \"}\")}`;\n}\n\nexport function formatJsonValue(value: unknown, indent = 0): string {\n const primitive = formatPrimitive(value);\n if (primitive !== null) return primitive;\n if (Array.isArray(value)) return formatArray(value, indent);\n if (typeof value === \"object\" && value !== null)\n return formatObject(value, indent);\n return jsonSpan(\"--json-fallback\", escapeHtml(String(value)));\n}\n\n/**\n * CSS custom properties for JSON syntax highlighting colors\n */\nexport const JSON_CSS_VARIABLES = {\n \"--json-key\": \"#2563eb\",\n \"--json-string\": \"#16a34a\",\n \"--json-number\": \"#ea580c\",\n \"--json-boolean\": \"#2563eb\",\n \"--json-null\": \"#64748b\",\n \"--json-punctuation\": \"#475569\",\n \"--json-fallback\": \"#6b7280\",\n} as const;\n","/**\n * Copy text to the system clipboard.\n *\n * Optionally calls `onSuccess` after a successful write. The caller\n * provides its own notification mechanism (e.g. `notification.success`\n * from the shell API) to keep this utility free of sonner or any other\n * toast dependency.\n */\nexport async function copyTextToClipboard(\n text: string,\n options?: { onSuccess?: (message: string) => void },\n): Promise<void> {\n await navigator.clipboard.writeText(text);\n options?.onSuccess?.(`${text} copied to clipboard`);\n}\n","function snakeCaseToTitleCase(snakeCase: string): string {\n const words = snakeCase.split(\"_\");\n const titleCaseWords = words.map(\n (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n );\n return titleCaseWords.join(\" \");\n}\n\nexport default snakeCaseToTitleCase;\n","/**\n * Error normalizer -- extract typed error info from any thrown value.\n *\n * Generic utility with no framework dependencies. Handles standard\n * Error objects and Axios-shaped error responses via duck-typing\n * (no axios import required).\n */\n\nexport interface NormalizedError {\n message: string;\n status?: number;\n details?: string[];\n}\n\n/**\n * Normalize any thrown value into a structured error object.\n *\n * Handles:\n * - Axios-shaped errors (duck-typed via `isAxiosError` property)\n * - Standard Error objects\n * - Arbitrary values (stringified)\n */\n// Extract validation detail messages from a FastAPI-style detail array.\nfunction extractDetailMessages(detail: unknown[]): string[] {\n const msgs: string[] = [];\n for (const item of detail) {\n if (\n item &&\n typeof item === \"object\" &&\n typeof (item as Record<string, unknown>).msg === \"string\"\n ) {\n msgs.push((item as Record<string, unknown>).msg as string);\n }\n }\n return msgs;\n}\n\n// Extract message and details from an Axios-like response data payload.\nfunction extractFromResponseData(\n data: unknown,\n fallback: string,\n): { message: string; details: string[] } {\n if (typeof data === \"string\") return { message: data, details: [] };\n if (typeof data !== \"object\" || data === null)\n return { message: fallback, details: [] };\n\n const d = data as Record<string, unknown>;\n if (typeof d.detail === \"string\") return { message: d.detail, details: [] };\n if (Array.isArray(d.detail)) {\n const details = extractDetailMessages(d.detail);\n return { message: details.length ? details.join(\"; \") : fallback, details };\n }\n if (typeof d.error === \"string\") return { message: d.error, details: [] };\n return { message: fallback, details: [] };\n}\n\n// Normalize an Axios-like error into a structured error object.\nfunction normalizeAxiosError(err: AxiosLikeError): NormalizedError {\n const status = err.response?.status;\n const { message, details } = extractFromResponseData(\n err.response?.data,\n err.message,\n );\n return { message, status, details: details.length ? details : undefined };\n}\n\nexport function normalizeError(err: unknown): NormalizedError {\n if (isAxiosLikeError(err)) return normalizeAxiosError(err);\n if (err instanceof Error) return { message: err.message };\n return { message: String(err) };\n}\n\n// Duck-type check for Axios-like errors.\ninterface AxiosLikeError {\n isAxiosError: true;\n message: string;\n response?: {\n status?: number;\n data?: unknown;\n };\n}\n\nfunction isAxiosLikeError(err: unknown): err is AxiosLikeError {\n return (\n err !== null &&\n typeof err === \"object\" &&\n \"isAxiosError\" in err &&\n (err as Record<string, unknown>).isAxiosError === true\n );\n}\n","import * as React from \"react\";\n\ntype PossibleRef<T> = React.Ref<T> | undefined;\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === \"function\") {\n return ref(value);\n }\n\n if (ref !== null && ref !== undefined) {\n ref.current = value;\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false;\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node);\n if (!hasCleanup && typeof cleanup === \"function\") {\n hasCleanup = true;\n }\n return cleanup;\n });\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i];\n if (typeof cleanup === \"function\") {\n cleanup();\n } else {\n setRef(refs[i], null);\n }\n }\n };\n }\n };\n}\n\n/**\n * A custom hook that composes multiple refs.\n * Accepts callback refs and RefObject(s).\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // Store the latest refs in a mutable ref so the stable callback always\n // sees the current values without needing a dynamic dependency array.\n const refsRef = React.useRef(refs);\n React.useEffect(() => {\n refsRef.current = refs;\n });\n\n return React.useCallback((node: T) => {\n composeRefs(...refsRef.current)(node);\n }, []);\n}\n\nexport { composeRefs, useComposedRefs };\n","/**\n * Resolve JSON Pointer (RFC 6901) paths to character offset ranges\n * within a formatted JSON string.\n *\n * Given a JSON string and a list of JSON Pointers, returns the\n * [from, to] byte ranges covering the *value* of each pointer.\n * The range includes the full value (object braces, array brackets,\n * string quotes, nested content) so the user can freely edit\n * everything inside.\n *\n * Zero external dependencies — pure TypeScript.\n * Maps to @petrarca/sonnet-core on extraction.\n */\n\nexport interface OffsetRange {\n /** JSON Pointer that was resolved */\n pointer: string;\n /** Start character offset (inclusive) */\n from: number;\n /** End character offset (exclusive) */\n to: number;\n}\n\n/**\n * Unescape a JSON Pointer token per RFC 6901:\n * ~1 -> /\n * ~0 -> ~\n */\nfunction unescapeToken(token: string): string {\n return token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\n\n/**\n * Parse a JSON Pointer string into an array of unescaped tokens.\n * \"\" returns [] (root document, per RFC 6901)\n * \"/\" returns [] (sentinel for \"entire document\" -- treated as root)\n * \"/a/b\" returns [\"a\", \"b\"]\n */\nfunction parsePointer(pointer: string): string[] {\n if (pointer === \"\" || pointer === \"/\") return [];\n if (!pointer.startsWith(\"/\")) {\n throw new Error(`Invalid JSON Pointer: \"${pointer}\" (must start with /)`);\n }\n return pointer.slice(1).split(\"/\").map(unescapeToken);\n}\n\n/**\n * Find the character offset range of a value at the given path\n * within a JSON string. Walks the string character by character\n * to find the key, then captures the full value range.\n */\n/** Mutable cursor for walking a JSON string character by character. */\ninterface Cursor {\n pos: number;\n json: string;\n}\n\nfunction skipWs(c: Cursor): void {\n while (c.pos < c.json.length && /\\s/.test(c.json[c.pos])) c.pos++;\n}\n\nfunction skipString(c: Cursor): number {\n c.pos++; // skip opening \"\n while (c.pos < c.json.length) {\n if (c.json[c.pos] === \"\\\\\") {\n c.pos += 2;\n continue;\n }\n if (c.json[c.pos] === '\"') {\n c.pos++;\n return c.pos;\n }\n c.pos++;\n }\n return c.pos;\n}\n\nfunction skipContainer(c: Cursor, open: string, close: string): number {\n c.pos++; // skip opening bracket\n skipWs(c);\n if (c.json[c.pos] === close) {\n c.pos++;\n return c.pos;\n }\n while (c.pos < c.json.length) {\n if (open === \"{\") {\n skipValue(c); // key\n skipWs(c);\n if (c.json[c.pos] === \":\") c.pos++;\n }\n skipValue(c);\n skipWs(c);\n if (c.json[c.pos] === \",\") {\n c.pos++;\n skipWs(c);\n continue;\n }\n if (c.json[c.pos] === close) {\n c.pos++;\n return c.pos;\n }\n break;\n }\n return c.pos;\n}\n\nfunction skipValue(c: Cursor): number {\n skipWs(c);\n if (c.pos >= c.json.length) return c.pos;\n const ch = c.json[c.pos];\n if (ch === '\"') return skipString(c);\n if (ch === \"{\") return skipContainer(c, \"{\", \"}\");\n if (ch === \"[\") return skipContainer(c, \"[\", \"]\");\n // Number, bool, null -- consume until delimiter\n while (c.pos < c.json.length && !/[,\\]}\\s]/.test(c.json[c.pos])) c.pos++;\n return c.pos;\n}\n\n/** Read and return the next JSON string key, advancing past the closing quote. */\nfunction readKey(c: Cursor): string {\n const keyStart = c.pos + 1;\n c.pos++;\n while (c.pos < c.json.length) {\n if (c.json[c.pos] === \"\\\\\") {\n c.pos += 2;\n continue;\n }\n if (c.json[c.pos] === '\"') break;\n c.pos++;\n }\n const key = c.json.slice(keyStart, c.pos);\n c.pos++; // skip closing \"\n return key;\n}\n\n/** Navigate into a JSON object to the value at `token`. */\nfunction navigateObject(c: Cursor, token: string): boolean {\n c.pos++; // skip {\n skipWs(c);\n while (c.pos < c.json.length && c.json[c.pos] !== \"}\") {\n if (c.json[c.pos] !== '\"') return false;\n const key = readKey(c);\n skipWs(c);\n if (c.json[c.pos] === \":\") c.pos++;\n skipWs(c);\n if (key === token) return true;\n skipValue(c);\n skipWs(c);\n if (c.json[c.pos] === \",\") {\n c.pos++;\n skipWs(c);\n }\n }\n return false;\n}\n\n/** Navigate into a JSON array to the element at `index`. */\nfunction navigateArray(c: Cursor, index: number): boolean {\n c.pos++; // skip [\n skipWs(c);\n for (let j = 0; j < index; j++) {\n if (c.pos >= c.json.length || c.json[c.pos] === \"]\") return false;\n skipValue(c);\n skipWs(c);\n if (c.json[c.pos] === \",\") {\n c.pos++;\n skipWs(c);\n }\n }\n return true;\n}\n\nfunction findValueRange(\n json: string,\n tokens: string[],\n): { from: number; to: number } | null {\n const c: Cursor = { pos: 0, json };\n\n for (const token of tokens) {\n skipWs(c);\n if (c.json[c.pos] === \"{\") {\n if (!navigateObject(c, token)) return null;\n } else if (c.json[c.pos] === \"[\") {\n const index = parseInt(token, 10);\n if (isNaN(index) || !navigateArray(c, index)) return null;\n } else {\n return null;\n }\n }\n\n skipWs(c);\n const from = c.pos;\n const to = skipValue(c);\n return { from, to };\n}\n\n/**\n * Resolve a list of JSON Pointers to character offset ranges.\n *\n * @param json - The formatted JSON string\n * @param pointers - Array of JSON Pointer strings (e.g. \"/metadata\", \"/definitions/Patient\")\n * @returns Array of resolved ranges sorted by position (unresolvable pointers are silently skipped)\n */\nexport function resolvePointerRanges(\n json: string,\n pointers: string[],\n): OffsetRange[] {\n const ranges: OffsetRange[] = [];\n\n for (const pointer of pointers) {\n const tokens = parsePointer(pointer);\n const range = findValueRange(json, tokens);\n if (range) {\n ranges.push({ pointer, from: range.from, to: range.to });\n }\n }\n\n // Sort by position so consumers can walk ranges in document order\n ranges.sort((a, b) => a.from - b.from);\n return ranges;\n}\n","/**\n * Pagination types for paginated list responses.\n *\n * Generic shapes with no application-specific content.\n * Extractable to @petrarca/sonnet-core: no app-specific imports.\n */\n\n/** Pagination metadata included in paginated list responses. */\nexport interface PageMeta {\n total: number;\n limit: number;\n offset: number;\n has_next: boolean;\n has_prev: boolean;\n}\n\n/** Paginated list response envelope. */\nexport interface PageResult<T> {\n data: T[];\n meta: PageMeta;\n}\n\n/**\n * Wrap a full array as a single-page PageResult.\n *\n * Bridges \"regular\" (un-paginated) list APIs that return a bare array into the\n * PageResult envelope that paginated consumers (e.g. EntityTable) expect. The\n * whole array is treated as one complete page: total = length, offset = 0, and\n * no next/prev page. Use for small lists served without server-side pagination.\n */\nexport function toPageResult<T>(rows: T[]): PageResult<T> {\n return {\n data: rows,\n meta: {\n total: rows.length,\n limit: rows.length,\n offset: 0,\n has_next: false,\n has_prev: false,\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/format.ts","../src/dateParser.ts","../src/timeParser.ts","../src/localeFormat.ts","../src/jsonUtils.ts","../src/utils/copyTextToClipboard.tsx","../src/utils/snakeCaseToTitleCase.ts","../src/errorNormalizer.ts","../src/compose-refs.ts","../src/resolvePointerRanges.ts","../src/pagination.ts"],"sourcesContent":["// Reusable formatting utilities.\n// Thin wrappers around Intl for consistent output across the app.\n\nconst numberFormatter = new Intl.NumberFormat(undefined, {\n maximumFractionDigits: 0,\n});\n\nexport function formatNumber(\n value: number | string | undefined | null,\n): string {\n if (value === null || value === undefined) return \"0\";\n const num = typeof value === \"string\" ? Number(value) : value;\n if (!Number.isFinite(num)) return String(value);\n return numberFormatter.format(num as number);\n}\n\nexport function formatNumberCompact(\n value: number | string | undefined | null,\n): string {\n if (value === null || value === undefined) return \"0\";\n const num = typeof value === \"string\" ? Number(value) : value;\n if (!Number.isFinite(num)) return String(value);\n return new Intl.NumberFormat(undefined, {\n notation: \"compact\",\n maximumFractionDigits: 1,\n }).format(num as number);\n}\n\n/** Format an ISO 8601 string as a short date (e.g. \"Jan 15, 2026\"). */\nexport function formatDate(iso: string | null | undefined): string {\n if (!iso) return \"\\u2014\";\n return new Date(iso).toLocaleDateString(undefined, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Format an ISO 8601 string as date + time (e.g. \"Jan 15, 2026, 09:32 AM\"). */\nexport function formatDateTime(iso: string | null | undefined): string {\n if (!iso) return \"\\u2014\";\n return new Date(iso).toLocaleString(undefined, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n/**\n * Format a timezone-aware ISO 8601 string preserving the original offset.\n *\n * Parses the date/time components and offset directly from the string so\n * the emitter's local time and offset are shown exactly as recorded --\n * independent of the viewer's timezone.\n *\n * Examples:\n * \"2026-02-22T10:00:00+01:00\" -> \"22 Feb 2026 at 10:00 +01:00\"\n * \"2026-02-22T09:00:00Z\" -> \"22 Feb 2026 at 09:00 UTC\"\n */\nexport function formatDateTimeTz(iso: string | null | undefined): string {\n if (!iso) return \"\\u2014\";\n\n // Match ISO 8601: date, time (HH:MM), optional seconds, offset or Z.\n const match = iso.match(\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$/,\n );\n if (!match) return iso;\n\n const [, year, month, day, hour, minute, rawOffset] = match;\n\n const months = [\n \"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\",\n ];\n const monthName = months[parseInt(month, 10) - 1];\n const offset = rawOffset === \"Z\" ? \"UTC\" : rawOffset;\n\n return `${parseInt(day, 10)} ${monthName} ${year} at ${hour}:${minute} ${offset}`;\n}\n\n/** Return \"{count} {word}\" with the word pluralized when count != 1. */\nexport function pluralize(count: number, word: string): string {\n return `${count} ${word}${count !== 1 ? \"s\" : \"\"}`;\n}\n","/**\n * Date parsing and formatting -- pure functional API.\n *\n * The public surface is a set of pure functions. A `CompiledDateFormat`\n * pre-computes the format structure so repeated parse/format calls (e.g.\n * on every keystroke) don't re-derive component positions each time. Call\n * `compileDateFormat` once in a `useMemo` and pass the result to\n * `parseDate` / `formatDateInput`.\n *\n * The parser operates on native `Date` values internally. Widgets and form\n * data exchange locale-independent ISO 8601 strings -- use\n * `formatIsoDate` / `parseIsoDate` at the boundary.\n */\n\n// ---- Types ------------------------------------------------------------------\n\n/**\n * Pre-compiled date format. Opaque to callers; produced by\n * {@link compileDateFormat} and consumed by {@link parseDate} and\n * {@link formatDateInput}.\n */\nexport interface CompiledDateFormat {\n readonly format: string;\n readonly yearThreshold: number;\n readonly dayIndex: number;\n readonly monthIndex: number;\n readonly yearIndex: number;\n readonly has2DigitYear: boolean;\n readonly validSeparators: readonly string[];\n}\n\n/** Options for {@link compileDateFormat}. */\nexport interface DateFormatOptions {\n /**\n * Component order for parsing and display. Supported tokens: `DD` (day),\n * `MM` (month), `YYYY` or `YY` (year). Default: `\"DD/MM/YYYY\"`.\n */\n format?: string;\n\n /**\n * Threshold for expanding 2-digit years. If a 2-digit year is greater than\n * this value it is treated as the prior century, otherwise the current one.\n * Special cases: `0` always current century, `-1` always prior century.\n * Default: the current year modulo 100, captured at compile time.\n */\n yearThreshold?: number;\n}\n\n/** Result of {@link parseDate}. */\nexport interface DateParseResult {\n /** Normalized display string (formatted per the compiled format), or \"\" on failure. */\n value: string;\n /** Parsed `Date` object, or null on failure. Needed by calendar components. */\n date: Date | null;\n /** Error message on failure, or \"\" on success. */\n error: string;\n}\n\n/**\n * Precision of a partial ISO 8601 date:\n * year -> \"YYYY\"\n * month -> \"YYYY-MM\"\n * day -> \"YYYY-MM-DD\"\n */\nexport type DatePrecision = \"year\" | \"month\" | \"day\";\n\n// ---- Compilation ------------------------------------------------------------\n\nconst VALID_SEPARATORS = [\"/\", \"-\", \".\"] as const;\n\n/**\n * Pre-compile a date format string into an opaque `CompiledDateFormat`.\n *\n * Call once per format string (e.g. in `useMemo`) and pass the result to\n * {@link parseDate} and {@link formatDateInput}.\n */\nexport function compileDateFormat(\n options: DateFormatOptions = {},\n): CompiledDateFormat {\n const format = options.format ?? \"DD/MM/YYYY\";\n const yearThreshold = options.yearThreshold ?? new Date().getFullYear() % 100;\n\n const parts = format.split(/[^A-Z]+/);\n const dayIndex = parts.findIndex((p) => p === \"DD\");\n const monthIndex = parts.findIndex((p) => p === \"MM\");\n const yearIndex = parts.findIndex((p) => p === \"YYYY\" || p === \"YY\");\n const has2DigitYear = yearIndex !== -1 && parts[yearIndex] === \"YY\";\n\n if (dayIndex === -1 && monthIndex === -1 && yearIndex === -1) {\n throw new Error(\n \"Invalid date format. Must contain at least one of DD, MM, or YYYY/YY.\",\n );\n }\n\n return {\n format,\n yearThreshold,\n dayIndex,\n monthIndex,\n yearIndex,\n has2DigitYear,\n validSeparators: VALID_SEPARATORS,\n };\n}\n\n// ---- Parsing ----------------------------------------------------------------\n\n// Strip characters that are not digits, separators, or sign markers.\nfunction cleanInput(input: string, fmt: CompiledDateFormat): string {\n return input.replace(\n new RegExp(\n `[^0-9${fmt.validSeparators.map((s) => \"\\\\\" + s).join(\"\")}+-]`,\n \"g\",\n ),\n \"\",\n );\n}\n\n// Expand a year string, using the century captured at compile time.\nfunction expandYear(yearStr: string, fmt: CompiledDateFormat): number {\n const year = parseInt(yearStr, 10);\n if (yearStr.length >= 4) return year;\n\n // Century is derived from the yearThreshold captured at compileDateFormat\n // time, so both year and century use the same reference point.\n const refYear =\n fmt.yearThreshold + Math.floor(new Date().getFullYear() / 100) * 100;\n const century = Math.floor(refYear / 100) * 100;\n\n if (fmt.yearThreshold === 0) return century + year;\n if (fmt.yearThreshold === -1) return century - 100 + year;\n return year > fmt.yearThreshold ? century - 100 + year : century + year;\n}\n\n// Parse colon/separator-split input assigning parts by component position.\nfunction parseWithSeparators(\n input: string,\n fmt: CompiledDateFormat,\n): { day: number | null; month: number | null; year: number | null } {\n const parts = input.split(\n new RegExp(`[${fmt.validSeparators.map((s) => \"\\\\\" + s).join(\"\")}]`),\n );\n const result = {\n day: null as number | null,\n month: null as number | null,\n year: null as number | null,\n };\n for (let i = 0; i < parts.length; i++) {\n if (!parts[i]) continue;\n if (i === fmt.dayIndex) result.day = parseInt(parts[i], 10);\n else if (i === fmt.monthIndex) result.month = parseInt(parts[i], 10);\n else if (i === fmt.yearIndex) result.year = expandYear(parts[i], fmt);\n }\n return result;\n}\n\n// Parse no-separator input by slicing fixed-width components in format order.\nfunction parseWithoutSeparators(\n input: string,\n fmt: CompiledDateFormat,\n): { day: number | null; month: number | null; year: number | null } {\n const result = {\n day: null as number | null,\n month: null as number | null,\n year: null as number | null,\n };\n const yearLength = fmt.has2DigitYear ? 2 : 4;\n const components = [\n { type: \"day\", index: fmt.dayIndex, length: 2 },\n { type: \"month\", index: fmt.monthIndex, length: 2 },\n { type: \"year\", index: fmt.yearIndex, length: yearLength },\n ]\n .filter((c) => c.index !== -1)\n .sort((a, b) => a.index - b.index);\n\n let remaining = input;\n for (const c of components) {\n if (!remaining.length) break;\n const len = Math.min(c.length, remaining.length);\n const val = remaining.substring(0, len);\n remaining = remaining.substring(len);\n if (c.type === \"day\") result.day = parseInt(val, 10);\n else if (c.type === \"month\") result.month = parseInt(val, 10);\n else if (c.type === \"year\") result.year = expandYear(val, fmt);\n }\n return result;\n}\n\n// Number of days in the given 1-based month, accounting for leap years.\nfunction daysInMonth(month: number, year: number): number {\n if (month === 2) {\n const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n return leap ? 29 : 28;\n }\n return [4, 6, 9, 11].includes(month) ? 30 : 31;\n}\n\nfunction isValidDate(day: number, month: number, year: number): boolean {\n if (month < 1 || month > 12) return false;\n if (year < 1900 || year > 2100) return false;\n if (day < 1 || day > daysInMonth(month, year)) return false;\n return true;\n}\n\n// Fill missing components from today, validate, and build the result.\nfunction buildDateResult(\n parsed: { day: number | null; month: number | null; year: number | null },\n fmt: CompiledDateFormat,\n): DateParseResult {\n const today = new Date();\n const day = parsed.day ?? today.getDate();\n const month = parsed.month ?? today.getMonth() + 1;\n const year = parsed.year ?? today.getFullYear();\n\n if (!isValidDate(day, month, year)) {\n return { value: \"\", date: null, error: \"Invalid date\" };\n }\n\n const date = new Date(year, month - 1, day);\n return { value: formatDateInput(date, fmt), date, error: \"\" };\n}\n\n/**\n * Parse a user-entered date string against a compiled format.\n *\n * Accepts colon/separator-split and compact numeric input. The shorthands\n * `\".\"`, `\"t\"`, and `\"today\"` resolve to the current date. Empty input\n * returns `{ value: \"\", date: null, error: \"\" }`.\n */\nexport function parseDate(\n input: string,\n fmt: CompiledDateFormat,\n): DateParseResult {\n if (!input || !input.trim()) return { value: \"\", date: null, error: \"\" };\n\n if ([\".\", \"t\", \"today\"].includes(input.trim().toLowerCase())) {\n const today = new Date();\n return { value: formatDateInput(today, fmt), date: today, error: \"\" };\n }\n\n const cleaned = cleanInput(input, fmt);\n if (!cleaned) {\n return { value: \"\", date: null, error: \"Invalid characters in date\" };\n }\n\n const hasSeparators = fmt.validSeparators.some((s) => cleaned.includes(s));\n\n try {\n const parsed = hasSeparators\n ? parseWithSeparators(cleaned, fmt)\n : parseWithoutSeparators(cleaned, fmt);\n return buildDateResult(parsed, fmt);\n } catch (e) {\n return {\n value: \"\",\n date: null,\n error: e instanceof Error ? e.message : \"Invalid date format\",\n };\n }\n}\n\n// ---- Formatting -------------------------------------------------------------\n\n/**\n * Format a `Date` as a display string using the compiled format.\n * Returns \"\" for null or invalid dates.\n */\nexport function formatDateInput(\n date: Date | null | undefined,\n fmt: CompiledDateFormat,\n): string {\n if (!date || isNaN(date.getTime())) return \"\";\n const tokens: Record<string, string> = {\n DD: date.getDate().toString().padStart(2, \"0\"),\n MM: (date.getMonth() + 1).toString().padStart(2, \"0\"),\n YYYY: date.getFullYear().toString(),\n YY: date.getFullYear().toString().slice(-2),\n };\n return fmt.format.replace(/DD|MM|YYYY|YY/g, (m) => tokens[m]);\n}\n\n/** Whether two dates fall on the same calendar day. */\nexport function isDateEqual(a: Date | null, b: Date | null): boolean {\n if (!a || !b) return false;\n return (\n a.getDate() === b.getDate() &&\n a.getMonth() === b.getMonth() &&\n a.getFullYear() === b.getFullYear()\n );\n}\n\n// ---- ISO boundary helpers ---------------------------------------------------\n\n/**\n * Convert a local `Date` to a partial ISO date string at the given precision\n * (default `\"day\"`), using local components (no timezone shift).\n * Returns \"\" for null or invalid dates.\n */\nexport function formatIsoDate(\n date: Date | null | undefined,\n precision: DatePrecision = \"day\",\n): string {\n if (!date || isNaN(date.getTime())) return \"\";\n const year = date.getFullYear().toString().padStart(4, \"0\");\n if (precision === \"year\") return year;\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n if (precision === \"month\") return `${year}-${month}`;\n const day = date.getDate().toString().padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\n/**\n * Parse a partial ISO date string (`YYYY`, `YYYY-MM`, or `YYYY-MM-DD`) into a\n * local `Date`. Missing month/day default to January/1st. Returns null for\n * empty or malformed input.\n */\nexport function parseIsoDate(iso: string | null | undefined): Date | null {\n if (!iso) return null;\n const match = iso.match(/^(\\d{4})(?:-(\\d{2})(?:-(\\d{2}))?)?$/);\n if (!match) return null;\n const [, year, month, day] = match;\n const date = new Date(\n Number(year),\n month ? Number(month) - 1 : 0,\n day ? Number(day) : 1,\n );\n return isNaN(date.getTime()) ? null : date;\n}\n\n/**\n * Detect the precision of a partial ISO date string.\n * Returns `\"day\"` for empty, malformed, or full-date input.\n */\nexport function isoDatePrecision(\n iso: string | null | undefined,\n): DatePrecision {\n if (!iso) return \"day\";\n if (/^\\d{4}$/.test(iso)) return \"year\";\n if (/^\\d{4}-\\d{2}$/.test(iso)) return \"month\";\n return \"day\";\n}\n","/**\n * Time parsing and formatting -- pure functional API.\n *\n * A time-of-day is a zone-free wall-clock value (Temporal.PlainTime): it\n * carries no date and no timezone. Values are normalized ISO time strings:\n * `\"HH:mm\"` (minute granularity) or `\"HH:mm:ss\"` (second granularity).\n *\n * API conventions match dateParser.ts:\n * parseTime(input, granularity) -> TimeParseResult { value, error }\n * formatIsoTime(h, m, s, granularity) -> string\n * normalizeTime(iso, granularity) -> string\n * An empty or failed result is represented as `value: \"\"`, not null.\n */\n\n/** Granularity of a time value: minutes or seconds. */\nexport type TimeGranularity = \"minute\" | \"second\";\n\n/** Result of {@link parseTime}. */\nexport interface TimeParseResult {\n /** Normalized ISO time string, or \"\" when parsing failed or input is empty. */\n value: string;\n /** Error message on failure, or \"\" on success. */\n error: string;\n}\n\n// Split a numeric-only run (e.g. \"0930\", \"213005\") into H/M/S parts.\nfunction splitDigits(digits: string): number[] {\n if (digits.length <= 2) return [Number(digits)];\n if (digits.length <= 4) {\n return [\n Number(digits.slice(0, digits.length - 2)),\n Number(digits.slice(-2)),\n ];\n }\n return [\n Number(digits.slice(0, digits.length - 4)),\n Number(digits.slice(-4, -2)),\n Number(digits.slice(-2)),\n ];\n}\n\n// Extract [hour, minute, second] from a cleaned input string.\nfunction extractParts(input: string): number[] {\n if (input.includes(\":\")) {\n const parts = input.split(\":\");\n // Reject trailing colon or more than 3 segments.\n if (parts.length > 3 || parts[parts.length - 1] === \"\") {\n return [];\n }\n return parts.map((p) => Number(p));\n }\n return splitDigits(input);\n}\n\n// Whether the H/M/S components form a valid 24-hour time of day.\nfunction isValidTime(hour: number, minute: number, second: number): boolean {\n const inRange = (n: number, max: number): boolean =>\n Number.isInteger(n) && n >= 0 && n <= max;\n return inRange(hour, 23) && inRange(minute, 59) && inRange(second, 59);\n}\n\n/**\n * Format H/M/S integer components as a normalized ISO time string.\n * This is an internal building block; consumers typically use {@link normalizeTime}.\n */\nexport function formatIsoTime(\n hour: number,\n minute: number,\n second: number,\n granularity: TimeGranularity = \"minute\",\n): string {\n const hh = hour.toString().padStart(2, \"0\");\n const mm = minute.toString().padStart(2, \"0\");\n if (granularity === \"minute\") return `${hh}:${mm}`;\n const ss = second.toString().padStart(2, \"0\");\n return `${hh}:${mm}:${ss}`;\n}\n\n/**\n * Parse a user-entered time string into a normalized ISO time value.\n *\n * Accepts colon-separated (`\"9:30\"`, `\"21:05:00\"`) and compact numeric\n * (`\"0930\"`, `\"213005\"`) forms. Missing minutes/seconds default to zero.\n * The shorthands `\".\"`, `\"n\"`, and `\"now\"` resolve to the current time.\n * Empty input returns `{ value: \"\", error: \"\" }`.\n */\nexport function parseTime(\n input: string,\n granularity: TimeGranularity = \"minute\",\n): TimeParseResult {\n if (!input || !input.trim()) return { value: \"\", error: \"\" };\n\n // \".\", \"n\", and \"now\" are shorthand for the current time.\n if ([\".\", \"n\", \"now\"].includes(input.trim().toLowerCase())) {\n const now = new Date();\n return {\n value: formatIsoTime(\n now.getHours(),\n now.getMinutes(),\n now.getSeconds(),\n granularity,\n ),\n error: \"\",\n };\n }\n\n const cleaned = input.replace(/[^0-9:]/g, \"\");\n if (!cleaned) return { value: \"\", error: \"Invalid characters in time\" };\n\n return parseCleanedTime(cleaned, granularity);\n}\n\nfunction parseCleanedTime(\n cleaned: string,\n granularity: TimeGranularity,\n): TimeParseResult {\n const parts = extractParts(cleaned);\n if (!parts.length) return { value: \"\", error: \"Invalid time format\" };\n\n const hour = parts[0] ?? 0;\n const minute = parts[1] ?? 0;\n const second = parts[2] ?? 0;\n\n if (!isValidTime(hour, minute, second)) {\n return { value: \"\", error: \"Invalid time\" };\n }\n\n return { value: formatIsoTime(hour, minute, second, granularity), error: \"\" };\n}\n\n/**\n * Normalize an ISO time string (`\"HH:mm\"` or `\"HH:mm:ss\"`) to the requested\n * granularity. Returns \"\" for empty or malformed input.\n */\nexport function normalizeTime(\n iso: string | null | undefined,\n granularity: TimeGranularity = \"minute\",\n): string {\n if (!iso) return \"\";\n return parseTime(iso, granularity).value;\n}\n\n/**\n * Split a plain wall-clock datetime (`\"YYYY-MM-DDTHH:mm[:ss]\"`) into its date\n * (`\"YYYY-MM-DD\"`) and time (`\"HH:mm[:ss]\"`) halves. Missing halves return \"\".\n */\nexport function splitDateTime(iso: string | null | undefined): {\n date: string;\n time: string;\n} {\n if (!iso) return { date: \"\", time: \"\" };\n const [date, time] = iso.split(\"T\");\n return { date: date ?? \"\", time: time ?? \"\" };\n}\n\n/**\n * Join a date (`\"YYYY-MM-DD\"`) and time (`\"HH:mm[:ss]\"`) into a plain\n * wall-clock datetime. Returns \"\" when the date is missing; a missing time\n * yields the date alone.\n */\nexport function joinDateTime(date: string, time: string): string {\n if (!date) return \"\";\n return time ? `${date}T${time}` : date;\n}\n","/**\n * Locale-derived date formatting metadata.\n *\n * Uses the Intl APIs (no dependency) to derive, for a BCP-47 locale:\n * - the day/month/year order and separator, as a DateParser format string\n * - localized short weekday labels\n * - the first day of the week (0 = Sunday .. 6 = Saturday)\n *\n * These drive display and input parsing only; exchanged values stay ISO.\n */\n\nimport type { DatePrecision } from \"./dateParser\";\n\n/** DateParser format string per precision, derived for a locale. */\nexport interface LocaleDateFormats {\n year: string;\n month: string;\n day: string;\n}\n\n// Build the day-precision format (e.g. \"MM/DD/YYYY\") from Intl parts.\nfunction dayFormatFromParts(locale: string): string {\n const parts = new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).formatToParts(new Date(2023, 0, 2));\n\n const tokens: string[] = [];\n let separator = \"/\";\n for (const part of parts) {\n if (part.type === \"day\") tokens.push(\"DD\");\n else if (part.type === \"month\") tokens.push(\"MM\");\n else if (part.type === \"year\") tokens.push(\"YYYY\");\n else if (part.type === \"literal\") {\n // First non-space literal is the field separator.\n const trimmed = part.value.trim();\n if (trimmed) separator = trimmed[0];\n }\n }\n\n if (tokens.length !== 3) return \"DD/MM/YYYY\";\n return tokens.join(separator);\n}\n\n/** Derive DateParser format strings for each precision in the given locale. */\nexport function getLocaleDateFormats(locale: string): LocaleDateFormats {\n const day = dayFormatFromParts(locale);\n // Month precision drops the day token and its trailing separator.\n const month = day.replace(/DD.|.DD/, \"\");\n return { year: \"YYYY\", month, day };\n}\n\n/** Derive the DateParser format for a single precision in the given locale. */\nexport function getLocaleDateFormat(\n locale: string,\n precision: DatePrecision,\n): string {\n return getLocaleDateFormats(locale)[precision];\n}\n\n/**\n * Localized short weekday labels ordered from the locale's first day of week.\n * Returns 7 entries, e.g. `[\"Mon\",\"Tue\",...]` or `[\"Sun\",\"Mon\",...]`.\n */\nexport function getWeekdayLabels(locale: string): string[] {\n const first = getFirstDayOfWeek(locale);\n const formatter = new Intl.DateTimeFormat(locale, { weekday: \"short\" });\n // 2023-01-01 is a Sunday; offset by the locale's first day.\n return Array.from({ length: 7 }, (_, i) =>\n formatter.format(new Date(2023, 0, 1 + ((first + i) % 7))),\n );\n}\n\n// Intl.Locale week info is not yet in the TS lib types; describe the shape we\n// read. Both the getWeekInfo() method and the weekInfo property exist across\n// engines.\ninterface WeekInfo {\n firstDay?: number;\n}\ninterface LocaleWithWeekInfo {\n getWeekInfo?: () => WeekInfo;\n weekInfo?: WeekInfo;\n}\n\n/** First day of the week for the locale: 0 = Sunday .. 6 = Saturday. */\nexport function getFirstDayOfWeek(locale: string): number {\n try {\n const loc = new Intl.Locale(locale) as unknown as LocaleWithWeekInfo;\n const info = loc.getWeekInfo?.() ?? loc.weekInfo;\n if (info?.firstDay !== undefined) {\n // Intl weekInfo uses 1 = Monday .. 7 = Sunday; map to 0 = Sunday.\n return info.firstDay === 7 ? 0 : info.firstDay;\n }\n } catch {\n // Fall through to default when Intl.Locale/weekInfo is unavailable.\n }\n return 1; // Monday is the most common global default.\n}\n","/**\n * Escapes HTML characters to prevent XSS and rendering issues\n */\nexport function escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n\n/**\n * Formats a JSON value into colored HTML with proper syntax highlighting\n * @param value - The value to format (any JSON-serializable type)\n * @param indent - Current indentation level for nested objects/arrays\n * @returns HTML string with syntax highlighting\n */\nfunction jsonSpan(cssVar: string, content: string): string {\n return `<span style=\"color: var(${cssVar})\">${content}</span>`;\n}\n\nfunction formatPrimitive(value: unknown): string | null {\n if (value === null) return jsonSpan(\"--json-null\", \"null\");\n if (typeof value === \"undefined\") return jsonSpan(\"--json-null\", \"undefined\");\n if (typeof value === \"boolean\")\n return jsonSpan(\"--json-boolean\", String(value));\n if (typeof value === \"number\")\n return jsonSpan(\"--json-number\", String(value));\n if (typeof value === \"string\")\n return jsonSpan(\"--json-string\", `\"${escapeHtml(value)}\"`);\n return null;\n}\n\nfunction formatArray(value: unknown[], indent: number): string {\n if (value.length === 0) return jsonSpan(\"--json-punctuation\", \"[]\");\n const indentStr = \" \".repeat(indent);\n const items = value\n .map((item) => `${indentStr} ${formatJsonValue(item, indent + 1)}`)\n .join(\",\\n\");\n return `${jsonSpan(\"--json-punctuation\", \"[\")}\\n${items}\\n${indentStr}${jsonSpan(\"--json-punctuation\", \"]\")}`;\n}\n\nfunction formatObject(value: object, indent: number): string {\n const entries = Object.entries(value);\n if (entries.length === 0) return jsonSpan(\"--json-punctuation\", \"{}\");\n const indentStr = \" \".repeat(indent);\n const items = entries\n .map(\n ([key, val]) =>\n `${indentStr} ${jsonSpan(\"--json-key\", `\"${escapeHtml(key)}\"`)}${jsonSpan(\"--json-punctuation\", \":\")} ${formatJsonValue(val, indent + 1)}`,\n )\n .join(\",\\n\");\n return `${jsonSpan(\"--json-punctuation\", \"{\")}\\n${items}\\n${indentStr}${jsonSpan(\"--json-punctuation\", \"}\")}`;\n}\n\nexport function formatJsonValue(value: unknown, indent = 0): string {\n const primitive = formatPrimitive(value);\n if (primitive !== null) return primitive;\n if (Array.isArray(value)) return formatArray(value, indent);\n if (typeof value === \"object\" && value !== null)\n return formatObject(value, indent);\n return jsonSpan(\"--json-fallback\", escapeHtml(String(value)));\n}\n\n/**\n * CSS custom properties for JSON syntax highlighting colors\n */\nexport const JSON_CSS_VARIABLES = {\n \"--json-key\": \"#2563eb\",\n \"--json-string\": \"#16a34a\",\n \"--json-number\": \"#ea580c\",\n \"--json-boolean\": \"#2563eb\",\n \"--json-null\": \"#64748b\",\n \"--json-punctuation\": \"#475569\",\n \"--json-fallback\": \"#6b7280\",\n} as const;\n","/**\n * Copy text to the system clipboard.\n *\n * Optionally calls `onSuccess` after a successful write. The caller\n * provides its own notification mechanism (e.g. `notification.success`\n * from the shell API) to keep this utility free of sonner or any other\n * toast dependency.\n */\nexport async function copyTextToClipboard(\n text: string,\n options?: { onSuccess?: (message: string) => void },\n): Promise<void> {\n await navigator.clipboard.writeText(text);\n options?.onSuccess?.(`${text} copied to clipboard`);\n}\n","function snakeCaseToTitleCase(snakeCase: string): string {\n const words = snakeCase.split(\"_\");\n const titleCaseWords = words.map(\n (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n );\n return titleCaseWords.join(\" \");\n}\n\nexport default snakeCaseToTitleCase;\n","/**\n * Error normalizer -- extract typed error info from any thrown value.\n *\n * Generic utility with no framework dependencies. Handles standard\n * Error objects and Axios-shaped error responses via duck-typing\n * (no axios import required).\n */\n\nexport interface NormalizedError {\n message: string;\n status?: number;\n details?: string[];\n}\n\n/**\n * Normalize any thrown value into a structured error object.\n *\n * Handles:\n * - Axios-shaped errors (duck-typed via `isAxiosError` property)\n * - Standard Error objects\n * - Arbitrary values (stringified)\n */\n// Extract validation detail messages from a FastAPI-style detail array.\nfunction extractDetailMessages(detail: unknown[]): string[] {\n const msgs: string[] = [];\n for (const item of detail) {\n if (\n item &&\n typeof item === \"object\" &&\n typeof (item as Record<string, unknown>).msg === \"string\"\n ) {\n msgs.push((item as Record<string, unknown>).msg as string);\n }\n }\n return msgs;\n}\n\n// Extract message and details from an Axios-like response data payload.\nfunction extractFromResponseData(\n data: unknown,\n fallback: string,\n): { message: string; details: string[] } {\n if (typeof data === \"string\") return { message: data, details: [] };\n if (typeof data !== \"object\" || data === null)\n return { message: fallback, details: [] };\n\n const d = data as Record<string, unknown>;\n if (typeof d.detail === \"string\") return { message: d.detail, details: [] };\n if (Array.isArray(d.detail)) {\n const details = extractDetailMessages(d.detail);\n return { message: details.length ? details.join(\"; \") : fallback, details };\n }\n if (typeof d.error === \"string\") return { message: d.error, details: [] };\n return { message: fallback, details: [] };\n}\n\n// Normalize an Axios-like error into a structured error object.\nfunction normalizeAxiosError(err: AxiosLikeError): NormalizedError {\n const status = err.response?.status;\n const { message, details } = extractFromResponseData(\n err.response?.data,\n err.message,\n );\n return { message, status, details: details.length ? details : undefined };\n}\n\nexport function normalizeError(err: unknown): NormalizedError {\n if (isAxiosLikeError(err)) return normalizeAxiosError(err);\n if (err instanceof Error) return { message: err.message };\n return { message: String(err) };\n}\n\n// Duck-type check for Axios-like errors.\ninterface AxiosLikeError {\n isAxiosError: true;\n message: string;\n response?: {\n status?: number;\n data?: unknown;\n };\n}\n\nfunction isAxiosLikeError(err: unknown): err is AxiosLikeError {\n return (\n err !== null &&\n typeof err === \"object\" &&\n \"isAxiosError\" in err &&\n (err as Record<string, unknown>).isAxiosError === true\n );\n}\n","import * as React from \"react\";\n\ntype PossibleRef<T> = React.Ref<T> | undefined;\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === \"function\") {\n return ref(value);\n }\n\n if (ref !== null && ref !== undefined) {\n ref.current = value;\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false;\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node);\n if (!hasCleanup && typeof cleanup === \"function\") {\n hasCleanup = true;\n }\n return cleanup;\n });\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i];\n if (typeof cleanup === \"function\") {\n cleanup();\n } else {\n setRef(refs[i], null);\n }\n }\n };\n }\n };\n}\n\n/**\n * A custom hook that composes multiple refs.\n * Accepts callback refs and RefObject(s).\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // Store the latest refs in a mutable ref so the stable callback always\n // sees the current values without needing a dynamic dependency array.\n const refsRef = React.useRef(refs);\n React.useEffect(() => {\n refsRef.current = refs;\n });\n\n return React.useCallback((node: T) => {\n composeRefs(...refsRef.current)(node);\n }, []);\n}\n\nexport { composeRefs, useComposedRefs };\n","/**\n * Resolve JSON Pointer (RFC 6901) paths to character offset ranges\n * within a formatted JSON string.\n *\n * Given a JSON string and a list of JSON Pointers, returns the\n * [from, to] byte ranges covering the *value* of each pointer.\n * The range includes the full value (object braces, array brackets,\n * string quotes, nested content) so the user can freely edit\n * everything inside.\n *\n * Zero external dependencies — pure TypeScript.\n * Maps to @petrarca/sonnet-core on extraction.\n */\n\nexport interface OffsetRange {\n /** JSON Pointer that was resolved */\n pointer: string;\n /** Start character offset (inclusive) */\n from: number;\n /** End character offset (exclusive) */\n to: number;\n}\n\n/**\n * Unescape a JSON Pointer token per RFC 6901:\n * ~1 -> /\n * ~0 -> ~\n */\nfunction unescapeToken(token: string): string {\n return token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\n\n/**\n * Parse a JSON Pointer string into an array of unescaped tokens.\n * \"\" returns [] (root document, per RFC 6901)\n * \"/\" returns [] (sentinel for \"entire document\" -- treated as root)\n * \"/a/b\" returns [\"a\", \"b\"]\n */\nfunction parsePointer(pointer: string): string[] {\n if (pointer === \"\" || pointer === \"/\") return [];\n if (!pointer.startsWith(\"/\")) {\n throw new Error(`Invalid JSON Pointer: \"${pointer}\" (must start with /)`);\n }\n return pointer.slice(1).split(\"/\").map(unescapeToken);\n}\n\n/**\n * Find the character offset range of a value at the given path\n * within a JSON string. Walks the string character by character\n * to find the key, then captures the full value range.\n */\n/** Mutable cursor for walking a JSON string character by character. */\ninterface Cursor {\n pos: number;\n json: string;\n}\n\nfunction skipWs(c: Cursor): void {\n while (c.pos < c.json.length && /\\s/.test(c.json[c.pos])) c.pos++;\n}\n\nfunction skipString(c: Cursor): number {\n c.pos++; // skip opening \"\n while (c.pos < c.json.length) {\n if (c.json[c.pos] === \"\\\\\") {\n c.pos += 2;\n continue;\n }\n if (c.json[c.pos] === '\"') {\n c.pos++;\n return c.pos;\n }\n c.pos++;\n }\n return c.pos;\n}\n\nfunction skipContainer(c: Cursor, open: string, close: string): number {\n c.pos++; // skip opening bracket\n skipWs(c);\n if (c.json[c.pos] === close) {\n c.pos++;\n return c.pos;\n }\n while (c.pos < c.json.length) {\n if (open === \"{\") {\n skipValue(c); // key\n skipWs(c);\n if (c.json[c.pos] === \":\") c.pos++;\n }\n skipValue(c);\n skipWs(c);\n if (c.json[c.pos] === \",\") {\n c.pos++;\n skipWs(c);\n continue;\n }\n if (c.json[c.pos] === close) {\n c.pos++;\n return c.pos;\n }\n break;\n }\n return c.pos;\n}\n\nfunction skipValue(c: Cursor): number {\n skipWs(c);\n if (c.pos >= c.json.length) return c.pos;\n const ch = c.json[c.pos];\n if (ch === '\"') return skipString(c);\n if (ch === \"{\") return skipContainer(c, \"{\", \"}\");\n if (ch === \"[\") return skipContainer(c, \"[\", \"]\");\n // Number, bool, null -- consume until delimiter\n while (c.pos < c.json.length && !/[,\\]}\\s]/.test(c.json[c.pos])) c.pos++;\n return c.pos;\n}\n\n/** Read and return the next JSON string key, advancing past the closing quote. */\nfunction readKey(c: Cursor): string {\n const keyStart = c.pos + 1;\n c.pos++;\n while (c.pos < c.json.length) {\n if (c.json[c.pos] === \"\\\\\") {\n c.pos += 2;\n continue;\n }\n if (c.json[c.pos] === '\"') break;\n c.pos++;\n }\n const key = c.json.slice(keyStart, c.pos);\n c.pos++; // skip closing \"\n return key;\n}\n\n/** Navigate into a JSON object to the value at `token`. */\nfunction navigateObject(c: Cursor, token: string): boolean {\n c.pos++; // skip {\n skipWs(c);\n while (c.pos < c.json.length && c.json[c.pos] !== \"}\") {\n if (c.json[c.pos] !== '\"') return false;\n const key = readKey(c);\n skipWs(c);\n if (c.json[c.pos] === \":\") c.pos++;\n skipWs(c);\n if (key === token) return true;\n skipValue(c);\n skipWs(c);\n if (c.json[c.pos] === \",\") {\n c.pos++;\n skipWs(c);\n }\n }\n return false;\n}\n\n/** Navigate into a JSON array to the element at `index`. */\nfunction navigateArray(c: Cursor, index: number): boolean {\n c.pos++; // skip [\n skipWs(c);\n for (let j = 0; j < index; j++) {\n if (c.pos >= c.json.length || c.json[c.pos] === \"]\") return false;\n skipValue(c);\n skipWs(c);\n if (c.json[c.pos] === \",\") {\n c.pos++;\n skipWs(c);\n }\n }\n return true;\n}\n\nfunction findValueRange(\n json: string,\n tokens: string[],\n): { from: number; to: number } | null {\n const c: Cursor = { pos: 0, json };\n\n for (const token of tokens) {\n skipWs(c);\n if (c.json[c.pos] === \"{\") {\n if (!navigateObject(c, token)) return null;\n } else if (c.json[c.pos] === \"[\") {\n const index = parseInt(token, 10);\n if (isNaN(index) || !navigateArray(c, index)) return null;\n } else {\n return null;\n }\n }\n\n skipWs(c);\n const from = c.pos;\n const to = skipValue(c);\n return { from, to };\n}\n\n/**\n * Resolve a list of JSON Pointers to character offset ranges.\n *\n * @param json - The formatted JSON string\n * @param pointers - Array of JSON Pointer strings (e.g. \"/metadata\", \"/definitions/Patient\")\n * @returns Array of resolved ranges sorted by position (unresolvable pointers are silently skipped)\n */\nexport function resolvePointerRanges(\n json: string,\n pointers: string[],\n): OffsetRange[] {\n const ranges: OffsetRange[] = [];\n\n for (const pointer of pointers) {\n const tokens = parsePointer(pointer);\n const range = findValueRange(json, tokens);\n if (range) {\n ranges.push({ pointer, from: range.from, to: range.to });\n }\n }\n\n // Sort by position so consumers can walk ranges in document order\n ranges.sort((a, b) => a.from - b.from);\n return ranges;\n}\n","/**\n * Pagination types for paginated list responses.\n *\n * Generic shapes with no application-specific content.\n * Extractable to @petrarca/sonnet-core: no app-specific imports.\n */\n\n/** Pagination metadata included in paginated list responses. */\nexport interface PageMeta {\n total: number;\n limit: number;\n offset: number;\n has_next: boolean;\n has_prev: boolean;\n}\n\n/** Paginated list response envelope. */\nexport interface PageResult<T> {\n data: T[];\n meta: PageMeta;\n}\n\n/**\n * Wrap a full array as a single-page PageResult.\n *\n * Bridges \"regular\" (un-paginated) list APIs that return a bare array into the\n * PageResult envelope that paginated consumers (e.g. EntityTable) expect. The\n * whole array is treated as one complete page: total = length, offset = 0, and\n * no next/prev page. Use for small lists served without server-side pagination.\n */\nexport function toPageResult<T>(rows: T[]): PageResult<T> {\n return {\n data: rows,\n meta: {\n total: rows.length,\n limit: rows.length,\n offset: 0,\n has_next: false,\n has_prev: false,\n },\n };\n}\n"],"mappings":"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","names":[]}