@openg2p/registry-widgets 0.1.8 → 0.1.9
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.d.ts.map +1 -1
- package/dist/components/SectionsContainer.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.esm.js +380 -53
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +380 -52
- package/dist/index.js.map +1 -1
- package/dist/registry/defaultWidgets.d.ts.map +1 -1
- package/dist/widgets/HeaderSectionWidget.d.ts +7 -0
- package/dist/widgets/HeaderSectionWidget.d.ts.map +1 -0
- package/dist/widgets/index.d.ts +1 -0
- package/dist/widgets/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3835,8 +3835,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3835
3835
|
return [];
|
|
3836
3836
|
const snapshot = {};
|
|
3837
3837
|
let hasTable = false;
|
|
3838
|
-
if (!sectionRegisterId)
|
|
3839
|
-
return [];
|
|
3840
3838
|
const resolvePath = (path) => (pathPrefix ? `${pathPrefix}.${path}` : path);
|
|
3841
3839
|
widgets.forEach(widget => {
|
|
3842
3840
|
const widgetPath = widget['widget-data-path'];
|
|
@@ -3866,9 +3864,11 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3866
3864
|
: fullPath;
|
|
3867
3865
|
cleanedSnapshot[fieldPath] = value;
|
|
3868
3866
|
});
|
|
3869
|
-
const sectionData =
|
|
3870
|
-
?
|
|
3871
|
-
|
|
3867
|
+
const sectionData = sectionRegisterId
|
|
3868
|
+
? (pathPrefix
|
|
3869
|
+
? getValueByPath(sourceData, resolvePath(sectionRegisterId))
|
|
3870
|
+
: sourceData[sectionRegisterId])
|
|
3871
|
+
: {};
|
|
3872
3872
|
return [
|
|
3873
3873
|
{
|
|
3874
3874
|
...sectionData,
|
|
@@ -4020,7 +4020,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4020
4020
|
if (JSON.stringify(oldSchemaData) !== JSON.stringify(newSchemaData)) {
|
|
4021
4021
|
try {
|
|
4022
4022
|
const sectionchanges = {
|
|
4023
|
-
section_id: dbSectionId,
|
|
4023
|
+
section_id: dbSectionId ?? originalSection['section-id'],
|
|
4024
4024
|
section_register_id: sectionRegisterId,
|
|
4025
4025
|
records: [...newSchemaData],
|
|
4026
4026
|
files: [...sectionFiles]
|
|
@@ -4035,49 +4035,52 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4035
4035
|
};
|
|
4036
4036
|
// IntakeForm: save section then collapse current and expand next (or stay on final section)
|
|
4037
4037
|
const handleIntakeFormSave = React.useCallback(async () => {
|
|
4038
|
-
if (
|
|
4039
|
-
return;
|
|
4040
|
-
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4041
|
-
const currentState = store.getState().widget;
|
|
4042
|
-
const currentSchemaData = currentState.values || {};
|
|
4043
|
-
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch);
|
|
4044
|
-
if (!isSectionValid)
|
|
4038
|
+
if (sectionIndex === undefined)
|
|
4045
4039
|
return;
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
const
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
files: [...sectionFiles],
|
|
4040
|
+
// Only run save/validation logic when in draft mode and handlers are available
|
|
4041
|
+
if (isDraft !== false && store && onSectionSave) {
|
|
4042
|
+
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4043
|
+
const currentState = store.getState().widget;
|
|
4044
|
+
const currentSchemaData = currentState.values || {};
|
|
4045
|
+
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch);
|
|
4046
|
+
if (!isSectionValid)
|
|
4047
|
+
return;
|
|
4048
|
+
const oldSchemaData = schemaData || contextSchemaData;
|
|
4049
|
+
const newSchemaData = trackSectionChages(sectionWidgets, currentSchemaData, namespace);
|
|
4050
|
+
const sectionFiles = [];
|
|
4051
|
+
if (hasSupportingDocuments) {
|
|
4052
|
+
const originalSupportingDocuments = originalSection['section-supporting-documents'] || [];
|
|
4053
|
+
originalSupportingDocuments.forEach((doc) => {
|
|
4054
|
+
const originalDataPath = doc['document-data-path'];
|
|
4055
|
+
const storeDataPath = namespace && originalDataPath
|
|
4056
|
+
? `${namespace}.${originalDataPath}`
|
|
4057
|
+
: originalDataPath;
|
|
4058
|
+
sectionFiles.push(getValueByPath(currentSchemaData, storeDataPath));
|
|
4066
4059
|
});
|
|
4067
4060
|
}
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4061
|
+
if (JSON.stringify(oldSchemaData) !== JSON.stringify(newSchemaData)) {
|
|
4062
|
+
try {
|
|
4063
|
+
await onSectionSave({
|
|
4064
|
+
section_id: dbSectionId ?? originalSection['section-id'],
|
|
4065
|
+
section_register_id: sectionRegisterId,
|
|
4066
|
+
records: [...newSchemaData],
|
|
4067
|
+
files: [...sectionFiles],
|
|
4068
|
+
});
|
|
4069
|
+
}
|
|
4070
|
+
catch (error) {
|
|
4071
|
+
console.error('Section Changes Save failed', error);
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4071
4074
|
}
|
|
4075
|
+
if (mode === 'IntakeForm') {
|
|
4076
|
+
baselineSnapshotRef.current = buildSectionSnapshot(currentSchemaData, namespace);
|
|
4077
|
+
setIntakeFormBaselineTrigger((prev) => prev + 1);
|
|
4078
|
+
}
|
|
4079
|
+
onSectionDirtyChange?.(sectionId, false);
|
|
4072
4080
|
}
|
|
4073
|
-
//
|
|
4074
|
-
if (mode === 'IntakeForm') {
|
|
4075
|
-
baselineSnapshotRef.current = buildSectionSnapshot(currentSchemaData, namespace);
|
|
4076
|
-
setIntakeFormBaselineTrigger((prev) => prev + 1);
|
|
4077
|
-
}
|
|
4078
|
-
onSectionDirtyChange?.(sectionId, false);
|
|
4081
|
+
// Always navigate to the next section
|
|
4079
4082
|
onSectionSaveSuccess?.(sectionIndex);
|
|
4080
|
-
}, [store, onSectionSave, onSectionSaveSuccess, sectionIndex, originalSection, schemaData, contextSchemaData, namespace, hasSupportingDocuments, dbSectionId, sectionRegisterId, dispatch, buildSectionSnapshot, sectionId, onSectionDirtyChange, mode]);
|
|
4083
|
+
}, [store, onSectionSave, onSectionSaveSuccess, sectionIndex, originalSection, schemaData, contextSchemaData, namespace, hasSupportingDocuments, dbSectionId, sectionRegisterId, dispatch, buildSectionSnapshot, sectionId, onSectionDirtyChange, mode, isDraft]);
|
|
4081
4084
|
// Handle cancel button click
|
|
4082
4085
|
const handleCancel = () => {
|
|
4083
4086
|
// Revert values in store to original schema data
|
|
@@ -4398,7 +4401,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4398
4401
|
gap: '12px',
|
|
4399
4402
|
marginBottom: '20px',
|
|
4400
4403
|
width: '100%',
|
|
4401
|
-
}, children: [jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => onPreviousSection?.(sectionIndex),
|
|
4404
|
+
}, children: [typeof sectionIndex === 'number' && sectionIndex > 0 && (jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => onPreviousSection?.(sectionIndex), className: "intake-form-prev-btn", style: {
|
|
4402
4405
|
fontFamily: 'Roboto, sans-serif',
|
|
4403
4406
|
fontSize: '14px',
|
|
4404
4407
|
fontWeight: 400,
|
|
@@ -4406,25 +4409,25 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4406
4409
|
borderRadius: '10px',
|
|
4407
4410
|
border: '1px solid #FD8C3E',
|
|
4408
4411
|
background: '#F3F4F6',
|
|
4409
|
-
color:
|
|
4410
|
-
cursor:
|
|
4412
|
+
color: 'rgba(0, 0, 0, 0.5)',
|
|
4413
|
+
cursor: 'pointer',
|
|
4411
4414
|
display: 'inline-flex',
|
|
4412
4415
|
alignItems: 'center',
|
|
4413
4416
|
gap: '8px',
|
|
4414
|
-
}, children: [jsxRuntimeExports.jsx("img", { src: img$5, alt: "", "aria-hidden": true, style: { width: '14px', height: '14px', opacity:
|
|
4417
|
+
}, children: [jsxRuntimeExports.jsx("img", { src: img$5, alt: "", "aria-hidden": true, style: { width: '14px', height: '14px', opacity: 0.5 } }), translate('common.previous') || 'Prev'] })), jsxRuntimeExports.jsxs("button", { type: "button", onClick: handleIntakeFormSave, className: "intake-form-save-btn", style: {
|
|
4415
4418
|
fontFamily: 'Roboto, sans-serif',
|
|
4416
4419
|
fontSize: '14px',
|
|
4417
4420
|
fontWeight: 400,
|
|
4418
4421
|
padding: '8px 24px',
|
|
4419
4422
|
borderRadius: '10px',
|
|
4420
4423
|
border: '1px solid #FD8C3E',
|
|
4421
|
-
background:
|
|
4422
|
-
color:
|
|
4423
|
-
cursor:
|
|
4424
|
+
background: '#F3F4F6',
|
|
4425
|
+
color: 'rgba(0, 0, 0, 0.5)',
|
|
4426
|
+
cursor: 'pointer',
|
|
4424
4427
|
display: 'inline-flex',
|
|
4425
4428
|
alignItems: 'center',
|
|
4426
4429
|
gap: '8px',
|
|
4427
|
-
}, children: [translate('common.
|
|
4430
|
+
}, children: [translate('common.next') || 'Next', jsxRuntimeExports.jsx("img", { src: img$4, alt: "", "aria-hidden": true, style: { width: '14px', height: '14px' } })] })] })] }) }))] })) : (
|
|
4428
4431
|
/* RegistryView / CRView: standard layout */
|
|
4429
4432
|
jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [sectionToRender['section-title'] && (jsxRuntimeExports.jsxs("div", { style: {
|
|
4430
4433
|
marginTop: '35px',
|
|
@@ -4681,7 +4684,9 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
4681
4684
|
if (index + 1 < safeSections.length) {
|
|
4682
4685
|
setExpandedSectionIndex(index + 1);
|
|
4683
4686
|
}
|
|
4684
|
-
|
|
4687
|
+
else {
|
|
4688
|
+
setExpandedSectionIndex(null);
|
|
4689
|
+
}
|
|
4685
4690
|
}, [safeSections.length]);
|
|
4686
4691
|
// IntakeForm mode: called when Previous clicked - collapse current, expand previous
|
|
4687
4692
|
const handlePreviousSection = React.useCallback((index) => {
|
|
@@ -8883,6 +8888,326 @@ const TextAreaWidget = ({ config }) => {
|
|
|
8883
8888
|
}, children: charCounterText }))] }), hasError && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: errorMessage }))] })] }) }));
|
|
8884
8889
|
};
|
|
8885
8890
|
|
|
8891
|
+
const DEFAULT_STATUS_COLORS = {
|
|
8892
|
+
active: '#16A34A',
|
|
8893
|
+
inactive: '#D97706',
|
|
8894
|
+
archived: '#6B7280',
|
|
8895
|
+
};
|
|
8896
|
+
// ── Hook: load data-source options for a single field ────────────
|
|
8897
|
+
// Options are loaded in both view and edit modes because view mode
|
|
8898
|
+
// needs them to resolve display labels (e.g. "active" → "Active").
|
|
8899
|
+
// For API data sources, loading is deferred to edit mode to avoid
|
|
8900
|
+
// unnecessary network calls when only labels are needed.
|
|
8901
|
+
function useFieldDataSource(fieldKey, fieldConfig, isReadonly) {
|
|
8902
|
+
const [options, setOptions] = React.useState([]);
|
|
8903
|
+
const { dataSourceRequestHandler, schemaData } = useWidgetContext();
|
|
8904
|
+
const values = reactRedux.useSelector((state) => state.widget.values);
|
|
8905
|
+
const dataSource = fieldConfig?.['data-source'];
|
|
8906
|
+
const dsType = dataSource?.type;
|
|
8907
|
+
const dsKey = dataSource
|
|
8908
|
+
? `${fieldKey}-${dsType}-${JSON.stringify(dataSource)}`
|
|
8909
|
+
: '';
|
|
8910
|
+
React.useEffect(() => {
|
|
8911
|
+
if (!dataSource) {
|
|
8912
|
+
setOptions([]);
|
|
8913
|
+
return;
|
|
8914
|
+
}
|
|
8915
|
+
// API sources: only fetch when editable to avoid unnecessary calls
|
|
8916
|
+
if (dataSource.type === 'api' && isReadonly) {
|
|
8917
|
+
return;
|
|
8918
|
+
}
|
|
8919
|
+
let cancelled = false;
|
|
8920
|
+
const load = async () => {
|
|
8921
|
+
try {
|
|
8922
|
+
let raw = [];
|
|
8923
|
+
if (dataSource.type === 'static') {
|
|
8924
|
+
raw = getStaticDataSource(dataSource);
|
|
8925
|
+
}
|
|
8926
|
+
else if (dataSource.type === 'api') {
|
|
8927
|
+
if (!dataSourceRequestHandler)
|
|
8928
|
+
return;
|
|
8929
|
+
raw = await getApiDataSource(dataSource, values, dataSourceRequestHandler);
|
|
8930
|
+
}
|
|
8931
|
+
else if (dataSource.type === 'schema') {
|
|
8932
|
+
raw = getSchemaDataSource(dataSource, schemaData || {});
|
|
8933
|
+
}
|
|
8934
|
+
const transformed = transformDataSourceOptions(raw, dataSource.valueKey, dataSource.labelKey);
|
|
8935
|
+
if (!cancelled)
|
|
8936
|
+
setOptions(transformed);
|
|
8937
|
+
}
|
|
8938
|
+
catch (err) {
|
|
8939
|
+
console.error(`[HeaderSectionWidget] Error loading data-source for field "${fieldKey}":`, err);
|
|
8940
|
+
if (!cancelled)
|
|
8941
|
+
setOptions([]);
|
|
8942
|
+
}
|
|
8943
|
+
};
|
|
8944
|
+
load();
|
|
8945
|
+
return () => { cancelled = true; };
|
|
8946
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8947
|
+
}, [dsKey, isReadonly, dataSourceRequestHandler]);
|
|
8948
|
+
return options;
|
|
8949
|
+
}
|
|
8950
|
+
// ── Main component ───────────────────────────────────────────────
|
|
8951
|
+
const HeaderSectionWidget = ({ config }) => {
|
|
8952
|
+
const { config: widgetConfig, getFieldValue, } = useBaseWidget({ config });
|
|
8953
|
+
const dispatch = reactRedux.useDispatch();
|
|
8954
|
+
const { translateConfig } = useWidgetTranslation();
|
|
8955
|
+
const { schemaData } = useWidgetContext();
|
|
8956
|
+
const values = reactRedux.useSelector((state) => state.widget.values);
|
|
8957
|
+
const isReadonly = widgetConfig['widget-readonly'] !== false;
|
|
8958
|
+
const dataPath = widgetConfig['widget-data-path'];
|
|
8959
|
+
// ── Per-field config map ──────────────────────────────────────
|
|
8960
|
+
const fieldConfigMap = React.useMemo(() => {
|
|
8961
|
+
return widgetConfig['widget-field-config'] || {};
|
|
8962
|
+
}, [widgetConfig['widget-field-config']]);
|
|
8963
|
+
// ── Load data source options for the status field ─────────────
|
|
8964
|
+
const statusOptions = useFieldDataSource('status', fieldConfigMap['status'], isReadonly);
|
|
8965
|
+
// ── Resolve field values ──────────────────────────────────────
|
|
8966
|
+
const paths = React.useMemo(() => {
|
|
8967
|
+
if (!dataPath || typeof dataPath !== 'object')
|
|
8968
|
+
return {};
|
|
8969
|
+
return dataPath;
|
|
8970
|
+
}, [dataPath]);
|
|
8971
|
+
const findValue = React.useCallback((fieldKey) => {
|
|
8972
|
+
const path = paths[fieldKey];
|
|
8973
|
+
if (!path)
|
|
8974
|
+
return undefined;
|
|
8975
|
+
const searchIn = (source) => {
|
|
8976
|
+
if (!source)
|
|
8977
|
+
return undefined;
|
|
8978
|
+
let v = getValueByPath(source, path);
|
|
8979
|
+
if (v !== undefined)
|
|
8980
|
+
return v;
|
|
8981
|
+
for (const obj of Object.values(source)) {
|
|
8982
|
+
if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
|
|
8983
|
+
v = getValueByPath(obj, path);
|
|
8984
|
+
if (v !== undefined)
|
|
8985
|
+
return v;
|
|
8986
|
+
}
|
|
8987
|
+
}
|
|
8988
|
+
return undefined;
|
|
8989
|
+
};
|
|
8990
|
+
let result = searchIn(values);
|
|
8991
|
+
if (result === undefined)
|
|
8992
|
+
result = searchIn(schemaData);
|
|
8993
|
+
return result;
|
|
8994
|
+
}, [paths, values, schemaData]);
|
|
8995
|
+
const imageUrl = findValue('image') || null;
|
|
8996
|
+
const displayName = findValue('name') || '';
|
|
8997
|
+
const functionalId = findValue('functionalId') || '';
|
|
8998
|
+
const statusValue = findValue('status') || '';
|
|
8999
|
+
const statusReason = findValue('statusReason') || '';
|
|
9000
|
+
const createdBy = findValue('createdBy') || '';
|
|
9001
|
+
const createdAt = findValue('createdAt') || '';
|
|
9002
|
+
const lastApprovedBy = findValue('lastApprovedBy') || '';
|
|
9003
|
+
const lastApprovedAt = findValue('lastApprovedAt') || '';
|
|
9004
|
+
// ── Format options ────────────────────────────────────────────
|
|
9005
|
+
const format = (widgetConfig['widget-data-format'] || {});
|
|
9006
|
+
const imageSize = format.imageSize || 90;
|
|
9007
|
+
const nameColor = format.nameColor || '#ED7C22';
|
|
9008
|
+
const statusColors = {
|
|
9009
|
+
...DEFAULT_STATUS_COLORS,
|
|
9010
|
+
...(format.statusColors || {}),
|
|
9011
|
+
};
|
|
9012
|
+
// ── Value change helpers ──────────────────────────────────────
|
|
9013
|
+
const updateFieldValue = React.useCallback((fieldKey, newValue) => {
|
|
9014
|
+
const path = paths[fieldKey];
|
|
9015
|
+
if (!path)
|
|
9016
|
+
return;
|
|
9017
|
+
const updated = setValueByPath({ ...values }, path, newValue);
|
|
9018
|
+
dispatch(setValues(updated));
|
|
9019
|
+
}, [paths, values, dispatch]);
|
|
9020
|
+
// ── Status helpers ────────────────────────────────────────────
|
|
9021
|
+
const statusLabel = React.useMemo(() => {
|
|
9022
|
+
if (!statusValue)
|
|
9023
|
+
return '';
|
|
9024
|
+
const opt = statusOptions.find((o) => String(o.value).toLowerCase() === String(statusValue).toLowerCase());
|
|
9025
|
+
return opt ? opt.label : String(statusValue);
|
|
9026
|
+
}, [statusValue, statusOptions]);
|
|
9027
|
+
const statusColor = statusColors[String(statusValue).toLowerCase()] || '#6B7280';
|
|
9028
|
+
// ── Scoped class for CSS isolation ────────────────────────────
|
|
9029
|
+
const cls = `header-section-widget-${widgetConfig['widget-id']}`;
|
|
9030
|
+
// ── Indicator dot component ───────────────────────────────────
|
|
9031
|
+
const Dot = ({ color }) => (jsxRuntimeExports.jsx("span", { style: {
|
|
9032
|
+
display: 'inline-block',
|
|
9033
|
+
width: 8,
|
|
9034
|
+
height: 8,
|
|
9035
|
+
borderRadius: '50%',
|
|
9036
|
+
backgroundColor: color,
|
|
9037
|
+
flexShrink: 0,
|
|
9038
|
+
marginTop: 6,
|
|
9039
|
+
} }));
|
|
9040
|
+
// ── RENDER ────────────────────────────────────────────────────
|
|
9041
|
+
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
|
|
9042
|
+
.${cls} {
|
|
9043
|
+
display: flex;
|
|
9044
|
+
flex-direction: row;
|
|
9045
|
+
gap: 1.5rem;
|
|
9046
|
+
width: 100%;
|
|
9047
|
+
font-family: Roboto, sans-serif;
|
|
9048
|
+
padding: 35px 0 16px 0;
|
|
9049
|
+
}
|
|
9050
|
+
|
|
9051
|
+
.${cls} .hdr-left {
|
|
9052
|
+
display: flex;
|
|
9053
|
+
flex-direction: row;
|
|
9054
|
+
align-items: flex-start;
|
|
9055
|
+
gap: 1rem;
|
|
9056
|
+
flex: 1 1 55%;
|
|
9057
|
+
min-width: 0;
|
|
9058
|
+
}
|
|
9059
|
+
|
|
9060
|
+
.${cls} .hdr-right {
|
|
9061
|
+
display: flex;
|
|
9062
|
+
flex-direction: column;
|
|
9063
|
+
gap: 0.5rem;
|
|
9064
|
+
flex: 0 0 auto;
|
|
9065
|
+
min-width: 220px;
|
|
9066
|
+
}
|
|
9067
|
+
|
|
9068
|
+
.${cls} .hdr-avatar {
|
|
9069
|
+
width: ${imageSize}px;
|
|
9070
|
+
height: ${imageSize}px;
|
|
9071
|
+
border-radius: 8px;
|
|
9072
|
+
object-fit: cover;
|
|
9073
|
+
background-color: #e5e7eb;
|
|
9074
|
+
border: 2px solid #d1d5db;
|
|
9075
|
+
flex-shrink: 0;
|
|
9076
|
+
}
|
|
9077
|
+
|
|
9078
|
+
.${cls} .hdr-avatar-placeholder {
|
|
9079
|
+
width: ${imageSize}px;
|
|
9080
|
+
height: ${imageSize}px;
|
|
9081
|
+
border-radius: 8px;
|
|
9082
|
+
background-color: #e5e7eb;
|
|
9083
|
+
border: 2px solid #d1d5db;
|
|
9084
|
+
display: flex;
|
|
9085
|
+
align-items: center;
|
|
9086
|
+
justify-content: center;
|
|
9087
|
+
flex-shrink: 0;
|
|
9088
|
+
overflow: hidden;
|
|
9089
|
+
}
|
|
9090
|
+
|
|
9091
|
+
.${cls} .hdr-avatar-placeholder img {
|
|
9092
|
+
width: 100%;
|
|
9093
|
+
height: 100%;
|
|
9094
|
+
object-fit: cover;
|
|
9095
|
+
border-radius: 8px;
|
|
9096
|
+
}
|
|
9097
|
+
|
|
9098
|
+
.${cls} .hdr-info {
|
|
9099
|
+
display: flex;
|
|
9100
|
+
flex-direction: column;
|
|
9101
|
+
gap: 0.35rem;
|
|
9102
|
+
min-width: 0;
|
|
9103
|
+
flex: 1;
|
|
9104
|
+
}
|
|
9105
|
+
|
|
9106
|
+
.${cls} .hdr-name {
|
|
9107
|
+
font-size: 1.25rem;
|
|
9108
|
+
font-weight: 600;
|
|
9109
|
+
color: ${nameColor};
|
|
9110
|
+
line-height: 1.4;
|
|
9111
|
+
word-wrap: break-word;
|
|
9112
|
+
}
|
|
9113
|
+
|
|
9114
|
+
.${cls} .hdr-field-row {
|
|
9115
|
+
display: flex;
|
|
9116
|
+
align-items: flex-start;
|
|
9117
|
+
gap: 0.5rem;
|
|
9118
|
+
font-size: 0.875rem;
|
|
9119
|
+
line-height: 1.6;
|
|
9120
|
+
}
|
|
9121
|
+
|
|
9122
|
+
.${cls} .hdr-field-label {
|
|
9123
|
+
color: #6b7280;
|
|
9124
|
+
font-weight: 500;
|
|
9125
|
+
white-space: nowrap;
|
|
9126
|
+
}
|
|
9127
|
+
|
|
9128
|
+
.${cls} .hdr-field-value {
|
|
9129
|
+
color: #111827;
|
|
9130
|
+
font-weight: 600;
|
|
9131
|
+
}
|
|
9132
|
+
|
|
9133
|
+
.${cls} .hdr-status-badge {
|
|
9134
|
+
display: inline-block;
|
|
9135
|
+
padding: 2px 12px;
|
|
9136
|
+
border-radius: 4px;
|
|
9137
|
+
font-size: 0.75rem;
|
|
9138
|
+
font-weight: 600;
|
|
9139
|
+
color: #fff;
|
|
9140
|
+
}
|
|
9141
|
+
|
|
9142
|
+
.${cls} .hdr-meta-row {
|
|
9143
|
+
display: flex;
|
|
9144
|
+
align-items: baseline;
|
|
9145
|
+
gap: 0.35rem;
|
|
9146
|
+
font-size: 0.875rem;
|
|
9147
|
+
line-height: 1.6;
|
|
9148
|
+
}
|
|
9149
|
+
|
|
9150
|
+
.${cls} .hdr-meta-label {
|
|
9151
|
+
color: #6b7280;
|
|
9152
|
+
font-weight: 400;
|
|
9153
|
+
}
|
|
9154
|
+
|
|
9155
|
+
.${cls} .hdr-meta-value {
|
|
9156
|
+
color: #111827;
|
|
9157
|
+
font-weight: 600;
|
|
9158
|
+
}
|
|
9159
|
+
|
|
9160
|
+
.${cls} .hdr-select {
|
|
9161
|
+
height: 32px;
|
|
9162
|
+
padding: 0 8px;
|
|
9163
|
+
border: 1px solid #d1d5db;
|
|
9164
|
+
border-radius: 6px;
|
|
9165
|
+
font-size: 0.875rem;
|
|
9166
|
+
font-family: Roboto, sans-serif;
|
|
9167
|
+
background: #fff;
|
|
9168
|
+
min-width: 140px;
|
|
9169
|
+
color: #374151;
|
|
9170
|
+
}
|
|
9171
|
+
.${cls} .hdr-select:focus {
|
|
9172
|
+
outline: none;
|
|
9173
|
+
border-color: #ED7C22;
|
|
9174
|
+
box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
|
|
9175
|
+
}
|
|
9176
|
+
|
|
9177
|
+
.${cls} .hdr-input {
|
|
9178
|
+
height: 32px;
|
|
9179
|
+
padding: 0 8px;
|
|
9180
|
+
border: 1px solid #d1d5db;
|
|
9181
|
+
border-radius: 6px;
|
|
9182
|
+
font-size: 0.875rem;
|
|
9183
|
+
font-family: Roboto, sans-serif;
|
|
9184
|
+
background: #fff;
|
|
9185
|
+
min-width: 140px;
|
|
9186
|
+
color: #374151;
|
|
9187
|
+
}
|
|
9188
|
+
.${cls} .hdr-input:focus {
|
|
9189
|
+
outline: none;
|
|
9190
|
+
border-color: #ED7C22;
|
|
9191
|
+
box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
|
|
9192
|
+
}
|
|
9193
|
+
|
|
9194
|
+
@media (max-width: 768px) {
|
|
9195
|
+
.${cls} {
|
|
9196
|
+
flex-direction: column;
|
|
9197
|
+
}
|
|
9198
|
+
.${cls} .hdr-right {
|
|
9199
|
+
min-width: 0;
|
|
9200
|
+
}
|
|
9201
|
+
}
|
|
9202
|
+
` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [jsxRuntimeExports.jsxs("div", { className: "hdr-left", children: [jsxRuntimeExports.jsxs("div", { children: [imageUrl ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: displayName || 'Profile', className: "hdr-avatar", onError: (e) => {
|
|
9203
|
+
e.target.style.display = 'none';
|
|
9204
|
+
const placeholder = e.target
|
|
9205
|
+
.parentElement?.querySelector('.hdr-avatar-placeholder');
|
|
9206
|
+
if (placeholder)
|
|
9207
|
+
placeholder.style.display = 'flex';
|
|
9208
|
+
} })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: imageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-info", children: [displayName && jsxRuntimeExports.jsx("div", { className: "hdr-name", children: displayName }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: "#9CA3AF" }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [translateConfig('Functional Record ID') || 'Functional Record ID', " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? statusColor : '#F59E0B' }), jsxRuntimeExports.jsx("span", { className: "hdr-field-label", children: translateConfig('Record Status') || 'Record Status' }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: "-" }))) : (jsxRuntimeExports.jsxs("select", { className: "hdr-select", value: statusValue, onChange: (e) => updateFieldValue('status', e.target.value), children: [jsxRuntimeExports.jsx("option", { value: "", children: translateConfig('Select') || 'Select' }), statusOptions.map((opt) => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? '#9CA3AF' : '#F59E0B' }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [translateConfig('Status Reason') || 'Status Reason', " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsx("input", { type: "text", className: "hdr-input", value: statusReason, placeholder: translateConfig('Enter Reason') || 'Enter Reason', onChange: (e) => updateFieldValue('statusReason', e.target.value) }))] })] })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-right", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [translateConfig('Created by') || 'Created by', " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [translateConfig('Created at') || 'Created at', " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [translateConfig('Last Approved by') || 'Last Approved by', " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [translateConfig('Last Approved at') || 'Last Approved at', " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedAt || '-' })] })] })] })] }));
|
|
9209
|
+
};
|
|
9210
|
+
|
|
8886
9211
|
/**
|
|
8887
9212
|
* Register all default/generic widgets
|
|
8888
9213
|
* This is called automatically when the package is imported
|
|
@@ -8922,6 +9247,8 @@ const registerDefaultWidgets = () => {
|
|
|
8922
9247
|
widgetRegistry.register({ widget: 'display', component: DisplayWidget });
|
|
8923
9248
|
// Profile widget for displaying user identity (image, name, ID)
|
|
8924
9249
|
widgetRegistry.register({ widget: 'profile', component: ProfileWidget });
|
|
9250
|
+
// Header section widget for full-width registry header with profile, status, and metadata
|
|
9251
|
+
widgetRegistry.register({ widget: 'header-section', component: HeaderSectionWidget });
|
|
8925
9252
|
};
|
|
8926
9253
|
// Auto-register on import
|
|
8927
9254
|
registerDefaultWidgets();
|
|
@@ -9287,6 +9614,7 @@ exports.DateInputWidget = DateInputWidget;
|
|
|
9287
9614
|
exports.DateTimeInputWidget = DateTimeInputWidget;
|
|
9288
9615
|
exports.DisplayWidget = DisplayWidget;
|
|
9289
9616
|
exports.FileInputWidget = FileInputWidget;
|
|
9617
|
+
exports.HeaderSectionWidget = HeaderSectionWidget;
|
|
9290
9618
|
exports.IterableAccordionWidget = IterableAccordionWidget;
|
|
9291
9619
|
exports.JSONEditorPanel = JSONEditorPanel;
|
|
9292
9620
|
exports.NumberInputWidget = NumberInputWidget;
|