@openg2p/registry-widgets 1.1.2-dev.0 → 1.1.2-dev.2
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/hooks/useBaseWidget.d.ts.map +1 -1
- package/dist/hooks/useGeoWidgetCascade.d.ts.map +1 -1
- package/dist/index.d.ts +30 -2
- package/dist/index.esm.js +504 -305
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +512 -304
- package/dist/index.js.map +1 -1
- package/dist/utils/dataSource.d.ts.map +1 -1
- package/dist/utils/geoHierarchy.d.ts +23 -0
- package/dist/utils/geoHierarchy.d.ts.map +1 -1
- package/dist/utils/pathUtils.d.ts +5 -0
- package/dist/utils/pathUtils.d.ts.map +1 -1
- package/dist/widgets/TableWidget.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -173,15 +173,33 @@ const parseDataPath = (dataPath) => {
|
|
|
173
173
|
/**
|
|
174
174
|
* Get value from widget state using data path
|
|
175
175
|
*/
|
|
176
|
+
/**
|
|
177
|
+
* Resolve a widget-id reference in Redux values.
|
|
178
|
+
* Supports namespaced ids (e.g. "rv-section-0__region_code" when ref is "region_code").
|
|
179
|
+
*/
|
|
180
|
+
const resolveWidgetIdValue = (values, ref) => {
|
|
181
|
+
if (!ref) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
if (ref.includes('.')) {
|
|
185
|
+
return getValueByPath(values, ref);
|
|
186
|
+
}
|
|
187
|
+
if (Object.prototype.hasOwnProperty.call(values, ref)) {
|
|
188
|
+
return values[ref];
|
|
189
|
+
}
|
|
190
|
+
const suffix = `__${ref}`;
|
|
191
|
+
for (const [key, val] of Object.entries(values)) {
|
|
192
|
+
if (key.endsWith(suffix)) {
|
|
193
|
+
return val;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
};
|
|
176
198
|
const getWidgetValue = (values, dataPath, widgetId) => {
|
|
177
199
|
if (!dataPath) {
|
|
178
200
|
// Fallback to widget-id if no data path
|
|
179
201
|
return values[widgetId];
|
|
180
202
|
}
|
|
181
|
-
if (widgetId == "user-profile") {
|
|
182
|
-
console.log('values', values);
|
|
183
|
-
console.log('dataPath', dataPath);
|
|
184
|
-
}
|
|
185
203
|
if (typeof dataPath === 'string') {
|
|
186
204
|
return getValueByPath(values, dataPath);
|
|
187
205
|
}
|
|
@@ -1045,24 +1063,11 @@ const getApiDataSource = async (dataSource, allValues, dataSourceRequestHandler,
|
|
|
1045
1063
|
// dependsOn can be either a data path (e.g., "person.address") or a widget-id
|
|
1046
1064
|
let depValue = null;
|
|
1047
1065
|
if (dataSource.dependsOn) {
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
depValue = allValues
|
|
1053
|
-
// Smart resolution: If not found at top level, try to find the dependency in the same nested object
|
|
1054
|
-
// by looking for other keys in allValues that might contain the dependency.
|
|
1055
|
-
// We look for objects that contain both the current widget's path (if we can guess it) and the dependency.
|
|
1056
|
-
// But since we don't know the current widget's path here, we search for any object that has this dependency key.
|
|
1057
|
-
if (depValue === null || depValue === undefined || depValue === '') {
|
|
1058
|
-
for (const val of Object.values(allValues)) {
|
|
1059
|
-
if (val && typeof val === 'object' && !Array.isArray(val) && dataSource.dependsOn in val) {
|
|
1060
|
-
depValue = val[dataSource.dependsOn];
|
|
1061
|
-
if (depValue !== null && depValue !== undefined && depValue !== '')
|
|
1062
|
-
break;
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
+
if (dataSource.dependsOn.includes('.')) {
|
|
1067
|
+
depValue = getValueByPath(allValues, dataSource.dependsOn);
|
|
1068
|
+
}
|
|
1069
|
+
else {
|
|
1070
|
+
depValue = resolveWidgetIdValue(allValues, dataSource.dependsOn);
|
|
1066
1071
|
}
|
|
1067
1072
|
if (depValue === null || depValue === undefined || depValue === '') {
|
|
1068
1073
|
// If dependency is empty, return empty array
|
|
@@ -1931,6 +1936,247 @@ const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate
|
|
|
1931
1936
|
return content;
|
|
1932
1937
|
};
|
|
1933
1938
|
|
|
1939
|
+
/**
|
|
1940
|
+
* Geo Hierarchy Builder
|
|
1941
|
+
* Manages geo hierarchy state and builds hierarchy JSON structure
|
|
1942
|
+
*/
|
|
1943
|
+
function extractLevelValueFromStored(value, geoConfig) {
|
|
1944
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
1945
|
+
return value;
|
|
1946
|
+
}
|
|
1947
|
+
const hierarchy = value.hierarchy || value.geo_code_hierarchy_json?.hierarchy;
|
|
1948
|
+
if (Array.isArray(hierarchy)) {
|
|
1949
|
+
const levelData = hierarchy.find((l) => l.level === geoConfig.level);
|
|
1950
|
+
if (levelData) {
|
|
1951
|
+
return levelData.level_value_id;
|
|
1952
|
+
}
|
|
1953
|
+
// Level absent from hierarchy (e.g. cleared by upstream cascade) — do not use lowest-level fallback
|
|
1954
|
+
return undefined;
|
|
1955
|
+
}
|
|
1956
|
+
if ('geo_lowest_level_value_id' in value) {
|
|
1957
|
+
return value.geo_lowest_level_value_id;
|
|
1958
|
+
}
|
|
1959
|
+
if ('lowest_level_value_id' in value) {
|
|
1960
|
+
return value.lowest_level_value_id;
|
|
1961
|
+
}
|
|
1962
|
+
if (value.geo_code_hierarchy_json?.lowest_level_value_id) {
|
|
1963
|
+
return value.geo_code_hierarchy_json.lowest_level_value_id;
|
|
1964
|
+
}
|
|
1965
|
+
if (value.geo_code_hierarchy_json?.geo_lowest_level_value_id) {
|
|
1966
|
+
return value.geo_code_hierarchy_json.geo_lowest_level_value_id;
|
|
1967
|
+
}
|
|
1968
|
+
return undefined;
|
|
1969
|
+
}
|
|
1970
|
+
/**
|
|
1971
|
+
* Resolve the display value for a geo level widget.
|
|
1972
|
+
* When widgetId is explicitly set in Redux (including cleared undefined/null), do not
|
|
1973
|
+
* fall back to shared hierarchy dataPath — that stale path was keeping grandchildren visible.
|
|
1974
|
+
*/
|
|
1975
|
+
function resolveGeoWidgetLevelValue(values, widgetId, dataPath, geoConfig) {
|
|
1976
|
+
if (Object.prototype.hasOwnProperty.call(values, widgetId)) {
|
|
1977
|
+
let value = values[widgetId];
|
|
1978
|
+
if (value === undefined || value === null || value === '') {
|
|
1979
|
+
return value;
|
|
1980
|
+
}
|
|
1981
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
1982
|
+
return extractLevelValueFromStored(value, geoConfig);
|
|
1983
|
+
}
|
|
1984
|
+
return value;
|
|
1985
|
+
}
|
|
1986
|
+
if (!dataPath) {
|
|
1987
|
+
return undefined;
|
|
1988
|
+
}
|
|
1989
|
+
let value = getWidgetValue(values, dataPath, widgetId);
|
|
1990
|
+
if (value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value)) {
|
|
1991
|
+
value = extractLevelValueFromStored(value, geoConfig);
|
|
1992
|
+
}
|
|
1993
|
+
return value;
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Write the in-memory geo hierarchy builder state into Redux at the shared dataPath.
|
|
1997
|
+
*/
|
|
1998
|
+
function applySharedGeoHierarchyToValues(baseValues, groupId, dataPath, widgetId) {
|
|
1999
|
+
const hierarchyJson = geoHierarchyBuilder.buildHierarchyJson(groupId);
|
|
2000
|
+
if (!dataPath || typeof dataPath !== 'string') {
|
|
2001
|
+
return baseValues;
|
|
2002
|
+
}
|
|
2003
|
+
const inner = hierarchyJson?.geo_code_hierarchy_json;
|
|
2004
|
+
const lowestId = hierarchyJson?.geo_lowest_level_value_id;
|
|
2005
|
+
if (dataPath.endsWith('.geo_code_hierarchy_json')) {
|
|
2006
|
+
const prefix = dataPath.substring(0, dataPath.lastIndexOf('.'));
|
|
2007
|
+
let finalUpdatedValues = setWidgetValue(baseValues, dataPath, widgetId, inner);
|
|
2008
|
+
finalUpdatedValues = setWidgetValue(finalUpdatedValues, `${prefix}.geo_lowest_level_value_id`, widgetId, lowestId);
|
|
2009
|
+
return finalUpdatedValues;
|
|
2010
|
+
}
|
|
2011
|
+
return setWidgetValue(baseValues, dataPath, widgetId, inner);
|
|
2012
|
+
}
|
|
2013
|
+
class GeoHierarchyBuilder {
|
|
2014
|
+
constructor() {
|
|
2015
|
+
this.hierarchies = new Map();
|
|
2016
|
+
}
|
|
2017
|
+
/**
|
|
2018
|
+
* Get or create hierarchy state for a group
|
|
2019
|
+
*/
|
|
2020
|
+
getHierarchy(groupId = 'default') {
|
|
2021
|
+
if (!this.hierarchies.has(groupId)) {
|
|
2022
|
+
this.hierarchies.set(groupId, {
|
|
2023
|
+
levels: new Map(),
|
|
2024
|
+
order: [],
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
return this.hierarchies.get(groupId);
|
|
2028
|
+
}
|
|
2029
|
+
/**
|
|
2030
|
+
* Add a level to the hierarchy
|
|
2031
|
+
*/
|
|
2032
|
+
addLevel(level, level_value_id, level_value_mnemonic, groupId = 'default') {
|
|
2033
|
+
const hierarchy = this.getHierarchy(groupId);
|
|
2034
|
+
// If level already exists, remove it and everything after it
|
|
2035
|
+
const existingIndex = hierarchy.order.indexOf(level);
|
|
2036
|
+
if (existingIndex >= 0) {
|
|
2037
|
+
// Remove this level and all subsequent levels
|
|
2038
|
+
const levelsToRemove = hierarchy.order.slice(existingIndex);
|
|
2039
|
+
levelsToRemove.forEach((l) => {
|
|
2040
|
+
hierarchy.levels.delete(l);
|
|
2041
|
+
hierarchy.order = hierarchy.order.filter((o) => o !== l);
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
// Add new level
|
|
2045
|
+
hierarchy.levels.set(level, {
|
|
2046
|
+
level,
|
|
2047
|
+
level_value_id,
|
|
2048
|
+
level_value_mnemonic,
|
|
2049
|
+
});
|
|
2050
|
+
hierarchy.order.push(level);
|
|
2051
|
+
}
|
|
2052
|
+
/**
|
|
2053
|
+
* Remove a level and all levels below it
|
|
2054
|
+
*/
|
|
2055
|
+
removeLevelAndBelow(level, groupId = 'default') {
|
|
2056
|
+
const hierarchy = this.getHierarchy(groupId);
|
|
2057
|
+
const index = hierarchy.order.indexOf(level);
|
|
2058
|
+
if (index >= 0) {
|
|
2059
|
+
// Remove this level and all subsequent levels
|
|
2060
|
+
const levelsToRemove = hierarchy.order.slice(index);
|
|
2061
|
+
levelsToRemove.forEach((l) => {
|
|
2062
|
+
hierarchy.levels.delete(l);
|
|
2063
|
+
hierarchy.order = hierarchy.order.filter((o) => o !== l);
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Build hierarchy JSON structure
|
|
2069
|
+
*/
|
|
2070
|
+
buildHierarchyJson(groupId = 'default') {
|
|
2071
|
+
const hierarchy = this.getHierarchy(groupId);
|
|
2072
|
+
if (hierarchy.order.length === 0) {
|
|
2073
|
+
return null;
|
|
2074
|
+
}
|
|
2075
|
+
const hierarchyArray = hierarchy.order.map((level) => {
|
|
2076
|
+
const data = hierarchy.levels.get(level);
|
|
2077
|
+
return {
|
|
2078
|
+
level: data.level,
|
|
2079
|
+
level_value_id: data.level_value_id,
|
|
2080
|
+
level_value_mnemonic: data.level_value_mnemonic,
|
|
2081
|
+
};
|
|
2082
|
+
});
|
|
2083
|
+
const lowestLevel = hierarchy.order[hierarchy.order.length - 1];
|
|
2084
|
+
const lowestLevelData = hierarchy.levels.get(lowestLevel);
|
|
2085
|
+
return {
|
|
2086
|
+
geo_lowest_level_value_id: lowestLevelData.level_value_id,
|
|
2087
|
+
geo_code_hierarchy_json: {
|
|
2088
|
+
hierarchy: hierarchyArray,
|
|
2089
|
+
lowest_level_value_id: lowestLevelData.level_value_id,
|
|
2090
|
+
},
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
/**
|
|
2094
|
+
* Clear hierarchy for a group
|
|
2095
|
+
*/
|
|
2096
|
+
clear(groupId = 'default') {
|
|
2097
|
+
this.hierarchies.delete(groupId);
|
|
2098
|
+
}
|
|
2099
|
+
/**
|
|
2100
|
+
* Clear all hierarchies
|
|
2101
|
+
*/
|
|
2102
|
+
clearAll() {
|
|
2103
|
+
this.hierarchies.clear();
|
|
2104
|
+
}
|
|
2105
|
+
/**
|
|
2106
|
+
* Get current levels for a group
|
|
2107
|
+
*/
|
|
2108
|
+
getLevels(groupId = 'default') {
|
|
2109
|
+
const hierarchy = this.getHierarchy(groupId);
|
|
2110
|
+
return hierarchy.order.map((level) => hierarchy.levels.get(level));
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
// Singleton instance
|
|
2114
|
+
const geoHierarchyBuilder = new GeoHierarchyBuilder();
|
|
2115
|
+
/** Sentinel written to Redux when a geo level is cleared by cascade (distinct from "never set"). */
|
|
2116
|
+
const GEO_LEVEL_CLEARED = null;
|
|
2117
|
+
const geoWidgetParentRegistry = new Map();
|
|
2118
|
+
function registerGeoWidgetParent(widgetId, parentWidgetId) {
|
|
2119
|
+
geoWidgetParentRegistry.set(widgetId, parentWidgetId || null);
|
|
2120
|
+
}
|
|
2121
|
+
function unregisterGeoWidgetParent(widgetId) {
|
|
2122
|
+
geoWidgetParentRegistry.delete(widgetId);
|
|
2123
|
+
}
|
|
2124
|
+
/** True when changedWidgetId is any upstream geo parent of widgetId (not only immediate parent). */
|
|
2125
|
+
function isUpstreamGeoAncestor(changedWidgetId, widgetId, immediateParentWidgetId) {
|
|
2126
|
+
if (changedWidgetId === widgetId) {
|
|
2127
|
+
return false;
|
|
2128
|
+
}
|
|
2129
|
+
let cursor = immediateParentWidgetId;
|
|
2130
|
+
while (cursor) {
|
|
2131
|
+
if (cursor === changedWidgetId) {
|
|
2132
|
+
return true;
|
|
2133
|
+
}
|
|
2134
|
+
cursor = geoWidgetParentRegistry.get(cursor) ?? null;
|
|
2135
|
+
}
|
|
2136
|
+
return false;
|
|
2137
|
+
}
|
|
2138
|
+
function readStoredHierarchyLevels(values, dataPath, widgetId) {
|
|
2139
|
+
const stored = getWidgetValue(values, dataPath, widgetId);
|
|
2140
|
+
const hierarchy = stored?.hierarchy || stored?.geo_code_hierarchy_json?.hierarchy;
|
|
2141
|
+
if (!Array.isArray(hierarchy)) {
|
|
2142
|
+
return [];
|
|
2143
|
+
}
|
|
2144
|
+
return hierarchy.filter((entry) => entry?.level && entry.level_value_id);
|
|
2145
|
+
}
|
|
2146
|
+
function builderMatchesStored(groupId, storedLevels) {
|
|
2147
|
+
const builderLevels = geoHierarchyBuilder.getLevels(groupId);
|
|
2148
|
+
if (builderLevels.length !== storedLevels.length) {
|
|
2149
|
+
return false;
|
|
2150
|
+
}
|
|
2151
|
+
return storedLevels.every((stored, index) => {
|
|
2152
|
+
const built = builderLevels[index];
|
|
2153
|
+
return (built.level === stored.level &&
|
|
2154
|
+
String(built.level_value_id) === String(stored.level_value_id));
|
|
2155
|
+
});
|
|
2156
|
+
}
|
|
2157
|
+
/** Seed in-memory builder from persisted hierarchy JSON (edit-mode rehydration). */
|
|
2158
|
+
function seedGeoHierarchyFromValues(values, dataPath, widgetId, groupId) {
|
|
2159
|
+
if (!dataPath || typeof dataPath !== 'string') {
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
2162
|
+
const storedLevels = readStoredHierarchyLevels(values, dataPath, widgetId);
|
|
2163
|
+
if (storedLevels.length === 0) {
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
if (builderMatchesStored(groupId, storedLevels)) {
|
|
2167
|
+
return;
|
|
2168
|
+
}
|
|
2169
|
+
geoHierarchyBuilder.clear(groupId);
|
|
2170
|
+
storedLevels.forEach((entry) => {
|
|
2171
|
+
geoHierarchyBuilder.addLevel(entry.level, String(entry.level_value_id), entry.level_value_mnemonic || String(entry.level_value_id), groupId);
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2174
|
+
/** Force-clear builder for a group, then seed from Redux/schema values (e.g. after Cancel). */
|
|
2175
|
+
function resetAndSeedGeoHierarchyFromValues(values, dataPath, widgetId, groupId) {
|
|
2176
|
+
geoHierarchyBuilder.clear(groupId);
|
|
2177
|
+
seedGeoHierarchyFromValues(values, dataPath, widgetId, groupId);
|
|
2178
|
+
}
|
|
2179
|
+
|
|
1934
2180
|
// Define stable empty arrays to avoid selector reference issues
|
|
1935
2181
|
const EMPTY_ERRORS = [];
|
|
1936
2182
|
const EMPTY_DATA_SOURCE$1 = [];
|
|
@@ -2020,6 +2266,17 @@ const useBaseWidget = (options) => {
|
|
|
2020
2266
|
if (isLayoutWidget) {
|
|
2021
2267
|
return undefined; // Layout widgets don't have values
|
|
2022
2268
|
}
|
|
2269
|
+
const geoConfig = config['widget-geo-config'];
|
|
2270
|
+
if (geoConfig) {
|
|
2271
|
+
const value = resolveGeoWidgetLevelValue(values, widgetId, config['widget-data-path'], geoConfig);
|
|
2272
|
+
if (userHasSetValueRef.current) {
|
|
2273
|
+
return value;
|
|
2274
|
+
}
|
|
2275
|
+
if (value === null) {
|
|
2276
|
+
return null;
|
|
2277
|
+
}
|
|
2278
|
+
return value !== undefined ? value : config['widget-data-default'];
|
|
2279
|
+
}
|
|
2023
2280
|
// Try to get value from widgetId first (this should have the actual selected value)
|
|
2024
2281
|
// For geo widgets with dataPath, widgetId stores the actual ID, while dataPath stores the hierarchy object
|
|
2025
2282
|
let value = values[widgetId];
|
|
@@ -2229,6 +2486,14 @@ const useBaseWidget = (options) => {
|
|
|
2229
2486
|
// Track readonly state explicitly to detect changes
|
|
2230
2487
|
// Use JSON.stringify to create a stable reference for the dependency array
|
|
2231
2488
|
const isReadonly = config['widget-readonly'] ?? false;
|
|
2489
|
+
// Leaving edit mode (Cancel): allow mirror/rehydration on next Edit
|
|
2490
|
+
useEffect(() => {
|
|
2491
|
+
if (config['widget-readonly']) {
|
|
2492
|
+
userHasSetValueRef.current = false;
|
|
2493
|
+
lastMirroredValueRef.current = null;
|
|
2494
|
+
lastDispatchedValueRef.current = null;
|
|
2495
|
+
}
|
|
2496
|
+
}, [config['widget-readonly']]);
|
|
2232
2497
|
const dataSource = config['widget-data-source'];
|
|
2233
2498
|
const geoConfig = config['widget-geo-config'];
|
|
2234
2499
|
// Use ref to store handler to avoid stale closures
|
|
@@ -2433,113 +2698,6 @@ const useWidgetCascade = (options) => {
|
|
|
2433
2698
|
}, [cascadeConfig, eventBus, dataSource, widgetId, dispatch]);
|
|
2434
2699
|
};
|
|
2435
2700
|
|
|
2436
|
-
/**
|
|
2437
|
-
* Geo Hierarchy Builder
|
|
2438
|
-
* Manages geo hierarchy state and builds hierarchy JSON structure
|
|
2439
|
-
*/
|
|
2440
|
-
class GeoHierarchyBuilder {
|
|
2441
|
-
constructor() {
|
|
2442
|
-
this.hierarchies = new Map();
|
|
2443
|
-
}
|
|
2444
|
-
/**
|
|
2445
|
-
* Get or create hierarchy state for a group
|
|
2446
|
-
*/
|
|
2447
|
-
getHierarchy(groupId = 'default') {
|
|
2448
|
-
if (!this.hierarchies.has(groupId)) {
|
|
2449
|
-
this.hierarchies.set(groupId, {
|
|
2450
|
-
levels: new Map(),
|
|
2451
|
-
order: [],
|
|
2452
|
-
});
|
|
2453
|
-
}
|
|
2454
|
-
return this.hierarchies.get(groupId);
|
|
2455
|
-
}
|
|
2456
|
-
/**
|
|
2457
|
-
* Add a level to the hierarchy
|
|
2458
|
-
*/
|
|
2459
|
-
addLevel(level, level_value_id, level_value_mnemonic, groupId = 'default') {
|
|
2460
|
-
const hierarchy = this.getHierarchy(groupId);
|
|
2461
|
-
// If level already exists, remove it and everything after it
|
|
2462
|
-
const existingIndex = hierarchy.order.indexOf(level);
|
|
2463
|
-
if (existingIndex >= 0) {
|
|
2464
|
-
// Remove this level and all subsequent levels
|
|
2465
|
-
const levelsToRemove = hierarchy.order.slice(existingIndex);
|
|
2466
|
-
levelsToRemove.forEach((l) => {
|
|
2467
|
-
hierarchy.levels.delete(l);
|
|
2468
|
-
hierarchy.order = hierarchy.order.filter((o) => o !== l);
|
|
2469
|
-
});
|
|
2470
|
-
}
|
|
2471
|
-
// Add new level
|
|
2472
|
-
hierarchy.levels.set(level, {
|
|
2473
|
-
level,
|
|
2474
|
-
level_value_id,
|
|
2475
|
-
level_value_mnemonic,
|
|
2476
|
-
});
|
|
2477
|
-
hierarchy.order.push(level);
|
|
2478
|
-
}
|
|
2479
|
-
/**
|
|
2480
|
-
* Remove a level and all levels below it
|
|
2481
|
-
*/
|
|
2482
|
-
removeLevelAndBelow(level, groupId = 'default') {
|
|
2483
|
-
const hierarchy = this.getHierarchy(groupId);
|
|
2484
|
-
const index = hierarchy.order.indexOf(level);
|
|
2485
|
-
if (index >= 0) {
|
|
2486
|
-
// Remove this level and all subsequent levels
|
|
2487
|
-
const levelsToRemove = hierarchy.order.slice(index);
|
|
2488
|
-
levelsToRemove.forEach((l) => {
|
|
2489
|
-
hierarchy.levels.delete(l);
|
|
2490
|
-
hierarchy.order = hierarchy.order.filter((o) => o !== l);
|
|
2491
|
-
});
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
/**
|
|
2495
|
-
* Build hierarchy JSON structure
|
|
2496
|
-
*/
|
|
2497
|
-
buildHierarchyJson(groupId = 'default') {
|
|
2498
|
-
const hierarchy = this.getHierarchy(groupId);
|
|
2499
|
-
if (hierarchy.order.length === 0) {
|
|
2500
|
-
return null;
|
|
2501
|
-
}
|
|
2502
|
-
const hierarchyArray = hierarchy.order.map((level) => {
|
|
2503
|
-
const data = hierarchy.levels.get(level);
|
|
2504
|
-
return {
|
|
2505
|
-
level: data.level,
|
|
2506
|
-
level_value_id: data.level_value_id,
|
|
2507
|
-
level_value_mnemonic: data.level_value_mnemonic,
|
|
2508
|
-
};
|
|
2509
|
-
});
|
|
2510
|
-
const lowestLevel = hierarchy.order[hierarchy.order.length - 1];
|
|
2511
|
-
const lowestLevelData = hierarchy.levels.get(lowestLevel);
|
|
2512
|
-
return {
|
|
2513
|
-
geo_lowest_level_value_id: lowestLevelData.level_value_id,
|
|
2514
|
-
geo_code_hierarchy_json: {
|
|
2515
|
-
hierarchy: hierarchyArray,
|
|
2516
|
-
lowest_level_value_id: lowestLevelData.level_value_id,
|
|
2517
|
-
},
|
|
2518
|
-
};
|
|
2519
|
-
}
|
|
2520
|
-
/**
|
|
2521
|
-
* Clear hierarchy for a group
|
|
2522
|
-
*/
|
|
2523
|
-
clear(groupId = 'default') {
|
|
2524
|
-
this.hierarchies.delete(groupId);
|
|
2525
|
-
}
|
|
2526
|
-
/**
|
|
2527
|
-
* Clear all hierarchies
|
|
2528
|
-
*/
|
|
2529
|
-
clearAll() {
|
|
2530
|
-
this.hierarchies.clear();
|
|
2531
|
-
}
|
|
2532
|
-
/**
|
|
2533
|
-
* Get current levels for a group
|
|
2534
|
-
*/
|
|
2535
|
-
getLevels(groupId = 'default') {
|
|
2536
|
-
const hierarchy = this.getHierarchy(groupId);
|
|
2537
|
-
return hierarchy.order.map((level) => hierarchy.levels.get(level));
|
|
2538
|
-
}
|
|
2539
|
-
}
|
|
2540
|
-
// Singleton instance
|
|
2541
|
-
const geoHierarchyBuilder = new GeoHierarchyBuilder();
|
|
2542
|
-
|
|
2543
2701
|
// Define stable empty array to avoid selector reference issues
|
|
2544
2702
|
const EMPTY_DATA_SOURCE = [];
|
|
2545
2703
|
/**
|
|
@@ -2559,138 +2717,108 @@ const useGeoWidgetCascade = (options) => {
|
|
|
2559
2717
|
: 'default';
|
|
2560
2718
|
const valuesRef = useRef(values);
|
|
2561
2719
|
const handlerRef = useRef(dataSourceRequestHandler);
|
|
2720
|
+
const lastCascadePublishRef = useRef(undefined);
|
|
2562
2721
|
// Keep refs updated
|
|
2563
2722
|
useEffect(() => {
|
|
2564
2723
|
valuesRef.current = values;
|
|
2565
2724
|
handlerRef.current = dataSourceRequestHandler;
|
|
2566
2725
|
}, [values, dataSourceRequestHandler]);
|
|
2567
2726
|
// Get current value and data source options
|
|
2568
|
-
const currentValue = useSelector((state) =>
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
// If not found in widgetId, try dataPath
|
|
2572
|
-
if (value === undefined && dataPath) {
|
|
2573
|
-
value = getWidgetValue(state.widget.values, dataPath, widgetId);
|
|
2574
|
-
}
|
|
2575
|
-
// Extract value if it's a geo hierarchy object
|
|
2576
|
-
if (value && typeof value === 'object' && !Array.isArray(value) && geoConfig) {
|
|
2577
|
-
const hierarchy = value.hierarchy || value.geo_code_hierarchy_json?.hierarchy;
|
|
2578
|
-
if (Array.isArray(hierarchy)) {
|
|
2579
|
-
const levelData = hierarchy.find((l) => l.level === geoConfig.level);
|
|
2580
|
-
if (levelData) {
|
|
2581
|
-
return levelData.level_value_id;
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
|
-
// Extended fallbacks (matching useBaseWidget)
|
|
2585
|
-
if ('geo_lowest_level_value_id' in value) {
|
|
2586
|
-
return value.geo_lowest_level_value_id;
|
|
2587
|
-
}
|
|
2588
|
-
if ('lowest_level_value_id' in value) {
|
|
2589
|
-
return value.lowest_level_value_id;
|
|
2590
|
-
}
|
|
2591
|
-
if (value.geo_code_hierarchy_json?.lowest_level_value_id) {
|
|
2592
|
-
return value.geo_code_hierarchy_json.lowest_level_value_id;
|
|
2593
|
-
}
|
|
2594
|
-
if (value.geo_code_hierarchy_json?.geo_lowest_level_value_id) {
|
|
2595
|
-
return value.geo_code_hierarchy_json.geo_lowest_level_value_id;
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
return value;
|
|
2599
|
-
});
|
|
2727
|
+
const currentValue = useSelector((state) => geoConfig
|
|
2728
|
+
? resolveGeoWidgetLevelValue(state.widget.values, widgetId, dataPath, geoConfig)
|
|
2729
|
+
: state.widget.values[widgetId]);
|
|
2600
2730
|
// Memoize selector to avoid returning new array reference
|
|
2601
2731
|
const dataSourceOptions = useSelector((state) => state.widget.dataSources[widgetId] ?? EMPTY_DATA_SOURCE);
|
|
2732
|
+
// Register parent chain for upstream-ancestor detection (grandparent → grandchild reset)
|
|
2733
|
+
useEffect(() => {
|
|
2734
|
+
if (!geoConfig) {
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2737
|
+
registerGeoWidgetParent(widgetId, geoConfig.parentWidgetId);
|
|
2738
|
+
return () => unregisterGeoWidgetParent(widgetId);
|
|
2739
|
+
}, [widgetId, geoConfig]);
|
|
2740
|
+
// Keep in-memory builder in sync with persisted hierarchy (reload, cancel→re-edit, etc.)
|
|
2741
|
+
useEffect(() => {
|
|
2742
|
+
if (!geoConfig || typeof dataPath !== 'string') {
|
|
2743
|
+
return;
|
|
2744
|
+
}
|
|
2745
|
+
seedGeoHierarchyFromValues(values, dataPath, widgetId, groupId);
|
|
2746
|
+
}, [geoConfig, dataPath, widgetId, groupId, values]);
|
|
2602
2747
|
useEffect(() => {
|
|
2603
2748
|
if (!geoConfig || !eventBus || !dataSource || dataSource.type !== 'api') {
|
|
2604
2749
|
return;
|
|
2605
2750
|
}
|
|
2606
|
-
const { level, isLastLevel, parentWidgetId } = geoConfig;
|
|
2607
|
-
|
|
2608
|
-
if (parentWidgetId) {
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
// This ensures we don't accidentally overwrite the parent widget's value
|
|
2651
|
-
dispatch(setValue({ widgetId, value: undefined }));
|
|
2652
|
-
}
|
|
2653
|
-
}
|
|
2654
|
-
}
|
|
2655
|
-
else {
|
|
2656
|
-
dispatch(setValue({ widgetId, value: undefined }));
|
|
2751
|
+
const { level, isLastLevel, parentWidgetId: rawParentWidgetId } = geoConfig;
|
|
2752
|
+
const parentWidgetId = rawParentWidgetId || null;
|
|
2753
|
+
if (!parentWidgetId) {
|
|
2754
|
+
return;
|
|
2755
|
+
}
|
|
2756
|
+
const clearThisLevel = (baseValues) => {
|
|
2757
|
+
geoHierarchyBuilder.removeLevelAndBelow(level, groupId);
|
|
2758
|
+
if (dataPath) {
|
|
2759
|
+
dispatch(setValues(applySharedGeoHierarchyToValues(baseValues, groupId, dataPath, widgetId)));
|
|
2760
|
+
}
|
|
2761
|
+
dispatch(setValue({ widgetId, value: GEO_LEVEL_CLEARED }));
|
|
2762
|
+
if (!isLastLevel) {
|
|
2763
|
+
eventBus.publish({
|
|
2764
|
+
type: 'widget:change',
|
|
2765
|
+
widgetId,
|
|
2766
|
+
value: GEO_LEVEL_CLEARED,
|
|
2767
|
+
timestamp: Date.now(),
|
|
2768
|
+
});
|
|
2769
|
+
}
|
|
2770
|
+
dispatch(setDataSource({ widgetId, data: [] }));
|
|
2771
|
+
};
|
|
2772
|
+
const handleParentChange = async (event) => {
|
|
2773
|
+
const isDirectParent = event.widgetId === parentWidgetId;
|
|
2774
|
+
const isAncestor = isUpstreamGeoAncestor(event.widgetId, widgetId, parentWidgetId);
|
|
2775
|
+
if (!isDirectParent && !isAncestor) {
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
2779
|
+
const currentValues = valuesRef.current;
|
|
2780
|
+
const currentHandler = handlerRef.current;
|
|
2781
|
+
// Grandparent (or higher) changed: clear this level; only immediate parent drives reload
|
|
2782
|
+
if (isAncestor && !isDirectParent) {
|
|
2783
|
+
clearThisLevel(currentValues);
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
const parentCleared = event.value === undefined ||
|
|
2787
|
+
event.value === null ||
|
|
2788
|
+
event.value === '' ||
|
|
2789
|
+
event.value === GEO_LEVEL_CLEARED;
|
|
2790
|
+
let parentValue = event.value;
|
|
2791
|
+
if (!parentCleared && (parentValue === undefined || parentValue === null)) {
|
|
2792
|
+
parentValue = currentValues[parentWidgetId];
|
|
2793
|
+
if (parentValue === undefined && dataSource.dependsOn) {
|
|
2794
|
+
parentValue = getWidgetValue(currentValues, dataSource.dependsOn, '');
|
|
2657
2795
|
}
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
const valueKey = dataSource.valueKey || 'level_value_id';
|
|
2673
|
-
const labelKey = dataSource.labelKey || 'level_value_mnemonic';
|
|
2674
|
-
const transformed = transformDataSourceOptions(data, valueKey, labelKey);
|
|
2675
|
-
dispatch(setDataSource({ widgetId, data: transformed }));
|
|
2676
|
-
}
|
|
2677
|
-
catch (error) {
|
|
2678
|
-
console.error('Error reloading geo data source:', error);
|
|
2679
|
-
dispatch(setDataSource({ widgetId, data: [] }));
|
|
2680
|
-
}
|
|
2796
|
+
}
|
|
2797
|
+
clearThisLevel(currentValues);
|
|
2798
|
+
if (currentHandler && parentValue !== null && parentValue !== undefined && parentValue !== '') {
|
|
2799
|
+
try {
|
|
2800
|
+
const updatedValues = {
|
|
2801
|
+
...currentValues,
|
|
2802
|
+
[parentWidgetId]: parentValue,
|
|
2803
|
+
};
|
|
2804
|
+
const levelId = geoConfig.level;
|
|
2805
|
+
const data = await getApiDataSource(dataSource, updatedValues, currentHandler, levelId);
|
|
2806
|
+
const valueKey = dataSource.valueKey || 'level_value_id';
|
|
2807
|
+
const labelKey = dataSource.labelKey || 'level_value_mnemonic';
|
|
2808
|
+
const transformed = transformDataSourceOptions(data, valueKey, labelKey);
|
|
2809
|
+
dispatch(setDataSource({ widgetId, data: transformed }));
|
|
2681
2810
|
}
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
geoHierarchyBuilder.removeLevelAndBelow(level, groupId);
|
|
2811
|
+
catch (error) {
|
|
2812
|
+
console.error('Error reloading geo data source:', error);
|
|
2685
2813
|
dispatch(setDataSource({ widgetId, data: [] }));
|
|
2686
2814
|
}
|
|
2687
|
-
}
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
}
|
|
2693
|
-
}, [geoConfig, eventBus, dataSource, widgetId, dataPath, dispatch]);
|
|
2815
|
+
}
|
|
2816
|
+
};
|
|
2817
|
+
const unsubscribe = eventBus.subscribe('widget:change', handleParentChange);
|
|
2818
|
+
return () => {
|
|
2819
|
+
unsubscribe();
|
|
2820
|
+
};
|
|
2821
|
+
}, [geoConfig, eventBus, dataSource, widgetId, dataPath, dispatch, groupId]);
|
|
2694
2822
|
// Handle value changes to build hierarchy
|
|
2695
2823
|
useEffect(() => {
|
|
2696
2824
|
if (!geoConfig) {
|
|
@@ -2699,22 +2827,20 @@ const useGeoWidgetCascade = (options) => {
|
|
|
2699
2827
|
// Skip if value is undefined (it might still be loading or rehydrating)
|
|
2700
2828
|
// ONLY clear hierarchy if the value is explicitly null or empty string (user action)
|
|
2701
2829
|
if (currentValue === null || currentValue === '') {
|
|
2702
|
-
const { level } = geoConfig;
|
|
2830
|
+
const { level, isLastLevel } = geoConfig;
|
|
2703
2831
|
geoHierarchyBuilder.removeLevelAndBelow(level, groupId);
|
|
2704
2832
|
// If we have a dataPath, we need to update Redux with the cleared hierarchy
|
|
2705
2833
|
if (dataPath) {
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
}
|
|
2717
|
-
dispatch(setValues(finalUpdatedValues));
|
|
2834
|
+
dispatch(setValues(applySharedGeoHierarchyToValues(valuesRef.current, groupId, dataPath, widgetId)));
|
|
2835
|
+
}
|
|
2836
|
+
if (!isLastLevel && eventBus && lastCascadePublishRef.current !== GEO_LEVEL_CLEARED) {
|
|
2837
|
+
lastCascadePublishRef.current = GEO_LEVEL_CLEARED;
|
|
2838
|
+
eventBus.publish({
|
|
2839
|
+
type: 'widget:change',
|
|
2840
|
+
widgetId,
|
|
2841
|
+
value: GEO_LEVEL_CLEARED,
|
|
2842
|
+
timestamp: Date.now(),
|
|
2843
|
+
});
|
|
2718
2844
|
}
|
|
2719
2845
|
return;
|
|
2720
2846
|
}
|
|
@@ -2765,30 +2891,20 @@ const useGeoWidgetCascade = (options) => {
|
|
|
2765
2891
|
// Add level to hierarchy
|
|
2766
2892
|
geoHierarchyBuilder.addLevel(level, level_value_id, level_value_mnemonic, groupId);
|
|
2767
2893
|
// Build and store hierarchy JSON on every change
|
|
2768
|
-
if (dataPath) {
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
finalUpdatedValues = setWidgetValue(finalUpdatedValues, `${prefix}.geo_lowest_level_value_id`, widgetId, hierarchyJson.geo_lowest_level_value_id);
|
|
2781
|
-
}
|
|
2782
|
-
else {
|
|
2783
|
-
// Fallback if path doesn't follow the naming convention
|
|
2784
|
-
finalUpdatedValues = setWidgetValue(finalUpdatedValues, dataPath, widgetId, hierarchyJson.geo_code_hierarchy_json);
|
|
2785
|
-
}
|
|
2786
|
-
// CRITICAL: Use setValues for deep merge instead of replacing root keys with setValue
|
|
2787
|
-
// setWidgetValue returns the complete updated state object with all keys preserved
|
|
2788
|
-
dispatch(setValues(finalUpdatedValues));
|
|
2789
|
-
}
|
|
2894
|
+
if (dataPath && geoHierarchyBuilder.buildHierarchyJson(groupId)) {
|
|
2895
|
+
dispatch(setValues(applySharedGeoHierarchyToValues(valuesRef.current, groupId, dataPath, widgetId)));
|
|
2896
|
+
}
|
|
2897
|
+
// Notify descendants when this level changes via hierarchy/rehydration (handleChange may not run).
|
|
2898
|
+
if (!isLastLevel && eventBus && lastCascadePublishRef.current !== level_value_id) {
|
|
2899
|
+
lastCascadePublishRef.current = level_value_id;
|
|
2900
|
+
eventBus.publish({
|
|
2901
|
+
type: 'widget:change',
|
|
2902
|
+
widgetId,
|
|
2903
|
+
value: level_value_id,
|
|
2904
|
+
timestamp: Date.now(),
|
|
2905
|
+
});
|
|
2790
2906
|
}
|
|
2791
|
-
}, [geoConfig, currentValue, widgetId, dataPath, dispatch, dataSourceOptions]);
|
|
2907
|
+
}, [geoConfig, currentValue, widgetId, dataPath, dispatch, dataSourceOptions, eventBus, groupId]);
|
|
2792
2908
|
};
|
|
2793
2909
|
|
|
2794
2910
|
class WidgetRegistry {
|
|
@@ -4658,7 +4774,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4658
4774
|
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4659
4775
|
const currentState = store.getState().widget;
|
|
4660
4776
|
const currentSchemaData = currentState.values || {};
|
|
4661
|
-
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch,
|
|
4777
|
+
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch, false);
|
|
4662
4778
|
if (!isSectionValid)
|
|
4663
4779
|
return;
|
|
4664
4780
|
const oldSchemaData = schemaData || contextSchemaData;
|
|
@@ -8787,16 +8903,65 @@ const DisplayWidget = ({ config }) => {
|
|
|
8787
8903
|
return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] DisplayFieldWidget flex flex-col sm:flex-row sm:items-start", children: [jsxRuntimeExports.jsxs("div", { className: "text-base text-gray-600 font-medium md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: label, children: [label, ":"] }), jsxRuntimeExports.jsx("div", { className: "flex-1 min-w-0", children: jsxRuntimeExports.jsx("div", { className: "text-base text-gray-900 font-medium", title: String(displayValue ?? ''), children: displayValue }) })] }));
|
|
8788
8904
|
};
|
|
8789
8905
|
|
|
8906
|
+
const getDateColumnConstraintError = (column, cellValue, rowValues, translateConfig) => {
|
|
8907
|
+
const displayValue = cellValue && typeof cellValue === 'string' ? cellValue.split('T')[0] : '';
|
|
8908
|
+
if (!displayValue) {
|
|
8909
|
+
return null;
|
|
8910
|
+
}
|
|
8911
|
+
const optionsConfig = column['widget-data-options'];
|
|
8912
|
+
const formatConfig = column['widget-data-format'];
|
|
8913
|
+
const dateConstraint = formatConfig?.dateConstraint || 'any';
|
|
8914
|
+
const minDate = optionsConfig?.minDate;
|
|
8915
|
+
const maxDate = optionsConfig?.maxDate;
|
|
8916
|
+
const minDateField = optionsConfig?.minDateField;
|
|
8917
|
+
const maxDateField = optionsConfig?.maxDateField;
|
|
8918
|
+
const minDateMessage = optionsConfig?.minDateMessage
|
|
8919
|
+
? translateConfig(optionsConfig.minDateMessage)
|
|
8920
|
+
: undefined;
|
|
8921
|
+
const maxDateMessage = optionsConfig?.maxDateMessage
|
|
8922
|
+
? translateConfig(optionsConfig.maxDateMessage)
|
|
8923
|
+
: undefined;
|
|
8924
|
+
const resolveSiblingDate = (fieldRef) => {
|
|
8925
|
+
if (!fieldRef) {
|
|
8926
|
+
return undefined;
|
|
8927
|
+
}
|
|
8928
|
+
const raw = getValueByPath(rowValues, fieldRef) ?? rowValues[fieldRef];
|
|
8929
|
+
return resolveDateBoundFromFieldValue(raw);
|
|
8930
|
+
};
|
|
8931
|
+
const effectiveMinDate = mergeMinDateBounds(getMinDate(dateConstraint, minDate), resolveSiblingDate(minDateField));
|
|
8932
|
+
const effectiveMaxDate = mergeMaxDateBounds(getMaxDate(dateConstraint, maxDate), resolveSiblingDate(maxDateField));
|
|
8933
|
+
return validateDateConstraints(displayValue, effectiveMinDate, effectiveMaxDate, dateConstraint, { minDateMessage, maxDateMessage });
|
|
8934
|
+
};
|
|
8935
|
+
const isTableRowDataValid = (rowData, columns, tableReadonly, translateConfig) => {
|
|
8936
|
+
for (const col of columns) {
|
|
8937
|
+
if (tableReadonly || col['widget-readonly'] === true) {
|
|
8938
|
+
continue;
|
|
8939
|
+
}
|
|
8940
|
+
const columnKey = col['column-key'];
|
|
8941
|
+
const cellValue = rowData[columnKey];
|
|
8942
|
+
const widgetErrors = validateWidget(cellValue, col['widget-data-validation'], col['widget-required']);
|
|
8943
|
+
if (widgetErrors.length > 0) {
|
|
8944
|
+
return false;
|
|
8945
|
+
}
|
|
8946
|
+
if ((col.widget || 'text') === 'date') {
|
|
8947
|
+
const dateError = getDateColumnConstraintError(col, cellValue, rowData, translateConfig);
|
|
8948
|
+
if (dateError) {
|
|
8949
|
+
return false;
|
|
8950
|
+
}
|
|
8951
|
+
}
|
|
8952
|
+
}
|
|
8953
|
+
return true;
|
|
8954
|
+
};
|
|
8790
8955
|
const TableCellSelect = ({ config, value, onValueChange }) => {
|
|
8791
8956
|
const { translate } = useWidgetTranslation();
|
|
8792
8957
|
// Use useBaseWidget to get data source options (it handles loading)
|
|
8793
8958
|
const { dataSourceOptions, loading, config: widgetConfig, } = useBaseWidget({ config });
|
|
8794
8959
|
const isReadonly = config['widget-readonly'] || false;
|
|
8795
|
-
return (jsxRuntimeExports.jsxs("select", { value: value || '', onChange: (e) => onValueChange(e.target.value), disabled: isReadonly || loading, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly || loading ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8796
|
-
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8960
|
+
return (jsxRuntimeExports.jsxs("div", { className: "table-cell-field w-full", children: [jsxRuntimeExports.jsxs("select", { value: value || '', onChange: (e) => onValueChange(e.target.value), disabled: isReadonly || loading, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly || loading ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8961
|
+
borderRadius: '10px',
|
|
8962
|
+
borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
8963
|
+
backgroundColor: isReadonly || loading ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8964
|
+
}, children: [jsxRuntimeExports.jsx("option", { value: "", children: translate('common.select') || 'Select' }), dataSourceOptions.map((option) => (jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value)))] }), jsxRuntimeExports.jsx("p", { className: "table-cell-field-error", "aria-hidden": "true", children: '\u00a0' })] }));
|
|
8800
8965
|
};
|
|
8801
8966
|
const SelectDisplayValue$1 = ({ config, value }) => {
|
|
8802
8967
|
const { dataSourceOptions, loading } = useBaseWidget({ config });
|
|
@@ -8815,11 +8980,11 @@ const TableCellText = ({ config, value, onValueChange }) => {
|
|
|
8815
8980
|
config['widget-data-format'];
|
|
8816
8981
|
const maxLength = config['widget-data-validation']?.maxLength;
|
|
8817
8982
|
const displayValue = value !== null && value !== undefined ? String(value) : '';
|
|
8818
|
-
return (jsxRuntimeExports.jsx("input", { type: "text", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, maxLength: maxLength, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8983
|
+
return (jsxRuntimeExports.jsxs("div", { className: "table-cell-field w-full", children: [jsxRuntimeExports.jsx("input", { type: "text", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, maxLength: maxLength, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8984
|
+
borderRadius: '10px',
|
|
8985
|
+
borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
8986
|
+
backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8987
|
+
} }), jsxRuntimeExports.jsx("p", { className: "table-cell-field-error", "aria-hidden": "true", children: '\u00a0' })] }));
|
|
8823
8988
|
};
|
|
8824
8989
|
const TableCellNumber = ({ config, value, onValueChange }) => {
|
|
8825
8990
|
const isReadonly = config['widget-readonly'] || false;
|
|
@@ -8842,11 +9007,11 @@ const TableCellNumber = ({ config, value, onValueChange }) => {
|
|
|
8842
9007
|
onValueChange(inputValue);
|
|
8843
9008
|
}
|
|
8844
9009
|
};
|
|
8845
|
-
return (jsxRuntimeExports.jsx("input", { type: "number", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: validationConfig?.min, max: validationConfig?.max, step: formatConfig?.decimalPlaces ? Math.pow(0.1, formatConfig.decimalPlaces) : undefined, className: `w-full h-[28px] px-2 text-sm border focus:outline-none text-right ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
9010
|
+
return (jsxRuntimeExports.jsxs("div", { className: "table-cell-field w-full", children: [jsxRuntimeExports.jsx("input", { type: "number", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: validationConfig?.min, max: validationConfig?.max, step: formatConfig?.decimalPlaces ? Math.pow(0.1, formatConfig.decimalPlaces) : undefined, className: `w-full h-[28px] px-2 text-sm border focus:outline-none text-right ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
9011
|
+
borderRadius: '10px',
|
|
9012
|
+
borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
9013
|
+
backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
9014
|
+
} }), jsxRuntimeExports.jsx("p", { className: "table-cell-field-error", "aria-hidden": "true", children: '\u00a0' })] }));
|
|
8850
9015
|
};
|
|
8851
9016
|
const TableCellDate = ({ config, value, rowValues, onValueChange }) => {
|
|
8852
9017
|
const { translateConfig } = useWidgetTranslation();
|
|
@@ -8905,13 +9070,15 @@ const TableCellDate = ({ config, value, rowValues, onValueChange }) => {
|
|
|
8905
9070
|
setConstraintError(error);
|
|
8906
9071
|
};
|
|
8907
9072
|
const hasError = Boolean(constraintError);
|
|
8908
|
-
return (jsxRuntimeExports.jsxs("div", { className: "w-full", children: [jsxRuntimeExports.jsx("input", { type: "date", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: effectiveMinDate, max: effectiveMaxDate, title: constraintError || translateConfig(config['widget-data-tooltip']), className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''}
|
|
9073
|
+
return (jsxRuntimeExports.jsxs("div", { className: "table-cell-field w-full", children: [jsxRuntimeExports.jsx("input", { type: "date", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: effectiveMinDate, max: effectiveMaxDate, title: constraintError || translateConfig(config['widget-data-tooltip']), className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8909
9074
|
borderRadius: '10px',
|
|
8910
9075
|
borderColor: hasError
|
|
8911
9076
|
? 'var(--owt-color-error, #B91C1C)'
|
|
8912
9077
|
: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
8913
9078
|
backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8914
|
-
} }),
|
|
9079
|
+
} }), jsxRuntimeExports.jsx("p", { className: "table-cell-field-error text-xs mt-0.5 leading-tight", style: {
|
|
9080
|
+
color: hasError ? 'var(--owt-color-error, #B91C1C)' : 'transparent',
|
|
9081
|
+
}, "aria-live": "polite", children: constraintError ?? '\u00a0' })] }));
|
|
8915
9082
|
};
|
|
8916
9083
|
const TableWidget = ({ config }) => {
|
|
8917
9084
|
const { value, error, touched, isEnabled, onChange, config: widgetConfig, } = useBaseWidget({ config });
|
|
@@ -8937,6 +9104,18 @@ const TableWidget = ({ config }) => {
|
|
|
8937
9104
|
const isSectionEditMode = !isReadonly && operations.edit;
|
|
8938
9105
|
// Check if any row is being edited (either manually or via section edit mode)
|
|
8939
9106
|
const isAnyRowEditing = editingState !== null || isAdding;
|
|
9107
|
+
const canSaveEditingRow = useMemo(() => {
|
|
9108
|
+
if (!editingState) {
|
|
9109
|
+
return false;
|
|
9110
|
+
}
|
|
9111
|
+
return isTableRowDataValid(editingState.currentValue, columns, isReadonly, translateConfig);
|
|
9112
|
+
}, [editingState, columns, isReadonly, translateConfig]);
|
|
9113
|
+
const canSaveNewRow = useMemo(() => {
|
|
9114
|
+
if (!isAdding || !newRowData) {
|
|
9115
|
+
return false;
|
|
9116
|
+
}
|
|
9117
|
+
return isTableRowDataValid(newRowData, columns, isReadonly, translateConfig);
|
|
9118
|
+
}, [isAdding, newRowData, columns, isReadonly, translateConfig]);
|
|
8940
9119
|
// Show confirmation dialog
|
|
8941
9120
|
const showConfirmation = useCallback((message, onConfirm, onCancel) => {
|
|
8942
9121
|
setConfirmationState({
|
|
@@ -9026,6 +9205,8 @@ const TableWidget = ({ config }) => {
|
|
|
9026
9205
|
const saveEdit = useCallback(async () => {
|
|
9027
9206
|
if (!editingState)
|
|
9028
9207
|
return;
|
|
9208
|
+
if (!canSaveEditingRow)
|
|
9209
|
+
return;
|
|
9029
9210
|
const rowData = editingState.currentValue;
|
|
9030
9211
|
const rowIndex = editingState.rowIndex;
|
|
9031
9212
|
setLoadingRowIndex(rowIndex);
|
|
@@ -9097,7 +9278,7 @@ const TableWidget = ({ config }) => {
|
|
|
9097
9278
|
finally {
|
|
9098
9279
|
setLoadingRowIndex(null);
|
|
9099
9280
|
}
|
|
9100
|
-
}, [editingState, rows, onChange, dataSourceRequestHandler, apiConfig, translate, isSectionEditMode, originalRows, columns, widgetConfig, dispatch]);
|
|
9281
|
+
}, [editingState, canSaveEditingRow, rows, onChange, dataSourceRequestHandler, apiConfig, translate, isSectionEditMode, originalRows, columns, widgetConfig, dispatch]);
|
|
9101
9282
|
// Add new row
|
|
9102
9283
|
const startAdd = useCallback(() => {
|
|
9103
9284
|
// If there's an unsaved edit, cancel it first (no confirmation needed)
|
|
@@ -9115,6 +9296,8 @@ const TableWidget = ({ config }) => {
|
|
|
9115
9296
|
const saveAdd = useCallback(async () => {
|
|
9116
9297
|
if (!isAdding || !newRowData)
|
|
9117
9298
|
return;
|
|
9299
|
+
if (!canSaveNewRow)
|
|
9300
|
+
return;
|
|
9118
9301
|
setLoadingRowIndex(-1); // Use -1 to indicate new row
|
|
9119
9302
|
try {
|
|
9120
9303
|
let savedRow = { ...newRowData };
|
|
@@ -9145,7 +9328,7 @@ const TableWidget = ({ config }) => {
|
|
|
9145
9328
|
finally {
|
|
9146
9329
|
setLoadingRowIndex(null);
|
|
9147
9330
|
}
|
|
9148
|
-
}, [isAdding, newRowData, rows, onChange, dataSourceRequestHandler, apiConfig, translate, isSectionEditMode]);
|
|
9331
|
+
}, [isAdding, newRowData, canSaveNewRow, rows, onChange, dataSourceRequestHandler, apiConfig, translate, isSectionEditMode]);
|
|
9149
9332
|
// Delete row
|
|
9150
9333
|
const deleteRow = useCallback(async (rowIndex) => {
|
|
9151
9334
|
if (isAnyRowEditing) {
|
|
@@ -9423,6 +9606,22 @@ const TableWidget = ({ config }) => {
|
|
|
9423
9606
|
box-shadow: 0 0 0 1px var(--owt-widget-input-focus-border, #F07B1A);
|
|
9424
9607
|
border-color: var(--owt-widget-input-focus-border, #F07B1A);
|
|
9425
9608
|
}
|
|
9609
|
+
|
|
9610
|
+
/* Keep inputs and action buttons top-aligned when a cell shows validation text */
|
|
9611
|
+
.${tableWidgetId} tr.table-row-editing td {
|
|
9612
|
+
vertical-align: top;
|
|
9613
|
+
}
|
|
9614
|
+
|
|
9615
|
+
.${tableWidgetId} .table-cell-field-error {
|
|
9616
|
+
min-height: 1.125rem;
|
|
9617
|
+
}
|
|
9618
|
+
|
|
9619
|
+
.${tableWidgetId} .table-cell-actions {
|
|
9620
|
+
display: flex;
|
|
9621
|
+
flex-direction: row;
|
|
9622
|
+
gap: 0.5rem;
|
|
9623
|
+
align-items: flex-start;
|
|
9624
|
+
}
|
|
9426
9625
|
` }), jsxRuntimeExports.jsxs("div", { className: `table-widget-container ${tableWidgetId}`, children: [confirmationState?.show && (jsxRuntimeExports.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50", style: { backgroundColor: 'rgba(0,0,0,0.5)' }, children: jsxRuntimeExports.jsxs("div", { className: "rounded-lg p-6 max-w-md w-full mx-4", style: { backgroundColor: 'var(--owt-color-bg, #FFFFFF)' }, children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold mb-4", style: { color: 'var(--owt-color-text, #011627)' }, children: translate('table.confirm') || 'Confirm Action' }), jsxRuntimeExports.jsx("p", { className: "mb-6", style: { color: 'var(--owt-color-text, #011627)' }, children: confirmationState.message }), jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-3", children: [jsxRuntimeExports.jsx("button", { onClick: confirmationState.onCancel, className: "px-4 py-2 text-sm font-medium", style: {
|
|
9427
9626
|
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
9428
9627
|
border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
|
|
@@ -9441,7 +9640,7 @@ const TableWidget = ({ config }) => {
|
|
|
9441
9640
|
}, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: { borderRadius: 'var(--owt-widget-table-border-radius, 15px)', borderColor: 'var(--owt-widget-table-border-color, #C4C4C4)' }, children: jsxRuntimeExports.jsxs("table", { className: "min-w-full", style: { borderCollapse: 'separate', borderSpacing: 0 }, children: [jsxRuntimeExports.jsx("thead", { style: { backgroundColor: 'var(--owt-widget-table-header-bg, #F6F6F6)' }, children: jsxRuntimeExports.jsxs("tr", { style: { borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)' }, children: [columns.map((col) => (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translateConfig(col['widget-label']) }, col['column-key']))), ((operations.edit || operations.remove) && !isReadonly) || isAnyRowEditing || isSectionEditMode ? (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translate('common.actions') || 'Actions' })) : null] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && !isAdding && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: columns.length + (((operations.edit || operations.remove) && !isReadonly) || isSectionEditMode ? 1 : 0), className: "px-4 py-6 text-center text-sm", style: { color: 'var(--owt-widget-table-empty-color, #727474)' }, children: [translate('table.noData') || 'No records available.', operations.add && !isReadonly && ` ${translate('table.clickToAdd') || 'Click "Add New Record" to add one.'}`] }) })), rows.map((row, rowIndex) => {
|
|
9442
9641
|
const isEditing = isRowEditing(rowIndex);
|
|
9443
9642
|
const isLoading = loadingRowIndex === rowIndex;
|
|
9444
|
-
return (jsxRuntimeExports.jsxs("tr", { className: isLoading ? 'opacity-50' : ''
|
|
9643
|
+
return (jsxRuntimeExports.jsxs("tr", { className: `${isLoading ? 'opacity-50' : ''}${isEditing ? ' table-row-editing' : ''}`, style: {
|
|
9445
9644
|
borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
|
|
9446
9645
|
backgroundColor: isEditing
|
|
9447
9646
|
? 'var(--owt-widget-table-editing-row-bg, #FBE6AA)'
|
|
@@ -9452,7 +9651,7 @@ const TableWidget = ({ config }) => {
|
|
|
9452
9651
|
return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rowIndex, col, row) }, col['column-key']));
|
|
9453
9652
|
}), ((operations.edit || operations.remove) && !isReadonly) || isEditing || isSectionEditMode ? (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", style: { minWidth: '120px' }, children: isEditing ? (
|
|
9454
9653
|
// Show OK (Save)/Cancel buttons when row is being edited (works in both section edit mode and normal mode)
|
|
9455
|
-
jsxRuntimeExports.jsxs("div", { className: "
|
|
9654
|
+
jsxRuntimeExports.jsxs("div", { className: "table-cell-actions", style: { width: '100%' }, children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveEdit, disabled: isLoading || !canSaveEditingRow, className: "px-3 py-1 text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap flex-shrink-0", style: {
|
|
9456
9655
|
display: 'inline-block',
|
|
9457
9656
|
minWidth: '60px',
|
|
9458
9657
|
backgroundColor: 'var(--owt-color-success, #16A34A)',
|
|
@@ -9479,7 +9678,7 @@ const TableWidget = ({ config }) => {
|
|
|
9479
9678
|
backgroundColor: 'transparent',
|
|
9480
9679
|
border: 'none',
|
|
9481
9680
|
}, children: translate('common.remove') || 'Delete' }))] })) })) : null] }, rowIndex));
|
|
9482
|
-
}), isAdding && newRowData && (jsxRuntimeExports.jsxs("tr", { style: { backgroundColor: 'var(--owt-widget-table-editing-row-bg, #FBE6AA)' }, children: [columns.map((col) => (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rows.length, col, { ...newRowData, edit_action: 'ADD' }) }, col['column-key']))), jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsxs("div", { className: "
|
|
9681
|
+
}), isAdding && newRowData && (jsxRuntimeExports.jsxs("tr", { className: "table-row-editing", style: { backgroundColor: 'var(--owt-widget-table-editing-row-bg, #FBE6AA)' }, children: [columns.map((col) => (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rows.length, col, { ...newRowData, edit_action: 'ADD' }) }, col['column-key']))), jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsxs("div", { className: "table-cell-actions", children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveAdd, disabled: loadingRowIndex === -1 || !canSaveNewRow, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
9483
9682
|
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
9484
9683
|
backgroundColor: 'var(--owt-color-success, #16A34A)',
|
|
9485
9684
|
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
@@ -11767,5 +11966,5 @@ const translateUISchema = (schema, translate) => {
|
|
|
11767
11966
|
};
|
|
11768
11967
|
};
|
|
11769
11968
|
|
|
11770
|
-
export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DialogTableWidget, DisplayWidget, FileInputWidget, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getFormattedNumberLength, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, initI18n, isAllowedKey, normalizeNumericDefault, parseDataPath, parseNumber, registerDefaultWidgets, removeMask, resetAll, resetWidget, resolveTheme, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
|
|
11969
|
+
export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DialogTableWidget, DisplayWidget, FileInputWidget, GEO_LEVEL_CLEARED, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, applySharedGeoHierarchyToValues, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getFormattedNumberLength, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, initI18n, isAllowedKey, isUpstreamGeoAncestor, normalizeNumericDefault, parseDataPath, parseNumber, registerDefaultWidgets, registerGeoWidgetParent, removeMask, resetAll, resetAndSeedGeoHierarchyFromValues, resetWidget, resolveGeoWidgetLevelValue, resolveTheme, resolveWidgetIdValue, seedGeoHierarchyFromValues, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, unregisterGeoWidgetParent, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
|
|
11771
11970
|
//# sourceMappingURL=index.esm.js.map
|