@ic-reactor/candid 3.0.12-beta.0 → 3.0.14-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,104 @@
1
+ import {
2
+ ArgumentFieldType,
3
+ CompoundField,
4
+ FieldNode,
5
+ FieldByType,
6
+ PrimitiveField,
7
+ RecordField,
8
+ TupleField,
9
+ VariantField,
10
+ } from "./types"
11
+
12
+ /**
13
+ * Type guard for checking specific field types.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * function FieldInput({ field }: { field: Field }) {
18
+ * if (isFieldType(field, 'record')) {
19
+ * // field is now typed as RecordField
20
+ * return <RecordInput field={field} />
21
+ * }
22
+ * if (isFieldType(field, 'text')) {
23
+ * // field is now typed as TextField
24
+ * return <TextInput field={field} />
25
+ * }
26
+ * // ...
27
+ * }
28
+ * ```
29
+ */
30
+ export function isFieldType<T extends ArgumentFieldType>(
31
+ field: FieldNode,
32
+ type: T
33
+ ): field is FieldByType<T> {
34
+ return field.type === type
35
+ }
36
+
37
+ /** Check if a field is a compound type (contains other fields) */
38
+ export function isCompoundField(field: FieldNode): field is CompoundField {
39
+ return [
40
+ "record",
41
+ "variant",
42
+ "tuple",
43
+ "optional",
44
+ "vector",
45
+ "recursive",
46
+ ].includes(field.type)
47
+ }
48
+
49
+ /** Check if a field is a primitive type */
50
+ export function isPrimitiveField(field: FieldNode): field is PrimitiveField {
51
+ return ["principal", "number", "text", "boolean", "null"].includes(field.type)
52
+ }
53
+
54
+ /** Check if a field has children (for iteration) */
55
+ export function hasChildFields(
56
+ field: FieldNode
57
+ ): field is RecordField | VariantField | TupleField {
58
+ return "fields" in field && Array.isArray((field as RecordField).fields)
59
+ }
60
+
61
+ // ════════════════════════════════════════════════════════════════════════════
62
+ // Label Formatting Utilities
63
+ // ════════════════════════════════════════════════════════════════════════════
64
+
65
+ /**
66
+ * Format a raw Candid label into a human-readable display label.
67
+ * Handles common patterns like "__arg0", "_0_", "snake_case", etc.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * formatLabel("__arg0") // "Arg 0"
72
+ * formatLabel("_0_") // "Item 0"
73
+ * formatLabel("created_at") // "Created At"
74
+ * formatLabel("userAddress") // "User Address"
75
+ * ```
76
+ */
77
+ export function formatLabel(label: string): string {
78
+ // Handle argument labels: __arg0 -> Arg 0
79
+ if (label.startsWith("__arg")) {
80
+ const num = label.slice(5)
81
+ return `Arg ${num}`
82
+ }
83
+
84
+ // Handle tuple index labels: _0_ -> Item 0
85
+ if (/^_\d+_$/.test(label)) {
86
+ const num = label.slice(1, -1)
87
+ return `Item ${num}`
88
+ }
89
+
90
+ // Handle item labels for vectors: label_item -> Item
91
+ if (label.endsWith("_item")) {
92
+ return "Item"
93
+ }
94
+
95
+ // Convert snake_case or just clean up underscores
96
+ // and capitalize each word
97
+ return label
98
+ .replace(/^_+|_+$/g, "") // Remove leading/trailing underscores
99
+ .replace(/_/g, " ") // Replace underscores with spaces
100
+ .replace(/([a-z])([A-Z])/g, "$1 $2") // Add space before capitals (camelCase)
101
+ .split(" ")
102
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
103
+ .join(" ")
104
+ }