@nubitio/crud 0.5.20 → 0.5.22
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.cjs +29 -11
- package/dist/index.d.cts +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +29 -11
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -2110,7 +2110,7 @@ function buildToolbar(options, t, onAddClick, includeAddAction = true) {
|
|
|
2110
2110
|
showRefresh: options.toolbar?.showRefresh ?? true
|
|
2111
2111
|
};
|
|
2112
2112
|
}
|
|
2113
|
-
function SummaryFooter({ fields, hasCheckbox, hasDetail, hasRowActions, rows, summaryFields, footerRef, colWidths }) {
|
|
2113
|
+
function SummaryFooter({ fields, hasCheckbox, hasDetail, hasRowActions, rows, summaryFields, gridSummary, footerRef, colWidths }) {
|
|
2114
2114
|
if (!summaryFields?.length) return null;
|
|
2115
2115
|
const itemsByColumn = new Map(summaryFields.filter((item) => item.column).map((item) => [item.column, item]));
|
|
2116
2116
|
const unboundItems = summaryFields.filter((item) => !item.column);
|
|
@@ -2138,7 +2138,7 @@ function SummaryFooter({ fields, hasCheckbox, hasDetail, hasRowActions, rows, su
|
|
|
2138
2138
|
children: item.label
|
|
2139
2139
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2140
2140
|
className: "nb-datagrid__summary-value",
|
|
2141
|
-
children: resolveSummaryText(rows, item)
|
|
2141
|
+
children: item.column && gridSummary && item.column in gridSummary ? formatSummaryValue(gridSummary[item.column], item) : resolveSummaryText(rows, item)
|
|
2142
2142
|
})]
|
|
2143
2143
|
})
|
|
2144
2144
|
}, field.name);
|
|
@@ -2159,6 +2159,7 @@ const NativeDataGridView = (0, react.forwardRef)((options, ref) => {
|
|
|
2159
2159
|
const [rows, setRows] = (0, react.useState)([]);
|
|
2160
2160
|
const rowsRef = (0, react.useRef)([]);
|
|
2161
2161
|
const [totalCount, setTotalCount] = (0, react.useState)(0);
|
|
2162
|
+
const [gridSummary, setGridSummary] = (0, react.useState)(null);
|
|
2162
2163
|
const [selectedKeys, setSelectedKeys] = (0, react.useState)([]);
|
|
2163
2164
|
const [filters, setFilters] = (0, react.useState)({});
|
|
2164
2165
|
const [filterInputs, setFilterInputs] = (0, react.useState)({});
|
|
@@ -2340,6 +2341,7 @@ const NativeDataGridView = (0, react.forwardRef)((options, ref) => {
|
|
|
2340
2341
|
rowsRef.current = result.data;
|
|
2341
2342
|
setRows(result.data);
|
|
2342
2343
|
setTotalCount(result.totalCount);
|
|
2344
|
+
setGridSummary(result.gridSummary ?? null);
|
|
2343
2345
|
setIsGridLoading(false);
|
|
2344
2346
|
onContentReadyRef.current?.();
|
|
2345
2347
|
return result.data;
|
|
@@ -3135,6 +3137,7 @@ const NativeDataGridView = (0, react.forwardRef)((options, ref) => {
|
|
|
3135
3137
|
hasRowActions,
|
|
3136
3138
|
rows,
|
|
3137
3139
|
summaryFields: options.summaryFields,
|
|
3140
|
+
gridSummary,
|
|
3138
3141
|
footerRef: tfootRef,
|
|
3139
3142
|
colWidths: resolvedColWidths
|
|
3140
3143
|
})
|
|
@@ -3173,7 +3176,7 @@ const NativeDataGridView = (0, react.forwardRef)((options, ref) => {
|
|
|
3173
3176
|
children: item.label
|
|
3174
3177
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3175
3178
|
className: "nb-datagrid__summary-value",
|
|
3176
|
-
children: resolveSummaryText(rows, item)
|
|
3179
|
+
children: item.column && gridSummary && item.column in gridSummary ? formatSummaryValue(gridSummary[item.column], item) : resolveSummaryText(rows, item)
|
|
3177
3180
|
})]
|
|
3178
3181
|
}, index))
|
|
3179
3182
|
}),
|
|
@@ -7466,7 +7469,7 @@ function ResourceSchemaProvider({ children, resolver }) {
|
|
|
7466
7469
|
children
|
|
7467
7470
|
});
|
|
7468
7471
|
}
|
|
7469
|
-
function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout, workflow) {
|
|
7472
|
+
function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout, workflow, summaryFields) {
|
|
7470
7473
|
try {
|
|
7471
7474
|
return {
|
|
7472
7475
|
fields: resolver(),
|
|
@@ -7474,7 +7477,8 @@ function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout
|
|
|
7474
7477
|
error: void 0,
|
|
7475
7478
|
supportedOperations,
|
|
7476
7479
|
formLayout,
|
|
7477
|
-
workflow
|
|
7480
|
+
workflow,
|
|
7481
|
+
summaryFields
|
|
7478
7482
|
};
|
|
7479
7483
|
} catch (runtimeError) {
|
|
7480
7484
|
return {
|
|
@@ -7483,7 +7487,8 @@ function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout
|
|
|
7483
7487
|
error: runtimeError instanceof Error ? runtimeError : new Error(String(runtimeError)),
|
|
7484
7488
|
supportedOperations,
|
|
7485
7489
|
formLayout,
|
|
7486
|
-
workflow
|
|
7490
|
+
workflow,
|
|
7491
|
+
summaryFields
|
|
7487
7492
|
};
|
|
7488
7493
|
}
|
|
7489
7494
|
}
|
|
@@ -7509,7 +7514,7 @@ function useResolvedResourceFields({ apiUrl, manualFields, overrides, fieldContr
|
|
|
7509
7514
|
baselineFields: baseline.fields,
|
|
7510
7515
|
contract: fieldContract,
|
|
7511
7516
|
legacyOverrides: fieldContract ? void 0 : overrides
|
|
7512
|
-
}), baseline.supportedOperations, baseline.formLayout, baseline.workflow);
|
|
7517
|
+
}), baseline.supportedOperations, baseline.formLayout, baseline.workflow, baseline.summaryFields);
|
|
7513
7518
|
}, [
|
|
7514
7519
|
baseline,
|
|
7515
7520
|
fieldContract,
|
|
@@ -7611,7 +7616,7 @@ function SmartCrudPage({ resource, fieldOverrides, formRef, onSelectionChanged,
|
|
|
7611
7616
|
const effectiveGridRef = gridRef ?? internalGridRef;
|
|
7612
7617
|
const resolvedBaseResource = (0, react.useMemo)(() => resolveCrudResource(resource), [resource]);
|
|
7613
7618
|
const hasManualFields = !resource.fieldContract && Array.isArray(resource.fields) && resource.fields.length > 0;
|
|
7614
|
-
const { fields, isLoading, error, supportedOperations, formLayout: inferredFormLayout, workflow } = useResolvedResourceFields({
|
|
7619
|
+
const { fields, isLoading, error, supportedOperations, formLayout: inferredFormLayout, workflow, summaryFields: inferredSummaryFields } = useResolvedResourceFields({
|
|
7615
7620
|
apiUrl: resolvedBaseResource.apiUrl,
|
|
7616
7621
|
manualFields: hasManualFields ? buildFields(resource.fields) : void 0,
|
|
7617
7622
|
overrides: hasManualFields ? void 0 : fieldOverrides,
|
|
@@ -7653,6 +7658,7 @@ function SmartCrudPage({ resource, fieldOverrides, formRef, onSelectionChanged,
|
|
|
7653
7658
|
fields: hasManualFields ? buildFields(resource.fields) : gridFields,
|
|
7654
7659
|
formFields,
|
|
7655
7660
|
formLayout: resolvedBaseResource.formLayout ?? inferredFormLayout,
|
|
7661
|
+
summaryFields: resolvedBaseResource.summaryFields ?? inferredSummaryFields,
|
|
7656
7662
|
_supportedOperations: supportedOperations,
|
|
7657
7663
|
rowActions
|
|
7658
7664
|
};
|
|
@@ -7662,6 +7668,7 @@ function SmartCrudPage({ resource, fieldOverrides, formRef, onSelectionChanged,
|
|
|
7662
7668
|
gridFields,
|
|
7663
7669
|
hasManualFields,
|
|
7664
7670
|
inferredFormLayout,
|
|
7671
|
+
inferredSummaryFields,
|
|
7665
7672
|
normalizedApiUrl,
|
|
7666
7673
|
formFields,
|
|
7667
7674
|
resolvedBaseResource,
|
|
@@ -8627,15 +8634,26 @@ function createRestResourceStore(dialect = {}) {
|
|
|
8627
8634
|
if (result === null) return {
|
|
8628
8635
|
data: [],
|
|
8629
8636
|
totalCount: 0,
|
|
8630
|
-
summary: null
|
|
8637
|
+
summary: null,
|
|
8638
|
+
gridSummary: null
|
|
8631
8639
|
};
|
|
8632
8640
|
const body = result.data;
|
|
8633
8641
|
const data = Array.isArray(body) ? body : body.items ?? body.data ?? [];
|
|
8634
8642
|
const headerTotal = Number(result.headers.get("x-total-count"));
|
|
8643
|
+
const totalCount = Array.isArray(body) ? Number.isFinite(headerTotal) && headerTotal > 0 ? headerTotal : body.length : body.total ?? body.totalCount ?? data.length;
|
|
8644
|
+
const gridSummaryHeader = result.headers.get("x-grid-summary");
|
|
8645
|
+
let gridSummary = null;
|
|
8646
|
+
if (gridSummaryHeader) try {
|
|
8647
|
+
const parsed = JSON.parse(gridSummaryHeader);
|
|
8648
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) gridSummary = parsed;
|
|
8649
|
+
} catch {
|
|
8650
|
+
gridSummary = null;
|
|
8651
|
+
}
|
|
8635
8652
|
return {
|
|
8636
8653
|
data,
|
|
8637
|
-
totalCount
|
|
8638
|
-
summary: null
|
|
8654
|
+
totalCount,
|
|
8655
|
+
summary: null,
|
|
8656
|
+
gridSummary
|
|
8639
8657
|
};
|
|
8640
8658
|
},
|
|
8641
8659
|
async byKey(key) {
|
package/dist/index.d.cts
CHANGED
|
@@ -1549,6 +1549,8 @@ interface DataGridViewOptions {
|
|
|
1549
1549
|
/** Per-row gate for the Delete action. Absent = allowed. */
|
|
1550
1550
|
canDeleteRow?: (row: DataRecord$1) => boolean;
|
|
1551
1551
|
summaryFields?: DataGridSummaryItem[];
|
|
1552
|
+
/** Server-side aggregates for the current filtered collection. */
|
|
1553
|
+
gridSummary?: Record<string, unknown> | null;
|
|
1552
1554
|
filter?: FilterRule[];
|
|
1553
1555
|
sort?: Array<{
|
|
1554
1556
|
selector: string;
|
|
@@ -1919,6 +1921,7 @@ interface ResourceSchemaResolution {
|
|
|
1919
1921
|
*/
|
|
1920
1922
|
formLayout?: FormLayout;
|
|
1921
1923
|
workflow?: WorkflowSchema;
|
|
1924
|
+
summaryFields?: SummaryItem[];
|
|
1922
1925
|
}
|
|
1923
1926
|
interface ResourceSchemaResolver {
|
|
1924
1927
|
useResourceSchema(request: ResourceSchemaRequest): ResourceSchemaResolution;
|
package/dist/index.d.mts
CHANGED
|
@@ -1549,6 +1549,8 @@ interface DataGridViewOptions {
|
|
|
1549
1549
|
/** Per-row gate for the Delete action. Absent = allowed. */
|
|
1550
1550
|
canDeleteRow?: (row: DataRecord$1) => boolean;
|
|
1551
1551
|
summaryFields?: DataGridSummaryItem[];
|
|
1552
|
+
/** Server-side aggregates for the current filtered collection. */
|
|
1553
|
+
gridSummary?: Record<string, unknown> | null;
|
|
1552
1554
|
filter?: FilterRule[];
|
|
1553
1555
|
sort?: Array<{
|
|
1554
1556
|
selector: string;
|
|
@@ -1919,6 +1921,7 @@ interface ResourceSchemaResolution {
|
|
|
1919
1921
|
*/
|
|
1920
1922
|
formLayout?: FormLayout;
|
|
1921
1923
|
workflow?: WorkflowSchema;
|
|
1924
|
+
summaryFields?: SummaryItem[];
|
|
1922
1925
|
}
|
|
1923
1926
|
interface ResourceSchemaResolver {
|
|
1924
1927
|
useResourceSchema(request: ResourceSchemaRequest): ResourceSchemaResolution;
|
package/dist/index.mjs
CHANGED
|
@@ -2086,7 +2086,7 @@ function buildToolbar(options, t, onAddClick, includeAddAction = true) {
|
|
|
2086
2086
|
showRefresh: options.toolbar?.showRefresh ?? true
|
|
2087
2087
|
};
|
|
2088
2088
|
}
|
|
2089
|
-
function SummaryFooter({ fields, hasCheckbox, hasDetail, hasRowActions, rows, summaryFields, footerRef, colWidths }) {
|
|
2089
|
+
function SummaryFooter({ fields, hasCheckbox, hasDetail, hasRowActions, rows, summaryFields, gridSummary, footerRef, colWidths }) {
|
|
2090
2090
|
if (!summaryFields?.length) return null;
|
|
2091
2091
|
const itemsByColumn = new Map(summaryFields.filter((item) => item.column).map((item) => [item.column, item]));
|
|
2092
2092
|
const unboundItems = summaryFields.filter((item) => !item.column);
|
|
@@ -2114,7 +2114,7 @@ function SummaryFooter({ fields, hasCheckbox, hasDetail, hasRowActions, rows, su
|
|
|
2114
2114
|
children: item.label
|
|
2115
2115
|
}), /* @__PURE__ */ jsx("span", {
|
|
2116
2116
|
className: "nb-datagrid__summary-value",
|
|
2117
|
-
children: resolveSummaryText(rows, item)
|
|
2117
|
+
children: item.column && gridSummary && item.column in gridSummary ? formatSummaryValue(gridSummary[item.column], item) : resolveSummaryText(rows, item)
|
|
2118
2118
|
})]
|
|
2119
2119
|
})
|
|
2120
2120
|
}, field.name);
|
|
@@ -2135,6 +2135,7 @@ const NativeDataGridView = forwardRef((options, ref) => {
|
|
|
2135
2135
|
const [rows, setRows] = useState([]);
|
|
2136
2136
|
const rowsRef = useRef([]);
|
|
2137
2137
|
const [totalCount, setTotalCount] = useState(0);
|
|
2138
|
+
const [gridSummary, setGridSummary] = useState(null);
|
|
2138
2139
|
const [selectedKeys, setSelectedKeys] = useState([]);
|
|
2139
2140
|
const [filters, setFilters] = useState({});
|
|
2140
2141
|
const [filterInputs, setFilterInputs] = useState({});
|
|
@@ -2316,6 +2317,7 @@ const NativeDataGridView = forwardRef((options, ref) => {
|
|
|
2316
2317
|
rowsRef.current = result.data;
|
|
2317
2318
|
setRows(result.data);
|
|
2318
2319
|
setTotalCount(result.totalCount);
|
|
2320
|
+
setGridSummary(result.gridSummary ?? null);
|
|
2319
2321
|
setIsGridLoading(false);
|
|
2320
2322
|
onContentReadyRef.current?.();
|
|
2321
2323
|
return result.data;
|
|
@@ -3111,6 +3113,7 @@ const NativeDataGridView = forwardRef((options, ref) => {
|
|
|
3111
3113
|
hasRowActions,
|
|
3112
3114
|
rows,
|
|
3113
3115
|
summaryFields: options.summaryFields,
|
|
3116
|
+
gridSummary,
|
|
3114
3117
|
footerRef: tfootRef,
|
|
3115
3118
|
colWidths: resolvedColWidths
|
|
3116
3119
|
})
|
|
@@ -3149,7 +3152,7 @@ const NativeDataGridView = forwardRef((options, ref) => {
|
|
|
3149
3152
|
children: item.label
|
|
3150
3153
|
}), /* @__PURE__ */ jsx("span", {
|
|
3151
3154
|
className: "nb-datagrid__summary-value",
|
|
3152
|
-
children: resolveSummaryText(rows, item)
|
|
3155
|
+
children: item.column && gridSummary && item.column in gridSummary ? formatSummaryValue(gridSummary[item.column], item) : resolveSummaryText(rows, item)
|
|
3153
3156
|
})]
|
|
3154
3157
|
}, index))
|
|
3155
3158
|
}),
|
|
@@ -7442,7 +7445,7 @@ function ResourceSchemaProvider({ children, resolver }) {
|
|
|
7442
7445
|
children
|
|
7443
7446
|
});
|
|
7444
7447
|
}
|
|
7445
|
-
function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout, workflow) {
|
|
7448
|
+
function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout, workflow, summaryFields) {
|
|
7446
7449
|
try {
|
|
7447
7450
|
return {
|
|
7448
7451
|
fields: resolver(),
|
|
@@ -7450,7 +7453,8 @@ function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout
|
|
|
7450
7453
|
error: void 0,
|
|
7451
7454
|
supportedOperations,
|
|
7452
7455
|
formLayout,
|
|
7453
|
-
workflow
|
|
7456
|
+
workflow,
|
|
7457
|
+
summaryFields
|
|
7454
7458
|
};
|
|
7455
7459
|
} catch (runtimeError) {
|
|
7456
7460
|
return {
|
|
@@ -7459,7 +7463,8 @@ function resolveWithRuntimeErrors(resolver, supportedOperations = [], formLayout
|
|
|
7459
7463
|
error: runtimeError instanceof Error ? runtimeError : new Error(String(runtimeError)),
|
|
7460
7464
|
supportedOperations,
|
|
7461
7465
|
formLayout,
|
|
7462
|
-
workflow
|
|
7466
|
+
workflow,
|
|
7467
|
+
summaryFields
|
|
7463
7468
|
};
|
|
7464
7469
|
}
|
|
7465
7470
|
}
|
|
@@ -7485,7 +7490,7 @@ function useResolvedResourceFields({ apiUrl, manualFields, overrides, fieldContr
|
|
|
7485
7490
|
baselineFields: baseline.fields,
|
|
7486
7491
|
contract: fieldContract,
|
|
7487
7492
|
legacyOverrides: fieldContract ? void 0 : overrides
|
|
7488
|
-
}), baseline.supportedOperations, baseline.formLayout, baseline.workflow);
|
|
7493
|
+
}), baseline.supportedOperations, baseline.formLayout, baseline.workflow, baseline.summaryFields);
|
|
7489
7494
|
}, [
|
|
7490
7495
|
baseline,
|
|
7491
7496
|
fieldContract,
|
|
@@ -7587,7 +7592,7 @@ function SmartCrudPage({ resource, fieldOverrides, formRef, onSelectionChanged,
|
|
|
7587
7592
|
const effectiveGridRef = gridRef ?? internalGridRef;
|
|
7588
7593
|
const resolvedBaseResource = useMemo(() => resolveCrudResource(resource), [resource]);
|
|
7589
7594
|
const hasManualFields = !resource.fieldContract && Array.isArray(resource.fields) && resource.fields.length > 0;
|
|
7590
|
-
const { fields, isLoading, error, supportedOperations, formLayout: inferredFormLayout, workflow } = useResolvedResourceFields({
|
|
7595
|
+
const { fields, isLoading, error, supportedOperations, formLayout: inferredFormLayout, workflow, summaryFields: inferredSummaryFields } = useResolvedResourceFields({
|
|
7591
7596
|
apiUrl: resolvedBaseResource.apiUrl,
|
|
7592
7597
|
manualFields: hasManualFields ? buildFields(resource.fields) : void 0,
|
|
7593
7598
|
overrides: hasManualFields ? void 0 : fieldOverrides,
|
|
@@ -7629,6 +7634,7 @@ function SmartCrudPage({ resource, fieldOverrides, formRef, onSelectionChanged,
|
|
|
7629
7634
|
fields: hasManualFields ? buildFields(resource.fields) : gridFields,
|
|
7630
7635
|
formFields,
|
|
7631
7636
|
formLayout: resolvedBaseResource.formLayout ?? inferredFormLayout,
|
|
7637
|
+
summaryFields: resolvedBaseResource.summaryFields ?? inferredSummaryFields,
|
|
7632
7638
|
_supportedOperations: supportedOperations,
|
|
7633
7639
|
rowActions
|
|
7634
7640
|
};
|
|
@@ -7638,6 +7644,7 @@ function SmartCrudPage({ resource, fieldOverrides, formRef, onSelectionChanged,
|
|
|
7638
7644
|
gridFields,
|
|
7639
7645
|
hasManualFields,
|
|
7640
7646
|
inferredFormLayout,
|
|
7647
|
+
inferredSummaryFields,
|
|
7641
7648
|
normalizedApiUrl,
|
|
7642
7649
|
formFields,
|
|
7643
7650
|
resolvedBaseResource,
|
|
@@ -8603,15 +8610,26 @@ function createRestResourceStore(dialect = {}) {
|
|
|
8603
8610
|
if (result === null) return {
|
|
8604
8611
|
data: [],
|
|
8605
8612
|
totalCount: 0,
|
|
8606
|
-
summary: null
|
|
8613
|
+
summary: null,
|
|
8614
|
+
gridSummary: null
|
|
8607
8615
|
};
|
|
8608
8616
|
const body = result.data;
|
|
8609
8617
|
const data = Array.isArray(body) ? body : body.items ?? body.data ?? [];
|
|
8610
8618
|
const headerTotal = Number(result.headers.get("x-total-count"));
|
|
8619
|
+
const totalCount = Array.isArray(body) ? Number.isFinite(headerTotal) && headerTotal > 0 ? headerTotal : body.length : body.total ?? body.totalCount ?? data.length;
|
|
8620
|
+
const gridSummaryHeader = result.headers.get("x-grid-summary");
|
|
8621
|
+
let gridSummary = null;
|
|
8622
|
+
if (gridSummaryHeader) try {
|
|
8623
|
+
const parsed = JSON.parse(gridSummaryHeader);
|
|
8624
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) gridSummary = parsed;
|
|
8625
|
+
} catch {
|
|
8626
|
+
gridSummary = null;
|
|
8627
|
+
}
|
|
8611
8628
|
return {
|
|
8612
8629
|
data,
|
|
8613
|
-
totalCount
|
|
8614
|
-
summary: null
|
|
8630
|
+
totalCount,
|
|
8631
|
+
summary: null,
|
|
8632
|
+
gridSummary
|
|
8615
8633
|
};
|
|
8616
8634
|
},
|
|
8617
8635
|
async byKey(key) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nubitio/crud",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Declarative CRUD engine with field DSL, forms, datagrids, RBAC, conditional logic and pluggable adapters (Hydra/REST).",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"react-dom": "^19.0.0",
|
|
57
57
|
"react-i18next": "^14.0.0",
|
|
58
58
|
"react-router-dom": "^6.0.0",
|
|
59
|
-
"@nubitio/core": "^0.5.
|
|
60
|
-
"@nubitio/ui": "^0.5.
|
|
59
|
+
"@nubitio/core": "^0.5.22",
|
|
60
|
+
"@nubitio/ui": "^0.5.22"
|
|
61
61
|
}
|
|
62
62
|
}
|