@airoom/nextmin-react 2.0.1 → 2.0.3
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/README.md +57 -0
- package/dist/components/AddressAutocomplete.d.ts +4 -1
- package/dist/components/AddressAutocomplete.js +2 -2
- package/dist/components/AdminApp.js +86 -1
- package/dist/components/FileUploader.d.ts +3 -0
- package/dist/components/FileUploader.js +84 -28
- package/dist/components/PasswordInput.d.ts +2 -0
- package/dist/components/PasswordInput.js +2 -2
- package/dist/components/PhoneInput.d.ts +2 -0
- package/dist/components/PhoneInput.js +2 -2
- package/dist/components/QRCodeModal.d.ts +10 -0
- package/dist/components/QRCodeModal.js +153 -0
- package/dist/components/RefSelect.d.ts +4 -1
- package/dist/components/RefSelect.js +163 -65
- package/dist/components/SchemaForm.d.ts +2 -1
- package/dist/components/SchemaForm.js +132 -55
- package/dist/components/Sidebar.js +96 -7
- package/dist/components/TableFilters.js +1 -1
- package/dist/components/editor/TiptapEditor.js +46 -13
- package/dist/components/editor/Toolbar.js +195 -62
- package/dist/components/editor/components/CustomFontSizeModal.d.ts +13 -0
- package/dist/components/editor/components/CustomFontSizeModal.js +81 -0
- package/dist/components/editor/components/DistrictGridModal.js +1 -1
- package/dist/components/editor/components/SchemaInsertionModal.js +1 -1
- package/dist/components/editor/editor.css +2 -0
- package/dist/components/editor/extensions/FontSize.d.ts +19 -0
- package/dist/components/editor/extensions/FontSize.js +41 -0
- package/dist/components/viewer/DynamicViewer.js +50 -15
- package/dist/components/viewer/useViewDrawer.js +42 -2
- package/dist/hooks/useAppNavigation.d.ts +3 -0
- package/dist/hooks/useAppNavigation.js +37 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/lib/QueryBuilder.d.ts +3 -1
- package/dist/lib/QueryBuilder.js +10 -0
- package/dist/lib/api.d.ts +6 -0
- package/dist/lib/api.js +45 -24
- package/dist/lib/schemaUtils.js +1 -1
- package/dist/lib/types.d.ts +6 -1
- package/dist/nextmin.css +1 -1
- package/dist/providers/NextMinProvider.d.ts +5 -1
- package/dist/providers/NextMinProvider.js +12 -2
- package/dist/providers/themeResolver.d.ts +25 -0
- package/dist/providers/themeResolver.js +174 -0
- package/dist/router/NextMinRouter.d.ts +0 -1
- package/dist/router/NextMinRouter.js +0 -1
- package/dist/views/CreateEditPage.js +20 -11
- package/dist/views/DashboardPage.js +1 -1
- package/dist/views/ListPage.js +37 -6
- package/dist/views/SettingsEdit.js +1 -1
- package/dist/views/list/DataTableHero.d.ts +5 -5
- package/dist/views/list/DataTableHero.js +154 -41
- package/dist/views/list/ListHeader.js +9 -1
- package/package.json +5 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
export type RefSelectProps = {
|
|
2
3
|
name: string;
|
|
3
4
|
label: string;
|
|
@@ -12,5 +13,7 @@ export type RefSelectProps = {
|
|
|
12
13
|
className?: string;
|
|
13
14
|
pageSize?: number;
|
|
14
15
|
where?: Record<string, any>;
|
|
16
|
+
isInvalid?: boolean;
|
|
17
|
+
errorMessage?: React.ReactNode;
|
|
15
18
|
};
|
|
16
|
-
export declare function RefSelect({ name, label, refModel, showKey, value, onChange, multiple, description, disabled, required, className, pageSize, where, }: RefSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function RefSelect({ name, label, refModel, showKey, value, onChange, multiple, description, disabled, required, className, pageSize, where, isInvalid: isInvalidProp, errorMessage, }: RefSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,93 +1,159 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import { Select, SelectItem, Chip, Spinner, Input } from '@heroui/react';
|
|
5
5
|
import { useInfiniteScroll } from '@heroui/use-infinite-scroll';
|
|
6
6
|
import { api } from '../lib/api';
|
|
7
|
-
export function RefSelect({ name, label, refModel, showKey = 'name', value, onChange, multiple = false, description, disabled, required, className, pageSize = 20, where, }) {
|
|
7
|
+
export function RefSelect({ name, label, refModel, showKey = 'name', value, onChange, multiple = false, description, disabled, required, className, pageSize = 20, where, isInvalid: isInvalidProp, errorMessage, }) {
|
|
8
8
|
const [isOpen, setIsOpen] = useState(false);
|
|
9
9
|
const [items, setItems] = useState([]);
|
|
10
10
|
const [hasMore, setHasMore] = useState(true);
|
|
11
11
|
const [isLoading, setIsLoading] = useState(false);
|
|
12
|
+
const [isHydrating, setIsHydrating] = useState(false);
|
|
12
13
|
const [offset, setOffset] = useState(0);
|
|
13
14
|
const [searchFilter, setSearchFilter] = useState('');
|
|
14
15
|
const [allSeenItems, setAllSeenItems] = useState({});
|
|
15
|
-
const refModelLC = useMemo(() => refModel.toLowerCase(), [refModel]);
|
|
16
|
-
// Normalize IDs to strings
|
|
17
|
-
const normalizeId = (it) => {
|
|
16
|
+
const refModelLC = useMemo(() => (refModel ? String(refModel).toLowerCase() : ''), [refModel]);
|
|
17
|
+
// Normalize IDs to strings safely without producing "[object Object]"
|
|
18
|
+
const normalizeId = useCallback((it) => {
|
|
18
19
|
if (it == null)
|
|
19
20
|
return '';
|
|
20
21
|
if (typeof it === 'string')
|
|
21
|
-
return it;
|
|
22
|
+
return it.trim();
|
|
22
23
|
if (typeof it === 'number')
|
|
23
24
|
return String(it);
|
|
24
|
-
// Handle objects like MongoDB ObjectIds
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// Handle objects like MongoDB ObjectIds or document objects
|
|
26
|
+
if (typeof it === 'object') {
|
|
27
|
+
if (typeof it.toHexString === 'function')
|
|
28
|
+
return it.toHexString();
|
|
29
|
+
const id = it?.id ?? it?._id;
|
|
30
|
+
if (id != null && id !== it) {
|
|
31
|
+
return normalizeId(id);
|
|
32
|
+
}
|
|
33
|
+
if (typeof it.toString === 'function' && it.toString !== Object.prototype.toString) {
|
|
34
|
+
const str = it.toString();
|
|
35
|
+
if (str && str !== '[object Object]')
|
|
36
|
+
return str;
|
|
37
|
+
}
|
|
27
38
|
return '';
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return id.toHexString();
|
|
32
|
-
if (typeof id.toString === 'function' && id !== it)
|
|
33
|
-
return id.toString();
|
|
34
|
-
return String(id);
|
|
35
|
-
};
|
|
39
|
+
}
|
|
40
|
+
return String(it).trim();
|
|
41
|
+
}, []);
|
|
36
42
|
const getLabel = useCallback((it) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
if (it == null)
|
|
44
|
+
return '';
|
|
45
|
+
if (typeof it === 'string' || typeof it === 'number')
|
|
46
|
+
return String(it);
|
|
47
|
+
const val = it?.[showKey] ?? it?.name ?? it?.title ?? it?.label;
|
|
48
|
+
if (val != null && typeof val !== 'object')
|
|
49
|
+
return String(val);
|
|
50
|
+
const sid = normalizeId(it);
|
|
51
|
+
return sid;
|
|
52
|
+
}, [showKey, normalizeId]);
|
|
53
|
+
// Track which IDs have already been hydrated / in-flight to avoid duplicate fetches & loops
|
|
54
|
+
const hydratedIdsRef = React.useRef(new Set());
|
|
55
|
+
// Hydration: eagerly fetch labels for pre-selected values not yet in cache
|
|
40
56
|
useEffect(() => {
|
|
57
|
+
const rawList = Array.isArray(value) ? value : value ? [value] : [];
|
|
58
|
+
if (rawList.length === 0)
|
|
59
|
+
return;
|
|
60
|
+
// Pre-seed any hydrated objects passed directly in value prop
|
|
61
|
+
const newSeen = {};
|
|
62
|
+
for (const v of rawList) {
|
|
63
|
+
if (v && typeof v === 'object') {
|
|
64
|
+
const sid = normalizeId(v);
|
|
65
|
+
const lbl = getLabel(v);
|
|
66
|
+
if (sid && lbl) {
|
|
67
|
+
newSeen[sid] = { id: sid, label: lbl, ...v };
|
|
68
|
+
hydratedIdsRef.current.add(sid);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (Object.keys(newSeen).length > 0) {
|
|
73
|
+
setAllSeenItems(prev => ({ ...prev, ...newSeen }));
|
|
74
|
+
}
|
|
75
|
+
if (!refModelLC)
|
|
76
|
+
return;
|
|
77
|
+
// Only fetch IDs not already cached, pre-seeded, or previously fetched
|
|
78
|
+
const missingIds = rawList
|
|
79
|
+
.map(normalizeId)
|
|
80
|
+
.filter(id => !!id && !allSeenItems[id] && !newSeen[id] && !hydratedIdsRef.current.has(id));
|
|
81
|
+
if (missingIds.length === 0)
|
|
82
|
+
return;
|
|
83
|
+
// Mark as in-flight immediately to prevent duplicate requests
|
|
84
|
+
for (const id of missingIds)
|
|
85
|
+
hydratedIdsRef.current.add(id);
|
|
86
|
+
let isMounted = true;
|
|
41
87
|
const fetchLabels = async () => {
|
|
42
|
-
const ids = Array.isArray(value) ? value : value ? [value] : [];
|
|
43
|
-
if (ids.length === 0)
|
|
44
|
-
return;
|
|
45
|
-
// Filter out IDs we already have labels for
|
|
46
|
-
const missingIds = ids.filter(id => !items.some(it => it.id === id));
|
|
47
|
-
if (missingIds.length === 0)
|
|
48
|
-
return;
|
|
49
88
|
try {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
89
|
+
// Use a high limit so all selected IDs are fetched in one shot.
|
|
90
|
+
// Batch in chunks of 200 to stay within safe query limits.
|
|
91
|
+
const CHUNK = 200;
|
|
92
|
+
const selectProjection = Array.from(new Set(['id', '_id', showKey, 'name', 'title'])).join(',');
|
|
93
|
+
for (let i = 0; i < missingIds.length; i += CHUNK) {
|
|
94
|
+
const chunk = missingIds.slice(i, i + CHUNK);
|
|
95
|
+
const res = await api.list(refModelLC, {
|
|
96
|
+
where: { id: { $in: chunk } },
|
|
97
|
+
limit: chunk.length + 1, // +1 ensures no off-by-one truncation
|
|
98
|
+
page: 1,
|
|
99
|
+
select: selectProjection,
|
|
100
|
+
});
|
|
101
|
+
if (!isMounted)
|
|
102
|
+
return;
|
|
103
|
+
const docs = (res?.data ?? res);
|
|
104
|
+
if (!Array.isArray(docs))
|
|
105
|
+
continue;
|
|
106
|
+
const newItems = docs.map(d => ({
|
|
107
|
+
id: normalizeId(d),
|
|
108
|
+
label: getLabel(d),
|
|
109
|
+
...d,
|
|
110
|
+
})).filter(d => Boolean(d.id));
|
|
57
111
|
setAllSeenItems(prev => {
|
|
58
112
|
const next = { ...prev };
|
|
59
113
|
for (const item of newItems) {
|
|
60
|
-
|
|
114
|
+
if (item.id)
|
|
115
|
+
next[item.id] = item;
|
|
61
116
|
}
|
|
62
117
|
return next;
|
|
63
118
|
});
|
|
64
119
|
setItems(prev => {
|
|
65
120
|
const existingIds = new Set(prev.map(i => i.id));
|
|
66
|
-
const uniqueNew = newItems.filter(i => !existingIds.has(i.id));
|
|
67
|
-
return [...prev, ...uniqueNew];
|
|
121
|
+
const uniqueNew = newItems.filter(i => i.id && !existingIds.has(i.id));
|
|
122
|
+
return uniqueNew.length ? [...prev, ...uniqueNew] : prev;
|
|
68
123
|
});
|
|
69
124
|
}
|
|
70
125
|
}
|
|
71
126
|
catch (err) {
|
|
72
|
-
|
|
127
|
+
// Log warning and retain IDs in hydrated set to prevent infinite retry render loops
|
|
128
|
+
console.warn(`RefSelect: failed to hydrate labels for model "${refModel}"`, err);
|
|
73
129
|
}
|
|
74
130
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
131
|
+
setIsHydrating(true);
|
|
132
|
+
fetchLabels().finally(() => {
|
|
133
|
+
if (isMounted)
|
|
134
|
+
setIsHydrating(false);
|
|
135
|
+
});
|
|
136
|
+
return () => {
|
|
137
|
+
isMounted = false;
|
|
138
|
+
};
|
|
139
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
140
|
+
}, [value, refModelLC, showKey, getLabel, normalizeId]);
|
|
79
141
|
const loadMore = useCallback(async (isSearch = false) => {
|
|
80
142
|
if (isLoading || (!hasMore && !isSearch))
|
|
81
143
|
return;
|
|
144
|
+
if (!refModelLC)
|
|
145
|
+
return;
|
|
82
146
|
setIsLoading(true);
|
|
83
147
|
try {
|
|
84
148
|
const effectivePageSize = Number(pageSize) || 20;
|
|
85
149
|
const currentOffset = isSearch ? 0 : offset;
|
|
150
|
+
const selectProjection = Array.from(new Set(['id', '_id', showKey, 'name', 'title'])).join(',');
|
|
86
151
|
const params = {
|
|
87
152
|
limit: effectivePageSize,
|
|
88
153
|
page: Math.floor(currentOffset / effectivePageSize) + 1,
|
|
89
154
|
sort: showKey,
|
|
90
155
|
sortType: 'asc',
|
|
156
|
+
select: selectProjection,
|
|
91
157
|
};
|
|
92
158
|
if (searchFilter.length >= 1) {
|
|
93
159
|
params.where = {
|
|
@@ -101,12 +167,13 @@ export function RefSelect({ name, label, refModel, showKey = 'name', value, onCh
|
|
|
101
167
|
const res = await api.list(refModelLC, params);
|
|
102
168
|
const docs = (res?.data ?? res);
|
|
103
169
|
const normalized = Array.isArray(docs)
|
|
104
|
-
? docs.map(d => ({ id: normalizeId(d), label: getLabel(d), ...d }))
|
|
170
|
+
? docs.map(d => ({ id: normalizeId(d), label: getLabel(d), ...d })).filter(d => Boolean(d.id))
|
|
105
171
|
: [];
|
|
106
172
|
setAllSeenItems(prev => {
|
|
107
173
|
const next = { ...prev };
|
|
108
174
|
for (const item of normalized) {
|
|
109
|
-
|
|
175
|
+
if (item.id)
|
|
176
|
+
next[item.id] = item;
|
|
110
177
|
}
|
|
111
178
|
return next;
|
|
112
179
|
});
|
|
@@ -114,19 +181,19 @@ export function RefSelect({ name, label, refModel, showKey = 'name', value, onCh
|
|
|
114
181
|
if (isSearch)
|
|
115
182
|
return normalized;
|
|
116
183
|
const existingIds = new Set(prev.map(i => i.id));
|
|
117
|
-
const uniqueNew = normalized.filter(i => !existingIds.has(i.id));
|
|
184
|
+
const uniqueNew = normalized.filter(i => i.id && !existingIds.has(i.id));
|
|
118
185
|
return [...prev, ...uniqueNew];
|
|
119
186
|
});
|
|
120
187
|
setHasMore(normalized.length === effectivePageSize);
|
|
121
188
|
setOffset(prev => isSearch ? effectivePageSize : prev + effectivePageSize);
|
|
122
189
|
}
|
|
123
190
|
catch (err) {
|
|
124
|
-
console.
|
|
191
|
+
console.warn(`Failed to load RefSelect items for model "${refModel}"`, err);
|
|
125
192
|
}
|
|
126
193
|
finally {
|
|
127
194
|
setIsLoading(false);
|
|
128
195
|
}
|
|
129
|
-
}, [isLoading, hasMore, offset, pageSize, searchFilter, refModelLC, showKey, getLabel]);
|
|
196
|
+
}, [isLoading, hasMore, offset, pageSize, searchFilter, refModelLC, showKey, getLabel, normalizeId, where, refModel]);
|
|
130
197
|
const [, scrollerRef] = useInfiniteScroll({
|
|
131
198
|
hasMore,
|
|
132
199
|
isEnabled: isOpen,
|
|
@@ -154,7 +221,7 @@ export function RefSelect({ name, label, refModel, showKey = 'name', value, onCh
|
|
|
154
221
|
const onSelectionChange = (keys) => {
|
|
155
222
|
if (keys === 'all')
|
|
156
223
|
return;
|
|
157
|
-
const selectedIds = Array.from(keys).map(String);
|
|
224
|
+
const selectedIds = Array.from(keys).map(String).filter(Boolean);
|
|
158
225
|
if (multiple) {
|
|
159
226
|
onChange(selectedIds);
|
|
160
227
|
}
|
|
@@ -164,24 +231,39 @@ export function RefSelect({ name, label, refModel, showKey = 'name', value, onCh
|
|
|
164
231
|
};
|
|
165
232
|
const removeValue = (idToRemove) => {
|
|
166
233
|
if (Array.isArray(value)) {
|
|
167
|
-
onChange(value.filter(id => id !== idToRemove));
|
|
234
|
+
onChange(value.filter(id => normalizeId(id) !== idToRemove));
|
|
168
235
|
}
|
|
169
236
|
};
|
|
170
237
|
const selectedKeys = useMemo(() => {
|
|
238
|
+
const rawIds = Array.isArray(value) ? value : value ? [value] : [];
|
|
239
|
+
const normIds = rawIds.map(normalizeId).filter(Boolean);
|
|
171
240
|
if (multiple) {
|
|
172
|
-
return new Set(
|
|
241
|
+
return new Set(normIds);
|
|
173
242
|
}
|
|
174
|
-
return (
|
|
175
|
-
}, [value, multiple]);
|
|
243
|
+
return (normIds.length > 0 ? new Set([normIds[0]]) : new Set());
|
|
244
|
+
}, [value, multiple, normalizeId]);
|
|
176
245
|
const selectedItems = useMemo(() => {
|
|
177
246
|
const ids = Array.isArray(value) ? value : value ? [value] : [];
|
|
178
247
|
return ids.map(id => {
|
|
179
|
-
const
|
|
248
|
+
const sid = normalizeId(id);
|
|
249
|
+
if (!sid)
|
|
250
|
+
return { id: '', label: '' };
|
|
251
|
+
// Check cache first (populated by hydration fetch / object pre-seeding)
|
|
252
|
+
if (allSeenItems[sid])
|
|
253
|
+
return allSeenItems[sid];
|
|
254
|
+
// Check if object has embedded label
|
|
255
|
+
if (id && typeof id === 'object') {
|
|
256
|
+
const lbl = getLabel(id);
|
|
257
|
+
if (lbl)
|
|
258
|
+
return { id: sid, label: lbl, ...id };
|
|
259
|
+
}
|
|
260
|
+
// Then check current page items
|
|
261
|
+
const found = items.find(it => it.id === sid);
|
|
180
262
|
if (found)
|
|
181
263
|
return found;
|
|
182
|
-
return { id:
|
|
183
|
-
});
|
|
184
|
-
}, [value, items]);
|
|
264
|
+
return { id: sid, label: sid };
|
|
265
|
+
}).filter(it => Boolean(it.id));
|
|
266
|
+
}, [value, items, allSeenItems, getLabel, normalizeId]);
|
|
185
267
|
const isValueEmpty = useMemo(() => {
|
|
186
268
|
if (multiple)
|
|
187
269
|
return !Array.isArray(value) || value.length === 0;
|
|
@@ -193,10 +275,15 @@ export function RefSelect({ name, label, refModel, showKey = 'name', value, onCh
|
|
|
193
275
|
// 1. Add currently selected items (from allSeenItems cache)
|
|
194
276
|
const selectedIds = Array.isArray(value) ? value : value ? [value] : [];
|
|
195
277
|
for (const id of selectedIds) {
|
|
196
|
-
const stringId =
|
|
278
|
+
const stringId = normalizeId(id);
|
|
279
|
+
if (!stringId)
|
|
280
|
+
continue;
|
|
197
281
|
if (allSeenItems[stringId]) {
|
|
198
282
|
itemMap.set(stringId, allSeenItems[stringId]);
|
|
199
283
|
}
|
|
284
|
+
else if (id && typeof id === 'object') {
|
|
285
|
+
itemMap.set(stringId, { id: stringId, label: getLabel(id), ...id });
|
|
286
|
+
}
|
|
200
287
|
else {
|
|
201
288
|
// Fallback for cases where label isn't loaded yet
|
|
202
289
|
itemMap.set(stringId, { id: stringId, label: stringId });
|
|
@@ -204,22 +291,33 @@ export function RefSelect({ name, label, refModel, showKey = 'name', value, onCh
|
|
|
204
291
|
}
|
|
205
292
|
// 2. Add current results (highest priority for labels/data)
|
|
206
293
|
for (const item of items) {
|
|
207
|
-
|
|
294
|
+
if (item.id) {
|
|
295
|
+
itemMap.set(item.id, item);
|
|
296
|
+
}
|
|
208
297
|
}
|
|
209
298
|
return Array.from(itemMap.values());
|
|
210
|
-
}, [items, value, allSeenItems]);
|
|
211
|
-
|
|
299
|
+
}, [items, value, allSeenItems, getLabel, normalizeId]);
|
|
300
|
+
const placeholderText = refModel ? `Select ${refModel}...` : `Select ${label}...`;
|
|
301
|
+
return (_jsx("div", { className: `flex flex-col gap-2 ${className}`, children: _jsx(Select, { label: label, placeholder: placeholderText, variant: "bordered", labelPlacement: "outside", isMultiline: multiple, items: mergedDisplayItems, isLoading: isLoading || isHydrating, scrollRef: scrollerRef, selectionMode: multiple ? 'multiple' : 'single', selectedKeys: selectedKeys, onSelectionChange: onSelectionChange, onOpenChange: onOpenChange, isDisabled: disabled, isRequired: required, isInvalid: isInvalidProp || (required && isValueEmpty), errorMessage: errorMessage, validationBehavior: "aria", description: description, className: "w-full", classNames: {
|
|
212
302
|
trigger: 'min-h-12 py-2',
|
|
213
303
|
}, scrollShadowProps: {
|
|
214
304
|
isEnabled: false,
|
|
215
305
|
}, listboxProps: {
|
|
216
306
|
topContent: (_jsx("div", { className: "px-2 pt-2 pb-1 sticky top-0 z-20 bg-content1 shadow-sm pb-2 -mt-2 -mx-1", children: _jsx(Input, { placeholder: "Search...", size: "sm", variant: "bordered", value: searchFilter, onChange: onInputChange, onClear: () => setSearchFilter(''), isClearable: true,
|
|
217
|
-
// Prevent closing when clicking search
|
|
218
|
-
onClick: (e) =>
|
|
307
|
+
// Prevent closing when clicking search without triggering React Spectrum warning
|
|
308
|
+
onClick: (e) => {
|
|
309
|
+
if (typeof e?.continuePropagation === 'function')
|
|
310
|
+
return;
|
|
311
|
+
e?.stopPropagation?.();
|
|
312
|
+
}, onKeyDown: (e) => {
|
|
313
|
+
if (typeof e?.continuePropagation === 'function')
|
|
314
|
+
return;
|
|
315
|
+
e?.stopPropagation?.();
|
|
316
|
+
}, endContent: (isLoading || isHydrating) ? _jsx(Spinner, { size: "sm" }) : null }) })),
|
|
219
317
|
}, renderValue: (items) => {
|
|
220
318
|
if (multiple) {
|
|
221
|
-
return (_jsx("div", { className: "flex flex-wrap gap-1", children: items.map((item) => (_jsx(Chip, { size: "sm", variant: "flat", children: item.textValue }, item.key))) }));
|
|
319
|
+
return (_jsx("div", { className: "flex flex-wrap gap-1", children: items.map((item) => (_jsx(Chip, { size: "sm", variant: "flat", children: item.textValue || item.key }, item.key))) }));
|
|
222
320
|
}
|
|
223
|
-
return items[0]
|
|
224
|
-
}, children: (item) => (_jsx(SelectItem, { textValue: item.label, children: item.label }, item.id)) }) }));
|
|
321
|
+
return items[0]?.textValue ?? '';
|
|
322
|
+
}, children: (item) => (_jsx(SelectItem, { textValue: item.label || item.id, children: item.label || item.id }, item.id)) }) }));
|
|
225
323
|
}
|
|
@@ -13,7 +13,8 @@ type SchemaFormProps = {
|
|
|
13
13
|
showReset?: boolean;
|
|
14
14
|
onSubmit: (values: Record<string, any>) => void | Promise<void>;
|
|
15
15
|
fieldErrors?: FieldErrorItems[] | undefined;
|
|
16
|
+
isEdit?: boolean;
|
|
16
17
|
};
|
|
17
18
|
/** --------------------------------------------------------------------------------------- **/
|
|
18
|
-
export declare function SchemaForm({ model, schemaOverride, initialValues, submitLabel, busy, showReset, onSubmit, fieldErrors, }: SchemaFormProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function SchemaForm({ model, schemaOverride, initialValues, submitLabel, busy, showReset, onSubmit, fieldErrors, isEdit: isEditProp, }: SchemaFormProps): import("react/jsx-runtime").JSX.Element;
|
|
19
20
|
export {};
|