react-semaphor 0.1.177 → 0.1.179
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/chunks/{dashboard-controls-00cjSeD7.js → dashboard-controls-CeT5saB7.js} +8 -8
- package/dist/chunks/{dashboard-controls-C9IWIFfW.js → dashboard-controls-O2Vl2SaH.js} +204 -203
- package/dist/chunks/{dashboard-json--ke9XK9p.js → dashboard-json--jGkpREU.js} +1 -1
- package/dist/chunks/{dashboard-json-BDjl-3ej.js → dashboard-json-d1qZ8OYo.js} +1 -1
- package/dist/chunks/{edit-dashboard-visual-BBsC9feJ.js → edit-dashboard-visual-BsP87bZV.js} +2 -2
- package/dist/chunks/{edit-dashboard-visual-BroCdmtP.js → edit-dashboard-visual-ViDNkE8Q.js} +1 -1
- package/dist/chunks/{editor-action-buttons-JE9t84-4.js → editor-action-buttons-DseT424l.js} +1 -1
- package/dist/chunks/{editor-action-buttons-CHoiNw7F.js → editor-action-buttons-F4_UU-Mk.js} +2 -2
- package/dist/chunks/index-8Crk3ROJ.js +1 -0
- package/dist/chunks/index-B4EhQdS9.js +1857 -0
- package/dist/chunks/{index-CdfFCbJb.js → index-CFWw2cJ5.js} +228 -228
- package/dist/chunks/{index-DZjcALSv.js → index-v6ayK5K2.js} +19466 -21309
- package/dist/chunks/{resource-management-panel-DE8DnPSl.js → resource-management-panel-CApVr9Vd.js} +3 -3
- package/dist/chunks/{resource-management-panel-C96ElLa5.js → resource-management-panel-Cn1aOr6L.js} +1 -1
- package/dist/chunks/{schedule-dashboard-BFa0Uljc.js → schedule-dashboard-B4KUKLfW.js} +3 -3
- package/dist/chunks/{schedule-dashboard-CzU0ziLB.js → schedule-dashboard-vvFw8B1E.js} +1 -1
- package/dist/chunks/{use-role-aware-display-preferences-Rd1BhDG4.js → use-role-aware-display-preferences-Bxp6i8c7.js} +1 -1
- package/dist/chunks/{use-role-aware-display-preferences-Dovp_VmV.js → use-role-aware-display-preferences-C-N0-Iik.js} +1 -1
- package/dist/chunks/{use-visual-utils-Cnju2tnE.js → use-visual-utils-D19qzwzI.js} +1 -1
- package/dist/chunks/{use-visual-utils-BkRr5LoD.js → use-visual-utils-D9lMGeVv.js} +1 -1
- package/dist/dashboard/index.cjs +1 -1
- package/dist/dashboard/index.js +1 -1
- package/dist/format-utils/index.cjs +5 -0
- package/dist/format-utils/index.js +451 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +4 -4
- package/dist/surfboard/index.cjs +1 -1
- package/dist/surfboard/index.js +1 -1
- package/dist/types/format-utils.d.ts +375 -0
- package/package.json +14 -1
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
export declare interface AggregateExportConfig {
|
|
2
|
+
groupByColumns: GroupByField[];
|
|
3
|
+
pivotSchema: PivotColumnSchema[];
|
|
4
|
+
rowAggregates?: RowAggregate[];
|
|
5
|
+
includeSubtotals: boolean;
|
|
6
|
+
includeGrandTotal: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export declare interface AggregateRowData extends Record<string, unknown> {
|
|
10
|
+
isSubtotal?: boolean;
|
|
11
|
+
isGrandTotal?: boolean;
|
|
12
|
+
subtotalLevel?: string;
|
|
13
|
+
subtotalContext?: {
|
|
14
|
+
groupByValues?: Record<string, unknown>;
|
|
15
|
+
};
|
|
16
|
+
aggregate?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Convert a 2D array to CSV string
|
|
21
|
+
*/
|
|
22
|
+
export declare function arrayToCSV(rows: (string | number | null | undefined)[][], options?: Partial<CSVExportOptions>): string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Convert an array of values to a CSV row
|
|
26
|
+
*/
|
|
27
|
+
export declare function arrayToCSVRow(values: (string | number | null | undefined)[], delimiter?: string): string;
|
|
28
|
+
|
|
29
|
+
export declare interface ColorRange {
|
|
30
|
+
min: number;
|
|
31
|
+
max: number;
|
|
32
|
+
color: string;
|
|
33
|
+
applyTo: 'cell' | 'row';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export declare interface ColumnHeaderNode {
|
|
37
|
+
name: string;
|
|
38
|
+
level: number;
|
|
39
|
+
colspan: number;
|
|
40
|
+
children?: ColumnHeaderNode[];
|
|
41
|
+
columnKey?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare interface ColumnSettings {
|
|
45
|
+
type: 'none' | 'text' | 'number' | 'date' | 'badge' | 'link' | 'progress';
|
|
46
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
47
|
+
width?: number;
|
|
48
|
+
numberFormat?: {
|
|
49
|
+
style: 'decimal' | 'currency' | 'percent';
|
|
50
|
+
currency: string;
|
|
51
|
+
locale: string;
|
|
52
|
+
minimumFractionDigits: number;
|
|
53
|
+
maximumFractionDigits: number;
|
|
54
|
+
showDataBar?: boolean;
|
|
55
|
+
dataBarColor?: string;
|
|
56
|
+
dataBarMinValue?: number;
|
|
57
|
+
dataBarMaxValue?: number;
|
|
58
|
+
};
|
|
59
|
+
dateFormat?: {
|
|
60
|
+
format: string;
|
|
61
|
+
useCustomFormat: boolean;
|
|
62
|
+
customFormat: string;
|
|
63
|
+
useRelativeTime: boolean;
|
|
64
|
+
timezone?: string;
|
|
65
|
+
sourceTimezone?: string;
|
|
66
|
+
};
|
|
67
|
+
linkFormat?: {
|
|
68
|
+
urlTemplate: string;
|
|
69
|
+
labelType: 'value' | 'static' | 'column';
|
|
70
|
+
staticLabel?: string;
|
|
71
|
+
labelColumn?: string;
|
|
72
|
+
openInNewTab: boolean;
|
|
73
|
+
};
|
|
74
|
+
colorRanges?: ColorRange[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export declare type ColumnSettingsMap = Record<string, ColumnSettings>;
|
|
78
|
+
|
|
79
|
+
export declare interface ColumnSubtotalMeta {
|
|
80
|
+
columnKey: string;
|
|
81
|
+
label: string;
|
|
82
|
+
level: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export declare interface CSVExportOptions {
|
|
86
|
+
delimiter: ',' | ';' | '\t';
|
|
87
|
+
includeHeaders: boolean;
|
|
88
|
+
lineEnding: '\n' | '\r\n';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export declare interface DateFormatOptions {
|
|
92
|
+
/** date-fns format pattern (e.g., "MM/dd/yyyy") */
|
|
93
|
+
format: string;
|
|
94
|
+
/** Use custom format instead of preset */
|
|
95
|
+
useCustomFormat?: boolean;
|
|
96
|
+
/** Custom format pattern */
|
|
97
|
+
customFormat?: string;
|
|
98
|
+
/** Display timezone (e.g., "America/New_York") */
|
|
99
|
+
timezone?: string;
|
|
100
|
+
/** How to interpret source dates: 'auto' | 'UTC' | specific timezone */
|
|
101
|
+
sourceTimezone?: string;
|
|
102
|
+
/** Use relative time (e.g., "2 days ago") */
|
|
103
|
+
useRelativeTime?: boolean;
|
|
104
|
+
/** Locale for date formatting */
|
|
105
|
+
locale?: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Escape a value for CSV output (RFC 4180 compliant)
|
|
110
|
+
* Wraps in quotes if value contains delimiter, quotes, or newlines
|
|
111
|
+
*/
|
|
112
|
+
export declare function escapeCSVValue(value: string | number | null | undefined, delimiter?: string): string;
|
|
113
|
+
|
|
114
|
+
export declare interface ExportFormattingConfig {
|
|
115
|
+
/** Whether to apply formatting or export raw values */
|
|
116
|
+
useFormattedValues: boolean;
|
|
117
|
+
/** User's timezone for date formatting (REQUIRED for Lambda) */
|
|
118
|
+
timezone: string;
|
|
119
|
+
/** Locale for number/date formatting */
|
|
120
|
+
locale: string;
|
|
121
|
+
/** CSV delimiter */
|
|
122
|
+
delimiter: ',' | ';' | '\t';
|
|
123
|
+
/** Include header row */
|
|
124
|
+
includeHeaders: boolean;
|
|
125
|
+
/** Per-column formatting settings */
|
|
126
|
+
columnSettings: ColumnSettingsMap;
|
|
127
|
+
/** Ordered list of columns to include */
|
|
128
|
+
visibleColumns: string[];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Format an aggregate table row for CSV export
|
|
133
|
+
*/
|
|
134
|
+
export declare function formatAggregateRow(row: AggregateRowData, aggregateConfig: AggregateExportConfig, formattingConfig: ExportFormattingConfig): string[];
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Format aggregate table data for CSV export
|
|
138
|
+
*/
|
|
139
|
+
export declare function formatAggregateTableForCSV(data: AggregateRowData[], aggregateConfig: AggregateExportConfig, formattingConfig: ExportFormattingConfig): string[];
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Format a cell value for export based on column settings
|
|
143
|
+
* This is the main entry point for formatting individual cells
|
|
144
|
+
*/
|
|
145
|
+
export declare function formatCellValue(value: unknown, columnSettings: ColumnSettings | undefined, config: {
|
|
146
|
+
useFormattedValues: boolean;
|
|
147
|
+
timezone: string;
|
|
148
|
+
locale: string;
|
|
149
|
+
}): string;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Format a number as currency
|
|
153
|
+
*/
|
|
154
|
+
export declare function formatCurrency(value: number | null | undefined, options?: NumberFormatOptions): string;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Format a date with explicit timezone
|
|
158
|
+
* CRITICAL: Always use this in Lambda, never use plain format()
|
|
159
|
+
*/
|
|
160
|
+
export declare function formatDate(value: string | Date | null | undefined, options?: DateFormatOptions, contextTimezone?: string): string;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Format a date value based on ColumnSettings.dateFormat
|
|
164
|
+
* Used for export formatting
|
|
165
|
+
*/
|
|
166
|
+
export declare function formatDateWithColumnSettings(value: string | Date | null | undefined, dateFormat: {
|
|
167
|
+
format?: string;
|
|
168
|
+
useCustomFormat?: boolean;
|
|
169
|
+
customFormat?: string;
|
|
170
|
+
useRelativeTime?: boolean;
|
|
171
|
+
timezone?: string;
|
|
172
|
+
sourceTimezone?: string;
|
|
173
|
+
} | undefined, contextTimezone: string): string;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Format a number with locale-aware formatting
|
|
177
|
+
*/
|
|
178
|
+
export declare function formatNumber(value: number | null | undefined, options?: NumberFormatOptions): string;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Legacy wrapper for backward compatibility with existing code
|
|
182
|
+
* @deprecated Use formatNumber, formatCurrency, or formatPercent directly
|
|
183
|
+
*/
|
|
184
|
+
export declare function formatNumberCustom(value: number, type: 'number' | 'currency' | 'percent' | 'scientific', options?: FormatOptions): string;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Format a number value based on ColumnSettings.numberFormat
|
|
188
|
+
* Used for export formatting
|
|
189
|
+
*/
|
|
190
|
+
export declare function formatNumberWithColumnSettings(value: number | null | undefined, numberFormat: {
|
|
191
|
+
style?: 'decimal' | 'currency' | 'percent';
|
|
192
|
+
currency?: string;
|
|
193
|
+
locale?: string;
|
|
194
|
+
minimumFractionDigits?: number;
|
|
195
|
+
maximumFractionDigits?: number;
|
|
196
|
+
} | undefined, defaultLocale?: string): string;
|
|
197
|
+
|
|
198
|
+
export declare interface FormatOptions {
|
|
199
|
+
decimalPlaces?: number;
|
|
200
|
+
useSuffix?: boolean;
|
|
201
|
+
currency?: string;
|
|
202
|
+
locale?: string;
|
|
203
|
+
prefix?: string;
|
|
204
|
+
suffix?: string;
|
|
205
|
+
negativeInParentheses?: boolean;
|
|
206
|
+
multiplyBy?: number;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Format a number as percentage
|
|
211
|
+
* Note: Intl.NumberFormat percent style multiplies by 100, so we may need to divide
|
|
212
|
+
*/
|
|
213
|
+
export declare function formatPercent(value: number | null | undefined, options?: NumberFormatOptions & {
|
|
214
|
+
alreadyPercent?: boolean;
|
|
215
|
+
}): string;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Format a pivot table data row for CSV export
|
|
219
|
+
*/
|
|
220
|
+
export declare function formatPivotDataRow(row: PivotRowData, pivotConfig: PivotExportConfig, formattingConfig: ExportFormattingConfig): string[];
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Format pivot table data for CSV export
|
|
224
|
+
*/
|
|
225
|
+
export declare function formatPivotTableForCSV(data: PivotRowData[], pivotConfig: PivotExportConfig, formattingConfig: ExportFormattingConfig): string[];
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Format a date as relative time (e.g., "2 days ago")
|
|
229
|
+
*/
|
|
230
|
+
export declare function formatRelativeTime(value: string | Date | null | undefined): string;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Format a row of data for export
|
|
234
|
+
* Returns values in the order specified by visibleColumns
|
|
235
|
+
*/
|
|
236
|
+
export declare function formatRowForExport(row: Record<string, unknown>, config: ExportFormattingConfig): string[];
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Format a number in scientific notation
|
|
240
|
+
*/
|
|
241
|
+
export declare function formatScientific(value: number | null | undefined, options?: NumberFormatOptions): string;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Format table data for CSV export
|
|
245
|
+
* Returns array of CSV rows (strings)
|
|
246
|
+
*/
|
|
247
|
+
export declare function formatTableForCSV(data: Record<string, unknown>[], config: ExportFormattingConfig): string[];
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Generate headers for aggregate table export
|
|
251
|
+
*/
|
|
252
|
+
export declare function generateAggregateHeaders(aggregateConfig: AggregateExportConfig): string[];
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Generate multi-level headers for pivot table
|
|
256
|
+
*/
|
|
257
|
+
export declare function generatePivotHeaders(config: PivotExportConfig): string[][];
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Generate complete CSV content for a table
|
|
261
|
+
*/
|
|
262
|
+
export declare function generateTableCSV(data: Record<string, unknown>[], config: ExportFormattingConfig, lineEnding?: '\n' | '\r\n'): string;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get timezone abbreviation (e.g., "EST", "PST")
|
|
266
|
+
*/
|
|
267
|
+
export declare function getTimezoneAbbreviation(timezone: string, date?: Date): string;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Get friendly timezone name (e.g., "Eastern Time")
|
|
271
|
+
*/
|
|
272
|
+
export declare function getTimezoneName(timezone: string): string;
|
|
273
|
+
|
|
274
|
+
export declare interface GroupByField {
|
|
275
|
+
name: string;
|
|
276
|
+
alias: string;
|
|
277
|
+
label?: string;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Shared format types for export system
|
|
282
|
+
* IMPORTANT: No React imports allowed in this file
|
|
283
|
+
*
|
|
284
|
+
* These types are used by:
|
|
285
|
+
* - react-semaphor (browser) for client-side exports
|
|
286
|
+
* - semaphor-app (Next.js) for API routes
|
|
287
|
+
* - Lambda (Node.js) for async export processing
|
|
288
|
+
*/
|
|
289
|
+
export declare interface NumberFormatOptions {
|
|
290
|
+
style: 'decimal' | 'currency' | 'percent';
|
|
291
|
+
locale?: string;
|
|
292
|
+
currency?: string;
|
|
293
|
+
minimumFractionDigits?: number;
|
|
294
|
+
maximumFractionDigits?: number;
|
|
295
|
+
useGrouping?: boolean;
|
|
296
|
+
/** Multiply value before formatting (e.g., 100 for percent) */
|
|
297
|
+
multiplyBy?: number;
|
|
298
|
+
/** Add prefix string (e.g., "$") */
|
|
299
|
+
prefix?: string;
|
|
300
|
+
/** Add suffix string (e.g., " USD") */
|
|
301
|
+
suffix?: string;
|
|
302
|
+
/** Show negative numbers in parentheses instead of minus sign */
|
|
303
|
+
negativeInParentheses?: boolean;
|
|
304
|
+
/** Use magnitude suffixes (K, M, B) */
|
|
305
|
+
useSuffix?: boolean;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Convert an array of objects to CSV string
|
|
310
|
+
*/
|
|
311
|
+
export declare function objectsToCSV(data: Record<string, unknown>[], options?: Partial<CSVExportOptions> & {
|
|
312
|
+
columns?: string[];
|
|
313
|
+
}): string;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Parse a date string with source timezone interpretation
|
|
317
|
+
*
|
|
318
|
+
* @param dateString - The date string to parse
|
|
319
|
+
* @param sourceTimezone - How to interpret the date:
|
|
320
|
+
* - 'auto': If date has Z/offset, use it; otherwise assume UTC
|
|
321
|
+
* - 'UTC': Always interpret as UTC
|
|
322
|
+
* - specific TZ: Use explicit timezone if present, otherwise assume UTC
|
|
323
|
+
*/
|
|
324
|
+
export declare function parseWithSourceTimezone(dateString: string, sourceTimezone?: string): Date;
|
|
325
|
+
|
|
326
|
+
export declare interface PivotByColumn {
|
|
327
|
+
name: string;
|
|
328
|
+
alias: string;
|
|
329
|
+
label?: string;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export declare interface PivotCellData {
|
|
333
|
+
value: unknown;
|
|
334
|
+
formatted?: string;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export declare interface PivotColumnSchema {
|
|
338
|
+
alias: string;
|
|
339
|
+
displayLabel?: string;
|
|
340
|
+
metricLabel?: string;
|
|
341
|
+
metricName?: string;
|
|
342
|
+
isMetricColumn: boolean;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export declare interface PivotExportConfig {
|
|
346
|
+
groupByColumns: GroupByField[];
|
|
347
|
+
pivotByColumns: PivotByColumn[];
|
|
348
|
+
columnHeadersTree: ColumnHeaderNode[];
|
|
349
|
+
columnHeaders: string[];
|
|
350
|
+
columnSubtotalMeta?: ColumnSubtotalMeta[];
|
|
351
|
+
includeSubtotals: boolean;
|
|
352
|
+
includeGrandTotal: boolean;
|
|
353
|
+
showRowTotals: boolean;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export declare interface PivotRowData {
|
|
357
|
+
fieldValues: string[];
|
|
358
|
+
cells: Record<string, PivotCellData>;
|
|
359
|
+
isSubtotal?: boolean;
|
|
360
|
+
isGrandTotal?: boolean;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Resolve which timezone to use for formatting
|
|
365
|
+
* Priority: column-specific > context timezone
|
|
366
|
+
*/
|
|
367
|
+
export declare function resolveTimezone(columnTimezone: string | undefined, contextTimezone: string): string;
|
|
368
|
+
|
|
369
|
+
export declare interface RowAggregate {
|
|
370
|
+
function: 'SUM' | 'COUNT' | 'AVG' | 'MIN' | 'MAX';
|
|
371
|
+
groupLevel?: string;
|
|
372
|
+
label?: string;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export { }
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"email": "support@semaphor.cloud"
|
|
6
6
|
},
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"version": "0.1.
|
|
8
|
+
"version": "0.1.179",
|
|
9
9
|
"description": "Fully interactive and customizable dashboards for your apps.",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"react",
|
|
@@ -37,6 +37,11 @@
|
|
|
37
37
|
"import": "./dist/surfboard/index.js",
|
|
38
38
|
"require": "./dist/surfboard/index.cjs"
|
|
39
39
|
},
|
|
40
|
+
"./format-utils": {
|
|
41
|
+
"types": "./dist/types/format-utils.d.ts",
|
|
42
|
+
"import": "./dist/format-utils/index.js",
|
|
43
|
+
"require": "./dist/format-utils/index.cjs"
|
|
44
|
+
},
|
|
40
45
|
"./style.css": "./dist/style.css"
|
|
41
46
|
},
|
|
42
47
|
"scripts": {
|
|
@@ -135,6 +140,14 @@
|
|
|
135
140
|
"react": "^18.0.0 || ^19.0.0",
|
|
136
141
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
137
142
|
},
|
|
143
|
+
"peerDependenciesMeta": {
|
|
144
|
+
"react": {
|
|
145
|
+
"optional": true
|
|
146
|
+
},
|
|
147
|
+
"react-dom": {
|
|
148
|
+
"optional": true
|
|
149
|
+
}
|
|
150
|
+
},
|
|
138
151
|
"overrides": {
|
|
139
152
|
"react": "$react",
|
|
140
153
|
"react-dom": "$react-dom"
|