@openg2p/registry-widgets 1.1.3 → 1.1.4-dev.1
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/components/SectionRenderer/utils/executeSectionSave.d.ts.map +1 -1
- package/dist/components/SectionRenderer.d.ts +61 -0
- package/dist/components/SectionRenderer.d.ts.map +1 -0
- package/dist/hooks/useGeoHierarchy.d.ts +1 -0
- package/dist/hooks/useGeoHierarchy.d.ts.map +1 -1
- package/dist/hooks/useGeoWidgetCascade.d.ts +12 -0
- package/dist/hooks/useGeoWidgetCascade.d.ts.map +1 -0
- package/dist/hooks/useWidgetTranslation.d.ts +16 -0
- package/dist/hooks/useWidgetTranslation.d.ts.map +1 -0
- package/dist/i18n/config.d.ts +21 -0
- package/dist/i18n/config.d.ts.map +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.esm.js +141 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +141 -25
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +9 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/buildSectionChanges.d.ts +11 -0
- package/dist/utils/buildSectionChanges.d.ts.map +1 -0
- package/dist/utils/geoHierarchy.d.ts +13 -0
- package/dist/utils/geoHierarchy.d.ts.map +1 -1
- package/dist/utils/schemaNamespace.d.ts +12 -0
- package/dist/utils/schemaNamespace.d.ts.map +1 -0
- package/dist/widgets/ArrayWidget.d.ts +29 -0
- package/dist/widgets/ArrayWidget.d.ts.map +1 -0
- package/dist/widgets/CurrencyInputWidget.d.ts +24 -0
- package/dist/widgets/CurrencyInputWidget.d.ts.map +1 -0
- package/dist/widgets/DocsWidget.d.ts.map +1 -1
- package/dist/widgets/GeoHierarchyWidget.d.ts.map +1 -1
- package/dist/widgets/HeaderSectionWidget.d.ts.map +1 -1
- package/dist/widgets/IterableAccordionWidget.d.ts +30 -0
- package/dist/widgets/IterableAccordionWidget.d.ts.map +1 -0
- package/dist/widgets/SimpleTableWidget.d.ts +32 -0
- package/dist/widgets/SimpleTableWidget.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2990,6 +2990,15 @@ const extractProfileImage = (records) => {
|
|
|
2990
2990
|
profileImage = value;
|
|
2991
2991
|
copy[key] = '';
|
|
2992
2992
|
}
|
|
2993
|
+
else if (isSerializedFile(value)) {
|
|
2994
|
+
try {
|
|
2995
|
+
profileImage = deserializeFile(value);
|
|
2996
|
+
copy[key] = '';
|
|
2997
|
+
}
|
|
2998
|
+
catch (err) {
|
|
2999
|
+
console.error('Failed to deserialize profile image:', err);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
2993
3002
|
}
|
|
2994
3003
|
return copy;
|
|
2995
3004
|
});
|
|
@@ -8697,10 +8706,6 @@ const DEFAULT_LABELS = {
|
|
|
8697
8706
|
lastApprovedBy: 'Last Approved by',
|
|
8698
8707
|
lastApprovedAt: 'Last Approved at',
|
|
8699
8708
|
};
|
|
8700
|
-
// Options are loaded in both view and edit modes because view mode
|
|
8701
|
-
// needs them to resolve display labels (e.g. "active" → "Active").
|
|
8702
|
-
// For API data sources, loading is deferred to edit mode to avoid
|
|
8703
|
-
// unnecessary network calls when only labels are needed.
|
|
8704
8709
|
function useFieldDataSource(fieldKey, fieldConfig, isReadonly) {
|
|
8705
8710
|
const [options, setOptions] = React.useState([]);
|
|
8706
8711
|
const { dataSourceRequestHandler, schemaData } = useWidgetContext();
|
|
@@ -8804,11 +8809,15 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
8804
8809
|
const imageUrlVal = findValue('imageUrl');
|
|
8805
8810
|
const [previewUrl, setPreviewUrl] = React.useState(null);
|
|
8806
8811
|
React.useEffect(() => {
|
|
8807
|
-
if (imageUrlVal
|
|
8812
|
+
if (isFile(imageUrlVal)) {
|
|
8808
8813
|
const url = URL.createObjectURL(imageUrlVal);
|
|
8809
8814
|
setPreviewUrl(url);
|
|
8810
8815
|
return () => URL.revokeObjectURL(url);
|
|
8811
8816
|
}
|
|
8817
|
+
if (isSerializedFile(imageUrlVal) && imageUrlVal.data) {
|
|
8818
|
+
setPreviewUrl(`data:${imageUrlVal.type};base64,${imageUrlVal.data}`);
|
|
8819
|
+
return;
|
|
8820
|
+
}
|
|
8812
8821
|
setPreviewUrl(null);
|
|
8813
8822
|
}, [imageUrlVal]);
|
|
8814
8823
|
const displayImageUrl = previewUrl || (typeof imageUrlVal === 'string' && imageUrlVal ? imageUrlVal : null);
|
|
@@ -8912,16 +8921,25 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
8912
8921
|
}, [statusValue, statusOptions]);
|
|
8913
8922
|
const statusColor = statusColors[String(statusValue).toLowerCase()] || 'var(--owt-color-text-muted, #6B7280)';
|
|
8914
8923
|
const fileInputRef = React.useRef(null);
|
|
8915
|
-
const handleImageUpload = React.useCallback((e) => {
|
|
8924
|
+
const handleImageUpload = React.useCallback(async (e) => {
|
|
8916
8925
|
const file = e.target.files?.[0];
|
|
8917
8926
|
if (!file || !paths.imageUrl)
|
|
8918
8927
|
return;
|
|
8919
|
-
|
|
8920
|
-
|
|
8928
|
+
try {
|
|
8929
|
+
const serialized = await serializeFile(file);
|
|
8930
|
+
dispatch(setValues(setValueByPath({ ...values }, paths.imageUrl, serialized)));
|
|
8931
|
+
}
|
|
8932
|
+
catch (err) {
|
|
8933
|
+
console.error('[HeaderSectionWidget] Error serializing image:', err);
|
|
8934
|
+
}
|
|
8935
|
+
finally {
|
|
8936
|
+
e.target.value = '';
|
|
8937
|
+
}
|
|
8921
8938
|
}, [paths.imageUrl, values, dispatch]);
|
|
8922
8939
|
const handleImageDelete = React.useCallback(() => {
|
|
8923
8940
|
if (!paths.imageUrl)
|
|
8924
8941
|
return;
|
|
8942
|
+
setPreviewUrl(null);
|
|
8925
8943
|
dispatch(setValues(setValueByPath({ ...values }, paths.imageUrl, null)));
|
|
8926
8944
|
}, [paths.imageUrl, values, dispatch]);
|
|
8927
8945
|
const cls = `header-section-widget-${widgetConfig['widget-id']}`;
|
|
@@ -10598,6 +10616,33 @@ function buildOrderedLevels(flat) {
|
|
|
10598
10616
|
return ordered;
|
|
10599
10617
|
}
|
|
10600
10618
|
const GEO_SECTION_COLUMN_SLOTS = 3;
|
|
10619
|
+
/**
|
|
10620
|
+
* Suggested panel/widget column span from hierarchy depth:
|
|
10621
|
+
* ≤3 levels → 1, 4–5 → 2, ≥6 → 3.
|
|
10622
|
+
*/
|
|
10623
|
+
function suggestedGeoColumnSpan(levelCount) {
|
|
10624
|
+
if (levelCount <= 0) {
|
|
10625
|
+
return 1;
|
|
10626
|
+
}
|
|
10627
|
+
if (levelCount <= 3) {
|
|
10628
|
+
return 1;
|
|
10629
|
+
}
|
|
10630
|
+
if (levelCount < 6) {
|
|
10631
|
+
return 2;
|
|
10632
|
+
}
|
|
10633
|
+
return GEO_SECTION_COLUMN_SLOTS;
|
|
10634
|
+
}
|
|
10635
|
+
/** Clamp span to 1…GEO_SECTION_COLUMN_SLOTS and at most the level count. */
|
|
10636
|
+
function resolveGeoColumnSpan(levelCount, explicitSpan) {
|
|
10637
|
+
const preferred = explicitSpan !== undefined && explicitSpan !== null
|
|
10638
|
+
? explicitSpan
|
|
10639
|
+
: suggestedGeoColumnSpan(levelCount);
|
|
10640
|
+
const clamped = Math.min(GEO_SECTION_COLUMN_SLOTS, Math.max(1, Math.floor(preferred)));
|
|
10641
|
+
if (levelCount <= 0) {
|
|
10642
|
+
return clamped;
|
|
10643
|
+
}
|
|
10644
|
+
return Math.min(clamped, levelCount);
|
|
10645
|
+
}
|
|
10601
10646
|
/** Slice ordered levels into section columns per counts, e.g. [3, 2, 0]. */
|
|
10602
10647
|
function distributeLevelsToColumns(levels, columnCounts) {
|
|
10603
10648
|
const columns = columnCounts.map(() => []);
|
|
@@ -10628,19 +10673,22 @@ function resolveGeoLevelColumns(levels, layout) {
|
|
|
10628
10673
|
const columnCounts = layout.distribution === 'fixed'
|
|
10629
10674
|
? padColumnCounts(layout.columns, GEO_SECTION_COLUMN_SLOTS)
|
|
10630
10675
|
: layout.columns;
|
|
10676
|
+
const columns = distributeLevelsToColumns(levels, columnCounts);
|
|
10677
|
+
const occupied = columns.filter((column) => column.length > 0).length;
|
|
10631
10678
|
return {
|
|
10632
10679
|
columnCounts,
|
|
10633
|
-
columns
|
|
10680
|
+
columns,
|
|
10681
|
+
columnSpan: resolveGeoColumnSpan(levels.length, layout.columnSpan ?? occupied),
|
|
10634
10682
|
};
|
|
10635
10683
|
}
|
|
10636
|
-
//
|
|
10637
|
-
//
|
|
10638
|
-
|
|
10639
|
-
const
|
|
10640
|
-
const columns = distributeLevelsContiguous(levels, columnCount);
|
|
10684
|
+
// Distribute top-to-bottom across the allotted column span so order stays
|
|
10685
|
+
// correct when columns stack on small screens.
|
|
10686
|
+
const columnSpan = resolveGeoColumnSpan(levels.length, layout?.columnSpan);
|
|
10687
|
+
const columns = distributeLevelsContiguous(levels, columnSpan);
|
|
10641
10688
|
return {
|
|
10642
10689
|
columnCounts: columns.map((column) => column.length),
|
|
10643
10690
|
columns,
|
|
10691
|
+
columnSpan,
|
|
10644
10692
|
};
|
|
10645
10693
|
}
|
|
10646
10694
|
function padColumnCounts(counts, slotCount) {
|
|
@@ -10783,6 +10831,42 @@ function getDeepestSelectedValue(orderedLevels, selectedValues) {
|
|
|
10783
10831
|
}
|
|
10784
10832
|
return deepest;
|
|
10785
10833
|
}
|
|
10834
|
+
/** Build geo_code_hierarchy_json document from current selections (for save payload). */
|
|
10835
|
+
function buildHierarchyJson(orderedLevels, selectedValues, options, resolvedLabels = {}) {
|
|
10836
|
+
const hierarchy = [];
|
|
10837
|
+
for (const level of orderedLevels) {
|
|
10838
|
+
const levelValueId = selectedValues[level.level_id];
|
|
10839
|
+
if (!levelValueId) {
|
|
10840
|
+
break;
|
|
10841
|
+
}
|
|
10842
|
+
const optionLabel = options[level.level_id]?.find((item) => item.value === levelValueId)?.label;
|
|
10843
|
+
const mnemonic = optionLabel || resolvedLabels[levelValueId] || levelValueId;
|
|
10844
|
+
hierarchy.push({
|
|
10845
|
+
level_id: level.level_id,
|
|
10846
|
+
level: level.level_mnemonic,
|
|
10847
|
+
level_mnemonic: level.level_mnemonic,
|
|
10848
|
+
level_value_id: levelValueId,
|
|
10849
|
+
level_value_mnemonic: mnemonic,
|
|
10850
|
+
});
|
|
10851
|
+
}
|
|
10852
|
+
if (hierarchy.length === 0) {
|
|
10853
|
+
return null;
|
|
10854
|
+
}
|
|
10855
|
+
return {
|
|
10856
|
+
hierarchy,
|
|
10857
|
+
lowest_level_value_id: hierarchy[hierarchy.length - 1].level_value_id,
|
|
10858
|
+
};
|
|
10859
|
+
}
|
|
10860
|
+
/** Preserve string vs object storage shape used by the existing hierarchy field. */
|
|
10861
|
+
function formatHierarchyForPersist(document, previous) {
|
|
10862
|
+
if (document === null) {
|
|
10863
|
+
return typeof previous === 'string' ? '' : null;
|
|
10864
|
+
}
|
|
10865
|
+
if (typeof previous === 'string') {
|
|
10866
|
+
return JSON.stringify(document);
|
|
10867
|
+
}
|
|
10868
|
+
return document;
|
|
10869
|
+
}
|
|
10786
10870
|
function clearDescendants(orderedLevels, fromIndex, selectedValues, options) {
|
|
10787
10871
|
const nextSelected = { ...selectedValues };
|
|
10788
10872
|
const nextOptions = { ...options };
|
|
@@ -10858,7 +10942,10 @@ function useGeoHierarchy({ config }) {
|
|
|
10858
10942
|
const geoLayout = config['widget-geo-layout'];
|
|
10859
10943
|
const hierarchyJsonPath = React.useMemo(() => resolveHierarchyPath(config), [config]);
|
|
10860
10944
|
const dataPath = React.useMemo(() => resolveDataPath(config), [config]);
|
|
10861
|
-
/**
|
|
10945
|
+
/**
|
|
10946
|
+
* Approved hierarchy for hydrate/display: schema first, then store.
|
|
10947
|
+
* Edits persist draft hierarchy into store values for save; schema keeps approved.
|
|
10948
|
+
*/
|
|
10862
10949
|
const baseHierarchyJson = React.useMemo(() => {
|
|
10863
10950
|
if (!hierarchyJsonPath) {
|
|
10864
10951
|
return null;
|
|
@@ -10958,17 +11045,23 @@ function useGeoHierarchy({ config }) {
|
|
|
10958
11045
|
});
|
|
10959
11046
|
return transformGeoValueOptions(payload);
|
|
10960
11047
|
}, [fetchRawValues]);
|
|
10961
|
-
/**
|
|
10962
|
-
const persistDeepestValue = React.useCallback((nextSelectedValues, orderedLevels) => {
|
|
11048
|
+
/** Persist leaf id + current hierarchy structure for save (schema approved value stays preferred for read). */
|
|
11049
|
+
const persistDeepestValue = React.useCallback((nextSelectedValues, orderedLevels, nextOptions, nextResolvedLabels) => {
|
|
10963
11050
|
if (initializingRef.current || hydratingRef.current || isReadonly) {
|
|
10964
11051
|
return;
|
|
10965
11052
|
}
|
|
10966
11053
|
const deepest = getDeepestSelectedValue(orderedLevels, nextSelectedValues);
|
|
10967
11054
|
selfPersistedValueRef.current = deepest ? String(deepest) : '';
|
|
11055
|
+
const hierarchyDocument = buildHierarchyJson(orderedLevels, nextSelectedValues, nextOptions, nextResolvedLabels);
|
|
11056
|
+
const hierarchyPayload = formatHierarchyForPersist(hierarchyDocument, baseHierarchyRef.current);
|
|
10968
11057
|
const rawDataPath = config['widget-data-path'];
|
|
10969
11058
|
const nextValue = deepest ?? null;
|
|
10970
11059
|
if (rawDataPath && typeof rawDataPath === 'object') {
|
|
10971
|
-
|
|
11060
|
+
const payload = { value: nextValue };
|
|
11061
|
+
if ('hierarchy' in rawDataPath) {
|
|
11062
|
+
payload.hierarchy = hierarchyPayload;
|
|
11063
|
+
}
|
|
11064
|
+
base.onChange(payload);
|
|
10972
11065
|
}
|
|
10973
11066
|
else {
|
|
10974
11067
|
base.onChange(nextValue);
|
|
@@ -11110,9 +11203,7 @@ function useGeoHierarchy({ config }) {
|
|
|
11110
11203
|
nextSelectedValues = cleared.selectedValues;
|
|
11111
11204
|
setSelectedValues(nextSelectedValues);
|
|
11112
11205
|
setOptions(cleared.options);
|
|
11113
|
-
|
|
11114
|
-
persistDeepestValue(nextSelectedValues, levels);
|
|
11115
|
-
}
|
|
11206
|
+
persistDeepestValue(nextSelectedValues, levels, cleared.options, resolvedLabels);
|
|
11116
11207
|
if (!nextValue || levelIndex >= levels.length - 1) {
|
|
11117
11208
|
return;
|
|
11118
11209
|
}
|
|
@@ -11124,9 +11215,17 @@ function useGeoHierarchy({ config }) {
|
|
|
11124
11215
|
const message = error instanceof Error ? error.message : 'Failed to load child geo level values';
|
|
11125
11216
|
setGeoError(message);
|
|
11126
11217
|
}
|
|
11127
|
-
}, [
|
|
11218
|
+
}, [
|
|
11219
|
+
isReadonly,
|
|
11220
|
+
levels,
|
|
11221
|
+
selectedValues,
|
|
11222
|
+
options,
|
|
11223
|
+
resolvedLabels,
|
|
11224
|
+
persistDeepestValue,
|
|
11225
|
+
loadOptionsForLevel,
|
|
11226
|
+
]);
|
|
11128
11227
|
const readonlyPath = React.useMemo(() => buildReadonlyPath(levels, selectedValues, options, resolvedLabels), [levels, selectedValues, options, resolvedLabels]);
|
|
11129
|
-
const { columnCounts, columns: levelColumns } = React.useMemo(() => resolveGeoLevelColumns(levels, geoLayout), [levels, geoLayout]);
|
|
11228
|
+
const { columnCounts, columns: levelColumns, columnSpan } = React.useMemo(() => resolveGeoLevelColumns(levels, geoLayout), [levels, geoLayout]);
|
|
11130
11229
|
const visibleColumns = React.useMemo(() => {
|
|
11131
11230
|
const columnIndex = geoLayout?.columnIndex;
|
|
11132
11231
|
if (columnIndex === undefined || columnIndex === null) {
|
|
@@ -11144,6 +11243,7 @@ function useGeoHierarchy({ config }) {
|
|
|
11144
11243
|
options,
|
|
11145
11244
|
resolvedLabels,
|
|
11146
11245
|
columnCounts,
|
|
11246
|
+
columnSpan,
|
|
11147
11247
|
visibleColumns,
|
|
11148
11248
|
loadingLevels,
|
|
11149
11249
|
loadingLevelId,
|
|
@@ -11213,11 +11313,12 @@ const GeoHierarchyWidget = ({ config }) => {
|
|
|
11213
11313
|
isLevelEnabled,
|
|
11214
11314
|
formatLevelLabel,
|
|
11215
11315
|
};
|
|
11316
|
+
const layoutColumnCount = Math.max(visibleColumns.length, 1);
|
|
11216
11317
|
const content = visibleColumns.length <= 1 ? (renderLevelRows({
|
|
11217
11318
|
...rowProps,
|
|
11218
11319
|
columnLevels: visibleColumns[0]?.levels ?? levels,
|
|
11219
11320
|
})) : (jsxRuntimeExports.jsx("div", { className: "flex flex-col lg:grid w-full", style: {
|
|
11220
|
-
gridTemplateColumns: `repeat(${
|
|
11321
|
+
gridTemplateColumns: `repeat(${layoutColumnCount}, minmax(200px, 1fr))`,
|
|
11221
11322
|
}, children: visibleColumns.map((column, position) => {
|
|
11222
11323
|
const isLast = position === visibleColumns.length - 1;
|
|
11223
11324
|
const columnClassName = [
|
|
@@ -11345,7 +11446,22 @@ const DocsWidget = ({ config }) => {
|
|
|
11345
11446
|
fileInputRefs.current[docKey] = el;
|
|
11346
11447
|
} })] })), hasFile && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: (e) => handlePreview(file, e), className: "inline-flex items-center px-3 py-1 rounded-md border border-gray-300 text-sm font-medium text-gray-900 bg-gray-50 focus:outline-none", title: fileName, children: t?.('common.view') ?? 'View' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: () => handleRemove(docKey), className: "inline-flex items-center px-3 py-1 rounded-md border border-gray-300 text-sm font-medium text-gray-900 bg-gray-50 focus:outline-none", title: "Remove", children: t?.('common.remove') ?? 'Remove' })] }))] }) })] }) }, docKey));
|
|
11347
11448
|
};
|
|
11348
|
-
return (jsxRuntimeExports.jsxs("div", { className: isReadonly ? 'DocsDisplayWidget mb-[10px]' : 'DocsWidget mb-[10px]', children: [jsxRuntimeExports.jsx("div", { className: "flex flex-col lg:grid
|
|
11449
|
+
return (jsxRuntimeExports.jsxs("div", { className: isReadonly ? 'DocsDisplayWidget mb-[10px]' : 'DocsWidget mb-[10px]', children: [jsxRuntimeExports.jsx("div", { className: "flex flex-col lg:grid w-full", style: { gridTemplateColumns: `repeat(${docColumns.length || 1}, minmax(0, 1fr))` }, children: docColumns.map((column, columnIndex) => {
|
|
11450
|
+
const isLast = columnIndex === docColumns.length - 1;
|
|
11451
|
+
const columnClassName = [
|
|
11452
|
+
'flex flex-col min-w-0 relative',
|
|
11453
|
+
columnIndex > 0 ? 'lg:pl-10' : '',
|
|
11454
|
+
isLast ? '' : 'lg:pr-10',
|
|
11455
|
+
]
|
|
11456
|
+
.filter(Boolean)
|
|
11457
|
+
.join(' ');
|
|
11458
|
+
return (jsxRuntimeExports.jsxs("div", { className: columnClassName, children: [!isLast && (jsxRuntimeExports.jsx("div", { className: "hidden lg:block absolute right-0 top-0 w-px", style: {
|
|
11459
|
+
bottom: '5px',
|
|
11460
|
+
backgroundColor: isReadonly
|
|
11461
|
+
? 'var(--owt-panel-divider-color, #C4C4C4)'
|
|
11462
|
+
: 'var(--owt-color-primary, #F5BB1A)',
|
|
11463
|
+
} })), column.map((doc) => renderSlot(doc))] }, `docs-column-${columnIndex}`));
|
|
11464
|
+
}) }), jsxRuntimeExports.jsx(FilePreviewModal, { file: previewFile, isOpen: isPreviewOpen && !!previewFile, onClose: () => {
|
|
11349
11465
|
setIsPreviewOpen(false);
|
|
11350
11466
|
setPreviewFile(null);
|
|
11351
11467
|
} })] }));
|